1 /*
2 * Copyright (c) 2022 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 "app_recovery_api.h"
17
18 #include "app_recovery.h"
19 #include "hilog_wrapper.h"
20 #include "js_runtime.h"
21 #include "js_runtime_utils.h"
22
23 #include "napi/native_api.h"
24 #include "napi/native_common.h"
25 #include "napi/native_node_api.h"
26
27 #include "napi_common_want.h"
28 #include "recovery_param.h"
29 #include "want.h"
30
31 namespace OHOS {
32 namespace AbilityRuntime {
33 using namespace OHOS::AppExecFwk;
34 namespace {
35 enum RestartErrno {
36 NO_ERROR,
37 SAVED_STATE_NOT_EXIST,
38 LAST_RESTART_ENCOUNTER_ERROR,
39 };
40 class AppRecoveryApiRegistry {
41 public:
42 AppRecoveryApiRegistry() = default;
43 ~AppRecoveryApiRegistry() = default;
44
Finalizer(NativeEngine * engine,void * data,void * hint)45 static void Finalizer(NativeEngine *engine, void *data, void *hint)
46 {
47 std::unique_ptr<AppRecoveryApiRegistry>(static_cast<AppRecoveryApiRegistry*>(data));
48 }
49
EnableAppRecovery(NativeEngine * engine,NativeCallbackInfo * info)50 static NativeValue *EnableAppRecovery(NativeEngine *engine, NativeCallbackInfo *info)
51 {
52 AppRecoveryApiRegistry *me = CheckParamsAndGetThis<AppRecoveryApiRegistry>(engine, info);
53 return (me != nullptr) ? me->OnEnableAppRecovery(*engine, *info) : nullptr;
54 }
55
RestartApp(NativeEngine * engine,NativeCallbackInfo * info)56 static NativeValue *RestartApp(NativeEngine *engine, NativeCallbackInfo *info)
57 {
58 AppRecoveryApiRegistry *me = CheckParamsAndGetThis<AppRecoveryApiRegistry>(engine, info);
59 return (me != nullptr) ? me->OnRestartApp(*engine, *info) : nullptr;
60 }
61
SaveAppState(NativeEngine * engine,NativeCallbackInfo * info)62 static NativeValue *SaveAppState(NativeEngine *engine, NativeCallbackInfo *info)
63 {
64 AppRecoveryApiRegistry *me = CheckParamsAndGetThis<AppRecoveryApiRegistry>(engine, info);
65 return (me != nullptr) ? me->OnSaveAppState(*engine, *info) : nullptr;
66 }
67
SetRestartWant(NativeEngine * engine,NativeCallbackInfo * info)68 static NativeValue *SetRestartWant(NativeEngine *engine, NativeCallbackInfo *info)
69 {
70 AppRecoveryApiRegistry *me = CheckParamsAndGetThis<AppRecoveryApiRegistry>(engine, info);
71 return (me != nullptr) ? me->OnSetRestartWant(*engine, *info) : nullptr;
72 }
73
74 private:
OnEnableAppRecovery(NativeEngine & engine,NativeCallbackInfo & info)75 NativeValue *OnEnableAppRecovery(NativeEngine &engine, NativeCallbackInfo &info)
76 {
77 size_t parameterCount = info.argc;
78 NativeValue* result = engine.CreateUndefined();
79 constexpr int maxCount = 3;
80 if (parameterCount > maxCount) {
81 return result;
82 }
83
84 uint16_t flags[] = {
85 RestartFlag::ALWAYS_RESTART,
86 SaveOccasionFlag::SAVE_WHEN_ERROR,
87 SaveModeFlag::SAVE_WITH_FILE
88 };
89
90 for (size_t i = 0; i < parameterCount; ++i) {
91 napi_valuetype paramType;
92 napi_typeof(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(info.argv[i]), ¶mType);
93 if (paramType != napi_number) {
94 HILOG_ERROR("AppRecoveryApi info.argv[%{public}s] type isn't number", std::to_string(i).c_str());
95 return result;
96 }
97 int32_t tmp = 0;
98 napi_get_value_int32(reinterpret_cast<napi_env>(&engine),
99 reinterpret_cast<napi_value>(info.argv[i]), &tmp);
100 flags[i] = static_cast<uint16_t>(tmp);
101 }
102
103 if (!CheckParamsValid(flags)) {
104 return result;
105 }
106
107 AppRecovery::GetInstance().EnableAppRecovery(flags[0], // 0:RestartFlag
108 flags[1], // 1:SaveOccasionFlag
109 flags[2]); // 2:SaveModeFlag
110 return result;
111 }
112
CheckParamsValid(const uint16_t params[])113 bool CheckParamsValid(const uint16_t params[])
114 {
115 uint16_t restartFlag = params[0];
116 constexpr uint16_t restartMaxVal = 0x0003;
117 if ((restartFlag < 0 || restartFlag > restartMaxVal) && (restartFlag != RestartFlag::NO_RESTART)) {
118 HILOG_ERROR("AppRecoveryApi CheckParamsValid restartFlag: %{public}d is Invalid", restartFlag);
119 return false;
120 }
121 uint16_t saveFlag = params[1];
122 constexpr uint16_t saveMaxVal = 0x0003;
123 if (saveFlag < SaveOccasionFlag::SAVE_WHEN_ERROR || saveFlag > saveMaxVal) {
124 HILOG_ERROR("AppRecoveryApi CheckParamsValid SaveOccasionFlag: %{public}d is Invalid", saveFlag);
125 return false;
126 }
127 uint16_t saveModeFlag = params[2];
128 if (saveModeFlag < SaveModeFlag::SAVE_WITH_FILE || saveModeFlag > SaveModeFlag::SAVE_WITH_SHARED_MEMORY) {
129 HILOG_ERROR("AppRecoveryApi CheckParamsValid saveModeFlag: %{public}d is Invalid", saveModeFlag);
130 return false;
131 }
132 return true;
133 }
134
OnSaveAppState(NativeEngine & engine,const NativeCallbackInfo & info)135 NativeValue *OnSaveAppState(NativeEngine &engine, const NativeCallbackInfo &info)
136 {
137 if (info.argc > 1) {
138 HILOG_ERROR("AppRecoveryApi SaveAppState Incorrect number of parameters");
139 return engine.CreateBoolean(false);
140 }
141 uintptr_t ability = 0;
142 if (info.argc == 1) {
143 NativeValue* value = reinterpret_cast<NativeValue*>(info.argv[0]);
144 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
145 if (obj == nullptr) {
146 HILOG_ERROR("AppRecoveryApi Invalid abilityContext.");
147 return engine.CreateBoolean(false);
148 }
149 ability = reinterpret_cast<uintptr_t>(obj->GetNativePointer());
150 }
151 if (AppRecovery::GetInstance().ScheduleSaveAppState(StateReason::DEVELOPER_REQUEST, ability)) {
152 return engine.CreateBoolean(true);
153 }
154 return engine.CreateBoolean(false);
155 }
156
OnRestartApp(NativeEngine & engine,const NativeCallbackInfo & info)157 NativeValue *OnRestartApp(NativeEngine &engine, const NativeCallbackInfo &info)
158 {
159 if (info.argc != 0) {
160 HILOG_ERROR("AppRecoveryApi OnRestartApp Incorrect number of parameters");
161 return engine.CreateUndefined();
162 }
163
164 AppRecovery::GetInstance().ScheduleRecoverApp(StateReason::DEVELOPER_REQUEST);
165 return engine.CreateUndefined();
166 }
167
OnSetRestartWant(NativeEngine & engine,const NativeCallbackInfo & info)168 NativeValue *OnSetRestartWant(NativeEngine &engine, const NativeCallbackInfo &info)
169 {
170 if (info.argc != 1) {
171 HILOG_ERROR("AppRecoveryApi OnSetRestartWant Incorrect number of parameters");
172 return engine.CreateUndefined();
173 }
174 std::shared_ptr<AAFwk::Want> want = std::make_shared<AAFwk::Want>();
175 OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
176 reinterpret_cast<napi_value>(info.argv[0]), *(want.get()));
177 AppRecovery::GetInstance().SetRestartWant(want);
178 return engine.CreateUndefined();
179 }
180 };
181 } // namespace
182
AppRecoveryRestartFlagInit(NativeEngine * engine)183 NativeValue *AppRecoveryRestartFlagInit(NativeEngine *engine)
184 {
185 if (engine == nullptr) {
186 HILOG_ERROR("AppRecoveryRestartFlagInit Invalid input parameters");
187 return nullptr;
188 }
189
190 NativeValue *objValue = engine->CreateObject();
191 NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
192
193 if (object == nullptr) {
194 HILOG_ERROR("AppRecoveryRestartFlagInit Failed to get object");
195 return nullptr;
196 }
197
198 object->SetProperty("ALWAYS_RESTART", CreateJsValue(*engine, RestartFlag::ALWAYS_RESTART));
199 object->SetProperty("RESTART_WHEN_JS_CRASH", CreateJsValue(*engine, RestartFlag::RESTART_WHEN_JS_CRASH));
200 object->SetProperty("RESTART_WHEN_APP_FREEZE", CreateJsValue(*engine, RestartFlag::RESTART_WHEN_APP_FREEZE));
201 object->SetProperty("NO_RESTART", CreateJsValue(*engine, RestartFlag::NO_RESTART));
202 return objValue;
203 }
204
AppRecoveryStateSaveFlagInit(NativeEngine * engine)205 NativeValue *AppRecoveryStateSaveFlagInit(NativeEngine *engine)
206 {
207 if (engine == nullptr) {
208 HILOG_ERROR("AppRecoveryStateSaveFlagInit Invalid input parameters");
209 return nullptr;
210 }
211
212 NativeValue *objValue = engine->CreateObject();
213 NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
214
215 if (object == nullptr) {
216 HILOG_ERROR("AppRecoveryStateSaveFlagInit Failed to get object");
217 return nullptr;
218 }
219
220 object->SetProperty("NONE", CreateJsValue(*engine, SaveOccasionFlag::NO_SAVE));
221 object->SetProperty("SAVE_WHEN_ERROR", CreateJsValue(*engine, SaveOccasionFlag::SAVE_WHEN_ERROR));
222 object->SetProperty("SAVE_WHEN_BACKGROUND", CreateJsValue(*engine, SaveOccasionFlag::SAVE_WHEN_BACKGROUND));
223 return objValue;
224 }
225
AppRecoverySaveModeFlagInit(NativeEngine * engine)226 NativeValue *AppRecoverySaveModeFlagInit(NativeEngine *engine)
227 {
228 if (engine == nullptr) {
229 HILOG_ERROR("AppRecoverySaveModeFlagInit Invalid input parameters");
230 return nullptr;
231 }
232
233 NativeValue *objValue = engine->CreateObject();
234 NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
235
236 if (object == nullptr) {
237 HILOG_ERROR("AppRecoverySaveModeFlagInit Failed to get object");
238 return nullptr;
239 }
240
241 object->SetProperty("SAVE_WITH_FILE", CreateJsValue(*engine, SaveModeFlag::SAVE_WITH_FILE));
242 object->SetProperty("SAVE_WITH_SHARED_MEMORY", CreateJsValue(*engine, SaveModeFlag::SAVE_WITH_SHARED_MEMORY));
243 return objValue;
244 }
245
InitAppRecoveryApiModule(NativeEngine * engine,NativeValue * exportObj)246 NativeValue *InitAppRecoveryApiModule(NativeEngine *engine, NativeValue *exportObj)
247 {
248 if (engine == nullptr || exportObj == nullptr) {
249 HILOG_ERROR("AppRecovery API Invalid input parameters");
250 return nullptr;
251 }
252
253 NativeObject *object = ConvertNativeValueTo<NativeObject>(exportObj);
254 if (object == nullptr) {
255 HILOG_ERROR("AppRecovery API Failed to get object");
256 return nullptr;
257 }
258
259 std::unique_ptr<AppRecoveryApiRegistry> appRecoveryApi = std::make_unique<AppRecoveryApiRegistry>();
260 object->SetNativePointer(appRecoveryApi.release(), AppRecoveryApiRegistry::Finalizer, nullptr);
261
262 const char *moduleName = "AppRecovery";
263 BindNativeFunction(*engine, *object, "enableAppRecovery", moduleName, AppRecoveryApiRegistry::EnableAppRecovery);
264 BindNativeFunction(*engine, *object, "restartApp", moduleName, AppRecoveryApiRegistry::RestartApp);
265 BindNativeFunction(*engine, *object, "saveAppState", moduleName, AppRecoveryApiRegistry::SaveAppState);
266 BindNativeFunction(*engine, *object, "setRestartWant", moduleName, AppRecoveryApiRegistry::SetRestartWant);
267
268 object->SetProperty("RestartFlag", AppRecoveryRestartFlagInit(engine));
269 object->SetProperty("SaveOccasionFlag", AppRecoveryStateSaveFlagInit(engine));
270 object->SetProperty("SaveModeFlag", AppRecoverySaveModeFlagInit(engine));
271
272 return engine->CreateUndefined();
273 }
274 } // namespace AbilityRuntime
275 } // namespace OHOS