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