diff --git a/frameworks/native/ability/native/ui_service_extension_ability/js_ui_service_extension.cpp b/frameworks/native/ability/native/ui_service_extension_ability/js_ui_service_extension.cpp new file mode 100644 index 0000000000..8975d1af28 --- /dev/null +++ b/frameworks/native/ability/native/ui_service_extension_ability/js_ui_service_extension.cpp @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed 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 "js_ui_service_extension.h" + +#include + +#include "ability_business_error.h" +#include "ability_handler.h" +#include "ability_info.h" +#include "ability.h" +#include "ability_manager_client.h" +#include "configuration_utils.h" +#include "hitrace_meter.h" +#include "hilog_tag_wrapper.h" +#include "js_extension_common.h" +#include "js_extension_context.h" +#include "js_runtime.h" +#include "js_runtime_utils.h" +#include "js_ui_service_extension_context.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "napi_common_configuration.h" +#include "napi_common_want.h" +#include "napi_remote_object.h" +#include "scene_board_judgement.h" +#include "ability_context.h" +#include "session_info.h" +#include "window_scene.h" +#include "js_window_stage.h" +#include "wm_common.h" +#include "window.h" +#ifdef SUPPORT_GRAPHICS +#include "iservice_registry.h" +#include "system_ability_definition.h" +#endif + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr size_t ARGC_ONE = 1; +constexpr size_t ARGC_TWO = 2; +} + +using namespace OHOS::AppExecFwk; + +napi_value AttachUIServiceExtensionContext(napi_env env, void *value, void *) +{ + if (value == nullptr) { + TAG_LOGW(AAFwkTag::UISERVC_EXT, "invalid parameter."); + return nullptr; + } + auto ptr = reinterpret_cast *>(value)->lock(); + if (ptr == nullptr) { + TAG_LOGW(AAFwkTag::UISERVC_EXT, "invalid context."); + return nullptr; + } + napi_value object = AbilityRuntime::CreateJsUIServiceExtensionContext(env, ptr); + auto sysModule = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(env, + "application.UIServiceExtensionContext", &object, 1); + if (sysModule == nullptr) { + TAG_LOGW(AAFwkTag::UISERVC_EXT, "load module failed."); + return nullptr; + } + auto contextObj = sysModule->GetNapiValue(); + napi_coerce_to_native_binding_object( + env, contextObj, AbilityRuntime::DetachCallbackFunc, AttachUIServiceExtensionContext, value, nullptr); + auto workContext = new (std::nothrow) std::weak_ptr(ptr); + napi_wrap(env, contextObj, workContext, + [](napi_env, void *data, void *) { + TAG_LOGD(AAFwkTag::UISERVC_EXT, "Finalizer for weak_ptr service extension context is called"); + delete static_cast *>(data); + }, + nullptr, nullptr); + return contextObj; +} + +JsUIServiceExtension* JsUIServiceExtension::Create(const std::unique_ptr& runtime) +{ + return new JsUIServiceExtension(static_cast(*runtime)); +} + +JsUIServiceExtension::JsUIServiceExtension(AbilityRuntime::JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {} + +JsUIServiceExtension::~JsUIServiceExtension() +{ + auto context = GetContext(); + if (context) { + context->Unbind(); + } + + jsRuntime_.FreeNativeReference(std::move(jsObj_)); + jsRuntime_.FreeNativeReference(std::move(shellContextRef_)); +} + +void JsUIServiceExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token) +{ + UIServiceExtension::Init(record, application, handler, token); + std::string srcPath = ""; + GetSrcPath(srcPath); + if (srcPath.empty()) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get srcPath"); + return; + } + + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "JsServiceExtension::Init moduleName:%{public}s,srcPath:%{public}s.", + moduleName.c_str(), srcPath.c_str()); + HandleScope handleScope(jsRuntime_); + auto env = jsRuntime_.GetNapiEnv(); + + jsObj_ = jsRuntime_.LoadModule( + moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE); + if (jsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get jsObj_"); + return; + } + + TAG_LOGD(AAFwkTag::UISERVC_EXT, "ConvertNativeValueTo."); + napi_value obj = jsObj_->GetNapiValue(); + if (!CheckTypeForNapiValue(env, obj, napi_object)) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get JsServiceExtension object"); + return; + } + + BindContext(env, obj); + + SetExtensionCommon(JsExtensionCommon::Create(jsRuntime_, static_cast(*jsObj_), shellContextRef_)); + + handler_ = handler; + auto context = GetContext(); + auto appContext = Context::GetApplicationContext(); + if (context != nullptr && appContext != nullptr) { + auto appConfig = appContext->GetConfiguration(); + if (appConfig != nullptr) { + TAG_LOGD(AAFwkTag::UISERVC_EXT, "Original config dump: %{public}s", appConfig->GetName().c_str()); + context->SetConfiguration(std::make_shared(*appConfig)); + } + } + ListenWMS(); +} + +void JsUIServiceExtension::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId, + const std::string& deviceId) +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "systemAbilityId: %{public}d add", systemAbilityId); + if (systemAbilityId == WINDOW_MANAGER_SERVICE_ID) { + Rosen::DisplayManager::GetInstance().RegisterDisplayListener(tmpDisplayListener_); + } +} + +void JsUIServiceExtension::BindContext(napi_env env, napi_value obj) +{ + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get context"); + return; + } + TAG_LOGD(AAFwkTag::UISERVC_EXT, "call"); + napi_value contextObj = CreateJsUIServiceExtensionContext(env, context); + shellContextRef_ = JsRuntime::LoadSystemModuleByEngine(env, "application.UIServiceExtensionContext", + &contextObj, ARGC_ONE); + if (shellContextRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to load module"); + return; + } + contextObj = shellContextRef_->GetNapiValue(); + if (!CheckTypeForNapiValue(env, contextObj, napi_object)) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get context native object"); + return; + } + auto workContext = new (std::nothrow) std::weak_ptr(context); + napi_coerce_to_native_binding_object( + env, contextObj, DetachCallbackFunc, AttachUIServiceExtensionContext, workContext, nullptr); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "Bind."); + context->Bind(jsRuntime_, shellContextRef_.get()); + napi_set_named_property(env, obj, "context", contextObj); + + napi_wrap(env, contextObj, workContext, + [](napi_env, void* data, void*) { + delete static_cast*>(data); + }, + nullptr, nullptr); + + TAG_LOGD(AAFwkTag::UISERVC_EXT, "end."); +} + +void JsUIServiceExtension::OnStart(const AAFwk::Want &want) +{ + Extension::OnStart(want); + TAG_LOGE(AAFwkTag::UISERVC_EXT, "call"); + + auto context = GetContext(); + if (context != nullptr) { + int32_t displayId = static_cast(Rosen::DisplayManager::GetInstance().GetDefaultDisplayId()); + displayId = want.GetIntParam(Want::PARAM_RESV_DISPLAY_ID, displayId); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "displayId %{public}d", displayId); + auto configUtils = std::make_shared(); + configUtils->InitDisplayConfig(displayId, context->GetConfiguration(), context->GetResourceManager()); + } + + HandleScope handleScope(jsRuntime_); + napi_env env = jsRuntime_.GetNapiEnv(); + + // display config has changed, need update context.config + if (context != nullptr) { + JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, context->GetConfiguration()); + } + + napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want); + napi_value argv[] = {napiWant}; + CallObjectMethod("onCreate", argv, ARGC_ONE); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "ok"); +} + + +void JsUIServiceExtension::OnStop() +{ + Extension::OnStop(); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "call"); + CallObjectMethod("onDestroy"); + bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken()); + if (ret) { + ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "The service extension connection is not disconnected."); + } + Rosen::DisplayManager::GetInstance().UnregisterDisplayListener(displayListener_); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "ok"); +} + +sptr JsUIServiceExtension::OnConnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo> *callbackInfo, bool &isAsyncCallback) +{ + return nullptr; +} + +void JsUIServiceExtension::OnDisconnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) +{ +} + +void JsUIServiceExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId) +{ + Extension::OnCommand(want, restart, startId); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "restart=%{public}s,startId=%{public}d.", + restart ? "true" : "false", + startId); + // wrap want + HandleScope handleScope(jsRuntime_); + napi_env env = jsRuntime_.GetNapiEnv(); + napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want); + // wrap startId + napi_value napiStartId = nullptr; + napi_create_int32(env, startId, &napiStartId); + napi_value argv[] = {napiWant, napiStartId}; + CallObjectMethod("onRequest", argv, ARGC_TWO); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "ok"); +} + +napi_value JsUIServiceExtension::CallObjectMethod(const char* name, napi_value const* argv, size_t argc) +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "name:%{public}s", name); + + if (!jsObj_) { + TAG_LOGW(AAFwkTag::UISERVC_EXT, "Not found ServiceExtension.js"); + return nullptr; + } + + HandleScope handleScope(jsRuntime_); + napi_env env = jsRuntime_.GetNapiEnv(); + + napi_value obj = jsObj_->GetNapiValue(); + if (!CheckTypeForNapiValue(env, obj, napi_object)) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get ServiceExtension object"); + return nullptr; + } + + napi_value method = nullptr; + napi_get_named_property(env, obj, name, &method); + if (!CheckTypeForNapiValue(env, method, napi_function)) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get '%{public}s' from ServiceExtension object", name); + return nullptr; + } + TAG_LOGD(AAFwkTag::UISERVC_EXT, "CallFunction(%{public}s) ok", name); + napi_value result = nullptr; + napi_call_function(env, obj, method, argc, argv, &result); + return result; +} + +void JsUIServiceExtension::GetSrcPath(std::string &srcPath) +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "GetSrcPath start."); + if (!Extension::abilityInfo_->srcEntrance.empty()) { + srcPath.append(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + srcPath.erase(srcPath.rfind('.')); + srcPath.append(".abc"); + } +} + +void JsUIServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration) +{ + UIServiceExtension::OnConfigurationUpdated(configuration); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "call"); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Context is invalid."); + return; + } + + auto contextConfig = context->GetConfiguration(); + if (contextConfig != nullptr) { + TAG_LOGD(AAFwkTag::UISERVC_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str()); + std::vector changeKeyV; + contextConfig->CompareDifferent(changeKeyV, configuration); + if (!changeKeyV.empty()) { + contextConfig->Merge(changeKeyV, configuration); + } + TAG_LOGD(AAFwkTag::UISERVC_EXT, "Config dump after merge: %{public}s", contextConfig->GetName().c_str()); + } + ConfigurationUpdated(); +} + +void JsUIServiceExtension::ConfigurationUpdated() +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "called."); + HandleScope handleScope(jsRuntime_); + napi_env env = jsRuntime_.GetNapiEnv(); + + // Notify extension context + auto fullConfig = GetContext()->GetConfiguration(); + if (!fullConfig) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "configuration is nullptr."); + return; + } + + napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig); + CallObjectMethod("onConfigurationUpdate", &napiConfiguration, ARGC_ONE); + JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, fullConfig); +} + +void JsUIServiceExtension::ListenWMS() +{ +#ifdef SUPPORT_GRAPHICS + TAG_LOGD(AAFwkTag::UISERVC_EXT, "RegisterDisplayListener"); + auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get SaMgr."); + return; + } + + auto jsUIServiceExtension = std::static_pointer_cast(shared_from_this()); + displayListener_ = sptr::MakeSptr(jsUIServiceExtension); + if (displayListener_ == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to create display listener."); + return; + } + + auto listener = sptr::MakeSptr(displayListener_); + if (listener == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to create status change listener."); + return; + } + + auto ret = abilityManager->SubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, listener); + if (ret != 0) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "subscribe system ability failed, ret = %{public}d.", ret); + } +#endif +} + +#ifdef SUPPORT_GRAPHICS +void JsUIServiceExtension::OnCreate(Rosen::DisplayId displayId) +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "enter."); +} + +void JsUIServiceExtension::OnDestroy(Rosen::DisplayId displayId) +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "exit."); +} + +void JsUIServiceExtension::OnChange(Rosen::DisplayId displayId) +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "displayId: %{public}" PRIu64"", displayId); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Context is invalid."); + return; + } + + auto contextConfig = context->GetConfiguration(); + if (contextConfig == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "Configuration is invalid."); + return; + } + + TAG_LOGD(AAFwkTag::UISERVC_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str()); + bool configChanged = false; + auto configUtils = std::make_shared(); + configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), configChanged); + TAG_LOGD(AAFwkTag::UISERVC_EXT, "Config dump after update: %{public}s", contextConfig->GetName().c_str()); + + if (configChanged) { + auto jsUIServiceExtension = std::static_pointer_cast(shared_from_this()); + auto task = [jsUIServiceExtension]() { + if (jsUIServiceExtension) { + jsUIServiceExtension->ConfigurationUpdated(); + } + }; + if (handler_ != nullptr) { + handler_->PostTask(task, "JsServiceExtension:OnChange"); + } + } + + TAG_LOGD(AAFwkTag::UISERVC_EXT, "finished."); +} + +#endif +} +} // OHOS diff --git a/frameworks/native/ability/native/ui_service_extension_ability/ui_service_extension.cpp b/frameworks/native/ability/native/ui_service_extension_ability/ui_service_extension.cpp new file mode 100644 index 0000000000..95bd881391 --- /dev/null +++ b/frameworks/native/ability/native/ui_service_extension_ability/ui_service_extension.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed 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 "ui_service_extension.h" + +#include +#include + +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "ability_delegator_registry.h" +#include "napi_common_util.h" +#include "runtime.h" +#include "js_runtime_utils.h" +#include "js_ui_service_extension.h" +#include "napi_common_configuration.h" +#include "napi_common_want.h" +#include "napi_remote_object.h" +#include "ui_service_extension_context.h" +#include "time_util.h" + + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; + +UIServiceExtension* UIServiceExtension::Create(const std::unique_ptr& runtime) +{ + if (!runtime) { + return new UIServiceExtension(); + } + TAG_LOGD(AAFwkTag::UISERVC_EXT, "UIServiceExtension Create runtime"); + switch (runtime->GetLanguage()) { + case Runtime::Language::JS: + return JsUIServiceExtension::Create(runtime); + + default: + return new UIServiceExtension(); + } +} + +void UIServiceExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, + const sptr &token) +{ + TAG_LOGD(AAFwkTag::UISERVC_EXT, "UIExtension begin init"); + ExtensionBase::Init(record, application, handler, token); +} + +std::shared_ptr UIServiceExtension::CreateAndInitContext( + const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, + const sptr &token) +{ + std::shared_ptr context = + ExtensionBase::CreateAndInitContext(record, application, handler, token); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "UIServiceExtension CreateAndInitContext context is nullptr"); + return context; + } + return context; +} +} +} diff --git a/frameworks/native/ability/native/ui_service_extension_ability/ui_service_extension_module_loader.cpp b/frameworks/native/ability/native/ui_service_extension_ability/ui_service_extension_module_loader.cpp new file mode 100644 index 0000000000..780dfa010a --- /dev/null +++ b/frameworks/native/ability/native/ui_service_extension_ability/ui_service_extension_module_loader.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed 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 "ui_service_extension_module_loader.h" +#include "ui_service_extension.h" + +namespace OHOS::AbilityRuntime { +UIServiceExtensionModuleLoader::UIServiceExtensionModuleLoader() = default; +UIServiceExtensionModuleLoader::~UIServiceExtensionModuleLoader() = default; + +Extension *UIServiceExtensionModuleLoader::Create(const std::unique_ptr& runtime) const +{ + return UIServiceExtension::Create(runtime); +} + +std::map UIServiceExtensionModuleLoader::GetParams() +{ + std::map params; + // type means extension type in ExtensionAbilityType of extension_ability_info.h, 269 means uiService. + params.insert(std::pair("type", "269")); + // extension name + params.insert(std::pair("name", "UIServiceExtensionAbility")); + return params; +} + +extern "C" __attribute__((visibility("default"))) void* OHOS_EXTENSION_GetExtensionModule() +{ + return &UIServiceExtensionModuleLoader::GetInstance(); +} +} // namespace OHOS::AbilityRuntime diff --git a/interfaces/kits/native/ability/native/ui_service_extension_ability/js_ui_service_extension.h b/interfaces/kits/native/ability/native/ui_service_extension_ability/js_ui_service_extension.h new file mode 100644 index 0000000000..bed4cc7601 --- /dev/null +++ b/interfaces/kits/native/ability/native/ui_service_extension_ability/js_ui_service_extension.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed 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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_JS_UI_SERVICE_EXTENSION_H +#define OHOS_ABILITY_RUNTIME_JS_UI_SERVICE_EXTENSION_H + +#include "ui_service_extension.h" +#include "configuration.h" +#include "ability_info.h" +#include "ui_service_extension_context.h" +#ifdef SUPPORT_GRAPHICS +#include "display_manager.h" +#include "system_ability_status_change_stub.h" +#include "js_window_stage.h" +#include "window_option.h" +#endif +#include "ui_service_extension.h" + +class NativeReference; + +namespace OHOS { +namespace AbilityRuntime { +class UIServiceExtension; +class Runtime; +class UIServiceExtensionContext; +class JsUIServiceExtension; + +/** + * @brief Basic service components. + */ +class JsUIServiceExtension : public UIServiceExtension { +public: + explicit JsUIServiceExtension(JsRuntime& jsRuntime); + virtual ~JsUIServiceExtension() override; + + /** + * @brief Create JsServiceExtension. + * + * @param runtime The runtime. + * @return The JsServiceExtension instance. + */ + static JsUIServiceExtension* Create(const std::unique_ptr& runtime); + + /** + * @brief Init the extension. + * + * @param record the extension record. + * @param application the application info. + * @param handler the extension handler. + * @param token the remote token. + */ + virtual void Init(const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, + const sptr &token) override; + + /** + * @brief Called when this extension is started. You must override this function if you want to perform some + * initialization operations during extension startup. + * + * This function can be called only once in the entire lifecycle of an extension. + * @param Want Indicates the {@link Want} structure containing startup information about the extension. + */ + virtual void OnStart(const AAFwk::Want &want) override; + + /** + * @brief Called when this extension enters the STATE_STOP state. + * + * The extension in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + */ + virtual void OnStop() override; + + /** + * @brief Called when this Service extension is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information about the Service extension. + * @param callbackInfo Indicates the lifecycle transaction callback information + * @param isAsyncCallback Indicates whether it is an asynchronous lifecycle callback + * @return Returns a pointer to the sid of the connected Service extension. + */ + virtual sptr OnConnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo> *callbackInfo, bool &isAsyncCallback) override; + + /** + * @brief Called when all abilities connected to this Service extension are disconnected. + * + * You can override this function to implement your own processing logic. + * @param callbackInfo Indicates the lifecycle transaction callback information + * @param isAsyncCallback Indicates whether it is an asynchronous lifecycle callback + */ + virtual void OnDisconnect(const AAFwk::Want &want, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, + bool &isAsyncCallback) override; + + /** + * @brief Called back when Service is started. + * This method can be called only by Service. You can use the StartAbility(ohos.aafwk.content.Want) method to start + * Service. Then the system calls back the current method to use the transferred want parameter to execute its own + * logic. + * + * @param want Indicates the want of Service to start. + * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * @param startId Indicates the number of times the Service extension has been started. The startId is incremented + * by 1 every time the extension is started. For example, if the extension has been started for six times, the + * value of startId is 6. + */ + virtual void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; + + /** + * @brief Called when the system configuration is updated. + * + * @param configuration Indicates the updated configuration information. + */ + void OnConfigurationUpdated(const AppExecFwk::Configuration& configuration) override; + + /** + * @brief Called when configuration changed, including system configuration and window configuration. + * + */ + void ConfigurationUpdated(); + +protected: + bool showOnLockScreen_ = false; + +private: + napi_value CallObjectMethod(const char* name, napi_value const *argv = nullptr, size_t argc = 0); + + void BindContext(napi_env env, napi_value obj); + + void GetSrcPath(std::string& srcPath); + + void ListenWMS(); + + JsRuntime& jsRuntime_; + std::unique_ptr jsObj_; + std::shared_ptr aContext_ = nullptr; + std::shared_ptr shellContextRef_ = nullptr; + std::shared_ptr handler_ = nullptr; + +#ifdef SUPPORT_GRAPHICS +protected: + class JsUIServiceExtensionDisplayListener : public Rosen::DisplayManager::IDisplayListener { + public: + explicit JsUIServiceExtensionDisplayListener(const std::weak_ptr& jsUIServiceExtension) + { + jsUIServiceExtension_ = jsUIServiceExtension; + } + + void OnCreate(Rosen::DisplayId displayId) override + { + auto ptrJsUIServiceExtension = jsUIServiceExtension_.lock(); + if (ptrJsUIServiceExtension != nullptr) { + ptrJsUIServiceExtension->OnCreate(displayId); + } + } + + void OnDestroy(Rosen::DisplayId displayId) override + { + auto ptrJsUIServiceExtension = jsUIServiceExtension_.lock(); + if (ptrJsUIServiceExtension != nullptr) { + ptrJsUIServiceExtension->OnDestroy(displayId); + } + } + + void OnChange(Rosen::DisplayId displayId) override + { + auto ptrJsUIServiceExtension = jsUIServiceExtension_.lock(); + if (ptrJsUIServiceExtension != nullptr) { + ptrJsUIServiceExtension->OnChange(displayId); + } + } + + private: + std::weak_ptr jsUIServiceExtension_; + }; + + void OnCreate(Rosen::DisplayId displayId); + void OnDestroy(Rosen::DisplayId displayId); + void OnChange(Rosen::DisplayId displayId); + +private: + class SystemAbilityStatusChangeListener : public OHOS::SystemAbilityStatusChangeStub { + public: + SystemAbilityStatusChangeListener(sptr displayListener) + : tmpDisplayListener_(displayListener) {}; + virtual void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override; + virtual void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override {} + + private: + sptr tmpDisplayListener_ = nullptr; + }; + + sptr displayListener_ = nullptr; +#endif +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_JS_SERVICE_EXTENSION_H diff --git a/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension.h b/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension.h new file mode 100644 index 0000000000..0db425eb8d --- /dev/null +++ b/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed 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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_UI_SERVICE_EXTENSION_H +#define OHOS_ABILITY_RUNTIME_UI_SERVICE_EXTENSION_H + +#include "extension_base.h" +#include "freeze_util.h" +#include "js_runtime.h" +#include "context/context.h" + +namespace OHOS { +namespace AbilityRuntime { +class UIServiceExtensionContext; +class Runtime; +using AbilityHandler = AppExecFwk::AbilityHandler; +using OHOSApplication = AppExecFwk::OHOSApplication; + +/** + * @brief Basic ui extension components. + */ +class UIServiceExtension : public ExtensionBase { +public: + UIServiceExtension() = default; + virtual ~UIServiceExtension() = default; + + /** + * @brief Create and init context. + * + * @param record the ui service extension record. + * @param application the application info. + * @param handler the ui service extension handler. + * @param token the remote token. + * @return The created context. + */ + virtual std::shared_ptr CreateAndInitContext( + const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, + const sptr &token) override; + + /** + * @brief Init the ui service extension. + * + * @param record the ui service extension record. + * @param application the application info. + * @param handler the ui service extension handler. + * @param token the remote token. + */ + virtual void Init(const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, + const sptr &token) override; + + /** + * @brief Create ui service extension. + * + * @param runtime The runtime. + * @return The ui service extension instance. + */ + static UIServiceExtension* Create(const std::unique_ptr& runtime); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_UI_SERVICE_EXTENSION_H diff --git a/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension_module_loader.h b/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension_module_loader.h new file mode 100644 index 0000000000..4d7b5ec255 --- /dev/null +++ b/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension_module_loader.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed 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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_UI_SERVICE_EXTENSION_MODULE_LOADER_H +#define OHOS_ABILITY_RUNTIME_UI_SERVICE_EXTENSION_MODULE_LOADER_H + +#include "extension_module_loader.h" + +namespace OHOS::AbilityRuntime { +class UIServiceExtensionModuleLoader : public ExtensionModuleLoader, public Singleton { + DECLARE_SINGLETON(UIServiceExtensionModuleLoader); + +public: + /** + * @brief Create Extension. + * + * @param runtime The runtime. + * @return The Extension instance. + */ + virtual Extension *Create(const std::unique_ptr& runtime) const override; + + virtual std::map GetParams() override; +}; +} +#endif // OHOS_ABILITY_RUNTIME_UI_SERVICE_EXTENSION_MODULE_LOADER_H diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 2c240468b4..83e2d87f6e 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -8970,9 +8970,11 @@ int AbilityManagerService::CheckCallOtherExtensionPermission(const AbilityReques if (AAFwk::UIExtensionUtils::IsUIExtension(extensionType)) { return CheckUIExtensionPermission(abilityRequest); } - if (extensionType == AppExecFwk::ExtensionAbilityType::VPN) { + if (extensionType == AppExecFwk::ExtensionAbilityType::VPN || + extensionType == AppExecFwk::ExtensionAbilityType::UI_SERVICE) { return ERR_OK; } + const std::string fileAccessPermission = "ohos.permission.FILE_ACCESS_MANAGER"; if (extensionType == AppExecFwk::ExtensionAbilityType::FILEACCESS_EXTENSION && AAFwk::PermissionVerification::GetInstance()->VerifyCallingPermission(fileAccessPermission)) { diff --git a/services/common/include/hilog_tag_wrapper.h b/services/common/include/hilog_tag_wrapper.h index 03aa9c5ef9..8108f4707c 100644 --- a/services/common/include/hilog_tag_wrapper.h +++ b/services/common/include/hilog_tag_wrapper.h @@ -77,6 +77,7 @@ enum class AAFwkLogTag : uint32_t { UI_EXT, ACTION_EXT, EMBEDDED_EXT, + UISERVC_EXT, WANTAGENT = DEFAULT + 0x50, // 0xD001350 AUTOFILLMGR, @@ -145,7 +146,7 @@ inline const char* GetDomainName3(AAFwkLogTag tag) inline const char* GetDomainName4(AAFwkLogTag tag) { const char* tagNames[] = { "AAFwkExt", "AAFwkAutoFillExt", "AAFwkServiceExt", "AAFwkFormExt", "AAFwkShareExt", - "AAFwkUIExt", "AAFwkActionExt", "AAFwkEmbeddedExt" }; + "AAFwkUIExt", "AAFwkActionExt", "AAFwkEmbeddedExt", "AAFwkUIServiceExt" }; uint32_t offset = GetOffset(tag, AAFwkLogTag::EXT); if (offset >= sizeof(tagNames) / sizeof(const char*)) { return "AAFwkUN";