• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ani_ability_access_ctrl.h"
17 
18 #include <iostream>
19 #include <map>
20 #include <mutex>
21 
22 #include "access_token_error.h"
23 #include "accesstoken_kit.h"
24 #include "accesstoken_common_log.h"
25 #include "ani_request_global_switch_on_setting.h"
26 #include "ani_request_permission.h"
27 #include "ani_request_permission_on_setting.h"
28 #include "hisysevent.h"
29 #include "parameter.h"
30 #include "permission_list_state.h"
31 #include "permission_map.h"
32 #include "token_setproc.h"
33 
34 namespace OHOS {
35 namespace Security {
36 namespace AccessToken {
37 namespace {
38 constexpr int32_t VALUE_MAX_LEN = 32;
39 std::mutex g_lockCache;
40 static PermissionParamCache g_paramCache;
41 std::map<std::string, PermissionStatusCache> g_cache;
42 static constexpr const char* PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change";
43 }
44 constexpr const char* PERM_STATE_CHANGE_FIELD_TOKEN_ID = "tokenID";
45 constexpr const char* PERM_STATE_CHANGE_FIELD_PERMISSION_NAME = "permissionName";
46 constexpr const char* PERM_STATE_CHANGE_FIELD_CHANGE = "change";
47 std::mutex g_lockForPermStateChangeRegisters;
48 std::vector<RegisterPermStateChangeInf*> g_permStateChangeRegisters;
49 static const char* REGISTER_PERMISSION_STATE_CHANGE_TYPE = "permissionStateChange";
50 static const char* REGISTER_SELF_PERMISSION_STATE_CHANGE_TYPE = "selfPermissionStateChange";
51 
RegisterPermStateChangeScopePtr(const PermStateChangeScope & subscribeInfo)52 RegisterPermStateChangeScopePtr::RegisterPermStateChangeScopePtr(const PermStateChangeScope& subscribeInfo)
53     : PermStateChangeCallbackCustomize(subscribeInfo)
54 {}
55 
~RegisterPermStateChangeScopePtr()56 RegisterPermStateChangeScopePtr::~RegisterPermStateChangeScopePtr()
57 {
58     if (vm_ == nullptr) {
59         LOGE(ATM_DOMAIN, ATM_TAG, "Vm is null.");
60         return;
61     }
62     bool isSameThread = (threadId_ == std::this_thread::get_id());
63     ani_env* env = isSameThread ? env_ : GetCurrentEnv(vm_);
64     if (env == nullptr) {
65         LOGE(ATM_DOMAIN, ATM_TAG, "Current env is null.");
66     } else if (ref_ != nullptr) {
67         env->GlobalReference_Delete(ref_);
68     }
69     ref_ = nullptr;
70 
71     if (!isSameThread) {
72         vm_->DetachCurrentThread();
73     }
74 }
75 
SetEnv(ani_env * env)76 void RegisterPermStateChangeScopePtr::SetEnv(ani_env* env)
77 {
78     env_ = env;
79 }
80 
SetCallbackRef(const ani_ref & ref)81 void RegisterPermStateChangeScopePtr::SetCallbackRef(const ani_ref& ref)
82 {
83     ref_ = ref;
84 }
85 
SetValid(bool valid)86 void RegisterPermStateChangeScopePtr::SetValid(bool valid)
87 {
88     std::lock_guard<std::mutex> lock(validMutex_);
89     valid_ = valid;
90 }
91 
SetVm(ani_vm * vm)92 void RegisterPermStateChangeScopePtr::SetVm(ani_vm* vm)
93 {
94     vm_ = vm;
95 }
96 
SetThreadId(const std::thread::id threadId)97 void RegisterPermStateChangeScopePtr::SetThreadId(const std::thread::id threadId)
98 {
99     threadId_ = threadId;
100 }
101 
SetStringProperty(ani_env * env,ani_object & aniObject,const char * propertyName,const std::string & in)102 static bool SetStringProperty(ani_env* env, ani_object& aniObject, const char* propertyName, const std::string& in)
103 {
104     ani_string aniString = CreateAniString(env, in);
105     if (env->Object_SetPropertyByName_Ref(aniObject, propertyName, aniString) != ANI_OK) {
106         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to Object_SetPropertyByName_Ref!");
107         return false;
108     }
109 
110     return true;
111 }
112 
transPermStateChangeTypeToAniInt(const int32_t permStateChangeType,ani_size & index)113 static void transPermStateChangeTypeToAniInt(const int32_t permStateChangeType, ani_size& index)
114 {
115     index = static_cast<ani_size>(permStateChangeType);
116     return;
117 }
118 
ConvertPermStateChangeInfo(ani_env * env,const PermStateChangeInfo & result,ani_object & aniObject)119 static void ConvertPermStateChangeInfo(ani_env* env, const PermStateChangeInfo& result, ani_object& aniObject)
120 {
121     // class implements from interface should use property, independent class use field
122     aniObject = CreateClassObject(env, "L@ohos/abilityAccessCtrl/abilityAccessCtrl/PermissionStateChangeInfoInner;");
123     if (aniObject == nullptr) {
124         return;
125     }
126 
127     // set tokenId: int32_t
128     SetIntProperty(env, aniObject, PERM_STATE_CHANGE_FIELD_TOKEN_ID, static_cast<int32_t>(result.tokenID));
129 
130     // set permissionName: Permissions
131     SetStringProperty(env, aniObject, PERM_STATE_CHANGE_FIELD_PERMISSION_NAME, result.permissionName);
132 
133     // set permStateChangeType: int32_t
134     ani_size index;
135     transPermStateChangeTypeToAniInt(result.permStateChangeType, index);
136     const char* activeStatusDes = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/PermissionStateChangeType;";
137     SetEnumProperty(
138         env, aniObject, activeStatusDes, PERM_STATE_CHANGE_FIELD_CHANGE, static_cast<int32_t>(index));
139 }
140 
PermStateChangeCallback(PermStateChangeInfo & PermStateChangeInfo)141 void RegisterPermStateChangeScopePtr::PermStateChangeCallback(PermStateChangeInfo& PermStateChangeInfo)
142 {
143     if (vm_ == nullptr) {
144         LOGE(ATM_DOMAIN, ATM_TAG, "Vm is null.");
145         return;
146     }
147 
148     ani_option interopEnabled {"--interop=disable", nullptr};
149     ani_options aniArgs {1, &interopEnabled};
150     ani_env* env;
151     if (vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env) != ANI_OK) {
152         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to AttachCurrentThread!");
153         return;
154     }
155     ani_fn_object fnObj = reinterpret_cast<ani_fn_object>(ref_);
156     if (fnObj == nullptr) {
157         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to Reinterpret_cast!");
158         return;
159     }
160 
161     ani_object aniObject;
162     ConvertPermStateChangeInfo(env, PermStateChangeInfo, aniObject);
163 
164     std::vector<ani_ref> args;
165     args.emplace_back(aniObject);
166     ani_ref result;
167     if (!AniFunctionalObjectCall(env, fnObj, args.size(), args.data(), result)) {
168         return;
169     }
170     if (vm_->DetachCurrentThread() != ANI_OK) {
171         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to DetachCurrentThread!");
172         return;
173     }
174 }
175 
CreateAtManager(ani_env * env)176 static ani_object CreateAtManager([[maybe_unused]] ani_env* env)
177 {
178     ani_object atManagerObj = {};
179     if (env == nullptr) {
180         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null");
181         return atManagerObj;
182     }
183 
184     static const char* className = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;";
185     ani_class cls;
186     if (ANI_OK != env->FindClass(className, &cls)) {
187         LOGE(ATM_DOMAIN, ATM_TAG, "Not found %{public}s.", className);
188         return atManagerObj;
189     }
190 
191     ani_method ctor;
192     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
193         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ctor %{public}s.", className);
194         return atManagerObj;
195     }
196 
197     if (ANI_OK != env->Object_New(cls, ctor, &atManagerObj)) {
198         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to create Object %{public}s.", className);
199         return atManagerObj;
200     }
201     return atManagerObj;
202 }
203 
GetPermParamValue()204 static std::string GetPermParamValue()
205 {
206     long long sysCommitId = GetSystemCommitId();
207     if (sysCommitId == g_paramCache.sysCommitIdCache) {
208         LOGD(ATM_DOMAIN, ATM_TAG, "SysCommitId = %{public}lld.", sysCommitId);
209         return g_paramCache.sysParamCache;
210     }
211     g_paramCache.sysCommitIdCache = sysCommitId;
212     if (g_paramCache.handle == PARAM_DEFAULT_VALUE) {
213         int32_t handle = static_cast<int32_t>(FindParameter(PERMISSION_STATUS_CHANGE_KEY));
214         if (handle == PARAM_DEFAULT_VALUE) {
215             LOGE(ATM_DOMAIN, ATM_TAG, "Failed to FindParameter.");
216             return "-1";
217         }
218         g_paramCache.handle = handle;
219     }
220 
221     int32_t currCommitId = static_cast<int32_t>(GetParameterCommitId(g_paramCache.handle));
222     if (currCommitId != g_paramCache.commitIdCache) {
223         char value[VALUE_MAX_LEN] = { 0 };
224         auto ret = GetParameterValue(g_paramCache.handle, value, VALUE_MAX_LEN - 1);
225         if (ret < 0) {
226             LOGE(ATM_DOMAIN, ATM_TAG, "Return default value, ret=%{public}d.", ret);
227             return "-1";
228         }
229         std::string resStr(value);
230         g_paramCache.sysParamCache = resStr;
231         g_paramCache.commitIdCache = currCommitId;
232     }
233     return g_paramCache.sysParamCache;
234 }
235 
UpdatePermissionCache(AtManagerAsyncContext * asyncContext)236 static void UpdatePermissionCache(AtManagerAsyncContext* asyncContext)
237 {
238     std::lock_guard<std::mutex> lock(g_lockCache);
239     auto iter = g_cache.find(asyncContext->permissionName);
240     if (iter != g_cache.end()) {
241         std::string currPara = GetPermParamValue();
242         if (currPara != iter->second.paramValue) {
243             asyncContext->grantStatus =
244                 AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName);
245             iter->second.status = asyncContext->grantStatus;
246             iter->second.paramValue = currPara;
247             LOGD(ATM_DOMAIN, ATM_TAG, "Param changed currPara %{public}s.", currPara.c_str());
248         } else {
249             asyncContext->grantStatus = iter->second.status;
250         }
251     } else {
252         asyncContext->grantStatus =
253             AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName);
254         g_cache[asyncContext->permissionName].status = asyncContext->grantStatus;
255         g_cache[asyncContext->permissionName].paramValue = GetPermParamValue();
256         LOGD(ATM_DOMAIN, ATM_TAG, "Success to set G_cacheParam(%{public}s).",
257             g_cache[asyncContext->permissionName].paramValue.c_str());
258     }
259 }
260 
CheckAccessTokenExecute(ani_env * env,ani_object object,ani_int aniTokenID,ani_string aniPermission)261 static ani_int CheckAccessTokenExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object,
262     ani_int aniTokenID, ani_string aniPermission)
263 {
264     if (env == nullptr) {
265         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
266         return AccessToken::PermissionState::PERMISSION_DENIED;
267     }
268     AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
269     std::string permissionName = ParseAniString(env, static_cast<ani_string>(aniPermission));
270     if ((!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) ||
271         (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName))) {
272         LOGE(ATM_DOMAIN, ATM_TAG, "TokenId(%{public}u) or Permission(%{public}s) is invalid.",
273             tokenID, permissionName.c_str());
274         return AccessToken::PermissionState::PERMISSION_DENIED;
275     }
276 
277     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext();
278     if (asyncContext == nullptr) {
279         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to alloc memory for asyncContext.");
280         return AccessToken::PermissionState::PERMISSION_DENIED;
281     }
282     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
283     asyncContext->tokenId = static_cast<AccessTokenID>(tokenID);
284     asyncContext->permissionName = permissionName;
285     static uint64_t selfTokenId = GetSelfTokenID();
286     if (asyncContext->tokenId != static_cast<AccessTokenID>(selfTokenId)) {
287         asyncContext->grantStatus = AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, permissionName);
288         return static_cast<ani_int>(asyncContext->grantStatus);
289     }
290     UpdatePermissionCache(asyncContext);
291     LOGI(ATM_DOMAIN, ATM_TAG, "CheckAccessTokenExecute result : %{public}d.", asyncContext->grantStatus);
292     return static_cast<ani_int>(asyncContext->grantStatus);
293 }
294 
GrantUserGrantedPermissionExecute(ani_env * env,ani_object object,ani_int aniTokenID,ani_string aniPermission,ani_int aniFlags)295 static void GrantUserGrantedPermissionExecute([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
296     ani_int aniTokenID, ani_string aniPermission, ani_int aniFlags)
297 {
298     if (env == nullptr) {
299         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
300         return;
301     }
302     AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
303     std::string permissionName = ParseAniString(env, static_cast<ani_string>(aniPermission));
304     uint32_t permissionFlags = static_cast<uint32_t>(aniFlags);
305     if ((!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) ||
306         (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName)) ||
307         (!BusinessErrorAni::ValidatePermissionFlagWithThrowError(env, permissionFlags))) {
308         LOGE(ATM_DOMAIN, ATM_TAG, "TokenId(%{public}u) or Permission(%{public}s)  or flags(%{public}u)is invalid.",
309             tokenID, permissionName.c_str(), permissionFlags);
310         return;
311     }
312 
313     PermissionBriefDef def;
314     if (!GetPermissionBriefDef(permissionName, def) || def.grantMode != USER_GRANT) {
315         std::string errMsg = GetErrorMessage(STS_ERROR_PERMISSION_NOT_EXIST,
316             "The specified permission does not exist or is not a user_grant permission.");
317         BusinessErrorAni::ThrowError(env, STS_ERROR_PERMISSION_NOT_EXIST, errMsg);
318         return;
319     }
320 
321     int32_t res = AccessTokenKit::GrantPermission(tokenID, permissionName, permissionFlags);
322     if (res != RET_SUCCESS) {
323         int32_t stsCode = BusinessErrorAni::GetStsErrorCode(res);
324         BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
325     }
326 }
327 
RevokeUserGrantedPermissionExecute(ani_env * env,ani_object object,ani_int aniTokenID,ani_string aniPermission,ani_int aniFlags)328 static void RevokeUserGrantedPermissionExecute([[maybe_unused]] ani_env* env,
329     [[maybe_unused]] ani_object object, ani_int aniTokenID, ani_string aniPermission, ani_int aniFlags)
330 {
331     LOGI(ATM_DOMAIN, ATM_TAG, "RevokeUserGrantedPermission begin.");
332     if (env == nullptr) {
333         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
334         return;
335     }
336     AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
337     std::string permissionName = ParseAniString(env, static_cast<ani_string>(aniPermission));
338     uint32_t permissionFlags = static_cast<uint32_t>(aniFlags);
339     if ((!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) ||
340         (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName)) ||
341         (!BusinessErrorAni::ValidatePermissionFlagWithThrowError(env, permissionFlags))) {
342         LOGE(ATM_DOMAIN, ATM_TAG, "TokenId(%{public}u) or Permission(%{public}s)  or flags(%{public}u)is invalid.",
343             tokenID, permissionName.c_str(), permissionFlags);
344         return;
345     }
346 
347     PermissionBriefDef def;
348     if (!GetPermissionBriefDef(permissionName, def) || def.grantMode != USER_GRANT) {
349         std::string errMsg = GetErrorMessage(STS_ERROR_PERMISSION_NOT_EXIST,
350             "The specified permission does not exist or is not a user_grant permission.");
351         BusinessErrorAni::ThrowError(env, STS_ERROR_PERMISSION_NOT_EXIST, errMsg);
352         return;
353     }
354 
355     int32_t ret = AccessTokenKit::RevokePermission(tokenID, permissionName, permissionFlags);
356     if (ret != RET_SUCCESS) {
357         int32_t stsCode = BusinessErrorAni::GetStsErrorCode(ret);
358         BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
359     }
360 }
361 
GetVersionExecute(ani_env * env,ani_object object)362 static ani_int GetVersionExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object)
363 {
364     LOGI(ATM_DOMAIN, ATM_TAG, "GetVersionExecute begin.");
365     uint32_t version = -1;
366     if (env == nullptr) {
367         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
368         return static_cast<ani_int>(version);
369     }
370 
371     int32_t result = AccessTokenKit::GetVersion(version);
372     if (result != RET_SUCCESS) {
373         int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result);
374         BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
375         return static_cast<ani_int>(version);
376     }
377     return static_cast<ani_int>(version);
378 }
379 
GetPermissionsStatusExecute(ani_env * env,ani_object object,ani_int aniTokenID,ani_array_ref aniPermissionList)380 static ani_ref GetPermissionsStatusExecute([[maybe_unused]] ani_env* env,
381     [[maybe_unused]] ani_object object, ani_int aniTokenID, ani_array_ref aniPermissionList)
382 {
383     LOGI(ATM_DOMAIN, ATM_TAG, "GetPermissionsStatusExecute begin.");
384     if ((env == nullptr) || (aniPermissionList == nullptr)) {
385         LOGE(ATM_DOMAIN, ATM_TAG, "AniPermissionList or env is null.");
386         return nullptr;
387     }
388     AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
389     if (!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) {
390         LOGE(ATM_DOMAIN, ATM_TAG, "TokenId(%{public}u) is invalid.", tokenID);
391         return nullptr;
392     }
393     std::vector<std::string> permissionList = ParseAniStringVector(env, aniPermissionList);
394     if (permissionList.empty()) {
395         BusinessErrorAni::ThrowError(
396             env, STS_ERROR_INNER,  GetErrorMessage(STS_ERROR_INNER, "Empty permissionList."));
397         return nullptr;
398     }
399 
400     std::vector<PermissionListState> permList;
401     for (const auto& permission : permissionList) {
402         PermissionListState permState;
403         permState.permissionName = permission;
404         permState.state = INVALID_OPER;
405         permList.emplace_back(permState);
406     }
407 
408     int32_t result = RET_SUCCESS;
409     result = AccessTokenKit::GetPermissionsStatus(tokenID, permList);
410     if (result != RET_SUCCESS) {
411         int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result);
412         BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
413         return nullptr;
414     }
415     std::vector<int32_t> permissionQueryResults;
416     for (const auto& permState : permList) {
417         permissionQueryResults.emplace_back(permState.state);
418     }
419 
420     return CreateAniArrayInt(env, permissionQueryResults);
421 }
422 
GetPermissionFlagsExecute(ani_env * env,ani_object object,ani_int aniTokenID,ani_string aniPermissionName)423 static ani_int GetPermissionFlagsExecute([[maybe_unused]] ani_env* env,
424     [[maybe_unused]] ani_object object, ani_int aniTokenID, ani_string aniPermissionName)
425 {
426     uint32_t flag = PERMISSION_DEFAULT_FLAG;
427     if (env == nullptr) {
428         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
429         return flag;
430     }
431     AccessTokenID tokenID = static_cast<AccessTokenID>(aniTokenID);
432     std::string permissionName = ParseAniString(env, static_cast<ani_string>(aniPermissionName));
433     if ((!BusinessErrorAni::ValidateTokenIDWithThrowError(env, tokenID)) ||
434         (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName))) {
435         LOGE(ATM_DOMAIN, ATM_TAG, "TokenId(%{public}u) or Permission(%{public}s) is invalid.",
436             tokenID, permissionName.c_str());
437         return flag;
438     }
439 
440     int32_t result = AccessTokenKit::GetPermissionFlag(tokenID, permissionName, flag);
441     if (result != RET_SUCCESS) {
442         LOGE(ATM_DOMAIN, ATM_TAG, "Result = %{public}d  errcode = %{public}d",
443             result, BusinessErrorAni::GetStsErrorCode(result));
444         BusinessErrorAni::ThrowError(
445             env, BusinessErrorAni::GetStsErrorCode(result), GetErrorMessage(BusinessErrorAni::GetStsErrorCode(result)));
446     }
447     return flag;
448 }
449 
SetPermissionRequestToggleStatusExecute(ani_env * env,ani_object object,ani_string aniPermissionName,ani_int status)450 static void SetPermissionRequestToggleStatusExecute([[maybe_unused]] ani_env* env,
451     [[maybe_unused]] ani_object object, ani_string aniPermissionName, ani_int status)
452 {
453     if (env == nullptr) {
454         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
455         return;
456     }
457     std::string permissionName = ParseAniString(env, static_cast<ani_string>(aniPermissionName));
458     if (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName)) {
459         LOGE(ATM_DOMAIN, ATM_TAG, "Invalid Permission(%{public}s).", permissionName.c_str());
460         return;
461     }
462     int32_t result = AccessTokenKit::SetPermissionRequestToggleStatus(permissionName, status, 0);
463     if (result != RET_SUCCESS) {
464         BusinessErrorAni::ThrowError(
465             env, BusinessErrorAni::GetStsErrorCode(result), GetErrorMessage(BusinessErrorAni::GetStsErrorCode(result)));
466     }
467     return;
468 }
469 
GetPermissionRequestToggleStatusExecute(ani_env * env,ani_object object,ani_string aniPermissionName)470 static ani_int GetPermissionRequestToggleStatusExecute([[maybe_unused]] ani_env* env,
471     [[maybe_unused]] ani_object object, ani_string aniPermissionName)
472 {
473     uint32_t flag = CLOSED;
474     if (env == nullptr) {
475         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
476         return flag;
477     }
478     std::string permissionName = ParseAniString(env, static_cast<ani_string>(aniPermissionName));
479     if (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName)) {
480         LOGE(ATM_DOMAIN, ATM_TAG, "Invalid Permission(%{public}s).", permissionName.c_str());
481         return flag;
482     }
483 
484     int32_t result = AccessTokenKit::GetPermissionRequestToggleStatus(permissionName, flag, 0);
485     if (result != RET_SUCCESS) {
486         BusinessErrorAni::ThrowError(
487             env, BusinessErrorAni::GetStsErrorCode(result), GetErrorMessage(BusinessErrorAni::GetStsErrorCode(result)));
488     }
489     return flag;
490 }
491 
RequestAppPermOnSettingExecute(ani_env * env,ani_object object,ani_int tokenID)492 static void RequestAppPermOnSettingExecute([[maybe_unused]] ani_env* env,
493     [[maybe_unused]] ani_object object, ani_int tokenID)
494 {
495     if (env == nullptr) {
496         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
497         return;
498     }
499 
500     int32_t result = AccessTokenKit::RequestAppPermOnSetting(static_cast<AccessTokenID>(tokenID));
501     if (result != RET_SUCCESS) {
502         LOGE(ATM_DOMAIN, ATM_TAG, "Result=%{public}d, errcode=%{public}d.",
503             result, BusinessErrorAni::GetStsErrorCode(result));
504         BusinessErrorAni::ThrowError(env, BusinessErrorAni::GetStsErrorCode(result),
505             GetErrorMessage(BusinessErrorAni::GetStsErrorCode(result)));
506     }
507 }
508 
SetupPermissionSubscriber(RegisterPermStateChangeInf * context,const PermStateChangeScope & scopeInfo,const ani_ref & callback)509 static bool SetupPermissionSubscriber(
510     RegisterPermStateChangeInf* context, const PermStateChangeScope& scopeInfo, const ani_ref& callback)
511 {
512     ani_vm* vm;
513     if (context->env->GetVM(&vm) != ANI_OK) {
514         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetVM!");
515         return false;
516     }
517 
518     auto sortedTokenIDs = scopeInfo.tokenIDs;
519     auto sortedPermList = scopeInfo.permList;
520     std::sort(sortedTokenIDs.begin(), sortedTokenIDs.end());
521     std::sort(sortedPermList.begin(), sortedPermList.end());
522 
523     context->callbackRef = callback;
524     context->scopeInfo.tokenIDs = sortedTokenIDs;
525     context->scopeInfo.permList = sortedPermList;
526     context->subscriber = std::make_shared<RegisterPermStateChangeScopePtr>(scopeInfo);
527     context->subscriber->SetVm(vm);
528     context->subscriber->SetEnv(context->env);
529     context->subscriber->SetCallbackRef(callback);
530 
531     return true;
532 }
533 
ParseInputToRegister(const ani_string & aniType,const ani_array_ref & aniId,const ani_array_ref & aniArray,const ani_ref & aniCallback,RegisterPermStateChangeInf * context,bool isReg)534 static bool ParseInputToRegister(const ani_string& aniType, const ani_array_ref& aniId, const ani_array_ref& aniArray,
535     const ani_ref& aniCallback, RegisterPermStateChangeInf* context, bool isReg)
536 {
537     std::string type = ParseAniString(context->env, aniType);
538     if (type.empty()) {
539         BusinessErrorAni::ThrowError(context->env, STS_ERROR_PARAM_INVALID, GetParamErrorMsg(
540             "type", "permissionStateChange or selfPermissionStateChange"));
541         return false;
542     }
543     if ((type != REGISTER_SELF_PERMISSION_STATE_CHANGE_TYPE) && (type != REGISTER_PERMISSION_STATE_CHANGE_TYPE)) {
544         BusinessErrorAni::ThrowError(
545             context->env, STS_ERROR_PARAM_INVALID, GetParamErrorMsg("type", "type is invalid"));
546         return false;
547     }
548 
549     context->permStateChangeType = type;
550     context->threadId = std::this_thread::get_id();
551 
552     PermStateChangeScope scopeInfo;
553     std::string errMsg;
554     if (type == REGISTER_PERMISSION_STATE_CHANGE_TYPE) {
555         if (!AniParseAccessTokenIDArray(context->env, aniId, scopeInfo.tokenIDs)) {
556             BusinessErrorAni::ThrowError(
557                 context->env, STS_ERROR_PARAM_INVALID, GetParamErrorMsg("tokenIDList", "Array<int>"));
558             return false;
559         }
560     } else if (type == REGISTER_SELF_PERMISSION_STATE_CHANGE_TYPE) {
561         scopeInfo.tokenIDs = {GetSelfTokenID()};
562     }
563     scopeInfo.permList = ParseAniStringVector(context->env, aniArray);
564     bool hasCallback = true;
565     if (!isReg) {
566         hasCallback = !(AniIsRefUndefined(context->env, aniCallback));
567     }
568 
569     ani_ref callback = nullptr;
570     if (hasCallback) {
571         if (!AniParseCallback(context->env, aniCallback, callback)) {
572             BusinessErrorAni::ThrowError(context->env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg(
573                 "callback", "Callback<PermissionStateChangeInfo>"));
574             return false;
575         }
576     }
577 
578     return SetupPermissionSubscriber(context, scopeInfo, callback);
579 }
580 
IsExistRegister(const RegisterPermStateChangeInf * context)581 static bool IsExistRegister(const RegisterPermStateChangeInf* context)
582 {
583     PermStateChangeScope targetScopeInfo;
584     context->subscriber->GetScope(targetScopeInfo);
585     std::vector<AccessTokenID> targetTokenIDs = targetScopeInfo.tokenIDs;
586     std::vector<std::string> targetPermList = targetScopeInfo.permList;
587     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
588 
589     for (const auto& item : g_permStateChangeRegisters) {
590         PermStateChangeScope scopeInfo;
591         item->subscriber->GetScope(scopeInfo);
592 
593         bool hasPermIntersection = false;
594         // Special cases:
595         // 1.Have registered full, and then register some
596         // 2.Have registered some, then register full
597         if (scopeInfo.permList.empty() || targetPermList.empty()) {
598             hasPermIntersection = true;
599         }
600         for (const auto& PermItem : targetPermList) {
601             if (hasPermIntersection) {
602                 break;
603             }
604             auto iter = std::find(scopeInfo.permList.begin(), scopeInfo.permList.end(), PermItem);
605             if (iter != scopeInfo.permList.end()) {
606                 hasPermIntersection = true;
607             }
608         }
609 
610         bool hasTokenIdIntersection = false;
611         if (scopeInfo.tokenIDs.empty() || targetTokenIDs.empty()) {
612             hasTokenIdIntersection = true;
613         }
614         for (const auto& tokenItem : targetTokenIDs) {
615             if (hasTokenIdIntersection) {
616                 break;
617             }
618             auto iter = std::find(scopeInfo.tokenIDs.begin(), scopeInfo.tokenIDs.end(), tokenItem);
619             if (iter != scopeInfo.tokenIDs.end()) {
620                 hasTokenIdIntersection = true;
621             }
622         }
623         bool isEqual = true;
624         if (!AniIsCallbackRefEqual(context->env, item->callbackRef, context->callbackRef, item->threadId, isEqual)) {
625             return true;
626         }
627         if (hasPermIntersection && hasTokenIdIntersection && isEqual) {
628             return true;
629         }
630     }
631     return false;
632 }
633 
RegisterPermStateChangeCallback(ani_env * env,ani_object object,ani_string aniType,ani_array_ref aniId,ani_array_ref aniArray,ani_ref callback)634 static void RegisterPermStateChangeCallback([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object,
635     ani_string aniType, ani_array_ref aniId, ani_array_ref aniArray, ani_ref callback)
636 {
637     if (env == nullptr) {
638         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
639         return;
640     }
641 
642     RegisterPermStateChangeInf* registerPermStateChangeInf = new (std::nothrow) RegisterPermStateChangeInf();
643     if (registerPermStateChangeInf == nullptr) {
644         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to allocate memory for RegisterPermStateChangeInf!");
645         return;
646     }
647     registerPermStateChangeInf->env = env;
648     std::unique_ptr<RegisterPermStateChangeInf> callbackPtr {registerPermStateChangeInf};
649     if (!ParseInputToRegister(aniType, aniId, aniArray, callback, registerPermStateChangeInf, true)) {
650         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to ParseInputToRegister.");
651         return;
652     }
653 
654     if (IsExistRegister(registerPermStateChangeInf)) {
655         LOGE(ATM_DOMAIN, ATM_TAG,
656             "Faield to Subscribe. The current subscriber has existed or Reference_StrictEquals failed!");
657         std::string errMsg = "The API reuses the same input. The subscriber already exists.";
658         if (registerPermStateChangeInf->permStateChangeType == REGISTER_SELF_PERMISSION_STATE_CHANGE_TYPE) {
659             BusinessErrorAni::ThrowError(env, STSErrorCode::STS_ERROR_NOT_USE_TOGETHER,
660                 GetErrorMessage(STSErrorCode::STS_ERROR_NOT_USE_TOGETHER, errMsg));
661         } else {
662             BusinessErrorAni::ThrowError(env, STSErrorCode::STS_ERROR_PARAM_INVALID,
663                 GetErrorMessage(STSErrorCode::STS_ERROR_PARAM_INVALID, errMsg));
664         }
665         return;
666     }
667 
668     int32_t result;
669     if (registerPermStateChangeInf->permStateChangeType == REGISTER_PERMISSION_STATE_CHANGE_TYPE) {
670         result = AccessTokenKit::RegisterPermStateChangeCallback(registerPermStateChangeInf->subscriber);
671     } else {
672         result = AccessTokenKit::RegisterSelfPermStateChangeCallback(registerPermStateChangeInf->subscriber);
673     }
674     if (result != RET_SUCCESS) {
675         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to RegisterPermStateChangeCallback.");
676         int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result);
677         BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
678         return;
679     }
680 
681     {
682         std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
683         g_permStateChangeRegisters.emplace_back(registerPermStateChangeInf);
684         LOGI(ATM_DOMAIN, ATM_TAG,
685             "g_PermStateChangeRegisters size = %{public}zu.", g_permStateChangeRegisters.size());
686     }
687     callbackPtr.release();
688     return;
689 }
690 
FindAndGetSubscriberInVector(RegisterPermStateChangeInf * unregisterPermStateChangeInf,std::vector<RegisterPermStateChangeInf * > & batchPermStateChangeRegisters)691 static bool FindAndGetSubscriberInVector(RegisterPermStateChangeInf* unregisterPermStateChangeInf,
692     std::vector<RegisterPermStateChangeInf*>& batchPermStateChangeRegisters)
693 {
694     LOGD(ATM_DOMAIN, ATM_TAG, "FindAndGetSubscriberInVector In.");
695     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
696     std::vector<AccessTokenID> targetTokenIDs = unregisterPermStateChangeInf->scopeInfo.tokenIDs;
697     std::vector<std::string> targetPermList = unregisterPermStateChangeInf->scopeInfo.permList;
698     bool callbackEqual;
699     ani_ref callbackRef = unregisterPermStateChangeInf->callbackRef;
700     bool isUndef = AniIsRefUndefined(unregisterPermStateChangeInf->env, unregisterPermStateChangeInf->callbackRef);
701 
702     for (const auto& item : g_permStateChangeRegisters) {
703         if (isUndef) {
704             // batch delete currentThread callback
705             LOGI(ATM_DOMAIN, ATM_TAG, "Callback is null.");
706             callbackEqual = IsCurrentThread(item->threadId);
707         } else {
708             LOGI(ATM_DOMAIN, ATM_TAG, "Compare callback.");
709             if (!AniIsCallbackRefEqual(unregisterPermStateChangeInf->env, callbackRef,
710                 unregisterPermStateChangeInf->callbackRef, item->threadId, callbackEqual)) {
711                 continue;
712             }
713         }
714 
715         PermStateChangeScope scopeInfo;
716         item->subscriber->GetScope(scopeInfo);
717         if (scopeInfo.tokenIDs == targetTokenIDs && scopeInfo.permList == targetPermList) {
718             unregisterPermStateChangeInf->subscriber = item->subscriber;
719             batchPermStateChangeRegisters.emplace_back(item);
720         }
721     }
722     if (!batchPermStateChangeRegisters.empty()) {
723         return true;
724     }
725     return false;
726 }
727 
DeleteRegisterFromVector(const RegisterPermStateChangeInf * context)728 static void DeleteRegisterFromVector(const RegisterPermStateChangeInf* context)
729 {
730     std::vector<AccessTokenID> targetTokenIDs = context->scopeInfo.tokenIDs;
731     std::vector<std::string> targetPermList = context->scopeInfo.permList;
732     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
733     auto item = g_permStateChangeRegisters.begin();
734     while (item != g_permStateChangeRegisters.end()) {
735         PermStateChangeScope stateChangeScope;
736         (*item)->subscriber->GetScope(stateChangeScope);
737         bool callbackEqual = true;
738         if (!AniIsCallbackRefEqual(
739             context->env, (*item)->callbackRef, context->callbackRef, (*item)->threadId, callbackEqual)) {
740             continue;
741         }
742         if (!callbackEqual) {
743             continue;
744         }
745 
746         if ((stateChangeScope.tokenIDs == targetTokenIDs) && (stateChangeScope.permList == targetPermList)) {
747             delete *item;
748             *item = nullptr;
749             g_permStateChangeRegisters.erase(item);
750             break;
751         } else {
752             ++item;
753         }
754     }
755 }
756 
UnregisterPermStateChangeCallback(ani_env * env,ani_object object,ani_string aniType,ani_array_ref aniId,ani_array_ref aniArray,ani_ref callback)757 static void UnregisterPermStateChangeCallback([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object,
758     ani_string aniType, ani_array_ref aniId, ani_array_ref aniArray, ani_ref callback)
759 {
760     LOGD(ATM_DOMAIN, ATM_TAG, "UnregisterPermStateChangeCallback In.");
761     if (env == nullptr) {
762         BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STSErrorCode::STS_ERROR_INNER));
763         return;
764     }
765 
766     RegisterPermStateChangeInf* context = new (std::nothrow) RegisterPermStateChangeInf();
767     if (context == nullptr) {
768         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to allocate memory for UnRegisterPermStateChangeInf!");
769         return;
770     }
771     context->env = env;
772     std::unique_ptr<RegisterPermStateChangeInf> callbackPtr {context};
773 
774     if (!ParseInputToRegister(aniType, aniId, aniArray, callback, context, false)) {
775         return;
776     }
777 
778     std::vector<RegisterPermStateChangeInf*> batchPermStateChangeRegisters;
779     if (!FindAndGetSubscriberInVector(context, batchPermStateChangeRegisters)) {
780         LOGE(ATM_DOMAIN, ATM_TAG,
781             "Failed to Unsubscribe. The current subscriber does not exist or Reference_StrictEquals failed!");
782         if (context->permStateChangeType == REGISTER_SELF_PERMISSION_STATE_CHANGE_TYPE) {
783             BusinessErrorAni::ThrowError(
784                 env, STSErrorCode::STS_ERROR_NOT_USE_TOGETHER,
785                 GetErrorMessage(STSErrorCode::STS_ERROR_NOT_USE_TOGETHER));
786         } else {
787             BusinessErrorAni::ThrowError(
788                 env, STSErrorCode::STS_ERROR_PARAM_INVALID, GetErrorMessage(STSErrorCode::STS_ERROR_PARAM_INVALID));
789         }
790         return;
791     }
792     for (const auto& item : batchPermStateChangeRegisters) {
793         PermStateChangeScope scopeInfo;
794         item->subscriber->GetScope(scopeInfo);
795         int32_t result;
796         if (context->permStateChangeType == REGISTER_PERMISSION_STATE_CHANGE_TYPE) {
797             result = AccessTokenKit::UnRegisterPermStateChangeCallback(item->subscriber);
798         } else {
799             result = AccessTokenKit::UnRegisterSelfPermStateChangeCallback(item->subscriber);
800         }
801         if (result == RET_SUCCESS) {
802             DeleteRegisterFromVector(item);
803         } else {
804             LOGE(ATM_DOMAIN, ATM_TAG, "Failed to UnregisterPermStateChangeCallback");
805             int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result);
806             BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode));
807             return;
808         }
809     }
810     return;
811 }
812 
AtManagerBindNativeFunction(ani_env * env,ani_class & cls)813 static ani_status AtManagerBindNativeFunction(ani_env* env, ani_class& cls)
814 {
815     std::array clsMethods = {
816         ani_native_function { "checkAccessTokenExecute", nullptr, reinterpret_cast<void*>(CheckAccessTokenExecute) },
817         ani_native_function { "requestPermissionsFromUserExecute",
818             nullptr, reinterpret_cast<void*>(RequestPermissionsFromUserExecute) },
819         ani_native_function { "requestPermissionOnSettingExecute",
820             nullptr, reinterpret_cast<void*>(RequestPermissionOnSettingExecute) },
821         ani_native_function {"requestGlobalSwitchExecute",
822             nullptr, reinterpret_cast<void*>(RequestGlobalSwitchExecute) },
823         ani_native_function { "grantUserGrantedPermissionExecute", nullptr,
824             reinterpret_cast<void*>(GrantUserGrantedPermissionExecute) },
825         ani_native_function { "revokeUserGrantedPermissionExecute",
826             nullptr, reinterpret_cast<void*>(RevokeUserGrantedPermissionExecute) },
827         ani_native_function { "getVersionExecute", nullptr, reinterpret_cast<void*>(GetVersionExecute) },
828         ani_native_function { "getPermissionsStatusExecute",
829             nullptr, reinterpret_cast<void*>(GetPermissionsStatusExecute) },
830         ani_native_function{ "getPermissionFlagsExecute",
831             nullptr, reinterpret_cast<void*>(GetPermissionFlagsExecute) },
832         ani_native_function{ "setPermissionRequestToggleStatusExecute",
833             nullptr, reinterpret_cast<void*>(SetPermissionRequestToggleStatusExecute) },
834         ani_native_function{ "getPermissionRequestToggleStatusExecute",
835             nullptr, reinterpret_cast<void*>(GetPermissionRequestToggleStatusExecute) },
836         ani_native_function{ "requestAppPermOnSettingExecute",
837             nullptr, reinterpret_cast<void*>(RequestAppPermOnSettingExecute) },
838         ani_native_function { "onExcute", nullptr, reinterpret_cast<void*>(RegisterPermStateChangeCallback) },
839         ani_native_function { "offExcute", nullptr, reinterpret_cast<void*>(UnregisterPermStateChangeCallback) },
840     };
841     return env->Class_BindNativeMethods(cls, clsMethods.data(), clsMethods.size());
842 }
843 
InitAbilityCtrlFunction(ani_env * env)844 ani_status InitAbilityCtrlFunction(ani_env* env)
845 {
846     if (env == nullptr) {
847         LOGE(ATM_DOMAIN, ATM_TAG, "Env is null.");
848         return ANI_OUT_OF_MEMORY;
849     }
850 
851     ani_status retStatus = ANI_OK;
852     ani_namespace aniAtNamespace;
853     const char* atNamespace = "L@ohos/abilityAccessCtrl/abilityAccessCtrl;";
854     retStatus = env->FindNamespace(atNamespace, &aniAtNamespace);
855     if (retStatus != ANI_OK) {
856         LOGE(ATM_DOMAIN, ATM_TAG, "Not found %{public}s.", atNamespace);
857         return retStatus;
858     }
859     std::array methods = {
860         ani_native_function { "createAtManager", nullptr, reinterpret_cast<void*>(CreateAtManager) },
861     };
862     retStatus = env->Namespace_BindNativeFunctions(aniAtNamespace, methods.data(), methods.size());
863     if (retStatus != ANI_OK) {
864         LOGE(ATM_DOMAIN, ATM_TAG, "Cannot bind native methods to %{public}s.", atNamespace);
865         return retStatus;
866     };
867     const char* atManagerClassName = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;";
868     ani_class aniAtManagerClassName;
869     retStatus = env->FindClass(atManagerClassName, &aniAtManagerClassName);
870     if (retStatus != ANI_OK) {
871         LOGE(ATM_DOMAIN, ATM_TAG, "Not found %{public}s.", atManagerClassName);
872         return retStatus;
873     }
874     retStatus = AtManagerBindNativeFunction(env, aniAtManagerClassName);
875     if (retStatus != ANI_OK) {
876         LOGE(ATM_DOMAIN, ATM_TAG, "Cannot bind native methods to %{public}s", atManagerClassName);
877         return retStatus;
878     };
879     return retStatus;
880 }
881 extern "C" {
ANI_Constructor(ani_vm * vm,uint32_t * result)882 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
883 {
884     if (vm == nullptr) {
885         LOGE(ATM_DOMAIN, ATM_TAG, "Vm is null.");
886         return ANI_INVALID_ARGS;
887     }
888     ani_env* env;
889     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
890         LOGE(ATM_DOMAIN, ATM_TAG, "Unsupported ANI_VERSION_1.");
891         return ANI_OUT_OF_MEMORY;
892     }
893     ani_status ret = InitAbilityCtrlFunction(env);
894     *result = ANI_VERSION_1;
895     if (ret != ANI_OK) {
896         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to init atmanger function.");
897     }
898     return ret;
899 }
900 }
901 } // namespace AccessToken
902 } // namespace Security
903 } // namespace OHOS
904