1 /*
2 * Copyright (c) 2025 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 "privacy_manager.h"
17
18 #include <iostream>
19
20 #include "accesstoken_common_log.h"
21 #include "ani_error.h"
22 #include "ani_utils.h"
23 #include "privacy_error.h"
24 #include "privacy_kit.h"
25
26 namespace OHOS {
27 namespace Security {
28 namespace AccessToken {
29 namespace {
30 std::mutex g_mutex;
31 std::vector<RegisterPermActiveChangeContext*> g_subScribers;
32 static constexpr size_t MAX_CALLBACK_SIZE = 200;
33 constexpr const char* ACTIVE_CHANGE_FIELD_CALLING_TOKEN_ID = "callingTokenId";
34 constexpr const char* ACTIVE_CHANGE_FIELD_TOKEN_ID = "tokenId";
35 constexpr const char* ACTIVE_CHANGE_FIELD_PERMISSION_NAME = "permissionName";
36 constexpr const char* ACTIVE_CHANGE_FIELD_DEVICE_ID = "deviceId";
37 constexpr const char* ACTIVE_CHANGE_FIELD_ACTIVE_STATUS = "activeStatus";
38 constexpr const char* ACTIVE_CHANGE_FIELD_USED_TYPE = "usedType";
39 }
40
GetStsErrorCode(int32_t errCode)41 static int32_t GetStsErrorCode(int32_t errCode)
42 {
43 int32_t stsCode;
44 switch (errCode) {
45 case RET_SUCCESS:
46 stsCode = STS_OK;
47 break;
48 case ERR_PERMISSION_DENIED:
49 stsCode = STS_ERROR_PERMISSION_DENIED;
50 break;
51 case ERR_NOT_SYSTEM_APP:
52 stsCode = STS_ERROR_NOT_SYSTEM_APP;
53 break;
54 case ERR_PARAM_INVALID:
55 stsCode = STS_ERROR_PARAM_INVALID;
56 break;
57 case ERR_TOKENID_NOT_EXIST:
58 stsCode = STS_ERROR_TOKENID_NOT_EXIST;
59 break;
60 case ERR_PERMISSION_NOT_EXIST:
61 stsCode = STS_ERROR_PERMISSION_NOT_EXIST;
62 break;
63 case ERR_CALLBACK_ALREADY_EXIST:
64 case ERR_CALLBACK_NOT_EXIST:
65 case ERR_PERMISSION_ALREADY_START_USING:
66 case ERR_PERMISSION_NOT_START_USING:
67 stsCode = STS_ERROR_NOT_USE_TOGETHER;
68 break;
69 case ERR_CALLBACKS_EXCEED_LIMITATION:
70 stsCode = STS_ERROR_REGISTERS_EXCEED_LIMITATION;
71 break;
72 case ERR_IDENTITY_CHECK_FAILED:
73 stsCode = STS_ERROR_PERMISSION_OPERATION_NOT_ALLOWED;
74 break;
75 case ERR_SERVICE_ABNORMAL:
76 case ERROR_IPC_REQUEST_FAIL:
77 case ERR_READ_PARCEL_FAILED:
78 case ERR_WRITE_PARCEL_FAILED:
79 stsCode = STS_ERROR_SERVICE_NOT_RUNNING;
80 break;
81 case ERR_MALLOC_FAILED:
82 stsCode = STS_ERROR_OUT_OF_MEMORY;
83 break;
84 default:
85 stsCode = STS_ERROR_INNER;
86 break;
87 }
88 LOGD(PRI_DOMAIN, PRI_TAG, "GetStsErrorCode nativeCode(%{public}d) stsCode(%{public}d).", errCode, stsCode);
89 return stsCode;
90 }
91
AddPermissionUsedRecordExecute(ani_env * env,ani_int aniTokenID,ani_string aniPermission,ani_int successCount,ani_int failCount,ani_object options)92 static void AddPermissionUsedRecordExecute([[maybe_unused]] ani_env* env,
93 ani_int aniTokenID, ani_string aniPermission, ani_int successCount, ani_int failCount, ani_object options)
94 {
95 if (env == nullptr) {
96 return;
97 }
98 AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
99 std::string permission = ParseAniString(env, aniPermission);
100 if ((!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) ||
101 (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permission))) {
102 LOGE(PRI_DOMAIN, PRI_TAG, "TokenId(%{public}u) or Permission(%{public}s) is invalid.",
103 tokenID, permission.c_str());
104 return;
105 }
106
107 int32_t usedType = 0;
108 if (!GetEnumProperty(env, options, "usedType", usedType)) {
109 return;
110 }
111 AddPermParamInfo info;
112 info.tokenId = static_cast<AccessTokenID>(tokenID);
113 info.permissionName = permission;
114 info.successCount = successCount;
115 info.failCount = failCount;
116 info.type = static_cast<PermissionUsedType>(usedType);
117 auto retCode = PrivacyKit::AddPermissionUsedRecord(info);
118 if (retCode != RET_SUCCESS) {
119 int32_t stsCode = GetStsErrorCode(retCode);
120 BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
121 return;
122 }
123 }
124
PermActiveStatusPtr(const std::vector<std::string> & permList)125 PermActiveStatusPtr::PermActiveStatusPtr(const std::vector<std::string>& permList)
126 : PermActiveStatusCustomizedCbk(permList)
127 {}
128
~PermActiveStatusPtr()129 PermActiveStatusPtr::~PermActiveStatusPtr()
130 {
131 if (vm_ == nullptr) {
132 LOGE(PRI_DOMAIN, PRI_TAG, "Vm is null.");
133 return;
134 }
135 bool isSameThread = (threadId_ == std::this_thread::get_id());
136 ani_env* env = isSameThread ? env_ : GetCurrentEnv(vm_);
137 if (env == nullptr) {
138 LOGE(PRI_DOMAIN, PRI_TAG, "Current env is null.");
139 } else if (ref_ != nullptr) {
140 env->GlobalReference_Delete(ref_);
141 }
142 ref_ = nullptr;
143
144 if (!isSameThread) {
145 vm_->DetachCurrentThread();
146 }
147 }
148
SetVm(ani_vm * vm)149 void PermActiveStatusPtr::SetVm(ani_vm* vm)
150 {
151 vm_ = vm;
152 }
153
SetEnv(ani_env * env)154 void PermActiveStatusPtr::SetEnv(ani_env* env)
155 {
156 env_ = env;
157 }
158
SetCallbackRef(const ani_ref & ref)159 void PermActiveStatusPtr::SetCallbackRef(const ani_ref& ref)
160 {
161 ref_ = ref;
162 }
163
SetThreadId(const std::thread::id threadId)164 void PermActiveStatusPtr::SetThreadId(const std::thread::id threadId)
165 {
166 threadId_ = threadId;
167 }
168
ConvertActiveChangeResponse(ani_env * env,const ActiveChangeResponse & result)169 static ani_object ConvertActiveChangeResponse(ani_env* env, const ActiveChangeResponse& result)
170 {
171 ani_object aniObject = CreateClassObject(env, "L@ohos/privacyManager/privacyManager/ActiveChangeResponseInner;");
172 if (aniObject == nullptr) {
173 return nullptr;
174 }
175
176 // set callingTokenID?: int optional parameter callingTokenID need box as a object
177 SetIntProperty(env, aniObject, ACTIVE_CHANGE_FIELD_CALLING_TOKEN_ID, static_cast<int32_t>(result.callingTokenID));
178
179 // set tokenID: int
180 SetIntProperty(env, aniObject, ACTIVE_CHANGE_FIELD_TOKEN_ID, static_cast<int32_t>(result.tokenID));
181
182 // set permissionName: string
183 SetStringProperty(env, aniObject, ACTIVE_CHANGE_FIELD_PERMISSION_NAME, result.permissionName);
184
185 // set deviceId: string
186 SetStringProperty(env, aniObject, ACTIVE_CHANGE_FIELD_DEVICE_ID, result.deviceId);
187
188 // set activeStatus: PermissionActiveStatus
189 const char* activeStatusDes = "L@ohos/privacyManager/privacyManager/PermissionActiveStatus;";
190 SetEnumProperty(
191 env, aniObject, activeStatusDes, ACTIVE_CHANGE_FIELD_ACTIVE_STATUS, static_cast<uint32_t>(result.type));
192
193 // set usedType?: PermissionUsedType
194 const char* permUsedTypeDes = "L@ohos/privacyManager/privacyManager/PermissionUsedType;";
195 SetEnumProperty(
196 env, aniObject, permUsedTypeDes, ACTIVE_CHANGE_FIELD_USED_TYPE, static_cast<uint32_t>(result.usedType));
197 return aniObject;
198 }
199
ActiveStatusChangeCallback(ActiveChangeResponse & activeChangeResponse)200 void PermActiveStatusPtr::ActiveStatusChangeCallback(ActiveChangeResponse& activeChangeResponse)
201 {
202 if (vm_ == nullptr) {
203 LOGE(PRI_DOMAIN, PRI_TAG, "Vm is null.");
204 return;
205 }
206
207 ani_option interopEnabled {"--interop=disable", nullptr};
208 ani_options aniArgs {1, &interopEnabled};
209 ani_env* env;
210 if (vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env) != ANI_OK) {
211 LOGE(PRI_DOMAIN, PRI_TAG, "AttachCurrentThread failed!");
212 return;
213 }
214
215 ani_fn_object fnObj = reinterpret_cast<ani_fn_object>(ref_);
216 if (fnObj == nullptr) {
217 LOGE(PRI_DOMAIN, PRI_TAG, "Reinterpret_cast failed!");
218 return;
219 }
220
221 ani_object aniObject = ConvertActiveChangeResponse(env, activeChangeResponse);
222 if (aniObject == nullptr) {
223 LOGE(PRI_DOMAIN, PRI_TAG, "Convert object is null.");
224 return;
225 }
226 std::vector<ani_ref> args;
227 args.emplace_back(aniObject);
228 ani_ref result;
229 if (!AniFunctionalObjectCall(env, fnObj, args.size(), args.data(), result)) {
230 return;
231 }
232
233 if (vm_->DetachCurrentThread() != ANI_OK) {
234 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to DetachCurrentThread!");
235 return;
236 }
237 }
238
ParseInputToRegister(const ani_string & aniType,const ani_array_ref & aniArray,const ani_ref & aniCallback,RegisterPermActiveChangeContext * context,bool isReg)239 static bool ParseInputToRegister(const ani_string& aniType, const ani_array_ref& aniArray,
240 const ani_ref& aniCallback, RegisterPermActiveChangeContext* context, bool isReg)
241 {
242 std::string type = ParseAniString(context->env, static_cast<ani_string>(aniType));
243 std::vector<std::string> permList = ParseAniStringVector(context->env, aniArray);
244 std::sort(permList.begin(), permList.end());
245
246 bool hasCallback = true;
247 if (!isReg) {
248 hasCallback = !AniIsRefUndefined(context->env, aniCallback);
249 }
250
251 ani_ref callback = nullptr; // callback: the third parameter is function
252 if (hasCallback) {
253 if (!AniParseCallback(context->env, aniCallback, callback)) {
254 BusinessErrorAni::ThrowParameterTypeError(
255 context->env, STS_ERROR_PARAM_INVALID, GetParamErrorMsg("callback", "Callback"));
256 return false;
257 }
258 }
259
260 ani_vm* vm;
261 if (context->env->GetVM(&vm) != ANI_OK) {
262 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to GetVM!");
263 return false;
264 }
265
266 context->callbackRef = callback;
267 context->type = type;
268 context->permissionList = permList;
269 context->subscriber = std::make_shared<PermActiveStatusPtr>(permList);
270 context->threadId = std::this_thread::get_id();
271
272 context->subscriber->SetVm(vm);
273 context->subscriber->SetEnv(context->env);
274 context->subscriber->SetCallbackRef(callback);
275 context->subscriber->SetThreadId(context->threadId);
276
277 return true;
278 }
279
IsExistRegister(const RegisterPermActiveChangeContext * context)280 static bool IsExistRegister(const RegisterPermActiveChangeContext* context)
281 {
282 std::vector<std::string> targetPermList;
283 context->subscriber->GetPermList(targetPermList);
284 std::lock_guard<std::mutex> lock(g_mutex);
285 for (const auto& item : g_subScribers) {
286 std::vector<std::string> permList;
287 item->subscriber->GetPermList(permList);
288 bool hasPermIntersection = false;
289 // Special cases:
290 // 1.Have registered full, and then register some
291 // 2.Have registered some, then register full
292 if (permList.empty() || targetPermList.empty()) {
293 hasPermIntersection = true;
294 }
295 for (const auto& PermItem : targetPermList) {
296 if (hasPermIntersection) {
297 break;
298 }
299 auto iter = std::find(permList.begin(), permList.end(), PermItem);
300 if (iter != permList.end()) {
301 hasPermIntersection = true;
302 }
303 }
304 bool isEqual = true;
305 if (!AniIsCallbackRefEqual(context->env, item->callbackRef, context->callbackRef, item->threadId, isEqual)) {
306 return true;
307 }
308 if (hasPermIntersection && isEqual) {
309 return true;
310 }
311 }
312 return false;
313 }
314
RegisterPermActiveStatusCallback(ani_env * env,ani_string aniType,ani_array_ref aniArray,ani_ref callback)315 static void RegisterPermActiveStatusCallback([[maybe_unused]] ani_env* env,
316 ani_string aniType, ani_array_ref aniArray, ani_ref callback)
317 {
318 if (env == nullptr) {
319 return;
320 }
321
322 RegisterPermActiveChangeContext* context = new (std::nothrow) RegisterPermActiveChangeContext();
323 if (context == nullptr) {
324 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to allocate memory for RegisterPermActiveChangeContext!");
325 return;
326 }
327 context->env = env;
328 std::unique_ptr<RegisterPermActiveChangeContext> callbackPtr {context};
329
330 if (!ParseInputToRegister(aniType, aniArray, callback, context, true)) {
331 return;
332 }
333
334 if (IsExistRegister(context)) {
335 std::string errMsg = GetErrorMessage(
336 STS_ERROR_NOT_USE_TOGETHER, "The API reuses the same input. The subscriber already exists.");
337 BusinessErrorAni::ThrowError(
338 env, STS_ERROR_NOT_USE_TOGETHER, GetErrorMessage(STS_ERROR_NOT_USE_TOGETHER, errMsg));
339 return;
340 }
341
342 int32_t result = PrivacyKit::RegisterPermActiveStatusCallback(context->subscriber);
343 if (result != RET_SUCCESS) {
344 LOGE(PRI_DOMAIN, PRI_TAG, "RegisterPermActiveStatusCallback failed, res is %{public}d.", result);
345 int32_t stsCode = GetStsErrorCode(result);
346 BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
347 return;
348 }
349
350 {
351 std::lock_guard<std::mutex> lock(g_mutex);
352 if (g_subScribers.size() >= MAX_CALLBACK_SIZE) {
353 LOGE(PRI_DOMAIN, PRI_TAG, "Subscribers size has reached the max %{public}zu.", MAX_CALLBACK_SIZE);
354 BusinessErrorAni::ThrowError(env, STSErrorCode::STS_ERROR_REGISTERS_EXCEED_LIMITATION,
355 GetErrorMessage(STSErrorCode::STS_ERROR_REGISTERS_EXCEED_LIMITATION));
356 return;
357 }
358 g_subScribers.emplace_back(context);
359 }
360
361 callbackPtr.release();
362 LOGI(PRI_DOMAIN, PRI_TAG, "RegisterPermActiveStatusCallback success!");
363 return;
364 }
365
FindAndGetSubscriber(const RegisterPermActiveChangeContext * context,std::vector<RegisterPermActiveChangeContext * > & batchPermActiveChangeSubscribers)366 static bool FindAndGetSubscriber(const RegisterPermActiveChangeContext* context,
367 std::vector<RegisterPermActiveChangeContext*>& batchPermActiveChangeSubscribers)
368 {
369 std::vector<std::string> targetPermList = context->permissionList;
370 std::lock_guard<std::mutex> lock(g_mutex);
371 bool callbackEqual;
372 ani_ref callbackRef = context->callbackRef;
373 bool isUndef = AniIsRefUndefined(context->env, context->callbackRef);
374 for (const auto& item : g_subScribers) {
375 std::vector<std::string> permList;
376 item->subscriber->GetPermList(permList);
377 // targetCallback == nullptr, Unsubscribe from all callbacks under the same permList
378 // targetCallback != nullptr, unregister the subscriber with same permList and callback
379 if (isUndef) {
380 // batch delete currentThread callback
381 LOGI(PRI_DOMAIN, PRI_TAG, "Callback is null.");
382 callbackEqual = IsCurrentThread(item->threadId);
383 } else {
384 LOGI(PRI_DOMAIN, PRI_TAG, "Compare callback.");
385 if (!AniIsCallbackRefEqual(context->env, item->callbackRef, callbackRef, item->threadId, callbackEqual)) {
386 continue;
387 }
388 }
389
390 if (callbackEqual && (permList == targetPermList)) {
391 batchPermActiveChangeSubscribers.emplace_back(item);
392 if (!isUndef) {
393 return true;
394 }
395 }
396 }
397 return !batchPermActiveChangeSubscribers.empty();
398 }
399
DeleteRegisterInVector(const RegisterPermActiveChangeContext * context)400 static void DeleteRegisterInVector(const RegisterPermActiveChangeContext* context)
401 {
402 std::vector<std::string> targetPermList;
403 context->subscriber->GetPermList(targetPermList);
404 std::lock_guard<std::mutex> lock(g_mutex);
405 auto item = g_subScribers.begin();
406 while (item != g_subScribers.end()) {
407 bool isEqual = true;
408 if (!AniIsCallbackRefEqual(
409 context->env, (*item)->callbackRef, context->callbackRef, (*item)->threadId, isEqual)) {
410 continue;
411 }
412 if (!isEqual) {
413 continue;
414 }
415
416 std::vector<std::string> permList;
417 (*item)->subscriber->GetPermList(permList);
418 if (permList == targetPermList) {
419 delete *item;
420 *item = nullptr;
421 g_subScribers.erase(item);
422 return;
423 } else {
424 ++item;
425 }
426 }
427 }
428
UnRegisterPermActiveStatusCallback(ani_env * env,ani_string aniType,ani_array_ref aniArray,ani_ref callback)429 static void UnRegisterPermActiveStatusCallback([[maybe_unused]] ani_env* env,
430 ani_string aniType, ani_array_ref aniArray, ani_ref callback)
431 {
432 if (env == nullptr) {
433 return;
434 }
435
436 RegisterPermActiveChangeContext* context = new (std::nothrow) RegisterPermActiveChangeContext();
437 if (context == nullptr) {
438 return;
439 }
440 context->env = env;
441 std::unique_ptr<RegisterPermActiveChangeContext> callbackPtr {context};
442 if (!ParseInputToRegister(aniType, aniArray, callback, context, false)) {
443 return;
444 }
445
446 std::vector<RegisterPermActiveChangeContext*> batchPermActiveChangeSubscribers;
447 if (!FindAndGetSubscriber(context, batchPermActiveChangeSubscribers)) {
448 std::string errMsg = GetErrorMessage(
449 STS_ERROR_NOT_USE_TOGETHER, "The API is not used in pair with 'on'. The subscriber does not exist.");
450 BusinessErrorAni::ThrowError(
451 env, STS_ERROR_NOT_USE_TOGETHER, GetErrorMessage(STS_ERROR_NOT_USE_TOGETHER, errMsg));
452 return;
453 }
454
455 for (const auto& item : batchPermActiveChangeSubscribers) {
456 int32_t result = PrivacyKit::UnRegisterPermActiveStatusCallback(item->subscriber);
457 if (result == RET_SUCCESS) {
458 DeleteRegisterInVector(item);
459 } else {
460 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to UnregisterPermActiveChangeCompleted.");
461 int32_t stsCode = GetStsErrorCode(result);
462 BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
463 }
464 }
465 LOGI(PRI_DOMAIN, PRI_TAG, "UnRegisterPermActiveStatusCallback success!");
466 return;
467 }
468
StopUsingPermissionExecute(ani_env * env,ani_int aniTokenID,ani_string aniPermission,ani_int pid)469 static void StopUsingPermissionExecute(
470 [[maybe_unused]] ani_env* env, ani_int aniTokenID, ani_string aniPermission, ani_int pid)
471 {
472 LOGI(PRI_DOMAIN, PRI_TAG, "StopUsingPermissionExecute begin.");
473 if (env == nullptr) {
474 LOGE(PRI_DOMAIN, PRI_TAG, "Env is null.");
475 return;
476 }
477
478 AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
479 std::string permission = ParseAniString(env, aniPermission);
480 if ((!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) ||
481 (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permission))) {
482 LOGE(PRI_DOMAIN, PRI_TAG, "TokenId(%{public}u) or Permission(%{public}s) is invalid.",
483 tokenID, permission.c_str());
484 return;
485 }
486
487 LOGI(PRI_DOMAIN, PRI_TAG, "PermissionName : %{public}s, tokenID : %{public}u, pid : %{public}d.",
488 permission.c_str(), tokenID, pid);
489
490 auto retCode = PrivacyKit::StopUsingPermission(tokenID, permission, pid);
491 if (retCode != RET_SUCCESS) {
492 int32_t stsCode = GetStsErrorCode(retCode);
493 BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
494 }
495 }
496
StartUsingPermissionExecute(ani_env * env,ani_int aniTokenID,ani_string aniPermission,ani_int pid,PermissionUsedType usedType)497 static void StartUsingPermissionExecute([[maybe_unused]] ani_env* env,
498 ani_int aniTokenID, ani_string aniPermission, ani_int pid, PermissionUsedType usedType)
499 {
500 LOGI(PRI_DOMAIN, PRI_TAG, "StartUsingPermissionExecute begin.");
501 if (env == nullptr) {
502 LOGE(PRI_DOMAIN, PRI_TAG, "Env is null.");
503 return;
504 }
505 AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
506 std::string permission = ParseAniString(env, aniPermission);
507 if ((!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) ||
508 (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permission))) {
509 LOGE(PRI_DOMAIN, PRI_TAG, "TokenId(%{public}u) or Permission(%{public}s) is invalid.",
510 tokenID, permission.c_str());
511 return;
512 }
513
514 LOGI(PRI_DOMAIN, PRI_TAG, "PermissionName : %{public}s, tokenID : %{public}u, pid : %{public}d.",
515 permission.c_str(), tokenID, pid);
516
517 auto retCode = PrivacyKit::StartUsingPermission(tokenID, permission, pid, usedType);
518 if (retCode != RET_SUCCESS) {
519 int32_t stsCode = GetStsErrorCode(retCode);
520 BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
521 }
522 }
523
ConvertSingleUsedRecordDetail(ani_env * env,const UsedRecordDetail & record)524 static ani_object ConvertSingleUsedRecordDetail(ani_env* env, const UsedRecordDetail& record)
525 {
526 ani_object arrayObj = CreateClassObject(env, "L@ohos/privacyManager/privacyManager/UsedRecordDetailInner;");
527 if (arrayObj == nullptr) {
528 return nullptr;
529 }
530 if (!SetIntProperty(env, arrayObj, "status", record.status)) {
531 return nullptr;
532 }
533 if (!SetOptionalIntProperty(env, arrayObj, "lockScreenStatus", record.lockScreenStatus)) {
534 return nullptr;
535 }
536 if (!SetLongProperty(env, arrayObj, "timestamp", record.timestamp)) {
537 return nullptr;
538 }
539 if (!SetLongProperty(env, arrayObj, "accessDuration", record.accessDuration)) {
540 return nullptr;
541 }
542 if (!SetOptionalIntProperty(env, arrayObj, "count", record.count)) {
543 return nullptr;
544 }
545 if (!SetEnumProperty(env, arrayObj, "L@ohos/privacyManager/privacyManager/PermissionUsedType;", "usedType",
546 static_cast<uint32_t>(record.type))) {
547 return nullptr;
548 }
549 return arrayObj;
550 }
551
ConvertUsedRecordDetails(ani_env * env,const std::vector<UsedRecordDetail> & details)552 static ani_object ConvertUsedRecordDetails(ani_env* env, const std::vector<UsedRecordDetail>& details)
553 {
554 ani_object arrayObj = CreateArrayObject(env, details.size());
555 if (arrayObj == nullptr) {
556 return nullptr;
557 }
558 ani_size index = 0;
559 for (const auto& record: details) {
560 ani_ref aniRecord = ConvertSingleUsedRecordDetail(env, record);
561 if (aniRecord == nullptr) {
562 LOGE(PRI_DOMAIN, PRI_TAG, "aniRecord is null.");
563 break;
564 }
565 ani_status status = env->Object_CallMethodByName_Void(
566 arrayObj, "$_set", "ILstd/core/Object;:V", index, aniRecord);
567 if (status != ANI_OK) {
568 LOGE(PRI_DOMAIN, PRI_TAG, "status : %{public}d.", status);
569 break;
570 }
571 ++index;
572 }
573 return arrayObj;
574 }
575
ConvertSinglePermissionRecord(ani_env * env,const PermissionUsedRecord & record)576 static ani_object ConvertSinglePermissionRecord(ani_env* env, const PermissionUsedRecord& record)
577 {
578 ani_object arrayObj = CreateClassObject(env, "L@ohos/privacyManager/privacyManager/PermissionUsedRecordInner;");
579 if (arrayObj == nullptr) {
580 return nullptr;
581 }
582 if (!SetStringProperty(env, arrayObj, "permissionName", record.permissionName)) {
583 return nullptr;
584 }
585 if (!SetIntProperty(env, arrayObj, "accessCount", record.accessCount)) {
586 return nullptr;
587 }
588 if (!SetIntProperty(env, arrayObj, "rejectCount", record.rejectCount)) {
589 return nullptr;
590 }
591 if (!SetLongProperty(env, arrayObj, "lastAccessTime", record.lastAccessTime)) {
592 return nullptr;
593 }
594 if (!SetLongProperty(env, arrayObj, "lastRejectTime", record.lastRejectTime)) {
595 return nullptr;
596 }
597 if (!SetLongProperty(env, arrayObj, "lastAccessDuration", record.lastAccessDuration)) {
598 return nullptr;
599 }
600 if (!SetRefProperty(env, arrayObj, "accessRecords", ConvertUsedRecordDetails(env, record.accessRecords))) {
601 return nullptr;
602 }
603 if (!SetRefProperty(env, arrayObj, "rejectRecords", ConvertUsedRecordDetails(env, record.rejectRecords))) {
604 return nullptr;
605 }
606 return arrayObj;
607 }
608
ConvertPermissionRecords(ani_env * env,const std::vector<PermissionUsedRecord> & permRecords)609 static ani_ref ConvertPermissionRecords(ani_env* env, const std::vector<PermissionUsedRecord>& permRecords)
610 {
611 ani_object arrayObj = CreateArrayObject(env, permRecords.size());
612 if (arrayObj == nullptr) {
613 return nullptr;
614 }
615 ani_size index = 0;
616 for (const auto& record: permRecords) {
617 ani_ref aniRecord = ConvertSinglePermissionRecord(env, record);
618 if (aniRecord == nullptr) {
619 break;
620 }
621 ani_status status = env->Object_CallMethodByName_Void(
622 arrayObj, "$_set", "ILstd/core/Object;:V", index, aniRecord);
623 if (status != ANI_OK) {
624 LOGE(PRI_DOMAIN, PRI_TAG,
625 "Failed to Set permission record, status: %{public}d.", static_cast<int32_t>(status));
626 break;
627 }
628 ++index;
629 }
630 return arrayObj;
631 }
632
ConvertBundleUsedRecord(ani_env * env,const BundleUsedRecord & record)633 static ani_object ConvertBundleUsedRecord(ani_env* env, const BundleUsedRecord& record)
634 {
635 ani_object aniRecord = CreateClassObject(env, "L@ohos/privacyManager/privacyManager/BundleUsedRecordInner;");
636 if (aniRecord == nullptr) {
637 return nullptr;
638 }
639 if (!SetIntProperty(env, aniRecord, "tokenId", static_cast<int32_t>(record.tokenId))) {
640 return nullptr;
641 }
642 if (!SetBoolProperty(env, aniRecord, "isRemote", record.isRemote)) {
643 return nullptr;
644 }
645
646 if (!SetStringProperty(env, aniRecord, "deviceId", record.deviceId)) {
647 return nullptr;
648 }
649
650 if (!SetStringProperty(env, aniRecord, "bundleName", record.bundleName)) {
651 return nullptr;
652 }
653
654 if (!SetRefProperty(env, aniRecord, "permissionRecords", ConvertPermissionRecords(env, record.permissionRecords))) {
655 return nullptr;
656 }
657 return aniRecord;
658 }
659
ConvertBundleUsedRecords(ani_env * env,const std::vector<BundleUsedRecord> & bundleRecord)660 static ani_object ConvertBundleUsedRecords(ani_env* env, const std::vector<BundleUsedRecord>& bundleRecord)
661 {
662 ani_object arrayObj = CreateArrayObject(env, bundleRecord.size());
663 if (arrayObj == nullptr) {
664 return nullptr;
665 }
666 ani_size index = 0;
667 for (const auto& record : bundleRecord) {
668 ani_ref aniRecord = ConvertBundleUsedRecord(env, record);
669 if (aniRecord == nullptr) {
670 LOGE(PRI_DOMAIN, PRI_TAG, "AniRecord is null.");
671 continue;
672 }
673 ani_status status = env->Object_CallMethodByName_Void(
674 arrayObj, "$_set", "ILstd/core/Object;:V", index, aniRecord);
675 if (status != ANI_OK) {
676 LOGE(PRI_DOMAIN, PRI_TAG, "Set bundle record fail, status: %{public}d.", static_cast<int32_t>(status));
677 continue;
678 }
679 ++index;
680 }
681 return arrayObj;
682 }
683
ProcessRecordResult(ani_env * env,const PermissionUsedResult & result)684 static ani_object ProcessRecordResult(ani_env* env, const PermissionUsedResult& result)
685 {
686 ani_object aObject = CreateClassObject(env, "L@ohos/privacyManager/privacyManager/PermissionUsedResponseInner;");
687 if (aObject == nullptr) {
688 return nullptr;
689 }
690 if (!SetLongProperty(env, aObject, "beginTime", result.beginTimeMillis)) {
691 return nullptr;
692 }
693 if (!SetLongProperty(env, aObject, "endTime", result.endTimeMillis)) {
694 return nullptr;
695 }
696
697 if (!SetRefProperty(env, aObject, "bundleRecords", ConvertBundleUsedRecords(env, result.bundleRecords))) {
698 return nullptr;
699 }
700 return aObject;
701 }
702
ParseRequest(ani_env * env,const ani_object & aniRequest,PermissionUsedRequest & request)703 static bool ParseRequest(ani_env* env, const ani_object& aniRequest, PermissionUsedRequest& request)
704 {
705 ani_class requestClass;
706 if (ANI_OK != env->FindClass("L@ohos/privacyManager/privacyManager/PermissionUsedRequest;", &requestClass)) {
707 return false;
708 }
709 ani_boolean isRequestObject = false;
710 if (ANI_OK != env->Object_InstanceOf(static_cast<ani_object>(aniRequest), requestClass, &isRequestObject)) {
711 return false;
712 }
713 if (!isRequestObject) {
714 LOGE(PRI_DOMAIN, PRI_TAG, "Object is not request type.");
715 return false;
716 }
717
718 int32_t value;
719 if (!GetIntProperty(env, aniRequest, "tokenId", value)) {
720 return false;
721 }
722 request.tokenId = static_cast<AccessTokenID>(value);
723
724 if (!GetBoolProperty(env, aniRequest, "isRemote", request.isRemote)) {
725 return false;
726 }
727
728 if (!GetStringProperty(env, aniRequest, "deviceId", request.deviceId)) {
729 return false;
730 }
731
732 if (!GetStringProperty(env, aniRequest, "bundleName", request.bundleName)) {
733 return false;
734 }
735
736 if (!GetLongProperty(env, aniRequest, "beginTime", request.beginTimeMillis)) {
737 return false;
738 }
739
740 if (!GetLongProperty(env, aniRequest, "endTime", request.endTimeMillis)) {
741 return false;
742 }
743
744 if (!GetStringVecProperty(env, aniRequest, "permissionNames", request.permissionList)) {
745 return false;
746 }
747
748 int32_t flag;
749 if (!GetEnumProperty(env, aniRequest, "flag", flag)) {
750 return false;
751 }
752 request.flag = static_cast<PermissionUsageFlag>(flag);
753 return true;
754 }
755
GetPermissionUsedRecordExecute(ani_env * env,ani_object aniRequest)756 static ani_object GetPermissionUsedRecordExecute([[maybe_unused]] ani_env* env, ani_object aniRequest)
757 {
758 LOGI(PRI_DOMAIN, PRI_TAG, "GetPermissionUsedRecordExecute Call.");
759 if (env == nullptr || aniRequest == nullptr) {
760 LOGE(PRI_DOMAIN, PRI_TAG, "Env or aniRequest is null.");
761 return nullptr;
762 }
763
764 PermissionUsedRequest request;
765 if (!ParseRequest(env, aniRequest, request)) {
766 return nullptr;
767 }
768
769 PermissionUsedResult retResult;
770 int32_t errcode = PrivacyKit::GetPermissionUsedRecords(request, retResult);
771 if (errcode != ANI_OK) {
772 int32_t stsCode = GetStsErrorCode(errcode);
773 BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
774 return nullptr;
775 }
776 return ProcessRecordResult(env, retResult);
777 }
778
ConvertPermissionUsedTypeInfo(ani_env * env,const PermissionUsedTypeInfo & info)779 static ani_object ConvertPermissionUsedTypeInfo(ani_env *env, const PermissionUsedTypeInfo& info)
780 {
781 ani_object aObject = CreateClassObject(env, "L@ohos/privacyManager/privacyManager/PermissionUsedTypeInfoInner;");
782 if (aObject == nullptr) {
783 return nullptr;
784 }
785 if (!SetIntProperty(env, aObject, "tokenId", info.tokenId)) {
786 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to set tokenId.");
787 return nullptr;
788 }
789 if (!SetStringProperty(env, aObject, "permissionName", info.permissionName)) {
790 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to set PermissionName.");
791 return nullptr;
792 }
793 const char* permUsedTypeDes = "L@ohos/privacyManager/privacyManager/PermissionUsedType;";
794 if (!SetEnumProperty(env, aObject, permUsedTypeDes, "usedType", static_cast<uint32_t>(info.type))) {
795 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to set UsedType.");
796 return nullptr;
797 }
798 return aObject;
799 }
800
ConvertPermissionUsedTypeInfos(ani_env * env,const std::vector<PermissionUsedTypeInfo> & infos)801 static ani_ref ConvertPermissionUsedTypeInfos(ani_env* env, const std::vector<PermissionUsedTypeInfo>& infos)
802 {
803 ani_object arrayObj = CreateArrayObject(env, infos.size());
804 if (arrayObj == nullptr) {
805 return nullptr;
806 }
807 ani_size index = 0;
808 for (const auto& type : infos) {
809 ani_ref aniType = ConvertPermissionUsedTypeInfo(env, type);
810 if (aniType == nullptr) {
811 LOGE(PRI_DOMAIN, PRI_TAG, "AniType is null.");
812 continue;
813 }
814 ani_status status = env->Object_CallMethodByName_Void(
815 arrayObj, "$_set", "ILstd/core/Object;:V", index, aniType);
816 if (status != ANI_OK) {
817 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to Set type, status: %{public}d.", static_cast<int32_t>(status));
818 continue;
819 }
820 ++index;
821 }
822 return arrayObj;
823 }
824
GetPermissionUsedTypeInfosExecute(ani_env * env,ani_int aniTokenID,ani_string aniPermission)825 static ani_ref GetPermissionUsedTypeInfosExecute([[maybe_unused]] ani_env* env,
826 ani_int aniTokenID, ani_string aniPermission)
827 {
828 if (env == nullptr) {
829 LOGE(PRI_DOMAIN, PRI_TAG, "Env is null.");
830 return nullptr;
831 }
832 AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
833 std::string permission = ParseAniString(env, static_cast<ani_string>(aniPermission));
834 std::vector<PermissionUsedTypeInfo> typeInfos;
835 int32_t retCode = PrivacyKit::GetPermissionUsedTypeInfos(tokenID, permission, typeInfos);
836 if (retCode != RET_SUCCESS) {
837 BusinessErrorAni::ThrowError(env, GetStsErrorCode(retCode),
838 GetErrorMessage(GetStsErrorCode(retCode)));
839 return nullptr;
840 }
841 return ConvertPermissionUsedTypeInfos(env, typeInfos);
842 }
843
SetPermissionUsedRecordToggleStatusExecute(ani_env * env,ani_boolean status)844 static void SetPermissionUsedRecordToggleStatusExecute([[maybe_unused]] ani_env* env, ani_boolean status)
845 {
846 if (env == nullptr) {
847 LOGE(PRI_DOMAIN, PRI_TAG, "Env is null.");
848 return;
849 }
850 int32_t userID = 0;
851 int32_t retCode = PrivacyKit::SetPermissionUsedRecordToggleStatus(userID, status);
852 if (retCode != RET_SUCCESS) {
853 int32_t stsCode = BusinessErrorAni::GetStsErrorCode(retCode);
854 BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
855 }
856 }
857
GetPermissionUsedRecordToggleStatusExecute(ani_env * env)858 static ani_boolean GetPermissionUsedRecordToggleStatusExecute([[maybe_unused]] ani_env* env)
859 {
860 if (env == nullptr) {
861 LOGE(PRI_DOMAIN, PRI_TAG, "Env is null.");
862 return false;
863 }
864 int32_t userID = 0;
865 bool isToggleStatus = false;
866 int32_t retCode = PrivacyKit::GetPermissionUsedRecordToggleStatus(userID, isToggleStatus);
867 if (retCode != RET_SUCCESS) {
868 BusinessErrorAni::ThrowError(env, GetStsErrorCode(retCode), GetErrorMessage(GetStsErrorCode(retCode)));
869 return false;
870 }
871 return isToggleStatus;
872 }
873
InitPrivacyFunction(ani_env * env)874 void InitPrivacyFunction(ani_env *env)
875 {
876 LOGI(PRI_DOMAIN, PRI_TAG, "InitPrivacyFunction call.");
877 if (env == nullptr) {
878 LOGE(PRI_DOMAIN, PRI_TAG, "Env is null.");
879 return;
880 }
881 if (env->ResetError() != ANI_OK) {
882 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to ResetError.");
883 }
884
885 ani_namespace ns;
886 if (ANI_OK != env->FindNamespace("L@ohos/privacyManager/privacyManager;", &ns)) {
887 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to FindNamespace privacyManager.");
888 return;
889 }
890
891 // namespace method input param without ani_object
892 std::array nsMethods = {
893 ani_native_function {"addPermissionUsedRecordExecute", nullptr,
894 reinterpret_cast<void *>(AddPermissionUsedRecordExecute)},
895 ani_native_function {"startUsingPermissionExecute", nullptr,
896 reinterpret_cast<void *>(StartUsingPermissionExecute)},
897 ani_native_function {"stopUsingPermissionExecute", nullptr,
898 reinterpret_cast<void *>(StopUsingPermissionExecute)},
899 ani_native_function {"getPermissionUsedRecordExecute", nullptr,
900 reinterpret_cast<void *>(GetPermissionUsedRecordExecute)},
901 ani_native_function {"getPermissionUsedTypeInfosExecute", nullptr,
902 reinterpret_cast<void *>(GetPermissionUsedTypeInfosExecute)},
903 ani_native_function {"setPermissionUsedRecordToggleStatusExecute",
904 nullptr, reinterpret_cast<void *>(SetPermissionUsedRecordToggleStatusExecute)},
905 ani_native_function {"getPermissionUsedRecordToggleStatusExecute",
906 nullptr, reinterpret_cast<void *>(GetPermissionUsedRecordToggleStatusExecute)},
907 ani_native_function {"onExecute", nullptr, reinterpret_cast<void *>(RegisterPermActiveStatusCallback)},
908 ani_native_function {"offExecute", nullptr, reinterpret_cast<void *>(UnRegisterPermActiveStatusCallback)},
909 };
910 ani_status status = env->Namespace_BindNativeFunctions(ns, nsMethods.data(), nsMethods.size());
911 if (status != ANI_OK) {
912 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to Namespace_BindNativeFunctions status : %{public}d.", status);
913 }
914 if (env->ResetError() != ANI_OK) {
915 LOGE(PRI_DOMAIN, PRI_TAG, "Failed to ResetError.");
916 }
917 LOGI(PRI_DOMAIN, PRI_TAG, "InitPrivacyFunction end.");
918 }
919
920 extern "C" {
ANI_Constructor(ani_vm * vm,uint32_t * result)921 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
922 {
923 LOGI(PRI_DOMAIN, PRI_TAG, "ANI_Constructor begin.");
924 if (vm == nullptr || result == nullptr) {
925 LOGE(PRI_DOMAIN, PRI_TAG, "Vm or result is null.");
926 return ANI_INVALID_ARGS;
927 }
928 ani_env* env;
929 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
930 LOGE(PRI_DOMAIN, PRI_TAG, "Unsupported ANI_VERSION_1.");
931 return ANI_OUT_OF_MEMORY;
932 }
933 InitPrivacyFunction(env);
934 *result = ANI_VERSION_1;
935 LOGI(PRI_DOMAIN, PRI_TAG, "ANI_Constructor end.");
936 return ANI_OK;
937 }
938 }
939 } // namespace AccessToken
940 } // namespace Security
941 } // namespace OHOS