1 /*
2 * Copyright (c) 2024 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 "cj_application_context_ffi.h"
17
18 #include "ability_delegator_registry.h"
19 #include "ability_manager_errors.h"
20 #include "application_context.h"
21 #include "cj_ability_runtime_error.h"
22 #include "cj_application_context.h"
23 #include "cj_lambda.h"
24 #include "cj_utils_ffi.h"
25 #include "hilog_tag_wrapper.h"
26 #include "running_process_info.h"
27 #include "js_application_context_utils.h"
28
29 namespace OHOS {
30 namespace ApplicationContextCJ {
31 using namespace OHOS::FFI;
32 using namespace OHOS::AbilityRuntime;
33
34 extern "C" {
FFIGetArea(int64_t id)35 int64_t FFIGetArea(int64_t id)
36 {
37 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
38 if (context == nullptr) {
39 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
40 return INVALID_CODE;
41 }
42 return context->GetArea();
43 }
44
FFICJApplicationInfo(int64_t id)45 CApplicationInfo *FFICJApplicationInfo(int64_t id)
46 {
47 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
48 if (context == nullptr) {
49 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
50 return nullptr;
51 }
52 auto appInfo = context->GetApplicationInfo();
53 CApplicationInfo *buffer = static_cast<CApplicationInfo *>(malloc(sizeof(CApplicationInfo)));
54 if (buffer == nullptr) {
55 TAG_LOGE(AAFwkTag::CONTEXT, "malloc appinfo fail");
56 return nullptr;
57 }
58 buffer->name = CreateCStringFromString(appInfo->name);
59 buffer->bundleName = CreateCStringFromString(appInfo->bundleName);
60 return buffer;
61 }
62
FfiCJApplicationContextOnOnEnvironment(int64_t id,void (* cfgCallback)(CConfiguration),void (* memCallback)(int32_t),int32_t * errCode)63 int32_t FfiCJApplicationContextOnOnEnvironment(int64_t id, void (*cfgCallback)(CConfiguration),
64 void (*memCallback)(int32_t), int32_t *errCode)
65 {
66 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
67 if (context == nullptr) {
68 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
69 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
70 return -1;
71 }
72 return context->OnOnEnvironment(cfgCallback, memCallback, false, errCode);
73 }
74
FfiCJApplicationContextOnOnAbilityLifecycle(int64_t id,CArrI64 cFuncIds,int32_t * errCode)75 int32_t FfiCJApplicationContextOnOnAbilityLifecycle(int64_t id, CArrI64 cFuncIds, int32_t *errCode)
76 {
77 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
78 if (context == nullptr) {
79 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
80 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
81 return -1;
82 }
83 return context->OnOnAbilityLifecycle(cFuncIds, false, errCode);
84 }
85
FfiCJApplicationContextOnOnApplicationStateChange(int64_t id,void (* foregroundCallback)(void),void (* backgroundCallback)(void),int32_t * errCode)86 int32_t FfiCJApplicationContextOnOnApplicationStateChange(int64_t id, void (*foregroundCallback)(void),
87 void (*backgroundCallback)(void), int32_t *errCode)
88 {
89 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
90 if (context == nullptr) {
91 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
92 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
93 return -1;
94 }
95 return context->OnOnApplicationStateChange(foregroundCallback, backgroundCallback, errCode);
96 }
97
FfiCJApplicationContextOnOff(int64_t id,const char * type,int32_t callbackId,int32_t * errCode)98 void FfiCJApplicationContextOnOff(int64_t id, const char *type, int32_t callbackId, int32_t *errCode)
99 {
100 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
101 if (context == nullptr) {
102 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
103 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
104 return;
105 }
106 auto typeString = std::string(type);
107 if (typeString == "environment") {
108 return context->OnOffEnvironment(callbackId, errCode);
109 }
110 if (typeString == "abilityLifecycle") {
111 return context->OnOffAbilityLifecycle(callbackId, errCode);
112 }
113 if (typeString == "applicationStateChange") {
114 return context->OnOffApplicationStateChange(callbackId, errCode);
115 }
116 TAG_LOGE(AAFwkTag::CONTEXT, "off function type not match");
117 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
118 return;
119 }
120
FfiCJApplicationContextSetFont(int64_t id,const char * font,int32_t * errCode)121 void FfiCJApplicationContextSetFont(int64_t id, const char *font, int32_t *errCode)
122 {
123 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
124 if (context == nullptr) {
125 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
126 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
127 return;
128 }
129 auto fontString = std::string(font);
130 context->OnSetFont(fontString);
131 }
132
FfiCJApplicationContextSetLanguage(int64_t id,const char * language,int32_t * errCode)133 void FfiCJApplicationContextSetLanguage(int64_t id, const char *language, int32_t *errCode)
134 {
135 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
136 if (context == nullptr) {
137 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
138 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
139 return;
140 }
141 auto languageString = std::string(language);
142 context->OnSetLanguage(languageString);
143 }
144
FfiCJApplicationContextSetColorMode(int64_t id,int32_t colorMode,int32_t * errCode)145 void FfiCJApplicationContextSetColorMode(int64_t id, int32_t colorMode, int32_t *errCode)
146 {
147 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
148 if (context == nullptr) {
149 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
150 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
151 return;
152 }
153 context->OnSetColorMode(colorMode);
154 }
155
ConvertToJsAppProcessState(const AppExecFwk::AppProcessState & appProcessState,const bool & isFocused)156 CjAppProcessState ConvertToJsAppProcessState(const AppExecFwk::AppProcessState &appProcessState, const bool &isFocused)
157 {
158 CjAppProcessState processState;
159 switch (appProcessState) {
160 case AppExecFwk::AppProcessState::APP_STATE_CREATE:
161 case AppExecFwk::AppProcessState::APP_STATE_READY:
162 processState = STATE_CREATE;
163 break;
164 case AppExecFwk::AppProcessState::APP_STATE_FOREGROUND:
165 processState = isFocused ? STATE_ACTIVE : STATE_FOREGROUND;
166 break;
167 case AppExecFwk::AppProcessState::APP_STATE_BACKGROUND:
168 processState = STATE_BACKGROUND;
169 break;
170 case AppExecFwk::AppProcessState::APP_STATE_TERMINATED:
171 case AppExecFwk::AppProcessState::APP_STATE_END:
172 processState = STATE_DESTROY;
173 break;
174 default:
175 TAG_LOGE(AAFwkTag::CONTEXT, "Process state is invalid.");
176 processState = STATE_DESTROY;
177 break;
178 }
179 return processState;
180 }
181
FfiCJApplicationContextGetRunningProcessInformation(int64_t id,int32_t * errCode)182 CArrProcessInformation FfiCJApplicationContextGetRunningProcessInformation(int64_t id, int32_t *errCode)
183 {
184 CArrProcessInformation cArrProcessInformation = {.head = nullptr, .size = 0};
185 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
186 if (context == nullptr) {
187 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
188 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
189 return cArrProcessInformation;
190 }
191 auto processInfo = context->OnGetRunningProcessInformation(errCode);
192 if (*errCode != ERR_OK) {
193 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INTERNAL_ERROR;
194 return cArrProcessInformation;
195 }
196
197 CProcessInformation *head = static_cast<CProcessInformation *>(malloc(sizeof(CProcessInformation)));
198 if (head == nullptr) {
199 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INTERNAL_ERROR;
200 return cArrProcessInformation;
201 }
202 head->processName = CreateCStringFromString(processInfo->processName_);
203 head->pid = processInfo->pid_;
204 head->uid = processInfo->uid_;
205 head->bundleNames.head = VectorToCArrString(processInfo->bundleNames);
206 head->bundleNames.size = (processInfo->bundleNames).size();
207 head->state = ConvertToJsAppProcessState(processInfo->state_, processInfo->isFocused);
208 head->bundleType = processInfo->bundleType;
209 head->appCloneIndex = processInfo->appCloneIndex;
210 cArrProcessInformation.size = 1;
211 cArrProcessInformation.head = head;
212 return cArrProcessInformation;
213 }
214
FfiCJApplicationContextKillAllProcesses(int64_t id,bool clearPageStack,int32_t * errCode)215 void FfiCJApplicationContextKillAllProcesses(int64_t id, bool clearPageStack, int32_t *errCode)
216 {
217 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
218 if (context == nullptr) {
219 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
220 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
221 return;
222 }
223 context->OnKillProcessBySelf(clearPageStack, errCode);
224 }
225
FfiCJApplicationContextGetCurrentAppCloneIndex(int64_t id,int32_t * errCode)226 int32_t FfiCJApplicationContextGetCurrentAppCloneIndex(int64_t id, int32_t *errCode)
227 {
228 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
229 if (context == nullptr) {
230 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
231 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
232 return -1;
233 }
234 return context->OnGetCurrentAppCloneIndex(errCode);
235 }
236
FfiCJApplicationContextRestartApp(int64_t id,WantHandle want,int32_t * errCode)237 void FfiCJApplicationContextRestartApp(int64_t id, WantHandle want, int32_t *errCode)
238 {
239 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
240 if (context == nullptr) {
241 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
242 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
243 return;
244 }
245 auto actualWant = reinterpret_cast<AAFwk::Want *>(want);
246 if (actualWant == nullptr) {
247 TAG_LOGE(AAFwkTag::CONTEXT, "null want");
248 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
249 return;
250 }
251 return context->OnRestartApp(*actualWant, errCode);
252 }
253
FfiCJApplicationContextClearUpApplicationData(int64_t id,int32_t * errCode)254 void FfiCJApplicationContextClearUpApplicationData(int64_t id, int32_t *errCode)
255 {
256 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
257 if (context == nullptr) {
258 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
259 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
260 return;
261 }
262 return context->OnClearUpApplicationData(errCode);
263 }
264
FfiCJApplicationContextSetSupportedProcessCache(int64_t id,bool isSupported,int32_t * errCode)265 void FfiCJApplicationContextSetSupportedProcessCache(int64_t id, bool isSupported, int32_t *errCode)
266 {
267 auto context = FFI::FFIData::GetData<CJApplicationContext>(id);
268 if (context == nullptr) {
269 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
270 *errCode = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER;
271 return;
272 }
273 return context->OnSetSupportedProcessCacheSelf(isSupported, errCode);
274 }
275
FfiConvertApplicationContext2Napi(napi_env env,int64_t id)276 CJ_EXPORT napi_value FfiConvertApplicationContext2Napi(napi_env env, int64_t id)
277 {
278 napi_value undefined = nullptr;
279 napi_get_undefined(env, &undefined);
280 auto cjApplicationContext = FFIData::GetData<CJApplicationContext>(id);
281 if (cjApplicationContext == nullptr || cjApplicationContext->GetApplicationContext() == nullptr) {
282 TAG_LOGE(AAFwkTag::CONTEXT, "cj context null ptr");
283 return undefined;
284 }
285
286 napi_value result = JsApplicationContextUtils::CreateJsApplicationContext(env);
287 if (result == nullptr) {
288 TAG_LOGE(AAFwkTag::CONTEXT, "null object");
289 return undefined;
290 }
291 auto workContext = new (std::nothrow) std::weak_ptr<ApplicationContext>(
292 cjApplicationContext->GetApplicationContext());
293 if (workContext != nullptr) {
294 auto res = napi_wrap(env, result, workContext,
295 [](napi_env, void *data, void *) {
296 TAG_LOGD(AAFwkTag::APPKIT, "Finalizer for weak_ptr application context is called");
297 delete static_cast<std::weak_ptr<ApplicationContext> *>(data);
298 data = nullptr;
299 },
300 nullptr, nullptr);
301 if (res != napi_ok && workContext != nullptr) {
302 TAG_LOGE(AAFwkTag::APPKIT, "napi_wrap failed:%{public}d", res);
303 delete workContext;
304 return undefined;
305 }
306 }
307 napi_value falseValue = nullptr;
308 napi_get_boolean((napi_env)env, true, &falseValue);
309 napi_set_named_property((napi_env)env, result, "stageMode", falseValue);
310
311 return result;
312 }
313
FfiCreateApplicationContextFromNapi(napi_env env,napi_value appContext)314 CJ_EXPORT int64_t FfiCreateApplicationContextFromNapi(napi_env env, napi_value appContext)
315 {
316 if (env == nullptr || appContext == nullptr) {
317 return ERR_INVALID_INSTANCE_CODE;
318 }
319
320 napi_valuetype type;
321 if (napi_typeof(env, appContext, &type) || type != napi_object) {
322 return ERR_INVALID_INSTANCE_CODE;
323 }
324
325 std::weak_ptr<ApplicationContext>* context = nullptr;
326 napi_status status = napi_unwrap(env, appContext, reinterpret_cast<void**>(&context));
327 if (status != napi_ok) {
328 return ERR_INVALID_INSTANCE_CODE;
329 }
330
331 if (context == nullptr || (*context).lock() == nullptr) {
332 TAG_LOGE(AAFwkTag::CONTEXT, "null context");
333 return ERR_INVALID_INSTANCE_CODE;
334 }
335 auto cjContext = FFI::FFIData::Create<CJApplicationContext>((*context).lock());
336 if (cjContext == nullptr) {
337 TAG_LOGE(AAFwkTag::CONTEXT, "null cjContext");
338 return ERR_INVALID_INSTANCE_CODE;
339 }
340
341 return cjContext->GetID();
342 }
343 }
344 } // namespace ApplicationContextCJ
345 } // namespace OHOS