diff --git a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets index 0f685d4eb473a04ad27b422fcfaa70ab90450e44..06a5f9409f1d66e73fb55d64d619ffc15c7b9e78 100644 --- a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets +++ b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets @@ -32,7 +32,6 @@ export type PermissionRequestResult = _PermissionRequestResult; export default namespace abilityAccessCtrl { loadLibrary("accesstoken_ani.z"); - export enum GrantStatus { PERMISSION_DENIED = -1, @@ -122,7 +121,6 @@ export default namespace abilityAccessCtrl { throw err; } } - native function createAtManager(): AtManager; interface AtManager { @@ -141,10 +139,18 @@ export default namespace abilityAccessCtrl { permissionList: Array, requestCallback: AsyncCallback ): void; - + requestPermissionsFromUser( context: Context, permissionList: Array): Promise; + + requestPermissionOnSettingExecute( + context: Context, + permissionList: Array): Array; + + requestPermissionOnSetting( + context: Context, + permissionList: Array): Promise>; } class AtManagerInner implements AtManager { @@ -219,5 +225,31 @@ export default namespace abilityAccessCtrl { }); return p; } + + native requestPermissionOnSettingExecute( + context: Context, + permissionList: Array): Array; + + requestPermissionOnSetting(context: Context, permissionList: Array): + Promise> { + validateRequestParams(context, permissionList); + let p = new Promise>((resolve: (v: Array) => + void, reject: (error: BusinessError) => void) => { + let func = async() => { + try { + let work = new EAWorker(); + let job = work.run>((): Array => { + return new AtManagerInner().requestPermissionOnSettingExecute(context, permissionList); + }); + let result = job.Await(); + resolve(result as Array); + } catch (err: BusinessError) { + reject(err); + } + }; + func(); + }); + return p; + } } } \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h b/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h index c2a0b1e78641dc4491dcf5e181e50c62a056f541..a59e24264d9a65bd0eb47d5e9ab30b3d39a2d22f 100644 --- a/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h +++ b/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h @@ -155,6 +155,57 @@ struct ResultCallback { std::shared_ptr data = nullptr; }; +struct RequestPermOnSettingAsyncContext { + AccessTokenID tokenId = 0; + int32_t result = RET_SUCCESS; + PermissionGrantInfo info; + int32_t resultCode = -1; + + std::vector permissionList; + napi_value requestResult = nullptr; + int32_t errorCode = -1; + std::vector stateList; + + std::shared_ptr abilityContext; + std::shared_ptr uiExtensionContext; + bool uiAbilityFlag = false; + std::mutex loadlock; + +#ifdef EVENTHANDLER_ENABLE + std::shared_ptr handler_ = + std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); +#endif +}; + +class PermissonOnSettingUICallback { +public: + explicit PermissonOnSettingUICallback(ani_env* env, + const std::shared_ptr& reqContext); + ~PermissonOnSettingUICallback(); + void SetSessionId(int32_t sessionId); + void ReleaseHandler(int32_t code); + void OnRelease(int32_t releaseCode); + void OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result); + void OnReceive(const OHOS::AAFwk::WantParams& request); + void OnError(int32_t code, const std::string& name, const std::string& message); + void OnRemoteReady(const std::shared_ptr& uiProxy); + void OnDestroy(); + +private: + ani_env* env_; + std::shared_ptr reqContext_ = nullptr; + int32_t sessionId_ = 0; + + std::mutex lockReleaseFlag; + bool releaseFlag = false; +}; + +struct PermissonOnSettingResultCallback { + int32_t jsCode; + std::vector stateList; + std::shared_ptr data = nullptr; +}; + std::map>> RequestAsyncInstanceControl::instanceIdMap_; std::mutex RequestAsyncInstanceControl::instanceIdMutex_; } // namespace AccessToken diff --git a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp b/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp index ed15891e1ad077479250d8a671274bac05eddcff..91f81d1402808d09ee962b4e9e72ab63184faf8c 100644 --- a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp +++ b/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp @@ -19,6 +19,7 @@ #include #include "access_token.h" +#include "access_token_error.h" #include "accesstoken_kit.h" #include "accesstoken_log.h" #include "ani_base_context.h" @@ -33,10 +34,18 @@ namespace OHOS { namespace Security { namespace AccessToken { std::mutex g_lockFlag; +std::mutex g_lockWindowFlag; +bool g_windowFlag = false; static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniAbilityAccessCtrl" }; constexpr int32_t MAX_LENGTH = 256; +constexpr int32_t REQUEST_REALDY_EXIST = 1; +const int32_t PERM_NOT_BELONG_TO_SAME_GROUP = 2; +const int32_t PERM_IS_NOT_DECLARE = 3; +const int32_t ALL_PERM_GRANTED = 4; +const int32_t PERM_REVOKE_BY_USER = 5; const std::string PERMISSION_KEY = "ohos.user.grant.permission"; +const std::string PERMISSION_SETTING_KEY = "ohos.user.setting.permission"; const std::string STATE_KEY = "ohos.user.grant.permission.state"; const std::string RESULT_KEY = "ohos.user.grant.permission.result"; const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType"; @@ -49,6 +58,8 @@ const std::string WINDOW_RECTANGLE_TOP_KEY = "ohos.ability.params.request.top"; const std::string WINDOW_RECTANGLE_HEIGHT_KEY = "ohos.ability.params.request.height"; const std::string WINDOW_RECTANGLE_WIDTH_KEY = "ohos.ability.params.request.width"; const std::string REQUEST_TOKEN_KEY = "ohos.ability.params.request.token"; +const std::string RESULT_ERROR_KEY = "ohos.user.setting.error_code"; +const std::string PERMISSION_RESULT_KEY = "ohos.user.setting.permission.result"; #define SETTER_METHOD_NAME(property) "" #property @@ -106,17 +117,20 @@ static bool IsDynamicRequest(std::shared_ptr& asyncContext) return ret == AccessToken::TypePermissionOper::DYNAMIC_OPER; } -static OHOS::Ace::UIContent* GetUIContent(const std::shared_ptr& asyncContext) +static OHOS::Ace::UIContent* GetUIContent(const std::shared_ptr& abilityContext, + std::shared_ptr& uiExtensionContext, bool uiAbilityFlag) { - if (asyncContext == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "asyncContext nullptr"); - return nullptr; - } OHOS::Ace::UIContent* uiContent = nullptr; - if (asyncContext->uiAbilityFlag) { - uiContent = asyncContext->abilityContext->GetUIContent(); + if (uiAbilityFlag) { + if (abilityContext == nullptr) { + return nullptr; + } + uiContent = abilityContext->GetUIContent(); } else { - uiContent = asyncContext->uiExtensionContext->GetUIContent(); + if (uiExtensionContext == nullptr) { + return nullptr; + } + uiContent = uiExtensionContext->GetUIContent(); } return uiContent; } @@ -126,7 +140,8 @@ static void CreateUIExtensionMainThread(std::shared_ptr& as const std::shared_ptr& uiExtCallback) { auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() { - OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext); + OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); if (uiContent == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); asyncContext->result = AccessToken::RET_FAILED; @@ -226,7 +241,8 @@ static bool CreateUIExtension(std::shared_ptr& asyncContext static void GetInstanceId(std::shared_ptr& asyncContext) { auto task = [asyncContext]() { - OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext); + OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); if (uiContent == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); return; @@ -585,7 +601,8 @@ static ani_object RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* en static void CloseModalUIExtensionMainThread(std::shared_ptr& asyncContext, int32_t sessionId) { auto task = [asyncContext, sessionId]() { - Ace::UIContent* uiContent = GetUIContent(asyncContext); + Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); if (uiContent == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); asyncContext->result = RET_FAILED; @@ -754,7 +771,8 @@ void AuthorizationResult::WindowShownCallback() if (asyncContext == nullptr) { return; } - OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext); + OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); if ((uiContent == nullptr) || !(asyncContext->uiContentFlag)) { return; } @@ -882,6 +900,410 @@ static ani_int CheckAccessTokenSync([[maybe_unused]] ani_env* env, [[maybe_unuse return static_cast(asyncContext->result); } +static ani_status GetContext( + ani_env* env, const ani_object& aniContext, std::shared_ptr& asyncContext) +{ + auto context = OHOS::AbilityRuntime::GetStageModeContext(env, aniContext); + if (context == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetStageModeContext failed"); + return ANI_ERROR; + } + asyncContext->abilityContext = + OHOS::AbilityRuntime::Context::ConvertTo(context); + if (asyncContext->abilityContext != nullptr) { + auto abilityInfo = asyncContext->abilityContext->GetApplicationInfo(); + if (abilityInfo == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetApplicationInfo failed"); + return ANI_ERROR; + } + asyncContext->uiAbilityFlag = true; + asyncContext->tokenId = abilityInfo->accessTokenId; + } else { + asyncContext->uiExtensionContext = + OHOS::AbilityRuntime::Context::ConvertTo(context); + if (asyncContext->uiExtensionContext == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertTo UIExtensionContext failed"); + return ANI_ERROR; + } + auto uiExtensionInfo = asyncContext->uiExtensionContext->GetApplicationInfo(); + if (uiExtensionInfo == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetApplicationInfo failed"); + return ANI_ERROR; + } + asyncContext->tokenId = uiExtensionInfo->accessTokenId; + } + return ANI_OK; +} + +static bool ParseRequestPermissionOnSetting(ani_env* env, ani_object& aniContext, ani_array_ref& permissionList, + std::shared_ptr& asyncContext) +{ + if (GetContext(env, aniContext, asyncContext) != ANI_OK) { + BusinessErrorAni::ThrowParameterTypeError(env, STSErrorCode::STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("context", "UIAbility or UIExtension Context")); + return false; + } + if (!ProcessArrayString(env, nullptr, permissionList, asyncContext->permissionList)) { + BusinessErrorAni::ThrowParameterTypeError(env, STSErrorCode::STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("permissionList", "Array")); + return false; + } + return true; +} + +static void ThrowError(ani_env* env, int32_t errCode) +{ + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(errCode); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); +} + + +static void StateToEnumIndex(int32_t state, ani_size& enumIndex) +{ + if (state == 0) { + enumIndex = 1; + } else { + enumIndex = 0; + } +} + +static ani_ref ReturnResult(ani_env* env, std::shared_ptr& asyncContext) +{ + ani_class arrayCls = nullptr; + if (env->FindClass("Lescompat/Array;", &arrayCls) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass name Lescompat/Array failed!"); + return nullptr; + } + + ani_method arrayCtor; + if (env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass failed!"); + return nullptr; + } + + ani_object arrayObj; + if (env->Object_New(arrayCls, arrayCtor, &arrayObj, asyncContext->stateList.size()) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object new failed!"); + return nullptr; + } + + const char* enumDescriptor = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/GrantStatus;"; + ani_enum enumType; + if (env->FindEnum(enumDescriptor, &enumType) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass name %{public}s failed!", enumDescriptor); + return nullptr; + } + + ani_size index = 0; + for (const auto& state: asyncContext->stateList) { + ani_enum_item enumItem; + ani_size enumIndex = 0; + StateToEnumIndex(state, enumIndex); + if (env->Enum_GetEnumItemByIndex(enumType, enumIndex, &enumItem) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetEnumItemByIndex value %{public}u failed!", state); + break; + } + + if (env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, enumItem) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_CallMethodByName_Void $_set failed!"); + break; + } + index++; + } + + return arrayObj; +} + +static int32_t TransferToStsErrorCode(int32_t errCode) +{ + int32_t stsCode = STSErrorCode::STS_OK; + switch (errCode) { + case RET_SUCCESS: + stsCode = STSErrorCode::STS_OK; + break; + case REQUEST_REALDY_EXIST: + stsCode = STSErrorCode::STS_ERROR_REQUEST_IS_ALREADY_EXIST; + break; + case PERM_NOT_BELONG_TO_SAME_GROUP: + stsCode = STSErrorCode::STS_ERROR_PARAM_INVALID; + break; + case PERM_IS_NOT_DECLARE: + stsCode = STSErrorCode::STS_ERROR_PARAM_INVALID; + break; + case ALL_PERM_GRANTED: + stsCode = STSErrorCode::STS_ERROR_ALL_PERM_GRANTED; + break; + case PERM_REVOKE_BY_USER: + stsCode = STSErrorCode::STS_ERROR_PERM_REVOKE_BY_USER; + break; + default: + stsCode = STSErrorCode::STS_ERROR_INNER; + break; + } + ACCESSTOKEN_LOG_ERROR(LABEL, "dialog error(%{public}d) stsCode(%{public}d).", errCode, stsCode); + return stsCode; +} + +static ani_ref RequestPermissionOnSettingComplete( + ani_env* env, std::shared_ptr& asyncContext) +{ + if (asyncContext->result == RET_SUCCESS) { + ani_ref result = ReturnResult(env, asyncContext); + if (result != nullptr) { + return result; + } + asyncContext->errorCode = RET_FAILED; + } + + int32_t stsCode = TransferToStsErrorCode(asyncContext->errorCode); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + return nullptr; +} + +PermissonOnSettingUICallback::PermissonOnSettingUICallback(ani_env* env, + const std::shared_ptr& reqContext) +{ + this->env_ = env; + this->reqContext_ = reqContext; +} + +PermissonOnSettingUICallback::~PermissonOnSettingUICallback() +{} + +void PermissonOnSettingUICallback::SetSessionId(int32_t sessionId) +{ + this->sessionId_ = sessionId; +} + +static void CloseSettingModalUIExtensionMainThread(std::shared_ptr& asyncContext, + int32_t sessionId) +{ + auto task = [asyncContext, sessionId]() { + Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); + if (uiContent == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); + asyncContext->result = RET_FAILED; + return; + } + uiContent->CloseModalUIExtension(sessionId); + ACCESSTOKEN_LOG_INFO(LABEL, "Close end, sessionId: %{public}d", sessionId); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread"); + } else { + task(); + } +#else + task(); +#endif +} + +void PermissonOnSettingUICallback::ReleaseHandler(int32_t code) +{ + { + std::lock_guard lock(this->lockReleaseFlag); + if (this->releaseFlag) { + ACCESSTOKEN_LOG_WARN(LABEL, "Callback has executed."); + return; + } + this->releaseFlag = true; + } + CloseSettingModalUIExtensionMainThread(this->reqContext_, this->sessionId_); + if (code == -1) { + this->reqContext_->errorCode = code; + } + int32_t stsCode = TransferToStsErrorCode(this->reqContext_->errorCode); + if (stsCode != STSErrorCode::STS_OK) { + this->reqContext_->result = RET_FAILED; + } + this->reqContext_->loadlock.unlock(); + std::lock_guard lock(g_lockWindowFlag); + g_windowFlag = false; +} + +/* + * when UIExtensionAbility use terminateSelfWithResult + */ +void PermissonOnSettingUICallback::OnResult(int32_t resultCode, const AAFwk::Want& result) +{ + this->reqContext_->errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0); + this->reqContext_->stateList = result.GetIntArrayParam(PERMISSION_RESULT_KEY); + ACCESSTOKEN_LOG_INFO(LABEL, "ResultCode is %{public}d, errorCode=%{public}d, listSize=%{public}zu.", + resultCode, this->reqContext_->errorCode, this->reqContext_->stateList.size()); + ReleaseHandler(0); +} + +/* + * when UIExtensionAbility send message to UIExtensionComponent + */ +void PermissonOnSettingUICallback::OnReceive(const AAFwk::WantParams& receive) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Called!"); +} + +/* + * when UIExtensionAbility disconnect or use terminate or process die + * releaseCode is 0 when process normal exit + */ +void PermissonOnSettingUICallback::OnRelease(int32_t releaseCode) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "ReleaseCode is %{public}d", releaseCode); + + ReleaseHandler(-1); +} + +/* + * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error + */ +void PermissonOnSettingUICallback::OnError(int32_t code, const std::string& name, const std::string& message) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Code is %{public}d, name is %{public}s, message is %{public}s", + code, name.c_str(), message.c_str()); + + ReleaseHandler(-1); +} + +/* + * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init, + * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy + */ +void PermissonOnSettingUICallback::OnRemoteReady(const std::shared_ptr& uiProxy) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Connect to UIExtensionAbility successfully."); +} + +/* + * when UIExtensionComponent destructed + */ +void PermissonOnSettingUICallback::OnDestroy() +{ + ACCESSTOKEN_LOG_INFO(LABEL, "UIExtensionAbility destructed."); + ReleaseHandler(-1); +} + +static void CreateSettingUIExtensionMainThread(std::shared_ptr& asyncContext, + const AAFwk::Want& want, const Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks, + const std::shared_ptr& uiExtCallback) +{ + auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() { + Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); + if (uiContent == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to get ui content!"); + asyncContext->result = RET_FAILED; + return; + } + + Ace::ModalUIExtensionConfig config; + config.isProhibitBack = true; + int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config); + ACCESSTOKEN_LOG_INFO(LABEL, "Create end, sessionId: %{public}d, tokenId: %{public}d.", + sessionId, asyncContext->tokenId); + if (sessionId == 0) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create component, sessionId is 0."); + asyncContext->result = RET_FAILED; + return; + } + uiExtCallback->SetSessionId(sessionId); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread"); + } else { + task(); + } +#else + task(); +#endif +} + +static bool StartUIExtension(ani_env* env, std::shared_ptr& asyncContext) +{ + AccessTokenKit::GetPermissionManagerInfo(asyncContext->info); + + OHOS::AAFwk::Want want; + want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.permStateAbilityName); + want.SetParam(PERMISSION_SETTING_KEY, asyncContext->permissionList); + want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); + + auto uiExtCallback = std::make_shared(env, asyncContext); + Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = { + [uiExtCallback](int32_t releaseCode) { + uiExtCallback->OnRelease(releaseCode); + }, + [uiExtCallback](int32_t resultCode, const AAFwk::Want& result) { + uiExtCallback->OnResult(resultCode, result); + }, + [uiExtCallback](const AAFwk::WantParams& receive) { + uiExtCallback->OnReceive(receive); + }, + [uiExtCallback](int32_t code, const std::string& name, [[maybe_unused]] const std::string& message) { + uiExtCallback->OnError(code, name, name); + }, + [uiExtCallback](const std::shared_ptr& uiProxy) { + uiExtCallback->OnRemoteReady(uiProxy); + }, + [uiExtCallback]() { + uiExtCallback->OnDestroy(); + }, + }; + + { + std::lock_guard lock(g_lockWindowFlag); + if (g_windowFlag) { + ACCESSTOKEN_LOG_WARN(LABEL, "The request already exists."); + asyncContext->result = RET_FAILED; + asyncContext->errorCode = REQUEST_REALDY_EXIST; + return false; + } + g_windowFlag = true; + } + CreateSettingUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); + if (asyncContext->result == RET_FAILED) { + { + std::lock_guard lock(g_lockWindowFlag); + g_windowFlag = false; + return false; + } + } + return true; +} + +static ani_ref RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_object aniContext, ani_array_ref permissionList) +{ + if (env == nullptr || permissionList == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "permissionList or env null"); + return nullptr; + } + + std::shared_ptr asyncContext = + std::make_shared(); + + if (!ParseRequestPermissionOnSetting(env, aniContext, permissionList, asyncContext)) { + return nullptr; + } + + static AccessTokenID selfTokenID = static_cast(GetSelfTokenID()); + if (selfTokenID != asyncContext->tokenId) { + ACCESSTOKEN_LOG_ERROR(LABEL, "The context tokenID %{public}d is not same with selfTokenID %{public}d.", + asyncContext->tokenId, selfTokenID); + ThrowError(env, RET_FAILED); + return nullptr; + } + asyncContext->loadlock.lock(); + bool flag = StartUIExtension(env, asyncContext); + if (!flag) { + asyncContext->loadlock.unlock(); + } + asyncContext->loadlock.lock(); + ani_ref result = RequestPermissionOnSettingComplete(env, asyncContext); + asyncContext->loadlock.unlock(); + return result; +} + extern "C" { ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) { @@ -923,6 +1345,9 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) ani_native_function { "requestPermissionsFromUserExecute", "Lapplication/Context/Context;Lescompat/Array;:Lsecurity/PermissionRequestResult/PermissionRequestResult;", reinterpret_cast(RequestPermissionsFromUserExecute) }, + ani_native_function { "requestPermissionOnSettingExecute", + "Lapplication/Context/Context;Lescompat/Array;:Lescompat/Array;", + reinterpret_cast(RequestPermissionOnSettingExecute) }, }; if (ANI_OK != env->Class_BindNativeMethods(cls, claMethods.data(), claMethods.size())) { ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", className);