已开启
applicationContext在有更新时复用缓存对象而非创建新对象 #20361
renguojun创建于 18 天前
applicationContext在有更新时复用缓存对象而非创建新对象 #20361
已开启
共 10 个文件变更+196-96
| @@ -24,6 +24,8 @@ namespace AbilityRuntime { | |||
| 24 | namespace ContextUtil { | 24 | namespace ContextUtil { |
| 25 | void BindApplicationInfo(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, | 25 | void BindApplicationInfo(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, |
| 26 | std::shared_ptr<Context> context); | 26 | std::shared_ptr<Context> context); |
| 27 | +void UpdateEtsApplicationContextInfo(ani_env *aniEnv, ani_object cachedObj, | ||
| 28 | + const std::shared_ptr<ApplicationContext>& applicationContext); | ||
| 27 | void BindResourceManager(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, | 29 | void BindResourceManager(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, |
| 28 | std::shared_ptr<Context> context); | 30 | std::shared_ptr<Context> context); |
| 29 | void CreateEtsBaseContext(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, | 31 | void CreateEtsBaseContext(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, |
| @@ -207,6 +207,27 @@ void BindApplicationInfo(ani_env *aniEnv, ani_class contextClass, ani_object con | |||
| 207 | } | 207 | } |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | +void UpdateEtsApplicationContextInfo(ani_env *aniEnv, ani_object cachedObj, | ||
| 211 | + const std::shared_ptr<ApplicationContext>& applicationContext) | ||
| 212 | +{ | ||
| 213 | + if (aniEnv == nullptr || cachedObj == nullptr || applicationContext == nullptr) { | ||
| 214 | + return; | ||
| 215 | + } | ||
| 216 | + auto appInfo = applicationContext->GetApplicationInfo(); | ||
| 217 | + if (appInfo == nullptr) { | ||
| 218 | + TAG_LOGW(AAFwkTag::APPKIT, "appInfo is null, restore update flag"); | ||
| 219 | + applicationContext->SetApplicationInfoUpdateFlag(true); | ||
| 220 | + return; | ||
| 221 | + } | ||
| 222 | + ani_class contextCls = nullptr; | ||
| 223 | + if (aniEnv->FindClass(CONTEXT_CLASS_NAME, &contextCls) != ANI_OK) { | ||
| 224 | + TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed"); | ||
| 225 | + applicationContext->SetApplicationInfoUpdateFlag(true); | ||
| 226 | + return; | ||
| 227 | + } | ||
| 228 | + BindApplicationInfo(aniEnv, contextCls, cachedObj, applicationContext); | ||
| 229 | +} | ||
| 230 | + | ||
| 210 | void BindResourceManager(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, | 231 | void BindResourceManager(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, |
| 211 | std::shared_ptr<Context> context) | 232 | std::shared_ptr<Context> context) |
| 212 | { | 233 | { |
| @@ -704,12 +725,13 @@ ani_object GetApplicationContextSync(ani_env *env, ani_object aniObj) | |||
| 704 | EtsErrorUtil::ThrowError(env, (int32_t)AbilityErrorCode::ERROR_CODE_INVALID_PARAM); | 725 | EtsErrorUtil::ThrowError(env, (int32_t)AbilityErrorCode::ERROR_CODE_INVALID_PARAM); |
| 705 | return {}; | 726 | return {}; |
| 706 | } | 727 | } |
| 707 | - if (!applicationContext->GetApplicationInfoUpdateFlag()) { | 728 | + auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); |
| 708 | - auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); | 729 | + if (appContextObj != nullptr && appContextObj->aniRef != nullptr) { |
| 709 | - if (appContextObj != nullptr && appContextObj->aniRef != nullptr) { | 730 | + auto cachedObj = reinterpret_cast<ani_object>(appContextObj->aniRef); |
| 710 | - TAG_LOGD(AAFwkTag::APPKIT, "appContextObj is not nullptr"); | 731 | + if (applicationContext->ConsumeApplicationInfoUpdateFlag()) { |
| 711 | - return reinterpret_cast<ani_object>(appContextObj->aniRef); | 732 | + UpdateEtsApplicationContextInfo(env, cachedObj, applicationContext); |
| 712 | } | 733 | } |
| 734 | + return cachedObj; | ||
| 713 | } | 735 | } |
| 714 | return GetApplicationContext(env, applicationContext); | 736 | return GetApplicationContext(env, applicationContext); |
| 715 | } | 737 | } |
| @@ -44,6 +44,8 @@ private: | |||
| 44 | static bool IsInstanceOf(ani_env *aniEnv, ani_object aniObj); | 44 | static bool IsInstanceOf(ani_env *aniEnv, ani_object aniObj); |
| 45 | static std::unique_ptr<NativeReference> CreateNativeReference(napi_env napiEnv, | 45 | static std::unique_ptr<NativeReference> CreateNativeReference(napi_env napiEnv, |
| 46 | std::shared_ptr<ApplicationContext> applicationContext); | 46 | std::shared_ptr<ApplicationContext> applicationContext); |
| 47 | + static napi_value GetOrCreateSubThreadObject(napi_env napiEnv, | ||
| 48 | + std::shared_ptr<ApplicationContext> applicationContext); | ||
| 47 | static ani_object CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, | 49 | static ani_object CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, |
| 48 | std::shared_ptr<ApplicationContext> applicationContext); | 50 | std::shared_ptr<ApplicationContext> applicationContext); |
| 49 | }; | 51 | }; |
| @@ -162,6 +162,24 @@ std::unique_ptr<NativeReference> EtsApplicationContextModule::CreateNativeRefere | |||
| 162 | return systemModule; | 162 | return systemModule; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | +napi_value EtsApplicationContextModule::GetOrCreateSubThreadObject(napi_env napiEnv, | ||
| 166 | + std::shared_ptr<ApplicationContext> applicationContext) | ||
| 167 | +{ | ||
| 168 | + auto subThreadObj = static_cast<NativeReference *>( | ||
| 169 | + applicationContext->GetSubThreadObject(static_cast<void *>(napiEnv))); | ||
| 170 | + if (subThreadObj != nullptr) { | ||
| 171 | + return subThreadObj->Get(); | ||
| 172 | + } | ||
| 173 | + auto subThreadRef = CreateNativeReference(napiEnv, applicationContext); | ||
| 174 | + if (subThreadRef == nullptr) { | ||
| 175 | + return nullptr; | ||
| 176 | + } | ||
| 177 | + auto newObject = subThreadRef->Get(); | ||
| 178 | + applicationContext->BindSubThreadObject( | ||
| 179 | + static_cast<void *>(napiEnv), static_cast<void *>(subThreadRef.release())); | ||
| 180 | + return newObject; | ||
| 181 | +} | ||
| 182 | + | ||
| 165 | napi_value EtsApplicationContextModule::GetOrCreateDynamicObject(napi_env napiEnv, | 183 | napi_value EtsApplicationContextModule::GetOrCreateDynamicObject(napi_env napiEnv, |
| 166 | std::shared_ptr<ApplicationContext> applicationContext) | 184 | std::shared_ptr<ApplicationContext> applicationContext) |
| 167 | { | 185 | { |
| @@ -170,52 +188,36 @@ napi_value EtsApplicationContextModule::GetOrCreateDynamicObject(napi_env napiEn | |||
| 170 | TAG_LOGE(AAFwkTag::CONTEXT, "null param"); | 188 | TAG_LOGE(AAFwkTag::CONTEXT, "null param"); |
| 171 | return nullptr; | 189 | return nullptr; |
| 172 | } | 190 | } |
| 173 | - | ||
| 174 | - // if sub-thread, create a new applicationContext and return | ||
| 175 | if (getpid() != syscall(SYS_gettid)) { | 191 | if (getpid() != syscall(SYS_gettid)) { |
| 176 | - auto subThreadObj = static_cast<NativeReference *>( | 192 | + return GetOrCreateSubThreadObject(napiEnv, applicationContext); |
| 177 | - applicationContext->GetSubThreadObject(static_cast<void *>(napiEnv))); | ||
| 178 | - if (subThreadObj != nullptr) { | ||
| 179 | - return subThreadObj->Get(); | ||
| 180 | - } | ||
| 181 | - auto subThreadRef = CreateNativeReference(napiEnv, applicationContext); | ||
| 182 | - if (subThreadRef == nullptr) { | ||
| 183 | - return nullptr; | ||
| 184 | - } | ||
| 185 | - auto newObject = subThreadRef->Get(); | ||
| 186 | - applicationContext->BindSubThreadObject( | ||
| 187 | - static_cast<void *>(napiEnv), static_cast<void *>(subThreadRef.release())); | ||
| 188 | - return newObject; | ||
| 189 | } | 193 | } |
| 190 | - | ||
| 191 | - // if main-thread, get bindingObj firstly | ||
| 192 | auto &bindingObj = applicationContext->GetBindingObject(); | 194 | auto &bindingObj = applicationContext->GetBindingObject(); |
| 193 | if (bindingObj == nullptr) { | 195 | if (bindingObj == nullptr) { |
| 194 | TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); | 196 | TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); |
| 195 | return nullptr; | 197 | return nullptr; |
| 196 | } | 198 | } |
| 197 | - | ||
| 198 | - // if main-thread bindingObj exist, return it directly | ||
| 199 | auto dynamicContext = bindingObj->Get<NativeReference>(); | 199 | auto dynamicContext = bindingObj->Get<NativeReference>(); |
| 200 | if (dynamicContext != nullptr) { | 200 | if (dynamicContext != nullptr) { |
| 201 | - TAG_LOGI(AAFwkTag::CONTEXT, "there exist a dynamicContext"); | 201 | + napi_value objValue = dynamicContext->Get(); |
| 202 | - return dynamicContext->Get(); | 202 | + if (applicationContext->ConsumeApplicationInfoUpdateFlag()) { |
| 203 | - } | 203 | + return JsApplicationContextUtils::UpdateApplicationContextInfo( |
| 204 | - | 204 | + napiEnv, objValue, applicationContext); |
| 205 | - if (!applicationContext->GetApplicationInfoUpdateFlag()) { | ||
| 206 | - auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetGlobalObject(napiEnv); | ||
| 207 | - if (appContextObj != nullptr) { | ||
| 208 | - TAG_LOGI(AAFwkTag::UIABILITY, "there exist a appContextObj"); | ||
| 209 | - return appContextObj->GetNapiValue(); | ||
| 210 | } | 205 | } |
| 206 | + return objValue; | ||
| 207 | + } | ||
| 208 | + auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetGlobalObject(napiEnv); | ||
| 209 | + if (appContextObj != nullptr) { | ||
| 210 | + napi_value objValue = appContextObj->GetNapiValue(); | ||
| 211 | + if (applicationContext->ConsumeApplicationInfoUpdateFlag()) { | ||
| 212 | + return JsApplicationContextUtils::UpdateApplicationContextInfo( | ||
| 213 | + napiEnv, objValue, applicationContext); | ||
| 214 | + } | ||
| 215 | + return objValue; | ||
| 211 | } | 216 | } |
| 212 | - | ||
| 213 | - // if main-thread bindingObj didn't exist, create and bind | ||
| 214 | auto nativeRef = CreateNativeReference(napiEnv, applicationContext); | 217 | auto nativeRef = CreateNativeReference(napiEnv, applicationContext); |
| 215 | if (nativeRef == nullptr) { | 218 | if (nativeRef == nullptr) { |
| 216 | return nullptr; | 219 | return nullptr; |
| 217 | } | 220 | } |
| 218 | - | ||
| 219 | auto object = nativeRef->Get(); | 221 | auto object = nativeRef->Get(); |
| 220 | applicationContext->Bind(nativeRef.release()); | 222 | applicationContext->Bind(nativeRef.release()); |
| 221 | return object; | 223 | return object; |
| @@ -556,22 +556,32 @@ ani_object EtsApplication::GetApplicationContextInstance(ani_env *env) | |||
| 556 | TAG_LOGE(AAFwkTag::APPKIT, "null env"); | 556 | TAG_LOGE(AAFwkTag::APPKIT, "null env"); |
| 557 | return nullptr; | 557 | return nullptr; |
| 558 | } | 558 | } |
| 559 | + auto applicationContext = ApplicationContext::GetInstance(); | ||
| 559 | auto etsReference = | 560 | auto etsReference = |
| 560 | AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); | 561 | AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); |
| 561 | - if (etsReference == nullptr || etsReference->aniRef == nullptr) { | 562 | + if (etsReference != nullptr && etsReference->aniRef != nullptr) { |
| 562 | - auto applicationContext = ApplicationContext::GetInstance(); | 563 | + auto cachedObj = reinterpret_cast<ani_object>(etsReference->aniRef); |
| 563 | - ani_object applicationContextObject = | 564 | + if (applicationContext != nullptr && applicationContext->ConsumeApplicationInfoUpdateFlag()) { |
| 564 | - EtsApplicationContextUtils::CreateEtsApplicationContext(env, applicationContext); | 565 | + ContextUtil::UpdateEtsApplicationContextInfo(env, cachedObj, applicationContext); |
| 565 | - if (applicationContextObject == nullptr) { | ||
| 566 | - TAG_LOGE(AAFwkTag::APPKIT, "null applicationContextObject"); | ||
| 567 | - AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); | ||
| 568 | - ani_ref result = nullptr; | ||
| 569 | - env->GetNull(&result); | ||
| 570 | - return static_cast<ani_object>(result); | ||
| 571 | } | 566 | } |
| 572 | - return applicationContextObject; | 567 | + return cachedObj; |
| 573 | } | 568 | } |
| 574 | - return reinterpret_cast<ani_object>(etsReference->aniRef); | 569 | + if (applicationContext == nullptr) { |
| 570 | + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); | ||
| 571 | + ani_ref result = nullptr; | ||
| 572 | + env->GetNull(&result); | ||
| 573 | + return static_cast<ani_object>(result); | ||
| 574 | + } | ||
| 575 | + ani_object applicationContextObject = | ||
| 576 | + EtsApplicationContextUtils::CreateEtsApplicationContext(env, applicationContext); | ||
| 577 | + if (applicationContextObject == nullptr) { | ||
| 578 | + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContextObject"); | ||
| 579 | + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); | ||
| 580 | + ani_ref result = nullptr; | ||
| 581 | + env->GetNull(&result); | ||
| 582 | + return static_cast<ani_object>(result); | ||
| 583 | + } | ||
| 584 | + return applicationContextObject; | ||
| 575 | } | 585 | } |
| 576 | 586 | ||
| 577 | ani_object EtsApplication::GetApplicationContext(ani_env *env) | 587 | ani_object EtsApplication::GetApplicationContext(ani_env *env) |
| @@ -581,8 +591,22 @@ ani_object EtsApplication::GetApplicationContext(ani_env *env) | |||
| 581 | TAG_LOGE(AAFwkTag::APPKIT, "null env"); | 591 | TAG_LOGE(AAFwkTag::APPKIT, "null env"); |
| 582 | return nullptr; | 592 | return nullptr; |
| 583 | } | 593 | } |
| 584 | - | ||
| 585 | auto applicationContext = ApplicationContext::GetInstance(); | 594 | auto applicationContext = ApplicationContext::GetInstance(); |
| 595 | + if (applicationContext == nullptr) { | ||
| 596 | + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); | ||
| 597 | + ani_ref result = nullptr; | ||
| 598 | + env->GetNull(&result); | ||
| 599 | + return static_cast<ani_object>(result); | ||
| 600 | + } | ||
| 601 | + auto etsReference = | ||
| 602 | + AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); | ||
| 603 | + if (etsReference != nullptr && etsReference->aniRef != nullptr) { | ||
| 604 | + auto cachedObj = reinterpret_cast<ani_object>(etsReference->aniRef); | ||
| 605 | + if (applicationContext->ConsumeApplicationInfoUpdateFlag()) { | ||
| 606 | + ContextUtil::UpdateEtsApplicationContextInfo(env, cachedObj, applicationContext); | ||
| 607 | + } | ||
| 608 | + return cachedObj; | ||
| 609 | + } | ||
| 586 | ani_object applicationContextObject = | 610 | ani_object applicationContextObject = |
| 587 | EtsApplicationContextUtils::CreateEtsApplicationContext(env, applicationContext); | 611 | EtsApplicationContextUtils::CreateEtsApplicationContext(env, applicationContext); |
| 588 | if (applicationContextObject == nullptr) { | 612 | if (applicationContextObject == nullptr) { |
| @@ -1049,17 +1049,22 @@ void ApplicationContext::SetApplicationInfo(const std::shared_ptr<AppExecFwk::Ap | |||
| 1049 | if (contextImpl_ != nullptr) { | 1049 | if (contextImpl_ != nullptr) { |
| 1050 | contextImpl_->SetApplicationInfo(info); | 1050 | contextImpl_->SetApplicationInfo(info); |
| 1051 | } | 1051 | } |
| 1052 | - applicationInfoUpdateFlag_ = true; | 1052 | + applicationInfoUpdateFlag_.store(true); |
| 1053 | } | 1053 | } |
| 1054 | 1054 | ||
| 1055 | bool ApplicationContext::GetApplicationInfoUpdateFlag() const | 1055 | bool ApplicationContext::GetApplicationInfoUpdateFlag() const |
| 1056 | { | 1056 | { |
| 1057 | - return applicationInfoUpdateFlag_; | 1057 | + return applicationInfoUpdateFlag_.load(); |
| 1058 | } | 1058 | } |
| 1059 | 1059 | ||
| 1060 | void ApplicationContext::SetApplicationInfoUpdateFlag(bool flag) | 1060 | void ApplicationContext::SetApplicationInfoUpdateFlag(bool flag) |
| 1061 | { | 1061 | { |
| 1062 | - applicationInfoUpdateFlag_ = flag; | 1062 | + applicationInfoUpdateFlag_.store(flag); |
| 1063 | +} | ||
| 1064 | + | ||
| 1065 | +bool ApplicationContext::ConsumeApplicationInfoUpdateFlag() | ||
| 1066 | +{ | ||
| 1067 | + return applicationInfoUpdateFlag_.exchange(false); | ||
| 1063 | } | 1068 | } |
| 1064 | 1069 | ||
| 1065 | std::shared_ptr<Global::Resource::ResourceManager> ApplicationContext::GetResourceManager() const | 1070 | std::shared_ptr<Global::Resource::ResourceManager> ApplicationContext::GetResourceManager() const |
| @@ -2095,45 +2095,15 @@ napi_value JsApplicationContextUtils::OnGetApplicationContext(napi_env env, Napi | |||
| 2095 | AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); | 2095 | AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); |
| 2096 | return CreateJsUndefined(env); | 2096 | return CreateJsUndefined(env); |
| 2097 | } | 2097 | } |
| 2098 | - | 2098 | + auto cachedObj = ApplicationContextManager::GetApplicationContextManager().GetGlobalObject(env); |
| 2099 | - if (!applicationContext->GetApplicationInfoUpdateFlag()) { | 2099 | + if (cachedObj != nullptr) { |
| 2100 | - auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetGlobalObject(env); | 2100 | + napi_value objValue = cachedObj->GetNapiValue(); |
| 2101 | - if (appContextObj != nullptr) { | 2101 | + if (applicationContext->ConsumeApplicationInfoUpdateFlag()) { |
| 2102 | - return appContextObj->GetNapiValue(); | 2102 | + return UpdateApplicationContextInfo(env, objValue, applicationContext); |
| 2103 | } | 2103 | } |
| 2104 | + return objValue; | ||
| 2104 | } | 2105 | } |
| 2105 | - | 2106 | + return CreateAndCacheApplicationContext(env, applicationContext); |
| 2106 | - napi_value value = CreateJsApplicationContext(env); | ||
| 2107 | - auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.ApplicationContext", &value, 1); | ||
| 2108 | - if (systemModule == nullptr) { | ||
| 2109 | - TAG_LOGW(AAFwkTag::APPKIT, "null systemModule"); | ||
| 2110 | - AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); | ||
| 2111 | - return CreateJsUndefined(env); | ||
| 2112 | - } | ||
| 2113 | - napi_value contextObj = systemModule->GetNapiValue(); | ||
| 2114 | - if (!CheckTypeForNapiValue(env, contextObj, napi_object)) { | ||
| 2115 | - TAG_LOGE(AAFwkTag::APPKIT, "get object failed"); | ||
| 2116 | - AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); | ||
| 2117 | - return CreateJsUndefined(env); | ||
| 2118 | - } | ||
| 2119 | - auto workContext = new (std::nothrow) std::weak_ptr<ApplicationContext>(applicationContext); | ||
| 2120 | - napi_coerce_to_native_binding_object( | ||
| 2121 | - env, contextObj, DetachCallbackFunc, AttachApplicationContext, workContext, nullptr); | ||
| 2122 | - if (workContext != nullptr) { | ||
| 2123 | - auto res = napi_wrap(env, contextObj, workContext, | ||
| 2124 | - [](napi_env, void *data, void *) { | ||
| 2125 | - TAG_LOGD(AAFwkTag::APPKIT, "Finalizer for weak_ptr application context is called"); | ||
| 2126 | - delete static_cast<std::weak_ptr<ApplicationContext> *>(data); | ||
| 2127 | - data = nullptr; | ||
| 2128 | - }, | ||
| 2129 | - nullptr, nullptr); | ||
| 2130 | - if (res != napi_ok && workContext != nullptr) { | ||
| 2131 | - TAG_LOGE(AAFwkTag::APPKIT, "napi_wrap failed:%{public}d", res); | ||
| 2132 | - delete workContext; | ||
| 2133 | - return CreateJsUndefined(env); | ||
| 2134 | - } | ||
| 2135 | - } | ||
| 2136 | - return contextObj; | ||
| 2137 | } | 2107 | } |
| 2138 | 2108 | ||
| 2139 | bool JsApplicationContextUtils::CheckCallerIsSystemApp() | 2109 | bool JsApplicationContextUtils::CheckCallerIsSystemApp() |
| @@ -2191,6 +2161,71 @@ napi_value JsApplicationContextUtils::CreateJsApplicationContext(napi_env env) | |||
| 2191 | return handleEscape.Escape(object); | 2161 | return handleEscape.Escape(object); |
| 2192 | } | 2162 | } |
| 2193 | 2163 | ||
| 2164 | +napi_value JsApplicationContextUtils::UpdateApplicationContextInfo( | ||
| 2165 | + napi_env env, napi_value cachedObj, | ||
| 2166 | + const std::shared_ptr<ApplicationContext>& applicationContext) | ||
| 2167 | +{ | ||
| 2168 | + if (cachedObj == nullptr || applicationContext == nullptr) { | ||
| 2169 | + return cachedObj; | ||
| 2170 | + } | ||
| 2171 | + auto appInfo = applicationContext->GetApplicationInfo(); | ||
| 2172 | + if (appInfo != nullptr) { | ||
| 2173 | + napi_set_named_property(env, cachedObj, "applicationInfo", | ||
| 2174 | + CreateJsApplicationInfo(env, *appInfo)); | ||
| 2175 | + } else { | ||
| 2176 | + TAG_LOGW(AAFwkTag::APPKIT, "appInfo is null, restore update flag"); | ||
| 2177 | + applicationContext->SetApplicationInfoUpdateFlag(true); | ||
| 2178 | + } | ||
| 2179 | + return cachedObj; | ||
| 2180 | +} | ||
| 2181 | + | ||
| 2182 | +napi_value JsApplicationContextUtils::CreateAndCacheApplicationContext( | ||
| 2183 | + napi_env env, const std::shared_ptr<ApplicationContext>& applicationContext) | ||
| 2184 | +{ | ||
| 2185 | + HandleEscape handleEscape(env); | ||
| 2186 | + napi_value value = CreateJsApplicationContext(env); | ||
| 2187 | + auto systemModule = JsRuntime::LoadSystemModuleByEngine( | ||
| 2188 | + env, "application.ApplicationContext", &value, 1); | ||
| 2189 | + if (systemModule == nullptr) { | ||
| 2190 | + TAG_LOGW(AAFwkTag::APPKIT, "null systemModule"); | ||
| 2191 | + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); | ||
| 2192 | + return CreateJsUndefined(env); | ||
| 2193 | + } | ||
| 2194 | + napi_value contextObj = systemModule->GetNapiValue(); | ||
| 2195 | + if (!CheckTypeForNapiValue(env, contextObj, napi_object)) { | ||
| 2196 | + TAG_LOGE(AAFwkTag::APPKIT, "get object failed"); | ||
| 2197 | + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); | ||
| 2198 | + return CreateJsUndefined(env); | ||
| 2199 | + } | ||
| 2200 | + auto workContext = new (std::nothrow) std::weak_ptr<ApplicationContext>(applicationContext); | ||
| 2201 | + napi_coerce_to_native_binding_object( | ||
| 2202 | + env, contextObj, DetachCallbackFunc, AttachApplicationContext, workContext, nullptr); | ||
| 2203 | + if (workContext != nullptr) { | ||
| 2204 | + auto res = napi_wrap(env, contextObj, workContext, | ||
| 2205 | + [](napi_env, void *data, void *) { | ||
| 2206 | + TAG_LOGD(AAFwkTag::APPKIT, "Finalizer for weak_ptr application context is called"); | ||
| 2207 | + delete static_cast<std::weak_ptr<ApplicationContext> *>(data); | ||
| 2208 | + data = nullptr; | ||
| 2209 | + }, | ||
| 2210 | + nullptr, nullptr); | ||
| 2211 | + if (res != napi_ok && workContext != nullptr) { | ||
| 2212 | + TAG_LOGE(AAFwkTag::APPKIT, "napi_wrap failed:%{public}d", res); | ||
| 2213 | + delete workContext; | ||
| 2214 | + return CreateJsUndefined(env); | ||
| 2215 | + } | ||
| 2216 | + } | ||
| 2217 | + napi_ref ref = nullptr; | ||
| 2218 | + napi_status refStatus = napi_create_reference(env, contextObj, 1, &ref); | ||
| 2219 | + if (refStatus != napi_ok || ref == nullptr) { | ||
| 2220 | + TAG_LOGE(AAFwkTag::APPKIT, "napi_create_reference failed:%{public}d", refStatus); | ||
| 2221 | + return CreateJsUndefined(env); | ||
| 2222 | + } | ||
| 2223 | + ApplicationContextManager::GetApplicationContextManager() | ||
| 2224 | + .AddGlobalObject(env, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref))); | ||
| 2225 | + applicationContext->SetApplicationInfoUpdateFlag(false); | ||
| 2226 | + return handleEscape.Escape(contextObj); | ||
| 2227 | +} | ||
| 2228 | + | ||
| 2194 | napi_value JsApplicationContextUtils::GetUIAbilityByInstanceId(napi_env env, napi_callback_info info) | 2229 | napi_value JsApplicationContextUtils::GetUIAbilityByInstanceId(napi_env env, napi_callback_info info) |
| 2195 | { | 2230 | { |
| 2196 | TAG_LOGD(AAFwkTag::APPKIT, "GetUIAbilityByInstanceId"); | 2231 | TAG_LOGD(AAFwkTag::APPKIT, "GetUIAbilityByInstanceId"); |
| @@ -694,13 +694,14 @@ napi_value JsBaseContext::OnGetApplicationContext(napi_env env, NapiCallbackInfo | |||
| 694 | return CreateJsUndefined(env); | 694 | return CreateJsUndefined(env); |
| 695 | } | 695 | } |
| 696 | 696 | ||
| 697 | - if (!applicationContext->GetApplicationInfoUpdateFlag()) { | 697 | + auto cachedObj = ApplicationContextManager::GetApplicationContextManager().GetGlobalObject(env); |
| 698 | - std::shared_ptr<NativeReference> applicationContextObj = | 698 | + if (cachedObj != nullptr) { |
| 699 | - ApplicationContextManager::GetApplicationContextManager().GetGlobalObject(env); | 699 | + napi_value objValue = cachedObj->GetNapiValue(); |
| 700 | - if (applicationContextObj != nullptr) { | 700 | + if (applicationContext->ConsumeApplicationInfoUpdateFlag()) { |
| 701 | - napi_value objValue = applicationContextObj->GetNapiValue(); | 701 | + return JsApplicationContextUtils::UpdateApplicationContextInfo( |
| 702 | - return objValue; | 702 | + env, objValue, applicationContext); |
| 703 | } | 703 | } |
| 704 | + return objValue; | ||
| 704 | } | 705 | } |
| 705 | return CreateJSApplicationContext(env, applicationContext); | 706 | return CreateJSApplicationContext(env, applicationContext); |
| 706 | } | 707 | } |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -203,6 +204,7 @@ public: | |||
| 203 | 204 | ||
| 204 | bool GetApplicationInfoUpdateFlag() const; | 205 | bool GetApplicationInfoUpdateFlag() const; |
| 205 | void SetApplicationInfoUpdateFlag(bool flag); | 206 | void SetApplicationInfoUpdateFlag(bool flag); |
| 207 | + bool ConsumeApplicationInfoUpdateFlag(); | ||
| 206 | void RegisterAppConfigUpdateObserver(AppConfigUpdateCallback appConfigChangeCallback); | 208 | void RegisterAppConfigUpdateObserver(AppConfigUpdateCallback appConfigChangeCallback); |
| 207 | void RegisterAppFontObserver(AppConfigUpdateCallback appFontCallback); | 209 | void RegisterAppFontObserver(AppConfigUpdateCallback appFontCallback); |
| 208 | void RegisterProcessSecurityExit(AppProcessExitCallback appProcessExitCallback); | 210 | void RegisterProcessSecurityExit(AppProcessExitCallback appProcessExitCallback); |
| @@ -273,7 +275,7 @@ private: | |||
| 273 | std::mutex interopCallbackLock_; | 275 | std::mutex interopCallbackLock_; |
| 274 | std::recursive_mutex envCallbacksLock_; | 276 | std::recursive_mutex envCallbacksLock_; |
| 275 | std::recursive_mutex applicationStateCallbackLock_; | 277 | std::recursive_mutex applicationStateCallbackLock_; |
| 276 | - bool applicationInfoUpdateFlag_ = false; | 278 | + std::atomic<bool> applicationInfoUpdateFlag_{false}; |
| 277 | AppConfigUpdateCallback appConfigChangeCallback_ = nullptr; | 279 | AppConfigUpdateCallback appConfigChangeCallback_ = nullptr; |
| 278 | AppConfigUpdateCallback appFontCallback_ = nullptr; | 280 | AppConfigUpdateCallback appFontCallback_ = nullptr; |
| 279 | AppProcessExitCallback appProcessExitCallback_ = nullptr; | 281 | AppProcessExitCallback appProcessExitCallback_ = nullptr; |
| @@ -133,6 +133,11 @@ public: | |||
| 133 | static napi_value GetRunningProcessInformation(napi_env env, napi_callback_info info); | 133 | static napi_value GetRunningProcessInformation(napi_env env, napi_callback_info info); |
| 134 | static napi_value GetUIAbilityChildProcessInfos(napi_env env, napi_callback_info info); | 134 | static napi_value GetUIAbilityChildProcessInfos(napi_env env, napi_callback_info info); |
| 135 | static napi_value CreateJsApplicationContext(napi_env env); | 135 | static napi_value CreateJsApplicationContext(napi_env env); |
| 136 | + static napi_value UpdateApplicationContextInfo( | ||
| 137 | + napi_env env, napi_value cachedObj, | ||
| 138 | + const std::shared_ptr<ApplicationContext>& applicationContext); | ||
| 139 | + static napi_value CreateAndCacheApplicationContext( | ||
| 140 | + napi_env env, const std::shared_ptr<ApplicationContext>& applicationContext); | ||
| 136 | static napi_value RestartApp(napi_env env, napi_callback_info info); | 141 | static napi_value RestartApp(napi_env env, napi_callback_info info); |
| 137 | static napi_value SetSupportedProcessCacheSelf(napi_env env, napi_callback_info info); | 142 | static napi_value SetSupportedProcessCacheSelf(napi_env env, napi_callback_info info); |
| 138 | static napi_value PreloadUIExtensionAbility(napi_env env, napi_callback_info info); | 143 | static napi_value PreloadUIExtensionAbility(napi_env env, napi_callback_info info); |