1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "js_app_service_extension.h"
17
18 #include "ability_business_error.h"
19 #include "ability_handler.h"
20 #include "ability_info.h"
21 #include "ability_manager_client.h"
22 #include "configuration_utils.h"
23 #include "display_util.h"
24 #include "freeze_util.h"
25 #include "hitrace_meter.h"
26 #include "hilog_tag_wrapper.h"
27 #include "js_extension_common.h"
28 #include "js_extension_context.h"
29 #include "js_runtime.h"
30 #include "js_runtime_utils.h"
31 #include "js_app_service_extension_context.h"
32 #include "napi/native_api.h"
33 #include "napi/native_node_api.h"
34 #include "napi_common_configuration.h"
35 #include "napi_common_want.h"
36 #include "napi_remote_object.h"
37 #ifdef SUPPORT_GRAPHICS
38 #include "iservice_registry.h"
39 #include "system_ability_definition.h"
40 #endif
41
42 namespace OHOS {
43 namespace AbilityRuntime {
44 namespace {
45 constexpr size_t ARGC_ONE = 1;
46 constexpr size_t ARGC_TWO = 2;
47 }
48
49 namespace {
GetNativeRemoteObject(napi_env env,napi_value obj)50 sptr<IRemoteObject> GetNativeRemoteObject(napi_env env, napi_value obj)
51 {
52 if (env == nullptr || obj == nullptr) {
53 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null obj");
54 return nullptr;
55 }
56 napi_valuetype type;
57 napi_typeof(env, obj, &type);
58 if (type == napi_undefined || type == napi_null) {
59 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "obj type invalid");
60 return nullptr;
61 }
62 if (type != napi_object) {
63 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "obj not object");
64 return nullptr;
65 }
66 return NAPI_ohos_rpc_getNativeRemoteObject(env, obj);
67 }
68 }
69
70 using namespace OHOS::AppExecFwk;
71
AttachAppServiceExtensionContext(napi_env env,void * value,void *)72 napi_value AttachAppServiceExtensionContext(napi_env env, void *value, void *)
73 {
74 if (value == nullptr) {
75 TAG_LOGW(AAFwkTag::APP_SERVICE_EXT, "null value");
76 return nullptr;
77 }
78 auto ptr = reinterpret_cast<std::weak_ptr<AppServiceExtensionContext> *>(value)->lock();
79 if (ptr == nullptr) {
80 TAG_LOGW(AAFwkTag::APP_SERVICE_EXT, "null ptr");
81 return nullptr;
82 }
83 napi_value object = CreateJsAppServiceExtensionContext(env, ptr);
84 auto sysModule = JsRuntime::LoadSystemModuleByEngine(env,
85 "application.AppServiceExtensionContext", &object, 1);
86 if (sysModule == nullptr) {
87 TAG_LOGW(AAFwkTag::APP_SERVICE_EXT, "null sysModule");
88 return nullptr;
89 }
90 auto contextObj = sysModule->GetNapiValue();
91 napi_coerce_to_native_binding_object(
92 env, contextObj, DetachCallbackFunc, AttachAppServiceExtensionContext, value, nullptr);
93 auto workContext = new (std::nothrow) std::weak_ptr<AppServiceExtensionContext>(ptr);
94 auto res = napi_wrap(env, contextObj, workContext,
95 [](napi_env, void *data, void *) {
96 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Finalizer for weak_ptr app service extension context is called");
97 delete static_cast<std::weak_ptr<AppServiceExtensionContext> *>(data);
98 },
99 nullptr, nullptr);
100 if (res != napi_ok && workContext != nullptr) {
101 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "napi_wrap failed:%{public}d", res);
102 delete workContext;
103 return nullptr;
104 }
105 return contextObj;
106 }
107
Create(const std::unique_ptr<Runtime> & runtime)108 JsAppServiceExtension* JsAppServiceExtension::Create(const std::unique_ptr<Runtime>& runtime)
109 {
110 return new JsAppServiceExtension(static_cast<JsRuntime&>(*runtime));
111 }
112
JsAppServiceExtension(JsRuntime & jsRuntime)113 JsAppServiceExtension::JsAppServiceExtension(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsAppServiceExtension()114 JsAppServiceExtension::~JsAppServiceExtension()
115 {
116 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "called");
117 auto context = GetContext();
118 if (context) {
119 context->Unbind();
120 }
121
122 jsRuntime_.FreeNativeReference(std::move(jsObj_));
123 jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
124 }
125
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)126 void JsAppServiceExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
127 const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
128 const sptr<IRemoteObject> &token)
129 {
130 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
131 AppServiceExtension::Init(record, application, handler, token);
132 std::string srcPath = "";
133 GetSrcPath(srcPath);
134 if (srcPath.empty()) {
135 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "get srcPath failed");
136 return;
137 }
138
139 std::string moduleName(Extension::abilityInfo_->moduleName);
140 moduleName.append("::").append(abilityInfo_->name);
141 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "called, moduleName:%{public}s,srcPath:%{public}s",
142 moduleName.c_str(), srcPath.c_str());
143 HandleScope handleScope(jsRuntime_);
144 auto env = jsRuntime_.GetNapiEnv();
145
146 jsObj_ = jsRuntime_.LoadModule(
147 moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE,
148 false, abilityInfo_->srcEntrance);
149 if (jsObj_ == nullptr) {
150 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null jsObj_");
151 return;
152 }
153
154 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "ConvertNativeValueTo");
155 napi_value obj = jsObj_->GetNapiValue();
156 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
157 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "get JsAppServiceExtension obj failed");
158 return;
159 }
160
161 BindContext(env, obj);
162
163 SetExtensionCommon(JsExtensionCommon::Create(jsRuntime_, static_cast<NativeReference&>(*jsObj_), shellContextRef_));
164
165 auto context = GetContext();
166 auto appContext = Context::GetApplicationContext();
167 if (context != nullptr && appContext != nullptr) {
168 auto appConfig = appContext->GetConfiguration();
169 if (appConfig != nullptr) {
170 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Original config dump: %{public}s", appConfig->GetName().c_str());
171 context->SetConfiguration(std::make_shared<Configuration>(*appConfig));
172 }
173 }
174 ListenWMS();
175 }
176
ListenWMS()177 void JsAppServiceExtension::ListenWMS()
178 {
179 #ifdef SUPPORT_GRAPHICS
180 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "RegisterDisplayListener");
181 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
182 if (abilityManager == nullptr) {
183 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null SaMgr");
184 return;
185 }
186
187 auto jsAppServiceExtension = std::static_pointer_cast<JsAppServiceExtension>(shared_from_this());
188 displayListener_ = sptr<JsAppServiceExtensionDisplayListener>::MakeSptr(jsAppServiceExtension);
189 if (displayListener_ == nullptr) {
190 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null displayListener");
191 return;
192 }
193
194 auto context = GetContext();
195 if (context == nullptr || context->GetToken() == nullptr) {
196 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null context");
197 return;
198 }
199
200 saStatusChangeListener_ =
201 sptr<SystemAbilityStatusChangeListener>::MakeSptr(displayListener_, context->GetToken());
202 if (saStatusChangeListener_ == nullptr) {
203 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null saStatusChangeListener");
204 return;
205 }
206
207 auto ret = abilityManager->SubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, saStatusChangeListener_);
208 if (ret != 0) {
209 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "subscribe system ability error:%{public}d.", ret);
210 }
211 #endif
212 }
213
BindContext(napi_env env,napi_value obj)214 void JsAppServiceExtension::BindContext(napi_env env, napi_value obj)
215 {
216 auto context = GetContext();
217 if (context == nullptr) {
218 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null context");
219 return;
220 }
221 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "call");
222 napi_value contextObj = CreateJsAppServiceExtensionContext(env, context);
223 shellContextRef_ = JsRuntime::LoadSystemModuleByEngine(env, "application.AppServiceExtensionContext",
224 &contextObj, ARGC_ONE);
225 if (shellContextRef_ == nullptr) {
226 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null shellContextRef");
227 return;
228 }
229 contextObj = shellContextRef_->GetNapiValue();
230 if (!CheckTypeForNapiValue(env, contextObj, napi_object)) {
231 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "get context native obj failed");
232 return;
233 }
234 auto workContext = new (std::nothrow) std::weak_ptr<AppServiceExtensionContext>(context);
235 napi_coerce_to_native_binding_object(
236 env, contextObj, DetachCallbackFunc, AttachAppServiceExtensionContext, workContext, nullptr);
237 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Bind");
238 context->Bind(jsRuntime_, shellContextRef_.get());
239 napi_set_named_property(env, obj, "context", contextObj);
240
241 auto res = napi_wrap(env, contextObj, workContext,
242 [](napi_env, void* data, void*) {
243 delete static_cast<std::weak_ptr<AppServiceExtensionContext>*>(data);
244 },
245 nullptr, nullptr);
246 if (res != napi_ok && workContext != nullptr) {
247 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "napi_wrap failed:%{public}d", res);
248 delete workContext;
249 return;
250 }
251 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "end");
252 }
253
OnStart(const AAFwk::Want & want)254 void JsAppServiceExtension::OnStart(const AAFwk::Want &want)
255 {
256 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
257 Extension::OnStart(want);
258 TAG_LOGI(AAFwkTag::APP_SERVICE_EXT, "call");
259
260 auto context = GetContext();
261 if (context != nullptr) {
262 #ifdef SUPPORT_GRAPHICS
263 int32_t displayId = AAFwk::DisplayUtil::GetDefaultDisplayId();
264 displayId = want.GetIntParam(Want::PARAM_RESV_DISPLAY_ID, displayId);
265 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "displayId %{public}d", displayId);
266 auto configUtils = std::make_shared<ConfigurationUtils>();
267 configUtils->InitDisplayConfig(displayId, context->GetConfiguration(), context->GetResourceManager());
268 #endif //SUPPORT_GRAPHICS
269 }
270
271 HandleScope handleScope(jsRuntime_);
272 napi_env env = jsRuntime_.GetNapiEnv();
273
274 // display config has changed, need update context.config
275 if (context != nullptr) {
276 JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, context->GetConfiguration());
277 }
278
279 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
280 napi_value argv[] = {napiWant};
281 CallObjectMethod("onCreate", argv, ARGC_ONE);
282 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "ok");
283 }
284
OnStop()285 void JsAppServiceExtension::OnStop()
286 {
287 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
288 AppServiceExtension::OnStop();
289 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "call");
290 CallObjectMethod("onDestroy");
291 bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
292 if (ret) {
293 ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
294 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "app service extension connection not disconnected");
295 }
296 TAG_LOGI(AAFwkTag::APP_SERVICE_EXT, "UnregisterDisplayInfoChangedListener");
297 auto context = GetContext();
298 if (context == nullptr || context->GetToken() == nullptr) {
299 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null context");
300 return;
301 }
302 #ifdef SUPPORT_GRAPHICS
303 Rosen::WindowManager::GetInstance()
304 .UnregisterDisplayInfoChangedListener(context->GetToken(), displayListener_);
305 if (saStatusChangeListener_) {
306 auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
307 if (saMgr) {
308 saMgr->UnSubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, saStatusChangeListener_);
309 } else {
310 TAG_LOGW(AAFwkTag::APP_SERVICE_EXT, "OnStop SaMgr null");
311 }
312 }
313 #endif //SUPPORT_GRAPHICS
314 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "ok");
315 }
316
AddLifecycleEventForJSCall(const std::string & eventStr)317 void JsAppServiceExtension::AddLifecycleEventForJSCall(const std::string &eventStr)
318 {
319 auto entry = std::string("JsAppServiceExtension:") + eventStr;
320 auto context = GetContext();
321 if (context) {
322 FreezeUtil::GetInstance().AddLifecycleEvent(context->GetToken(), entry);
323 }
324 }
325
OnConnect(const AAFwk::Want & want)326 sptr<IRemoteObject> JsAppServiceExtension::OnConnect(const AAFwk::Want &want)
327 {
328 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
329 HandleScope handleScope(jsRuntime_);
330 AddLifecycleEventForJSCall("OnConnect begin");
331 napi_value result = CallOnConnect(want);
332 AddLifecycleEventForJSCall("OnConnect end");
333 napi_env env = jsRuntime_.GetNapiEnv();
334 auto remoteObj = GetNativeRemoteObject(env, result);
335 if (remoteObj == nullptr) {
336 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null remoteObj");
337 }
338 return remoteObj;
339 }
340
OnDisconnect(const AAFwk::Want & want)341 void JsAppServiceExtension::OnDisconnect(const AAFwk::Want &want)
342 {
343 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
344 HandleScope handleScope(jsRuntime_);
345 Extension::OnDisconnect(want);
346 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "called");
347 CallOnDisconnect(want, false);
348 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "end");
349 }
350
OnCommand(const AAFwk::Want & want,bool restart,int startId)351 void JsAppServiceExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId)
352 {
353 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
354 Extension::OnCommand(want, restart, startId);
355 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "restart=%{public}s,startId=%{public}d",
356 restart ? "true" : "false",
357 startId);
358 // wrap want
359 HandleScope handleScope(jsRuntime_);
360 napi_env env = jsRuntime_.GetNapiEnv();
361 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
362 // wrap startId
363 napi_value napiStartId = nullptr;
364 napi_create_int32(env, startId, &napiStartId);
365 napi_value argv[] = {napiWant, napiStartId};
366 CallObjectMethod("onRequest", argv, ARGC_TWO);
367 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "ok");
368 }
369
CallObjectMethod(const char * name,napi_value const * argv,size_t argc)370 napi_value JsAppServiceExtension::CallObjectMethod(const char* name, napi_value const* argv, size_t argc)
371 {
372 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name);
373 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "name:%{public}s", name);
374
375 if (!jsObj_) {
376 TAG_LOGW(AAFwkTag::APP_SERVICE_EXT, "Not found AppServiceExtension.js");
377 return nullptr;
378 }
379
380 HandleScope handleScope(jsRuntime_);
381 napi_env env = jsRuntime_.GetNapiEnv();
382
383 napi_value obj = jsObj_->GetNapiValue();
384 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
385 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "get AppServiceExtension obj failed");
386 return nullptr;
387 }
388
389 napi_value method = nullptr;
390 napi_get_named_property(env, obj, name, &method);
391 if (!CheckTypeForNapiValue(env, method, napi_function)) {
392 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "get '%{public}s' from AppServiceExtension obj failed", name);
393 return nullptr;
394 }
395 TAG_LOGI(AAFwkTag::APP_SERVICE_EXT, "CallFunction(%{public}s) ok", name);
396 napi_value result = nullptr;
397 napi_status status = napi_call_function(env, obj, method, argc, argv, &result);
398 if (status != napi_ok) {
399 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "call js func failed: %{public}d", status);
400 }
401 return result;
402 }
403
GetSrcPath(std::string & srcPath)404 void JsAppServiceExtension::GetSrcPath(std::string &srcPath)
405 {
406 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "called");
407 if (!Extension::abilityInfo_->srcEntrance.empty()) {
408 srcPath.append(Extension::abilityInfo_->moduleName + "/");
409 srcPath.append(Extension::abilityInfo_->srcEntrance);
410 srcPath.erase(srcPath.rfind('.'));
411 srcPath.append(".abc");
412 }
413 }
414
CallOnConnect(const AAFwk::Want & want)415 napi_value JsAppServiceExtension::CallOnConnect(const AAFwk::Want &want)
416 {
417 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
418 Extension::OnConnect(want);
419 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "call");
420 napi_env env = jsRuntime_.GetNapiEnv();
421 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
422 napi_value argv[] = {napiWant};
423 if (!jsObj_) {
424 TAG_LOGW(AAFwkTag::APP_SERVICE_EXT, "Not found AppServiceExtension.js");
425 return nullptr;
426 }
427
428 napi_value obj = jsObj_->GetNapiValue();
429 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
430 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "get AppServiceExtension obj failed");
431 return nullptr;
432 }
433
434 napi_value method = nullptr;
435 napi_get_named_property(env, obj, "onConnect", &method);
436 if (method == nullptr) {
437 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null method");
438 return nullptr;
439 }
440 napi_value remoteNative = nullptr;
441 TAG_LOGI(AAFwkTag::APP_SERVICE_EXT, "Call onConnect");
442 napi_status status = napi_call_function(env, obj, method, ARGC_ONE, argv, &remoteNative);
443 if (status != napi_ok) {
444 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "call js func failed %{public}d", status);
445 }
446 if (remoteNative == nullptr) {
447 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null remoteNative");
448 }
449 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "ok");
450 return remoteNative;
451 }
452
CallOnDisconnect(const AAFwk::Want & want,bool withResult)453 napi_value JsAppServiceExtension::CallOnDisconnect(const AAFwk::Want &want, bool withResult)
454 {
455 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
456 HandleEscape handleEscape(jsRuntime_);
457 napi_env env = jsRuntime_.GetNapiEnv();
458 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
459 napi_value argv[] = { napiWant };
460 if (!jsObj_) {
461 TAG_LOGW(AAFwkTag::APP_SERVICE_EXT, "Not found AppServiceExtension.js");
462 return nullptr;
463 }
464
465 napi_value obj = jsObj_->GetNapiValue();
466 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
467 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "get AppServiceExtension obj failed");
468 return nullptr;
469 }
470
471 napi_value method = nullptr;
472 napi_get_named_property(env, obj, "onDisconnect", &method);
473 if (method == nullptr) {
474 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null method");
475 return nullptr;
476 }
477 TAG_LOGI(AAFwkTag::APP_SERVICE_EXT, "Call onDisconnect");
478 if (withResult) {
479 napi_value result = nullptr;
480 napi_status status = napi_call_function(env, obj, method, ARGC_ONE, argv, &result);
481 if (status != napi_ok) {
482 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "call js func failed %{public}d", status);
483 }
484 return handleEscape.Escape(result);
485 } else {
486 napi_status status = napi_call_function(env, obj, method, ARGC_ONE, argv, nullptr);
487 if (status != napi_ok) {
488 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "call js func failed %{public}d", status);
489 }
490 return nullptr;
491 }
492 }
493
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)494 void JsAppServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration)
495 {
496 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
497 AppServiceExtension::OnConfigurationUpdated(configuration);
498 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "call");
499 auto context = GetContext();
500 if (context == nullptr) {
501 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null context");
502 return;
503 }
504
505 auto contextConfig = context->GetConfiguration();
506 if (contextConfig != nullptr) {
507 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
508 std::vector<std::string> changeKeyV;
509 contextConfig->CompareDifferent(changeKeyV, configuration);
510 if (!changeKeyV.empty()) {
511 contextConfig->Merge(changeKeyV, configuration);
512 }
513 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Config dump after merge: %{public}s", contextConfig->GetName().c_str());
514 }
515 ConfigurationUpdated();
516 }
517
ConfigurationUpdated()518 void JsAppServiceExtension::ConfigurationUpdated()
519 {
520 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "called");
521 HandleScope handleScope(jsRuntime_);
522 napi_env env = jsRuntime_.GetNapiEnv();
523
524 // Notify extension context
525 auto fullConfig = GetContext()->GetConfiguration();
526 if (!fullConfig) {
527 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null configuration");
528 return;
529 }
530
531 napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig);
532 CallObjectMethod("onConfigurationUpdate", &napiConfiguration, ARGC_ONE);
533 JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, fullConfig);
534 }
535 #ifdef SUPPORT_GRAPHICS
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)536 void JsAppServiceExtension::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId,
537 const std::string& deviceId)
538 {
539 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "systemAbilityId: %{public}d add", systemAbilityId);
540 if (systemAbilityId == WINDOW_MANAGER_SERVICE_ID) {
541 TAG_LOGI(AAFwkTag::APP_SERVICE_EXT, "RegisterDisplayInfoChangedListener");
542 Rosen::WindowManager::GetInstance().RegisterDisplayInfoChangedListener(token_, tmpDisplayListener_);
543 }
544 }
545
OnCreate(Rosen::DisplayId displayId)546 void JsAppServiceExtension::OnCreate(Rosen::DisplayId displayId)
547 {
548 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "OnCreate");
549 }
550
OnDestroy(Rosen::DisplayId displayId)551 void JsAppServiceExtension::OnDestroy(Rosen::DisplayId displayId)
552 {
553 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "OnDestroy");
554 }
555
OnDisplayInfoChange(const sptr<IRemoteObject> & token,Rosen::DisplayId displayId,float density,Rosen::DisplayOrientation orientation)556 void JsAppServiceExtension::OnDisplayInfoChange(const sptr<IRemoteObject>& token, Rosen::DisplayId displayId,
557 float density, Rosen::DisplayOrientation orientation)
558 {
559 TAG_LOGI(AAFwkTag::APP_SERVICE_EXT, "displayId: %{public}" PRIu64, displayId);
560 auto context = GetContext();
561 if (context == nullptr) {
562 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null context");
563 return;
564 }
565
566 auto contextConfig = context->GetConfiguration();
567 if (contextConfig == nullptr) {
568 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null contextConfig");
569 return;
570 }
571
572 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
573 bool configChanged = false;
574 auto configUtils = std::make_shared<ConfigurationUtils>();
575 configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), configChanged);
576 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Config dump after update: %{public}s", contextConfig->GetName().c_str());
577
578 if (configChanged) {
579 auto jsAppServiceExtension = std::static_pointer_cast<JsAppServiceExtension>(shared_from_this());
580 auto task = [jsAppServiceExtension]() {
581 if (jsAppServiceExtension) {
582 jsAppServiceExtension->ConfigurationUpdated();
583 }
584 };
585 if (handler_ != nullptr) {
586 handler_->PostTask(task, "JsAppServiceExtension:OnChange");
587 }
588 }
589
590 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "finished");
591 }
592
OnChange(Rosen::DisplayId displayId)593 void JsAppServiceExtension::OnChange(Rosen::DisplayId displayId)
594 {
595 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "displayId: %{public}" PRIu64"", displayId);
596 auto context = GetContext();
597 if (context == nullptr) {
598 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null context");
599 return;
600 }
601
602 auto contextConfig = context->GetConfiguration();
603 if (contextConfig == nullptr) {
604 TAG_LOGE(AAFwkTag::APP_SERVICE_EXT, "null contextConfig");
605 return;
606 }
607
608 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
609 bool configChanged = false;
610 auto configUtils = std::make_shared<ConfigurationUtils>();
611 configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), configChanged);
612 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "Config dump after update: %{public}s", contextConfig->GetName().c_str());
613
614 if (configChanged) {
615 auto jsAppServiceExtension = std::static_pointer_cast<JsAppServiceExtension>(shared_from_this());
616 auto task = [jsAppServiceExtension]() {
617 if (jsAppServiceExtension) {
618 jsAppServiceExtension->ConfigurationUpdated();
619 }
620 };
621 if (handler_ != nullptr) {
622 handler_->PostTask(task, "JsAppServiceExtension:OnChange");
623 }
624 }
625
626 TAG_LOGD(AAFwkTag::APP_SERVICE_EXT, "finished");
627 }
628 #endif
629 } // AbilityRuntime
630 } // OHOS
631