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