| /** |
| * 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. |
| */ |
| |
| #include "android/bridge/platform/android_side.h" |
| |
| #include "android/base/string/string_utils.h" |
| #include "android/utils/ipc_string_result.h" |
| #include "android/utils/cache_utils.h" |
| #include "android/utils/params_utils.h" |
| #include "android/wrap/hash_set.h" |
| #include "android/wrap/log_utils.h" |
| #include "android/wrap/wml_bridge.h" |
| #include "android/wrap/wx_js_object.h" |
| #include "android/wrap/wx_map.h" |
| #include "base/android/jni/android_jni.h" |
| #include "base/android/jni/jbytearray_ref.h" |
| #include "base/android/jni_type.h" |
| #include "base/log_defines.h" |
| #include "core/layout/layout.h" |
| #include "core/layout/measure_func_adapter.h" |
| #include "core/manager/weex_core_manager.h" |
| #include "third_party/IPC/IPCResult.h" |
| |
| namespace WeexCore { |
| |
| AndroidSide::AndroidSide() |
| : wml_bridge_(WMLBridge::Instance()), wx_bridge_(WXBridge::Instance()) {} |
| |
| AndroidSide::~AndroidSide() {} |
| |
| WXCoreSize AndroidSide::InvokeMeasureFunction(const char *page_id, |
| long render_ptr, float width, |
| int width_measure_mode, |
| float height, |
| int height_measure_mode) { |
| return WeexCoreManager::Instance()->measure_function_adapter()->Measure( |
| page_id, render_ptr, width, static_cast<MeasureMode>(width_measure_mode), |
| height, static_cast<MeasureMode>(height_measure_mode)); |
| } |
| void AndroidSide::InvokeLayoutBefore(const char *page_id, long render_ptr) { |
| WeexCoreManager::Instance()->measure_function_adapter()->LayoutBefore( |
| page_id, render_ptr); |
| } |
| |
| void AndroidSide::InvokeLayoutPlatform(const char* page_id, long render_ptr) { |
| // do nothing |
| } |
| |
| void AndroidSide::TriggerVSync(const char* page_id) { |
| // do nothing |
| } |
| |
| void AndroidSide::InvokeLayoutAfter(const char *page_id, long render_ptr, |
| float width, float height) { |
| WeexCoreManager::Instance()->measure_function_adapter()->LayoutAfter( |
| page_id, render_ptr, width, height); |
| } |
| |
| void AndroidSide::SetJSVersion(const char *version) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wx_bridge_->SetJSFrmVersion(env, version); |
| } |
| |
| void AndroidSide::ReportException(const char *page_id, const char *func, |
| const char *exception_string) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wx_bridge_->ReportException(env, page_id, func, exception_string); |
| } |
| |
| void AndroidSide::ReportServerCrash(const char *instance_id) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| std::string crash_file; |
| crash_file.assign("/crash_dump.log"); |
| wx_bridge_->ReportServerCrash(env, instance_id, crash_file.c_str()); |
| } |
| |
| void AndroidSide::ReportNativeInitStatus(const char *status_code, |
| const char *error_msg) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wx_bridge_->ReportNativeInitStatus(env, status_code, error_msg); |
| } |
| |
| int AndroidSide::CallNative(const char *page_id, const char *task, |
| const char *callback) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->CallNative(env, page_id, task, callback); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callNative"); |
| } |
| return flag; |
| } |
| int AndroidSide::AddChildToRichtext(const char *pageId, const char *nodeType, const char *ref, const char *parentRef, |
| const char *richtextRef, std::map<std::string, std::string> *styles, |
| std::map<std::string, std::string> *attributes) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| int flag = wx_bridge_->AddChildToRichtext(env, pageId, nodeType, ref, parentRef, richtextRef, styles ,attributes); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop AddChildToRichtext"); |
| } |
| return flag; |
| } |
| int AndroidSide::RemoveChildFromRichtext(const char *pageId, const char *ref, const char *parent_ref, |
| const char *richtext_ref) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->RemoveChildFromRichtext(env, pageId, ref, parent_ref, richtext_ref); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop RemoveChildFromRichtext"); |
| } |
| return flag; |
| } |
| int AndroidSide::UpdateRichtextStyle(const char *pageId, const char *ref, |
| std::vector<std::pair<std::string, std::string>> *styles, const char *parent_ref, |
| const char *richtext_ref) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->UpdateRichtextStyle(env, pageId, ref, styles, parent_ref, richtext_ref); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop UpdateRichtextStyle"); |
| } |
| return flag; |
| } |
| int AndroidSide::UpdateRichtextChildAttr(const char *pageId, const char *ref, |
| std::vector<std::pair<std::string, std::string>> *attributes, |
| const char *parent_ref, const char *richtext_ref) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->UpdateRichtextChildAttr(env, pageId, ref, attributes, parent_ref, richtext_ref); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop UpdateRichtextChildAttr"); |
| } |
| return flag; |
| } |
| |
| std::unique_ptr<ValueWithType> AndroidSide::CallNativeModule( |
| const char *page_id, const char *module, const char *method, |
| const char *arguments, int arguments_length, const char *options, |
| int options_length) { |
| std::unique_ptr<ValueWithType> ipc_result(new ValueWithType()); |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return ipc_result; |
| |
| auto result = |
| wx_bridge_->CallNativeModule(env, page_id, module, method, arguments, |
| arguments_length, options, options_length); |
| |
| ipc_result->type = ParamsType::INT32; |
| ipc_result->value.int32Value = -1; |
| if (result.IsNull()) { |
| return ipc_result; |
| } |
| |
| auto wx_js_object_result = |
| std::unique_ptr<WXJSObject>(new WXJSObject(env, result.Get())); |
| jint jTypeInt = wx_js_object_result->GetType(env); |
| auto jDataObj = wx_js_object_result->GetData(env); |
| |
| if (jTypeInt == 1) { |
| ipc_result->type = ParamsType::DOUBLE; |
| ipc_result->value.doubleValue = |
| base::android::JNIType::DoubleValue(env, jDataObj.Get()); |
| } else if (jTypeInt == 2) { |
| jstring jDataStr = (jstring)jDataObj.Get(); |
| ipc_result->type = ParamsType::STRING; |
| ipc_result->value.string = jstring2WeexString(env, jDataStr); |
| } else if (jTypeInt == 3) { |
| jstring jDataStr = (jstring)jDataObj.Get(); |
| ipc_result->type = ParamsType::JSONSTRING; |
| ipc_result->value.string = jstring2WeexString(env, jDataStr); |
| } else if (jTypeInt == 4) { |
| jbyteArray array = (jbyteArray)jDataObj.Get(); |
| if (array != nullptr) { |
| int length = env->GetArrayLength(array); |
| void *data = env->GetByteArrayElements(array, 0); |
| ipc_result->type = ParamsType::BYTEARRAY; |
| ipc_result->value.byteArray = |
| genWeexByteArray((const char *)data, length); |
| env->ReleaseByteArrayElements(array, (jbyte *)data, 0); |
| } |
| } |
| |
| return ipc_result; |
| } |
| |
| void AndroidSide::CallNativeComponent(const char *page_id, const char *ref, |
| const char *method, const char *arguments, |
| int arguments_length, const char *options, |
| int options_length) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wx_bridge_->CallNativeComponent(env, page_id, ref, method, arguments, |
| arguments_length, options, options_length); |
| } |
| |
| void AndroidSide::SetTimeout(const char *callback_id, const char *time) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wx_bridge_->SetTimeout(env, callback_id, time); |
| } |
| |
| void AndroidSide::NativeLog(const char *str_array) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| LogUtils::NativeLog(env, str_array); |
| } |
| |
| int AndroidSide::UpdateFinish(const char *page_id, const char *task, |
| int taskLen, const char *callback, |
| int callbackLen) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->UpdateFinish(env, page_id, task, callback); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callUpdateFinish"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::RefreshFinish(const char *page_id, const char *task, |
| const char *callback) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->RefreshFinish(env, page_id, task, callback); |
| |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callNative"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::AddEvent(const char *page_id, const char *ref, |
| const char *event) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->AddEvent(env, page_id, ref, event); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callAddEvent"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::RemoveEvent(const char *page_id, const char *ref, |
| const char *event) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->RemoveEvent(env, page_id, ref, event); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callRemoveElement"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::CreateBody(const char *page_id, const char *component_type, |
| const char *ref, |
| std::map<std::string, std::string> *styles, |
| std::map<std::string, std::string> *attributes, |
| std::set<std::string> *events, |
| const WXCoreMargin &margins, |
| const WXCorePadding &paddings, |
| const WXCoreBorderWidth &borders) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = |
| wx_bridge_->CreateBody(env, page_id, component_type, ref, styles, |
| attributes, events, margins, paddings, borders); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callCreateBody"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::AddElement(const char *page_id, const char *component_type, |
| const char *ref, int &index, const char *parentRef, |
| std::map<std::string, std::string> *styles, |
| std::map<std::string, std::string> *attributes, |
| std::set<std::string> *events, |
| const WXCoreMargin &margins, |
| const WXCorePadding &paddings, |
| const WXCoreBorderWidth &borders, bool willLayout) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->AddElement(env, page_id, component_type, ref, index, |
| parentRef, styles, attributes, events, |
| margins, paddings, borders, willLayout); |
| |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callAddElement"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::Layout(const char *page_id, const char *ref, float top, |
| float bottom, float left, float right, float height, |
| float width, bool isRTL, int index) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = 0; |
| wx_bridge_->Layout(env, page_id, ref, top, bottom, left, right, |
| height, width, isRTL, index); |
| |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callLayout"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::UpdateStyle( |
| const char *page_id, const char *ref, |
| std::vector<std::pair<std::string, std::string>> *style, |
| std::vector<std::pair<std::string, std::string>> *margin, |
| std::vector<std::pair<std::string, std::string>> *padding, |
| std::vector<std::pair<std::string, std::string>> *border) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->UpdateStyle(env, page_id, ref, style, margin, padding, |
| border); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callUpdateStyle"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::UpdateAttr( |
| const char *page_id, const char *ref, |
| std::vector<std::pair<std::string, std::string>> *attrs) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = 0; |
| flag = wx_bridge_->UpdateAttr(env, page_id, ref, attrs); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callUpdateStyle"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::CreateFinish(const char *page_id) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->CreateFinish(env, page_id); |
| |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callCreateFinish"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::RenderSuccess(const char *page_id) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->RenderSuccess(env, page_id); |
| |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callRenderFinish"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::RemoveElement(const char *page_id, const char *ref) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->RemoveElement(env, page_id, ref); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callRemoveElement"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::MoveElement(const char *page_id, const char *ref, |
| const char *parent_ref, int index) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| int flag = wx_bridge_->MoveElement(env, page_id, ref, parent_ref, index); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callRemoveElement"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::AppendTreeCreateFinish(const char *page_id, const char *ref) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| int flag = wx_bridge_->AppendTreeCreateFinish(env, page_id, ref); |
| if (flag == -1) { |
| LOGE("instance destroy JFM must stop callAppendTreeCreateFinish"); |
| } |
| return flag; |
| } |
| |
| int AndroidSide::HasTransitionPros( |
| const char *page_id, const char *ref, |
| std::vector<std::pair<std::string, std::string>> *style) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return -1; |
| |
| if (style != nullptr) { |
| return wx_bridge_->HasTransitionPros(env, page_id, ref, *style); |
| } else { |
| return wx_bridge_->HasTransitionPros( |
| env, page_id, ref, std::vector<std::pair<std::string, std::string>>()); |
| } |
| } |
| |
| void AndroidSide::PostMessage(const char *vm_id, const char *data, int dataLength) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wml_bridge_->PostMessage(env, vm_id, data, dataLength); |
| } |
| |
| void AndroidSide::DispatchMessage(const char *client_id, |
| const char *data, int dataLength, const char *callback, const char *vm_id) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wml_bridge_->DispatchMessage(env, client_id, data, dataLength, callback, vm_id); |
| } |
| |
| std::unique_ptr<WeexJSResult> AndroidSide::DispatchMessageSync( |
| const char *client_id, const char *data, int dataLength, |
| const char *vm_id) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return std::unique_ptr<WeexJSResult>(); |
| |
| auto jni_result = |
| wml_bridge_->DispatchMessageSync(env, client_id, data, dataLength, vm_id); |
| JByteArrayRef byte_array(env, jni_result.Get()); |
| char *copy = nullptr; |
| if (byte_array.length() > 0) { |
| copy = new char[byte_array.length()]; |
| strcpy(copy, byte_array.getBytes()); |
| } |
| return std::unique_ptr<WeexJSResult>( |
| new WeexJSResult(std::unique_ptr<char[]>(copy), byte_array.length())); |
| } |
| |
| void AndroidSide::OnReceivedResult(long callback_id, std::unique_ptr<WeexJSResult>& result) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wx_bridge_->OnReceivedResult(env, callback_id, result); |
| } |
| |
| jobject AndroidSide::getMeasureFunc(const char *pageId, jlong renderObjectPtr) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return nullptr; |
| |
| return wx_bridge_->GetMeasureFunc(env, pageId, renderObjectPtr).Release(); |
| } |
| void AndroidSide::SetPageDirty(const char *page_id, bool dirty) { |
| JNIEnv *env = base::android::AttachCurrentThread(); |
| if (env == nullptr) |
| return; |
| |
| wx_bridge_->SetPageDirty(env, page_id, dirty); |
| } |
| } // namespace WeexCore |