1 /*
2 * Copyright (c) 2021 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 "ability_info.h"
17 #include "hilog_wrapper.h"
18 #include "hitrace_meter.h"
19 #include "js_runtime.h"
20 #include "js_runtime_utils.h"
21 #include "js_wallpaper_extension_ability.h"
22 #include "js_wallpaper_extension_context.h"
23 #include "napi/native_api.h"
24 #include "napi/native_node_api.h"
25 #include "napi_common_util.h"
26 #include "napi_common_want.h"
27 #include "napi_remote_object.h"
28 #include "uv_queue.h"
29 #include "wallpaper_extension_ability_stub.h"
30 #include "wallpaper_manager.h"
31
32 namespace OHOS {
33 namespace AbilityRuntime {
34 namespace {
35 constexpr size_t ARGC_ONE = 1;
36 } // namespace
37
38 JsWallpaperExtensionAbility *JsWallpaperExtensionAbility::jsWallpaperExtensionAbility = NULL;
39 std::mutex JsWallpaperExtensionAbility::mtx;
40 using namespace OHOS::AppExecFwk;
41 using namespace OHOS::MiscServices;
Create(const std::unique_ptr<Runtime> & runtime)42 JsWallpaperExtensionAbility *JsWallpaperExtensionAbility::Create(const std::unique_ptr<Runtime> &runtime)
43 {
44 HILOG_INFO("jws JsWallpaperExtensionAbility begin Create.");
45 std::lock_guard<std::mutex> lock(mtx);
46 jsWallpaperExtensionAbility = new JsWallpaperExtensionAbility(static_cast<JsRuntime &>(*runtime));
47 return jsWallpaperExtensionAbility;
48 }
49
JsWallpaperExtensionAbility(JsRuntime & jsRuntime)50 JsWallpaperExtensionAbility::JsWallpaperExtensionAbility(JsRuntime &jsRuntime) : jsRuntime_(jsRuntime)
51 {
52 }
~JsWallpaperExtensionAbility()53 JsWallpaperExtensionAbility::~JsWallpaperExtensionAbility()
54 {
55 jsRuntime_.FreeNativeReference(std::move(jsObj_));
56 std::lock_guard<std::mutex> lock(mtx);
57 jsWallpaperExtensionAbility = nullptr;
58 }
59
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)60 void JsWallpaperExtensionAbility::Init(const std::shared_ptr<AbilityLocalRecord> &record,
61 const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
62 const sptr<IRemoteObject> &token)
63 {
64 HILOG_INFO("jws JsWallpaperExtensionAbility begin Init.");
65 WallpaperExtensionAbility::Init(record, application, handler, token);
66 std::string srcPath = "";
67 GetSrcPath(srcPath);
68 if (srcPath.empty()) {
69 HILOG_ERROR("Failed to get srcPath!");
70 return;
71 }
72 return InitMoudle(srcPath);
73 }
74
InitMoudle(std::string srcPath)75 void JsWallpaperExtensionAbility::InitMoudle(std::string srcPath)
76 {
77 std::string moduleName(Extension::abilityInfo_->moduleName);
78 moduleName.append("::").append(abilityInfo_->name);
79 HandleScope handleScope(jsRuntime_);
80 napi_env env = jsRuntime_.GetNapiEnv();
81 jsObj_ = jsRuntime_.LoadModule(
82 moduleName, srcPath, abilityInfo_->hapPath, Extension::abilityInfo_->compileMode == CompileMode::ES_MODULE);
83 if (jsObj_ == nullptr) {
84 HILOG_ERROR("Failed to get jsObj_ !");
85 return;
86 }
87 napi_value obj = jsObj_->GetNapiValue();
88 if (obj == nullptr) {
89 HILOG_ERROR("Failed to get JsWallpaperExtensionAbility object!");
90 return;
91 }
92 auto context = GetContext();
93 if (context == nullptr) {
94 HILOG_ERROR("Failed to get context!");
95 return;
96 }
97 napi_value contextObj = CreateJsWallpaperExtensionContext(env, context);
98 auto shellContextRef = jsRuntime_.LoadSystemModule("WallpaperExtensionContext", &contextObj, ARGC_ONE);
99 if (shellContextRef == nullptr) {
100 HILOG_ERROR("Failed to load system module!");
101 return;
102 }
103 contextObj = shellContextRef->GetNapiValue();
104 context->Bind(jsRuntime_, shellContextRef.release());
105 napi_set_named_property(env, obj, "context", contextObj);
106 if (contextObj == nullptr) {
107 HILOG_ERROR("Failed to get wallpaper extension native object!");
108 return;
109 }
110 auto workContext = new (std::nothrow) WallpaperExtensionContext();
111 if (workContext == nullptr) {
112 HILOG_ERROR("Failed to new workContext!");
113 return;
114 }
115 auto ret = napi_wrap(
116 env, contextObj, workContext,
117 [](napi_env, void *data, void *) { delete static_cast<AbilityRuntime::Context *>(data); }, nullptr, nullptr);
118 if (ret != napi_ok) {
119 delete workContext;
120 }
121 }
122
OnStart(const AAFwk::Want & want)123 void JsWallpaperExtensionAbility::OnStart(const AAFwk::Want &want)
124 {
125 StartAsyncTrace(HITRACE_TAG_MISC, "OnStart", static_cast<int32_t>(TraceTaskId::ONSTART_EXTENSION));
126 StartAsyncTrace(
127 HITRACE_TAG_MISC, "Extension::OnStart", static_cast<int32_t>(TraceTaskId::ONSTART_MIDDLE_EXTENSION));
128 Extension::OnStart(want);
129 FinishAsyncTrace(
130 HITRACE_TAG_MISC, "Extension::OnStart", static_cast<int32_t>(TraceTaskId::ONSTART_MIDDLE_EXTENSION));
131 HILOG_INFO("jws JsWallpaperExtensionAbility OnStart begin.");
132 HandleScope handleScope(jsRuntime_);
133 napi_env env = jsRuntime_.GetNapiEnv();
134 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
135 napi_value argv[] = { napiWant };
136 StartAsyncTrace(HITRACE_TAG_MISC, "onCreate", static_cast<int32_t>(TraceTaskId::ONCREATE_EXTENSION));
137 CallObjectMethod("onCreate", argv, ARGC_ONE);
138 FinishAsyncTrace(HITRACE_TAG_MISC, "onCreate", static_cast<int32_t>(TraceTaskId::ONCREATE_EXTENSION));
139 CallObjectMethod("createWallpaperWin");
140 RegisterWallpaperCallback();
141 HILOG_INFO("%{public}s end.", __func__);
142 FinishAsyncTrace(HITRACE_TAG_MISC, "onCreate", static_cast<int32_t>(TraceTaskId::ONSTART_EXTENSION));
143 }
144
OnStop()145 void JsWallpaperExtensionAbility::OnStop()
146 {
147 WallpaperExtensionAbility::OnStop();
148 HILOG_INFO("jws JsWallpaperExtensionAbility OnStop begin.");
149 CallObjectMethod("onDestroy");
150 bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
151 if (ret) {
152 HILOG_INFO("The wallpaper extension connection is not disconnected.");
153 }
154 }
155
OnConnect(const AAFwk::Want & want)156 sptr<IRemoteObject> JsWallpaperExtensionAbility::OnConnect(const AAFwk::Want &want)
157 {
158 HILOG_INFO("jws JsWallpaperExtensionAbility OnConnect begin.");
159 Extension::OnConnect(want);
160 auto remoteObj = new (std::nothrow) WallpaperMgrService::WallpaperExtensionAbilityStub();
161 if (remoteObj == nullptr) {
162 HILOG_ERROR("failed to create IWallpaperExtensionAbility");
163 return nullptr;
164 }
165 return remoteObj;
166 }
167
OnDisconnect(const AAFwk::Want & want)168 void JsWallpaperExtensionAbility::OnDisconnect(const AAFwk::Want &want)
169 {
170 HILOG_INFO("jws JsWallpaperExtensionAbility OnDisconnect begin.");
171 Extension::OnDisconnect(want);
172 }
173
OnCommand(const AAFwk::Want & want,bool restart,int32_t startId)174 void JsWallpaperExtensionAbility::OnCommand(const AAFwk::Want &want, bool restart, int32_t startId)
175 {
176 HILOG_INFO("jws JsWallpaperExtensionAbility OnCommand begin.");
177 Extension::OnCommand(want, restart, startId);
178 HILOG_INFO(
179 "%{public}s begin restart=%{public}s,startId=%{public}d.", __func__, restart ? "true" : "false", startId);
180 }
181
CallObjectMethod(const std::string & name,napi_value const * argv,size_t argc)182 napi_value JsWallpaperExtensionAbility::CallObjectMethod(const std::string &name, napi_value const *argv, size_t argc)
183 {
184 HILOG_INFO("jws JsWallpaperExtensionAbility::CallObjectMethod(%{public}s), begin", name.c_str());
185
186 if (!jsObj_) {
187 HILOG_WARN("Not found WallpaperExtensionAbility.js .");
188 return nullptr;
189 }
190
191 HandleScope handleScope(jsRuntime_);
192 napi_env env = jsRuntime_.GetNapiEnv();
193 napi_value obj = jsObj_->GetNapiValue();
194 if (obj == nullptr) {
195 HILOG_ERROR("Failed to get WallpaperExtensionAbility object!");
196 return nullptr;
197 }
198
199 napi_value method = nullptr;
200 napi_get_named_property(env, obj, name.c_str(), &method);
201 if (method == nullptr) {
202 HILOG_ERROR("Failed to get '%{public}s' from WallpaperExtensionAbility object", name.c_str());
203 return nullptr;
204 }
205
206 HILOG_INFO("JsWallpaperExtensionAbility::CallFunction(%{public}s) success.", name.c_str());
207 napi_value remoteNapi = nullptr;
208 napi_status status = napi_call_function(env, obj, method, argc, argv, &remoteNapi);
209 if (status != napi_ok) {
210 HILOG_ERROR("JsWallpaperExtensionAbility::CallFunction(%{public}s) failed!", name.c_str());
211 return nullptr;
212 }
213 return remoteNapi;
214 }
215
GetSrcPath(std::string & srcPath)216 void JsWallpaperExtensionAbility::GetSrcPath(std::string &srcPath)
217 {
218 HILOG_INFO("jws JsWallpaperExtensionAbility GetSrcPath begin.");
219 if (!Extension::abilityInfo_->isModuleJson) {
220 /* temporary compatibility api8 + config.json */
221 srcPath.append(Extension::abilityInfo_->package);
222 srcPath.append("/assets/js/");
223 if (!Extension::abilityInfo_->srcPath.empty()) {
224 srcPath.append(Extension::abilityInfo_->srcPath);
225 }
226 srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
227 return;
228 }
229
230 if (!Extension::abilityInfo_->srcEntrance.empty()) {
231 srcPath.append(Extension::abilityInfo_->moduleName + "/");
232 srcPath.append(Extension::abilityInfo_->srcEntrance);
233 srcPath.erase(srcPath.rfind('.'));
234 srcPath.append(".abc");
235 }
236 }
237
RegisterWallpaperCallback()238 void JsWallpaperExtensionAbility::RegisterWallpaperCallback()
239 {
240 WallpaperMgrService::WallpaperManager::GetInstance().RegisterWallpaperCallback([](int32_t wallpaperType) -> bool {
241 HILOG_INFO("jsWallpaperExtensionAbility->CallObjectMethod.");
242 std::lock_guard<std::mutex> lock(mtx);
243 if (JsWallpaperExtensionAbility::jsWallpaperExtensionAbility == nullptr) {
244 return false;
245 }
246 napi_env napiEnv = (JsWallpaperExtensionAbility::jsWallpaperExtensionAbility->jsRuntime_).GetNapiEnv();
247 WorkData *workData = new (std::nothrow) WorkData(napiEnv, nullptr, wallpaperType);
248 if (workData == nullptr) {
249 return false;
250 }
251 uv_after_work_cb afterCallback = [](uv_work_t *work, int32_t status) {
252 WorkData *workData = reinterpret_cast<WorkData *>(work->data);
253 if (workData == nullptr) {
254 delete work;
255 return;
256 }
257 napi_handle_scope scope = nullptr;
258 napi_open_handle_scope(workData->env_, &scope);
259 if (scope == nullptr) {
260 delete workData;
261 delete work;
262 return;
263 }
264 napi_value type = OHOS::AppExecFwk::WrapInt32ToJS(workData->env_, workData->wallpaperType);
265
266 napi_value arg[] = { type };
267 std::lock_guard<std::mutex> lock(mtx);
268 if (JsWallpaperExtensionAbility::jsWallpaperExtensionAbility != nullptr) {
269 JsWallpaperExtensionAbility::jsWallpaperExtensionAbility->CallObjectMethod(
270 "onWallpaperChange", arg, ARGC_ONE);
271 }
272 napi_close_handle_scope(workData->env_, scope);
273 delete workData;
274 delete work;
275 };
276 UvQueue::Call(napiEnv, workData, afterCallback);
277 return true;
278 });
279 }
280
281 } // namespace AbilityRuntime
282 } // namespace OHOS
283