diff --git a/interfaces/innerkits/include/appspawn.h b/interfaces/innerkits/include/appspawn.h index 7372aff20a424a01b2fde50cfc21b0bae67e6552..5058b77a5056421b80d8b90c0d8a1c124a68fb21 100644 --- a/interfaces/innerkits/include/appspawn.h +++ b/interfaces/innerkits/include/appspawn.h @@ -120,6 +120,7 @@ typedef enum { MSG_UNINSTALL_DEBUG_HAP, MSG_LOCK_STATUS, MSG_OBSERVE_PROCESS_SIGNAL_STATUS, + MSG_DLCLOSE_WEBLIB_IN_SPAWNER, MAX_TYPE_INVALID } AppSpawnMsgType; diff --git a/modules/ace_adapter/BUILD.gn b/modules/ace_adapter/BUILD.gn index 4c274652ee644f13eccf8a25d308c44ca3cecc8f..d5c1fb76966a537dc0bd3bb171709ca2d3ab2094 100644 --- a/modules/ace_adapter/BUILD.gn +++ b/modules/ace_adapter/BUILD.gn @@ -30,6 +30,9 @@ ohos_shared_library("appspawn_ace") { "${appspawn_path}/util:libappspawn_util", ] defines = [] + if (target_cpu == "arm64") { + defines += [ "webview_arm64" ] + } if (asan_detector || is_asan) { defines += [ "ASAN_DETECTOR" ] } diff --git a/modules/ace_adapter/ace_adapter.cpp b/modules/ace_adapter/ace_adapter.cpp index 37da3a22e9b2e6340837e24f64e2999ff8d9286b..a86487dcc9595493c5d90dbc84ffcd3e6fc4449d 100644 --- a/modules/ace_adapter/ace_adapter.cpp +++ b/modules/ace_adapter/ace_adapter.cpp @@ -312,6 +312,31 @@ APPSPAWN_STATIC int DoDlopenLibs(const cJSON *root, ParseJsonContext *context) APPSPAWN_STATIC int DlopenAppSpawn(AppSpawnMgr *content) { +#if defined(webview_arm64) + Dl_namespace dlns; + dlns_init(&dlns, "nweb_ns"); + dlns_create(&dlns, + "/data/app/el1/bundle/public/com.huawei.hmos.arkwebcore/libs/arm64:" + "/data/storage/el1/bundle/arkwebcore/libs/arm64"); + void* webEngineHandle = dlopen_ns(&dlns, "libarkweb_engine.so", RTLD_NOW | RTLD_GLOBAL); + if (!webEngineHandle) { + APPSPAWN_LOGI("FAILED to dlopen libarkweb_engine.so in appspawn %{public}s", dlerror()); + } else { + APPSPAWN_LOGI("SUCCESS to dlopen libarkweb_engine.so in appspawn"); + } + + // preload dlopen libohos_adapter_glue_source.z.so + const std::string libName = "/system/lib64/libohos_adapter_glue_source.z.so"; + void *handle = dlopen(libName.c_str(), RTLD_NOW | RTLD_GLOBAL); + if (handle == nullptr) { + APPSPAWN_LOGI("FAILED to dlopen libohos_adapter_glue_source.so in appspawn %{public}s", dlerror()); + } else { + APPSPAWN_LOGI("SUCCESS to dlopen libohos_adapter_glue_source.so in appspawn"); + } + + OHOS::Ace::AceForwardCompatibility::ReclaimFileCache(getpid()); +#endif + if (!IsAppSpawnMode(content)) { return 0; } diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 70dae3e8a60b32f5792dc0117778faddd5256bce..23b0898cce2fcc42d8900f9de3fee3fe5722d063 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -15,6 +15,7 @@ #include "appspawn_service.h" +#include #include #include #include @@ -67,6 +68,9 @@ static void WaitChildDied(pid_t pid); static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen); static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message); +// When arkweb is upgraded, the maximum number of dlclose loop iterations. +const int MAX_DLCLOSE_COUNT = 10; + // FD_CLOEXEC static inline void SetFdCtrl(int fd, int opt) { @@ -1528,6 +1532,14 @@ static int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNod #else static int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) { + AppSpawnMsg* msg = &message->msgHeader; + APPSPAWN_LOGI("Recv ProcessSpawnRemountMsg message header magic: 0x%{public}x type: %{public}u" + "id: %{public}u len: %{public}u processName: %{public}s", + msg->magic, + msg->msgType, + msg->msgId, + msg->msgLen, + msg->processName); char srcPath[PATH_SIZE] = {0}; int len = GetArkWebInstallPath("persist.arkwebcore.install_path", srcPath); APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path"); @@ -1582,6 +1594,51 @@ static int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNod } #endif +static bool IsNWebLibLoaded(Dl_namespace dlns) +{ + void* handler = dlopen_ns(&dlns, "libarkweb_engine.so", RTLD_NOW | RTLD_NOLOAD); + if (handler) { + dlclose(handler); + return true; + } + return false; +} + +static int ProcessSpawnDlcloseMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) +{ + AppSpawnMsg* msg = &message->msgHeader; + APPSPAWN_LOGI("Recv ProcessSpawnReqMsg message header magic: 0x%{public}x type: %{public}u" + "id: %{public}u len: %{public}u processName: %{public}s", + msg->magic, + msg->msgType, + msg->msgId, + msg->msgLen, + msg->processName); + Dl_namespace dlns; + if (dlns_get("nweb_ns", &dlns) != 0) { + APPSPAWN_LOGE("Failed to get nweb ns"); + return 0; + } + + void* webEngineHandle = dlopen_ns(&dlns, "libarkweb_engine.so", RTLD_NOW | RTLD_GLOBAL); + if (!webEngineHandle) { + APPSPAWN_LOGI("FAILED to dlopen libarkweb_engine.so in appspawn %{public}s", dlerror()); + return 0; + } + + int cnt = MAX_DLCLOSE_COUNT; + do { + cnt--; + dlclose(webEngineHandle); + + if (cnt == 0 && IsNWebLibLoaded(dlns)) { + APPSPAWN_LOGE("ProcessSpawnReqMsg dlclose retry 10 times, return"); + } + } while (cnt > 0 && IsNWebLibLoaded(dlns)); + + return 0; +} + static void ProcessSpawnRestartMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) { AppSpawnContent *content = GetAppSpawnContent(); @@ -1874,6 +1931,9 @@ static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *mess case MSG_OBSERVE_PROCESS_SIGNAL_STATUS: ProcessObserveProcessSignalMsg(connection, message); break; + case MSG_DLCLOSE_WEBLIB_IN_SPAWNER: + ProcessSpawnDlcloseMsg(connection, message); + break; default: SendResponse(connection, msg, APPSPAWN_MSG_INVALID, 0); DeleteAppSpawnMsg(&message);