• 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 "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]), &paramType);
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