Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

Commit

Permalink
[core][Android] fix thread block when nested sync method to JSS in JS…
Browse files Browse the repository at this point in the history
… Thread (#1600)
  • Loading branch information
yxping authored and YorkShen committed Sep 30, 2018
1 parent 44051e5 commit a6e7134
Show file tree
Hide file tree
Showing 26 changed files with 334 additions and 53 deletions.
Binary file modified android/sdk/libs/armeabi-v7a/libweexcore.so
Binary file not shown.
Binary file modified android/sdk/libs/armeabi/libweexcore.so
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.taobao.weex.bridge;

public interface ResultCallback<T> {
void onReceiveResult(T result);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.taobao.weex.bridge;

import android.util.SparseArray;

/**
* Manage async callbacks which waiting for the result of executing javascript
*/
/* default */ class ResultCallbackManager {
// Unique id for callback after executing js
private static long sCallbackId = 0;
// Map for save callbacks, key is id
private static SparseArray<ResultCallback> mResultCallbacks = new SparseArray<>();

// Generate unique id
static long generateCallbackId(ResultCallback callback) {
if (sCallbackId >= Integer.MAX_VALUE) {
sCallbackId = 0;
}
int id = (int) sCallbackId++;
mResultCallbacks.put(id, callback);
return id;
}

// Remove id from callback map
static ResultCallback removeCallbackById(long id) {
ResultCallback callback = mResultCallbacks.get((int) id);
mResultCallbacks.remove((int) id);
return callback;
}
}
19 changes: 17 additions & 2 deletions android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.taobao.weex.bridge;

import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
Expand Down Expand Up @@ -60,6 +61,7 @@ public class WXBridge implements IWXBridge {
private native int nativeExecJSService(String javascript);

public native byte[] nativeExecJSWithResult(String instanceId, String _namespace, String _function, WXJSObject[] args);
public native void nativeExecJSWithCallback(String instanceId, String _namespace, String _function, WXJSObject[] args, long callbackId);

public native int nativeCreateInstanceContext(String instanceId, String name, String function, WXJSObject[] args);

Expand Down Expand Up @@ -138,8 +140,21 @@ public int execJS(String instanceId, String namespace, String function, WXJSObje
}

@Override
public byte[] execJSWithResult(String instanceId, String namespace, String function, WXJSObject[] args) {
return nativeExecJSWithResult(instanceId, namespace, function, args);
public void execJSWithCallback(String instanceId, String namespace, String function, WXJSObject[] args, ResultCallback callback) {
if (callback == null) {
execJS(instanceId, namespace, function, args);
}
nativeExecJSWithCallback(instanceId, namespace, function, args,
ResultCallbackManager.generateCallbackId(callback));
}

// Result from js engine
@CalledByNative
public void onReceivedResult(long callbackId, byte[] result) {
ResultCallback callback = ResultCallbackManager.removeCallbackById(callbackId);
if (callback != null) {
callback.onReceiveResult(result);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -999,20 +999,21 @@ public void run() {
WXJSObject[] jsArgs = {
new WXJSObject(WXJSObject.String, instanceId),
WXWsonJSONSwitch.toWsonOrJsonWXJSObject(tasks)};
byte[] taskResult = invokeExecJSWithResult(String.valueOf(instanceId), null, METHOD_CALL_JS, jsArgs, true);
if(eventCallback == null){
return;
}
if(taskResult != null){
JSONArray arrayResult = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(taskResult);
if(arrayResult != null && arrayResult.size() > 0){
result = arrayResult.get(0);
}
ResultCallback<byte[]> resultCallback = null;
if (eventCallback != null) {
resultCallback = new ResultCallback<byte[]>() {
@Override
public void onReceiveResult(byte[] result) {
JSONArray arrayResult = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(result);
if(arrayResult != null && arrayResult.size() > 0){
eventCallback.onCallback(arrayResult.get(0));
}
}
};
}
eventCallback.onCallback(result);
invokeExecJSWithCallback(String.valueOf(instanceId), null, METHOD_CALL_JS,
jsArgs, resultCallback, true);
jsArgs[0] = null;
taskResult = null;
jsArgs = null;
}catch (Exception e){
WXLogUtils.e("asyncCallJSEventWithResult" , e);
}
Expand Down Expand Up @@ -1741,8 +1742,8 @@ private String invokeExecJSOnInstance(String instanceId, String js, int type) {
return null;
}

private byte[] invokeExecJSWithResult(String instanceId, String namespace, String function,
WXJSObject[] args,boolean logTaskDetail){
private void invokeExecJSWithCallback(String instanceId, String namespace, String function,
WXJSObject[] args , ResultCallback callback, boolean logTaskDetail){
if (WXEnvironment.isOpenDebugLog() && BRIDGE_LOG_SWITCH) {
mLodBuilder.append("callJS >>>> instanceId:").append(instanceId)
.append("function:").append(function);
Expand All @@ -1753,9 +1754,8 @@ private byte[] invokeExecJSWithResult(String instanceId, String namespace, Strin
mLodBuilder.setLength(0);
}
if (isJSFrameworkInit()) {
return mWXBridge.execJSWithResult(instanceId, namespace, function, args);
mWXBridge.execJSWithCallback(instanceId, namespace, function, args, callback);
}
return null;
}

public @NonNull static String argsToJSON(WXJSObject[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.taobao.weex.WXEnvironment;
import com.taobao.weex.base.CalledByNative;
import com.taobao.weex.bridge.ResultCallback;
import com.taobao.weex.bridge.WXBridgeManager;
import com.taobao.weex.bridge.WXJSObject;
import com.taobao.weex.bridge.WXParams;
Expand Down Expand Up @@ -63,9 +64,9 @@ public interface IWXBridge extends IWXObject {
int execJS(String instanceId, String namespace, String function, WXJSObject[] args);

/**
* execute javascript function, return execute result as json array
* execute javascript function with asynchronous callback
*/
byte[] execJSWithResult(String instanceId, String namespace, String function, WXJSObject[] args);
void execJSWithCallback(String instanceId, String namespace, String function, WXJSObject[] args, ResultCallback callback);

int execJSService(String javascript);

Expand Down
2 changes: 2 additions & 0 deletions weex_core/Source/IPC/IPCMessageJS.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum class IPCJSMsg {
DESTORYINSTANCE,
EXECJSONINSTANCE,
EXECJSWITHRESULT,
EXECJSWITHCALLBACK,
UPDATEGLOBALCONFIG,
EXECTIMERCALLBACK,
INITAPPFRAMEWORK,
Expand Down Expand Up @@ -68,6 +69,7 @@ enum class IPCProxyMsg {
CLEARINTERVAL,
POSTMESSAGE,
DISPATCHMESSAGE,
ONRECEIVEDRESULT,
};
// Message from Script to Core in ScriptBridge

Expand Down
5 changes: 5 additions & 0 deletions weex_core/Source/android/bridge/platform/android_side.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ void AndroidSide::DispatchMessage(const char *client_id,
wml_bridge_->DispatchMessage(env, client_id, data, dataLength, callback, vm_id);
}

void AndroidSide::OnReceivedResult(long callback_id, std::unique_ptr<WeexJSResult>& result) {
JNIEnv *env = base::android::AttachCurrentThread();
wx_bridge_->OnReceivedResult(env, callback_id, result);
}

jobject AndroidSide::getMeasureFunc(const char *pageId, jlong renderObjectPtr) {
JNIEnv *env = base::android::AttachCurrentThread();
return wx_bridge_->GetMeasureFunc(env, pageId, renderObjectPtr).Release();
Expand Down
1 change: 1 addition & 0 deletions weex_core/Source/android/bridge/platform/android_side.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class AndroidSide : public PlatformBridge::PlatformSide {
void PostMessage(const char* vm_id, const char* data, int dataLength) override;
void DispatchMessage(const char* client_id,
const char* data, int dataLength, const char* callback, const char* vm_id) override;
void OnReceivedResult(long callback_id, std::unique_ptr<WeexJSResult>& result) override;

jobject getMeasureFunc(const char* pageId, jlong renderObjectPtr);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,46 @@ std::unique_ptr<WeexJSResult> ScriptSideInMultiProcess::ExecJSWithResult(
}
}

void ScriptSideInMultiProcess::ExecJSWithCallback(
const char *instanceId, const char *nameSpace, const char *func,
std::vector<VALUE_WITH_TYPE *> &params, long callback_id) {
std::unique_ptr<WeexJSResult> ret;
try {
if(sender_ == nullptr) {
LOGE("ExecJSWithResult sender is null");
return;
}
std::unique_ptr<IPCSerializer> serializer(createIPCSerializer());
serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSWITHCALLBACK));
serializer->add(instanceId, strlen(instanceId));
if (nameSpace)
serializer->add(nameSpace, strlen(nameSpace));
else {
uint16_t tmp = 0;
serializer->add(&tmp, 0);
}
serializer->add(func, strlen(func));
// pass callback_id before params
serializer->add(static_cast<int64_t>(callback_id));

for (int i = 0; i < params.size(); i++) {
VALUE_WITH_TYPE *param = params[i];
addParamsToIPCSerializer(serializer.get(), param);
}

std::unique_ptr<IPCBuffer> buffer = serializer->finish();
std::unique_ptr<IPCResult> result = sender_->send(buffer.get());

} catch (IPCException &e) {
LOGE("%s", e.msg());
// report crash here
WeexCoreManager::Instance()
->getPlatformBridge()
->platform_side()
->ReportServerCrash(instanceId);
}
}

int ScriptSideInMultiProcess::CreateInstance(
const char *instanceId, const char *func, const char *script,
const char *opts, const char *initData, const char *extendsApi) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ class ScriptSideInMultiProcess : public ScriptBridge::ScriptSide {
const char *func,
std::vector<VALUE_WITH_TYPE *> &params) override;

void ExecJSWithCallback(const char *instanceId, const char *nameSpace,
const char *func,
std::vector<VALUE_WITH_TYPE *> &params,
long callback_id) override;

int CreateInstance(const char *instanceId, const char *func,
const char *script, const char *opts, const char *initData,
const char *extendsApi) override;
Expand Down
12 changes: 12 additions & 0 deletions weex_core/Source/android/bridge/script/script_side_in_multi_so.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ std::unique_ptr<WeexJSResult> ScriptSideInMultiSo::ExecJSWithResult(
func, params);
}

void ScriptSideInMultiSo::ExecJSWithCallback(
const char *instanceId, const char *nameSpace, const char *func,
std::vector<VALUE_WITH_TYPE *> &params, long callback_id) {
if (script_side_functions_ == nullptr) {
LOGE(
"ScriptSideInMultiSo::ExecJSWithCallback script_side_functions_ is null");
return;
}
script_side_functions_->funcExeJSWithResultId(instanceId, nameSpace, func,
params, callback_id);
}

int ScriptSideInMultiSo::CreateInstance(const char *instanceId,
const char *func, const char *script,
const char *opts, const char *initData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ class ScriptSideInMultiSo : public ScriptBridge::ScriptSide {
const char *func,
std::vector<VALUE_WITH_TYPE *> &params) override;

void ExecJSWithCallback(const char *instanceId, const char *nameSpace,
const char *func,
std::vector<VALUE_WITH_TYPE *> &params,
long callback_id) override;

int CreateInstance(const char *instanceId, const char *func,
const char *script, const char *opts, const char *initData,
const char *extendsApi) override;
Expand Down
27 changes: 27 additions & 0 deletions weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,31 @@ std::unique_ptr<IPCResult> HandleDispatchMessage(IPCArguments *arguments) {
return createInt32Result(static_cast<int32_t>(true));
}

std::unique_ptr<IPCResult> OnReceivedResult(IPCArguments *arguments) {
long callback_id = arguments->get<long>(0);
std::unique_ptr<WeexJSResult> result;
result.reset(new WeexJSResult);
if (arguments->getType(1) == IPCType::BYTEARRAY &&
arguments->getByteArray(1)->length > 0) {
result->length = arguments->getByteArray(1)->length;
char *string = new char[result->length + 1];
result->data.reset(string);
memset(string, 0, result->length);
memcpy(string, arguments->getByteArray(1)->content, result->length);
string[result->length] = '\0';
}
WeexCoreManager::Instance()->script_thread()->message_loop()->PostTask(
weex::base::MakeCopyable([callback_id, result = std::move(result)]() {
WeexCoreManager::Instance()
->script_bridge()
->core_side()
->OnReceivedResult(
callback_id,
const_cast<std::unique_ptr<WeexJSResult> &>(result));
}));
return createInt32Result(static_cast<int32_t>(true));
}

ScriptBridgeInMultiProcess::ScriptBridgeInMultiProcess() {
set_script_side(new bridge::script::ScriptSideInMultiProcess);
set_core_side(new CoreSideInScript);
Expand Down Expand Up @@ -995,6 +1020,8 @@ void ScriptBridgeInMultiProcess::RegisterIPCCallback(IPCHandler *handler) {
HandlePostMessage);
handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::DISPATCHMESSAGE),
HandleDispatchMessage);
handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::ONRECEIVEDRESULT),
OnReceivedResult);
}

} // namespace WeexCore
17 changes: 16 additions & 1 deletion weex_core/Source/android/bridge/script_bridge_in_multi_so.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,20 @@ static void DispatchMessage(const char *client_id, const char *data, int dataLen
callback.c_str(), vm_id.c_str());
}));
}

static void OnReceivedResult(long callback_id,
std::unique_ptr<WeexJSResult> &result) {
WeexCoreManager::Instance()->script_thread()->message_loop()->PostTask(
weex::base::MakeCopyable([callback_id, result = std::move(result)]() {
WeexCoreManager::Instance()
->script_bridge()
->core_side()
->OnReceivedResult(
callback_id,
const_cast<std::unique_ptr<WeexJSResult> &>(result));
}));
}

static void ReportException(const char *page_id, const char *func,
const char *exception_string) {
// WeexCoreManager::Instance()->script_bridge()->core_side()->ReportException(
Expand Down Expand Up @@ -491,7 +505,8 @@ FunctionsExposedByCore *ScriptBridgeInMultiSo::GetExposedFunctions() {
CallGCanvasLinkNative,
CallT3DLinkNative,
PostMessage,
DispatchMessage};
DispatchMessage,
OnReceivedResult};
auto functions =
(FunctionsExposedByCore *)malloc(sizeof(FunctionsExposedByCore));
memset(functions, 0, sizeof(FunctionsExposedByCore));
Expand Down
Loading

0 comments on commit a6e7134

Please sign in to comment.