• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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]), &paramType);
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