1 /*
2  * Copyright (c) 2023 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 "standby_napi_module.h"
17 
18 #include <vector>
19 
20 #include "napi_base_context.h"
21 #include "singleton.h"
22 
23 #include "allow_info.h"
24 #include "allow_type.h"
25 #include "resourcce_request.h"
26 #include "standby_service_log.h"
27 #include "standby_service_client.h"
28 
29 #include "common.h"
30 
31 namespace OHOS {
32 namespace DevStandbyMgr {
33 namespace {
34 constexpr uint32_t IS_DEVICE_IN_STANDBY_MIN_PARAMS = 0;
35 constexpr uint32_t IS_DEVICE_IN_STANDBY_PARAMS = 1;
36 constexpr uint32_t GET_ALLOW_LIST_MIN_PARAMS = 1;
37 constexpr uint32_t GET_ALLOW_LIST_STANDBY_PARAMS = 2;
38 constexpr uint32_t APPLY_ALLOW_RESOURCE_PARAMS = 1;
39 }
40 
41 struct AsyncCallbackInfoIsDeviceInStandby : public AsyncWorkData {
AsyncCallbackInfoIsDeviceInStandbyOHOS::DevStandbyMgr::AsyncCallbackInfoIsDeviceInStandby42     explicit AsyncCallbackInfoIsDeviceInStandby(napi_env env) : AsyncWorkData(env) {}
43     bool isStandby {false};
44 };
45 
46 struct IsDeviceInStandbyParamsInfo {
47     napi_ref callback = nullptr;
48 };
49 
ParseInStandbyParameters(const napi_env & env,const napi_callback_info & info,IsDeviceInStandbyParamsInfo & params)50 napi_value ParseInStandbyParameters(const napi_env& env, const napi_callback_info& info,
51     IsDeviceInStandbyParamsInfo& params)
52 {
53     size_t argc = IS_DEVICE_IN_STANDBY_PARAMS;
54     napi_value argv[IS_DEVICE_IN_STANDBY_PARAMS] = {nullptr};
55     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
56     if (argc != IS_DEVICE_IN_STANDBY_MIN_PARAMS && argc != IS_DEVICE_IN_STANDBY_PARAMS) {
57         Common::HandleParamErr(env, ERR_PARAM_NUMBER_ERR);
58         return nullptr;
59     }
60 
61     // argv[0]: callback
62     if (argc == IS_DEVICE_IN_STANDBY_PARAMS) {
63         napi_valuetype valuetype = napi_undefined;
64         NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
65         if (valuetype != napi_function) {
66             Common::HandleParamErr(env, ERR_CALLBACK_NULL_OR_TYPE_ERR);
67             return nullptr;
68         }
69         NAPI_CALL(env, napi_create_reference(env, argv[0], 1, &params.callback));
70     }
71 
72     return Common::NapiGetNull(env);
73 }
74 
AddInStandbyExecuteCB(napi_env env,void * data)75 void AddInStandbyExecuteCB(napi_env env, void *data)
76 {
77     AsyncCallbackInfoIsDeviceInStandby *asyncCallbackInfo =
78     static_cast<AsyncCallbackInfoIsDeviceInStandby *>(data);
79     if (asyncCallbackInfo != nullptr) {
80         // return current state, whether in standby state or not
81         asyncCallbackInfo->errCode = StandbyServiceClient::GetInstance().
82             IsDeviceInStandby(asyncCallbackInfo->isStandby);
83     }
84 }
85 
AddInStandbyCallbackCompleteCB(napi_env env,napi_status status,void * data)86 void AddInStandbyCallbackCompleteCB(napi_env env, napi_status status, void *data)
87 {
88     AsyncCallbackInfoIsDeviceInStandby *asyncCallbackInfo =
89         static_cast<AsyncCallbackInfoIsDeviceInStandby *>(data);
90     std::unique_ptr<AsyncCallbackInfoIsDeviceInStandby> callbackPtr {asyncCallbackInfo};
91     if (asyncCallbackInfo != nullptr) {
92         napi_value result = nullptr;
93         napi_create_int32(env, asyncCallbackInfo->isStandby, &result);
94         Common::ReturnCallbackPromise(env, *asyncCallbackInfo, result);
95     }
96 }
97 
IsDeviceInStandby(napi_env env,napi_callback_info info)98 napi_value IsDeviceInStandby(napi_env env, napi_callback_info info)
99 {
100     IsDeviceInStandbyParamsInfo params;
101     if (ParseInStandbyParameters(env, info, params) == nullptr) {
102         return nullptr;
103     }
104 
105     napi_value promise = nullptr;
106     AsyncCallbackInfoIsDeviceInStandby *asyncCallbackInfo =
107         new (std::nothrow) AsyncCallbackInfoIsDeviceInStandby(env);
108     if (!asyncCallbackInfo) {
109         return nullptr;
110     }
111     std::unique_ptr<AsyncCallbackInfoIsDeviceInStandby> callbackPtr {asyncCallbackInfo};
112     Common::PaddingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
113 
114     napi_value resourceName = nullptr;
115     NAPI_CALL(env, napi_create_string_latin1(env, "IsDeviceInStandby", NAPI_AUTO_LENGTH, &resourceName));
116 
117     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, AddInStandbyExecuteCB,
118         AddInStandbyCallbackCompleteCB, static_cast<void *>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
119 
120     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
121     callbackPtr.release();
122     if (asyncCallbackInfo->isCallback) {
123         return Common::NapiGetNull(env);
124     }
125     return promise;
126 }
127 
128 struct AsyncCallbackInfoGetAllowList : public AsyncWorkData {
AsyncCallbackInfoGetAllowListOHOS::DevStandbyMgr::AsyncCallbackInfoGetAllowList129     explicit AsyncCallbackInfoGetAllowList(napi_env env) : AsyncWorkData(env) {}
130     uint32_t allowType = 0;
131     std::vector<AllowInfo> allowInfoArray {};
132 };
133 
134 struct GetAllowListParamsInfo {
135     uint32_t allowType = 0;
136     napi_ref callback = nullptr;
137 };
138 
AddGetAllowListExecuteCB(napi_env env,void * data)139 void AddGetAllowListExecuteCB(napi_env env, void *data)
140 {
141     AsyncCallbackInfoGetAllowList *asyncCallbackInfo =
142     static_cast<AsyncCallbackInfoGetAllowList *>(data);
143     if (asyncCallbackInfo != nullptr) {
144         asyncCallbackInfo->errCode = StandbyServiceClient::GetInstance().GetAllowList(
145             asyncCallbackInfo->allowType, asyncCallbackInfo->allowInfoArray, ReasonCodeEnum::REASON_APP_API);
146     }
147 }
148 
AddGetAllowListCallbackCompleteCB(napi_env env,napi_status status,void * data)149 void AddGetAllowListCallbackCompleteCB(napi_env env, napi_status status, void *data)
150 {
151     AsyncCallbackInfoGetAllowList *asyncCallbackInfo =
152         static_cast<AsyncCallbackInfoGetAllowList *>(data);
153     std::unique_ptr<AsyncCallbackInfoGetAllowList> callbackPtr {asyncCallbackInfo};
154     if (asyncCallbackInfo != nullptr) {
155         napi_value result = nullptr;
156         napi_create_array(env, &result);
157         int32_t index = 0;
158         for (const auto& allowInfo : asyncCallbackInfo->allowInfoArray) {
159             napi_value allowInfoObj = nullptr;
160             napi_create_object(env, &allowInfoObj);
161             Common::SetUint32Value(env, "resourceTypes", static_cast<uint32_t>(allowInfo.GetAllowType()), allowInfoObj);
162             Common::SetStringValue(env, "name", allowInfo.GetName(), allowInfoObj);
163             Common::SetInt32Value(env, "duration", allowInfo.GetDuration(), allowInfoObj);
164             napi_set_element(env, result, index, allowInfoObj);
165             ++index;
166         }
167 
168         Common::ReturnCallbackPromise(env, *asyncCallbackInfo, result);
169     }
170 }
171 
ParseGetAllowListParameters(const napi_env & env,const napi_callback_info & info,GetAllowListParamsInfo & params)172 napi_value ParseGetAllowListParameters(const napi_env& env, const napi_callback_info& info,
173     GetAllowListParamsInfo& params)
174 {
175     size_t argc = GET_ALLOW_LIST_STANDBY_PARAMS;
176     napi_value argv[GET_ALLOW_LIST_STANDBY_PARAMS] = {nullptr};
177     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
178     if (argc != GET_ALLOW_LIST_MIN_PARAMS && argc != GET_ALLOW_LIST_STANDBY_PARAMS) {
179         Common::HandleParamErr(env, ERR_PARAM_NUMBER_ERR);
180         return nullptr;
181     }
182 
183     // argv[0]: allowType
184     if (Common::GetUint32Value(env, argv[0], params.allowType) == nullptr) {
185         STANDBYSERVICE_LOGE("ParseParameters failed, allowType is nullptr.");
186         Common::HandleParamErr(env, ERR_RESOURCE_TYPES_INVALID);
187         return nullptr;
188     }
189 
190     // argv[1]: callback
191     if (argc == GET_ALLOW_LIST_STANDBY_PARAMS) {
192         napi_valuetype valuetype = napi_undefined;
193         NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
194         if (valuetype != napi_function) {
195             Common::HandleParamErr(env, ERR_CALLBACK_NULL_OR_TYPE_ERR);
196             return nullptr;
197         }
198         NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &params.callback));
199     }
200 
201     if (params.allowType == 0) {
202         Common::HandleParamErr(env, ERR_RESOURCE_TYPES_INVALID);
203         return nullptr;
204     }
205 
206     return Common::NapiGetNull(env);
207 }
208 
GetExemptionListApps(napi_env env,napi_callback_info info)209 napi_value GetExemptionListApps(napi_env env, napi_callback_info info)
210 {
211     GetAllowListParamsInfo params;
212     if (ParseGetAllowListParameters(env, info, params) == nullptr) {
213         return nullptr;
214     }
215 
216     napi_value promise = nullptr;
217     AsyncCallbackInfoGetAllowList *asyncCallbackInfo =
218         new (std::nothrow) AsyncCallbackInfoGetAllowList(env);
219     if (!asyncCallbackInfo) {
220         return nullptr;
221     }
222     std::unique_ptr<AsyncCallbackInfoGetAllowList> callbackPtr {asyncCallbackInfo};
223     asyncCallbackInfo->allowType = params.allowType;
224     Common::PaddingAsyncWorkData(env, params.callback, *asyncCallbackInfo, promise);
225 
226     napi_value resourceName = nullptr;
227     NAPI_CALL(env, napi_create_string_latin1(env, "GetAllowList", NAPI_AUTO_LENGTH, &resourceName));
228 
229     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, AddGetAllowListExecuteCB,
230         AddGetAllowListCallbackCompleteCB, static_cast<void *>(asyncCallbackInfo),
231         &asyncCallbackInfo->asyncWork));
232 
233     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
234     callbackPtr.release();
235     if (asyncCallbackInfo->isCallback) {
236         return Common::NapiGetNull(env);
237     }
238     return promise;
239 }
240 
ParseAllowResParameters(const napi_env & env,const napi_callback_info & info,sptr<ResourceRequest> & resourceRequest)241 napi_value ParseAllowResParameters(const napi_env &env, const napi_callback_info &info,
242     sptr<ResourceRequest> &resourceRequest)
243 {
244     size_t argc = APPLY_ALLOW_RESOURCE_PARAMS;
245     napi_value argv[APPLY_ALLOW_RESOURCE_PARAMS] = {nullptr};
246     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
247     if (argc != APPLY_ALLOW_RESOURCE_PARAMS) {
248         Common::HandleParamErr(env, ERR_PARAM_NUMBER_ERR);
249         return nullptr;
250     }
251     int32_t allowType {0};
252     int32_t uid {0};
253     std::string name {};
254     int32_t duration {0};
255     std::string reason {};
256 
257     if (!Common::GetNamedInt32Value(env, argv[0], "resourceTypes", allowType) || allowType <= 0
258         || static_cast<uint32_t>(allowType) > MAX_ALLOW_TYPE_NUMBER) {
259         Common::HandleParamErr(env, ERR_RESOURCE_TYPES_INVALID);
260         return nullptr;
261     }
262     if (!Common::GetNamedInt32Value(env, argv[0], "uid", uid) || uid < 0) {
263         Common::HandleParamErr(env, ERR_UID_INVALID);
264         return nullptr;
265     }
266     if (!Common::GetNamedStringValue(env, argv[0], "name", name) || name.empty()) {
267         Common::HandleParamErr(env, ERR_NAME_INVALID_OR_EMPTY);
268         return nullptr;
269     }
270     if (!Common::GetNamedInt32Value(env, argv[0], "duration", duration)) {
271         Common::HandleParamErr(env, ERR_DURATION_INVALID);
272         return nullptr;
273     }
274     if (!Common::GetNamedStringValue(env, argv[0], "reason", reason)) {
275         Common::HandleParamErr(env, ERR_REASON_INVALID_TYPE_ERR);
276         return nullptr;
277     }
278     resourceRequest = new (std::nothrow) ResourceRequest(allowType, uid,
279         name, duration, reason, ReasonCodeEnum::REASON_APP_API);
280     return Common::NapiGetNull(env);
281 }
282 
ApplyAllowResource(napi_env env,napi_callback_info info)283 napi_value ApplyAllowResource(napi_env env, napi_callback_info info)
284 {
285     sptr<ResourceRequest> resourceRequest {};
286     if (ParseAllowResParameters(env, info, resourceRequest) == nullptr) {
287         return Common::NapiGetNull(env);
288     }
289     ErrCode errCode = StandbyServiceClient::GetInstance().ApplyAllowResource(resourceRequest);
290     Common::HandleErrCode(env, errCode);
291     return Common::NapiGetNull(env);
292 }
293 
UnapplyAllowResource(napi_env env,napi_callback_info info)294 napi_value UnapplyAllowResource(napi_env env, napi_callback_info info)
295 {
296     sptr<ResourceRequest> resourceRequest {};
297     if (ParseAllowResParameters(env, info, resourceRequest) == nullptr) {
298         return Common::NapiGetNull(env);
299     }
300     ErrCode errCode = StandbyServiceClient::GetInstance().UnapplyAllowResource(resourceRequest);
301     Common::HandleErrCode(env, errCode);
302     return Common::NapiGetNull(env);
303 }
304 }  // namespace DevStandbyMgr
305 }  // namespace OHOS