diff --git a/frameworks/accesstoken/BUILD.gn b/frameworks/accesstoken/BUILD.gn index b05a2c71619d22d4fb37c568c55c2522ff4ac886..9960d5a51f134ce3e63fc0e734da08174caf77af 100644 --- a/frameworks/accesstoken/BUILD.gn +++ b/frameworks/accesstoken/BUILD.gn @@ -44,6 +44,8 @@ ohos_shared_library("accesstoken_communication_adapter_cxx") { "src/permission_def_parcel.cpp", "src/permission_list_state_parcel.cpp", "src/permission_state_full_parcel.cpp", + "src/permission_state_change_info_parcel.cpp", + "src/permission_state_change_scope_parcel.cpp", ] deps = [ "//utils/native/base:utils" ] diff --git a/frameworks/accesstoken/include/i_accesstoken_manager.h b/frameworks/accesstoken/include/i_accesstoken_manager.h index 46312f8d17a6daa96ffb84df853d9db8e323d494..fde0e93e548ee7c8e867e1030a0577b22f4acdfe 100644 --- a/frameworks/accesstoken/include/i_accesstoken_manager.h +++ b/frameworks/accesstoken/include/i_accesstoken_manager.h @@ -25,11 +25,13 @@ #include "hap_token_info_for_sync_parcel.h" #include "hap_token_info_parcel.h" #include "iremote_broker.h" +#include "i_permission_state_callback.h" #include "native_token_info_for_sync_parcel.h" #include "native_token_info_parcel.h" #include "permission_def_parcel.h" #include "permission_list_state_parcel.h" #include "permission_state_full_parcel.h" +#include "permission_state_change_scope_parcel.h" namespace OHOS { namespace Security { @@ -62,6 +64,9 @@ public: virtual int GetHapTokenInfo(AccessTokenID tokenID, HapTokenInfoParcel& hapTokenInfoRes) = 0; virtual int UpdateHapToken( AccessTokenID tokenID, const std::string& appIDDesc, const HapPolicyParcel& policyParcel) = 0; + virtual int32_t RegisterPermStateChangeCallback( + const PermStateChangeScopeParcel& scope, const sptr& callback) = 0; + virtual int32_t UnRegisterPermStateChangeCallback(const sptr& callback) = 0; #ifdef TOKEN_SYNC_ENABLE virtual int GetHapTokenInfoFromRemote(AccessTokenID tokenID, @@ -108,6 +113,8 @@ public: DUMP_TOKENINFO = 0xff30, GET_PERMISSION_OPER_STATE = 0xff31, + REGISTER_PERMISSION_STATE_CHANGE_CALLBACK = 0xff32, + UNREGISTER_PERMISSION_STATE_CHANGE_CALLBACK = 0xff33, }; }; } // namespace AccessToken diff --git a/frameworks/accesstoken/include/permission_state_change_info_parcel.h b/frameworks/accesstoken/include/permission_state_change_info_parcel.h new file mode 100644 index 0000000000000000000000000000000000000000..f10b5c4e83bdf67e3325ef7eeabf4376d465b3a5 --- /dev/null +++ b/frameworks/accesstoken/include/permission_state_change_info_parcel.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STATE_CHANGE_INFO_PRACEL_H +#define PERMISSION_STATE_CHANGE_INFO_PRACEL_H + +#include "parcel.h" +#include "permission_state_change_info.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +struct PermissionStateChangeInfoParcel final : public Parcelable { + PermissionStateChangeInfoParcel() = default; + + ~PermissionStateChangeInfoParcel() override = default; + + bool Marshalling(Parcel& out) const override; + + static PermissionStateChangeInfoParcel* Unmarshalling(Parcel& in); + + PermStateChangeInfo changeInfo; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +#endif // PERMISSION_STATE_CHANGE_INFO_PRACEL_H diff --git a/frameworks/accesstoken/include/permission_state_change_scope_parcel.h b/frameworks/accesstoken/include/permission_state_change_scope_parcel.h new file mode 100644 index 0000000000000000000000000000000000000000..9bd77dca02af6be35d74df1ad6d06375794253df --- /dev/null +++ b/frameworks/accesstoken/include/permission_state_change_scope_parcel.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STATE_CHANGE_SCOPE_PRACEL_H +#define PERMISSION_STATE_CHANGE_SCOPE_PRACEL_H + +#include "parcel.h" +#include "permission_state_change_info.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +struct PermStateChangeScopeParcel final : public Parcelable { + PermStateChangeScopeParcel() = default; + + ~PermStateChangeScopeParcel() override = default; + + bool Marshalling(Parcel& out) const override; + + static PermStateChangeScopeParcel* Unmarshalling(Parcel& in); + + PermStateChangeScope scope; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +#endif // PERMISSION_STATE_CHANGE_SCOPE_PRACEL_H diff --git a/frameworks/accesstoken/src/permission_state_change_info_parcel.cpp b/frameworks/accesstoken/src/permission_state_change_info_parcel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..173a2d25b8e3155d6dee4393818521c4d29e1f0e --- /dev/null +++ b/frameworks/accesstoken/src/permission_state_change_info_parcel.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_change_info_parcel.h" +#include "parcel_utils.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +bool PermissionStateChangeInfoParcel::Marshalling(Parcel& out) const +{ + RETURN_IF_FALSE(out.WriteInt32(this->changeInfo.PermStateChangeType)); + RETURN_IF_FALSE(out.WriteUint32(this->changeInfo.tokenID)); + RETURN_IF_FALSE(out.WriteString(this->changeInfo.permissionName)); + return true; +} + +PermissionStateChangeInfoParcel* PermissionStateChangeInfoParcel::Unmarshalling(Parcel& in) +{ + auto* permissionStateParcel = new (std::nothrow) PermissionStateChangeInfoParcel(); + if (permissionStateParcel == nullptr) { + return nullptr; + } + RELEASE_IF_FALSE(in.ReadInt32(permissionStateParcel->changeInfo.PermStateChangeType), permissionStateParcel); + RELEASE_IF_FALSE(in.ReadUint32(permissionStateParcel->changeInfo.tokenID), permissionStateParcel); + RELEASE_IF_FALSE(in.ReadString(permissionStateParcel->changeInfo.permissionName), permissionStateParcel); + + return permissionStateParcel; +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/frameworks/accesstoken/src/permission_state_change_scope_parcel.cpp b/frameworks/accesstoken/src/permission_state_change_scope_parcel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..003109135418bd9eebeedc33c439112ca44fdde3 --- /dev/null +++ b/frameworks/accesstoken/src/permission_state_change_scope_parcel.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_change_scope_parcel.h" +#include "parcel_utils.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +bool PermStateChangeScopeParcel::Marshalling(Parcel& out) const +{ + RETURN_IF_FALSE(out.WriteUint32((this->scope.tokenIDs.size()))); + for (auto tokenID : this->scope.tokenIDs) { + RETURN_IF_FALSE(out.WriteUint32(tokenID)); + } + + RETURN_IF_FALSE(out.WriteUint32((this->scope.permList.size()))); + for (auto permissionName : this->scope.permList) { + RETURN_IF_FALSE(out.WriteString(permissionName)); + } + return true; +} + +PermStateChangeScopeParcel* PermStateChangeScopeParcel::Unmarshalling(Parcel& in) +{ + auto* permStateChangeScopeParcel = new (std::nothrow) PermStateChangeScopeParcel(); + if (permStateChangeScopeParcel == nullptr) { + return nullptr; + } + uint32_t tokenIdListSize = 0; + RELEASE_IF_FALSE(in.ReadUint32(tokenIdListSize), permStateChangeScopeParcel); + RELEASE_IF_FALSE(tokenIdListSize <= TOKENID_LIST_SIZE_MAX, permStateChangeScopeParcel); + for (uint32_t i = 0; i < tokenIdListSize; i++) { + AccessTokenID tokenID; + RELEASE_IF_FALSE(in.ReadUint32(tokenID), permStateChangeScopeParcel); + permStateChangeScopeParcel->scope.tokenIDs.emplace_back(tokenID); + } + + uint32_t permListSize = 0; + RELEASE_IF_FALSE(in.ReadUint32(permListSize), permStateChangeScopeParcel); + RELEASE_IF_FALSE(permListSize <= PERM_LIST_SIZE_MAX, permStateChangeScopeParcel); + for (uint32_t i = 0; i < permListSize; i++) { + std::string permName;; + RELEASE_IF_FALSE(in.ReadString(permName), permStateChangeScopeParcel); + permStateChangeScopeParcel->scope.permList.emplace_back(permName); + } + return permStateChangeScopeParcel; +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/interfaces/innerkits/accesstoken/BUILD.gn b/interfaces/innerkits/accesstoken/BUILD.gn index 2fa4702487f35e78bcbafa78b55e6dcfcbcb9668..b88358311ca89d4ad51c076fc5e80b16f5826df2 100644 --- a/interfaces/innerkits/accesstoken/BUILD.gn +++ b/interfaces/innerkits/accesstoken/BUILD.gn @@ -41,6 +41,9 @@ ohos_shared_library("libaccesstoken_sdk") { "src/accesstoken_kit.cpp", "src/accesstoken_manager_client.cpp", "src/accesstoken_manager_proxy.cpp", + "src/perm_state_callback_customize.cpp", + "src/permission_state_change_callback.cpp", + "src/permission_state_change_callback_stub.cpp", ] deps = [ diff --git a/interfaces/innerkits/accesstoken/include/accesstoken_kit.h b/interfaces/innerkits/accesstoken/include/accesstoken_kit.h index 4ee095db065c8d1b77936ced8368ce784136838c..ee1b8dd56fd5dd8ff6c24a1c7c8cce0491e56f9a 100644 --- a/interfaces/innerkits/accesstoken/include/accesstoken_kit.h +++ b/interfaces/innerkits/accesstoken/include/accesstoken_kit.h @@ -21,10 +21,13 @@ #include "access_token.h" #include "hap_token_info.h" +#include "i_permission_state_callback.h" #include "native_token_info.h" #include "permission_def.h" #include "permission_list_state.h" +#include "permission_state_change_info.h" #include "permission_state_full.h" +#include "perm_state_callback_customize.h" namespace OHOS { namespace Security { @@ -56,6 +59,9 @@ public: static int GrantPermission(AccessTokenID tokenID, const std::string& permissionName, int flag); static int RevokePermission(AccessTokenID tokenID, const std::string& permissionName, int flag); static int ClearUserGrantedPermissionState(AccessTokenID tokenID); + static int32_t RegisterPermStateChangeCallback( + const std::shared_ptr &callback); + static int32_t UnRegisterPermStateChangeCallback(const std::shared_ptr &callback); #ifdef TOKEN_SYNC_ENABLE static int GetHapTokenInfoFromRemote(AccessTokenID tokenID, HapTokenInfoForSync& hapSync); diff --git a/interfaces/innerkits/accesstoken/include/i_permission_state_callback.h b/interfaces/innerkits/accesstoken/include/i_permission_state_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..508f28c1e0835b77563c49633fcb4cd25590f13c --- /dev/null +++ b/interfaces/innerkits/accesstoken/include/i_permission_state_callback.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef I_PERMISSION_STATE_CALLBACK_H +#define I_PERMISSION_STATE_CALLBACK_H + +#include + +#include "access_token.h" +#include "errors.h" +#include "iremote_broker.h" +#include "permission_state_change_info.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +class IPermissionStateCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.security.accesstoken.IPermissionStateCallback"); + + virtual void PermStateChangeCallback(PermStateChangeInfo& result) = 0; + + enum { + PERMISSION_STATE_CHANGE = 0, + }; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +#endif // I_PERMISSION_STATE_CALLBACK_H diff --git a/interfaces/innerkits/accesstoken/include/perm_state_callback_customize.h b/interfaces/innerkits/accesstoken/include/perm_state_callback_customize.h new file mode 100644 index 0000000000000000000000000000000000000000..76349204438a9c36978c24666d84b0775f8f07fb --- /dev/null +++ b/interfaces/innerkits/accesstoken/include/perm_state_callback_customize.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNER_KITS_PERM_STATE_CALLBACK_CUSTOMIZE_H +#define INTERFACES_INNER_KITS_PERM_STATE_CALLBACK_CUSTOMIZE_H + +#include "access_token.h" +#include "permission_state_change_info.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +class PermStateChangeCbCustomize { +public: + PermStateChangeCbCustomize(); + explicit PermStateChangeCbCustomize(const PermStateChangeScope &subscribeInfo); + virtual ~PermStateChangeCbCustomize(); + + virtual void PermStateChangeCallback(PermStateChangeInfo& result) = 0; + + void GetScope(PermStateChangeScope &scopeInfo) const; + +private: + PermStateChangeScope scopeInfo_; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +#endif // INTERFACES_INNER_KITS_PERM_STATE_CALLBACK_CUSTOMIZE_H \ No newline at end of file diff --git a/interfaces/innerkits/accesstoken/include/permission_state_change_info.h b/interfaces/innerkits/accesstoken/include/permission_state_change_info.h new file mode 100644 index 0000000000000000000000000000000000000000..2ed8f71451783c28a3531ae6282b1ba0c333445a --- /dev/null +++ b/interfaces/innerkits/accesstoken/include/permission_state_change_info.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNER_KITS_PERMISSION_STATE_CHANGE_INFO_H +#define INTERFACES_INNER_KITS_PERMISSION_STATE_CHANGE_INFO_H + +#include +#include + +#include "access_token.h" + +namespace OHOS { +namespace Security { +namespace AccessToken{ +#define TOKENID_LIST_SIZE_MAX 1024 +#define PERM_LIST_SIZE_MAX 1024 + +struct PermStateChangeInfo { + int32_t PermStateChangeType; + AccessTokenID tokenID; + std::string permissionName; +}; + +struct PermStateChangeScope { + std::vector tokenIDs; + std::vector permList; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +#endif // INTERFACES_INNER_KITS_PERMISSION_STATE_CHANGE_INFO_H diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp b/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp index a20496aa740e0cc921ca226710eea0835b055272..ae399bfb760378a2d7cc09953ef0c15084901405 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp +++ b/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp @@ -22,6 +22,7 @@ #include "accesstoken_manager_client.h" #include "constant_common.h" #include "data_validator.h" +#include "perm_state_callback_customize.h" namespace OHOS { namespace Security { @@ -302,6 +303,24 @@ int AccessTokenKit::ClearUserGrantedPermissionState(AccessTokenID tokenID) return AccessTokenManagerClient::GetInstance().ClearUserGrantedPermissionState(tokenID); } +int32_t AccessTokenKit::RegisterPermStateChangeCallback( + const std::shared_ptr &callback) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "called"); + if (callback == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "callback is nullptr"); + return RET_FAILED; + } + return AccessTokenManagerClient::GetInstance().RegisterPermStateChangeCallback(callback); +} + +int32_t AccessTokenKit::UnRegisterPermStateChangeCallback( + const std::shared_ptr &callback) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "called"); + return AccessTokenManagerClient::GetInstance().UnRegisterPermStateChangeCallback(callback); +} + #ifdef TOKEN_SYNC_ENABLE int AccessTokenKit::GetHapTokenInfoFromRemote(AccessTokenID tokenID, HapTokenInfoForSync& hapSync) { diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp index 7f88044333e47875412c76c06fde0f333de31ab5..f7eb783e9278352e31f539da3fb55b650793b669 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp +++ b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp @@ -22,6 +22,7 @@ #include "iservice_registry.h" #include "native_token_info_for_sync_parcel.h" #include "native_token_info.h" +#include "permission_state_change_callback.h" namespace OHOS { namespace Security { @@ -195,6 +196,81 @@ int AccessTokenManagerClient::ClearUserGrantedPermissionState(AccessTokenID toke return proxy->ClearUserGrantedPermissionState(tokenID); } +int32_t AccessTokenManagerClient::CreatePermStateChangeCallback( + const std::shared_ptr& customizedCb, sptr& callbackObject) +{ + std::lock_guard lock(callbackMutex_); + auto goalCallback = callbackMap_.find(customizedCb); + if (goalCallback != callbackMap_.end()) { + callbackObject = goalCallback->second->AsObject(); + ACCESSTOKEN_LOG_ERROR(LABEL, "subscriber already has os account event listener"); + return RET_FAILED; + } else { + if (callbackMap_.size() == 200) { + ACCESSTOKEN_LOG_ERROR(LABEL, "the maximum number of subscribers has been reached"); + return RET_FAILED; + } + sptr callback = new (std::nothrow) PermissionStateCallback(customizedCb); + if (!callback) { + ACCESSTOKEN_LOG_ERROR(LABEL, "memory allocation for callback failed!"); + return RET_FAILED; + } + callbackObject = callback->AsObject(); + callbackMap_[customizedCb] = callback; + } + return RET_SUCCESS; +} + +int32_t AccessTokenManagerClient::RegisterPermStateChangeCallback( + const std::shared_ptr &customizedCb) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "called!"); + + if (customizedCb == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "customizedCb is nullptr"); + return RET_FAILED; + } + + sptr callbackObject = nullptr; + int32_t result = CreatePermStateChangeCallback(customizedCb, callbackObject); + if (result != RET_SUCCESS) { + return result; + } + auto proxy = GetProxy(); + if (proxy == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "proxy is null"); + return RET_FAILED; + } + + PermStateChangeScopeParcel scopeParcel; + customizedCb->GetScope(scopeParcel.scope); + + return proxy->RegisterPermStateChangeCallback(scopeParcel, callbackObject); +} + +int32_t AccessTokenManagerClient::UnRegisterPermStateChangeCallback( + const std::shared_ptr &customizedCb) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "%{public}s: called!", __func__); + + std::lock_guard lock(callbackMutex_); + auto goalCallback = callbackMap_.find(customizedCb); + if (goalCallback == callbackMap_.end()) { + ACCESSTOKEN_LOG_ERROR(LABEL, "goalCallback already is not exist"); + return RET_FAILED; + } + + auto proxy = GetProxy(); + if (proxy == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "proxy is null"); + return RET_FAILED; + } + + int32_t result = proxy->UnRegisterPermStateChangeCallback(goalCallback->second->AsObject()); + callbackMap_.erase(goalCallback); + return result; +} + AccessTokenIDEx AccessTokenManagerClient::AllocHapToken(const HapInfoParams& info, const HapPolicyParams& policy) { AccessTokenIDEx res = { 0 }; diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h index 82e867de4d1b231a9675520fc0cefbde06a5b805..963f3c9cf4a9a6d42999ec4fd481b15d255db878 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h +++ b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h @@ -16,6 +16,7 @@ #ifndef ACCESSTOKEN_MANAGER_CLIENT_H #define ACCESSTOKEN_MANAGER_CLIENT_H +#include #include #include #include @@ -29,7 +30,9 @@ #include "native_token_info.h" #include "nocopyable.h" #include "permission_def.h" +#include "permission_state_change_callback.h" #include "permission_state_full.h" +#include "perm_state_callback_customize.h" namespace OHOS { namespace Security { @@ -60,6 +63,10 @@ public: int UpdateHapToken(AccessTokenID tokenID, const std::string& appIDDesc, const HapPolicyParams& policy); int GetHapTokenInfo(AccessTokenID tokenID, HapTokenInfo& hapTokenInfoRes); int GetNativeTokenInfo(AccessTokenID tokenID, NativeTokenInfo& nativeTokenInfoRes); + int32_t RegisterPermStateChangeCallback( + const std::shared_ptr &customizedCallback); + int32_t UnRegisterPermStateChangeCallback( + const std::shared_ptr &customizedCb); #ifdef TOKEN_SYNC_ENABLE int GetHapTokenInfoFromRemote(AccessTokenID tokenID, HapTokenInfoForSync& hapSync); @@ -77,6 +84,8 @@ public: private: AccessTokenManagerClient(); + int32_t CreatePermStateChangeCallback( + const std::shared_ptr& customizedCallback, sptr& callback); DISALLOW_COPY_AND_MOVE(AccessTokenManagerClient); std::mutex proxyMutex_; @@ -84,6 +93,8 @@ private: sptr serviceDeathObserver_ = nullptr; void InitProxy(); sptr GetProxy(); + std::mutex callbackMutex_; + std::map, sptr> callbackMap_; }; } // namespace AccessToken } // namespace Security diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.cpp b/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.cpp index d8fd1e7e8ee0766eddeb392943ce47badb8e877e..6b549c1334b73368a22f194d349165ff21e9b137 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.cpp +++ b/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.cpp @@ -400,6 +400,66 @@ int AccessTokenManagerProxy::ClearUserGrantedPermissionState(AccessTokenID token return result; } +int32_t AccessTokenManagerProxy::RegisterPermStateChangeCallback( + const PermStateChangeScopeParcel& scope, const sptr& callback) +{ + MessageParcel data; + data.WriteInterfaceToken(IAccessTokenManager::GetDescriptor()); + if (!data.WriteParcelable(&scope)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to write PermStateChangeScopeParcel."); + return RET_FAILED; + } + if (!data.WriteRemoteObject(callback)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to write remote object."); + return RET_FAILED; + } + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + sptr remote = Remote(); + if (remote == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "remote service null."); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IAccessTokenManager::InterfaceCode::REGISTER_PERMISSION_STATE_CHANGE_CALLBACK), + data, reply, option); + if (requestResult != NO_ERROR) { + ACCESSTOKEN_LOG_ERROR(LABEL, "request fail, result: %{public}d.", requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + return result; +} + +int32_t AccessTokenManagerProxy::UnRegisterPermStateChangeCallback(const sptr& callback) +{ + MessageParcel data; + data.WriteInterfaceToken(IAccessTokenManager::GetDescriptor()); + if (!data.WriteRemoteObject(callback)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to write remote object."); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + sptr remote = Remote(); + if (remote == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "remote service null."); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IAccessTokenManager::InterfaceCode::UNREGISTER_PERMISSION_STATE_CHANGE_CALLBACK), + data, reply, option); + if (requestResult != NO_ERROR) { + ACCESSTOKEN_LOG_ERROR(LABEL, "request fail, result: %{public}d.", requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + return result; +} + AccessTokenIDEx AccessTokenManagerProxy::AllocHapToken( const HapInfoParcel& hapInfo, const HapPolicyParcel& policyParcel) { diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.h b/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.h index 9bfbf432f5c2b9ab28e31ab01d65f4dbbae29a84..6177b1c6da6ecc6397b9902930b1a0797d505191 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.h +++ b/interfaces/innerkits/accesstoken/src/accesstoken_manager_proxy.h @@ -61,6 +61,9 @@ public: const HapPolicyParcel& policyPar) override; int GetHapTokenInfo(AccessTokenID tokenID, HapTokenInfoParcel& hapTokenInfoRes) override; int GetNativeTokenInfo(AccessTokenID tokenID, NativeTokenInfoParcel& nativeTokenInfoRes) override; + int32_t RegisterPermStateChangeCallback( + const PermStateChangeScopeParcel& scope, const sptr& callback) override; + int32_t UnRegisterPermStateChangeCallback(const sptr& callback) override; #ifdef TOKEN_SYNC_ENABLE int GetHapTokenInfoFromRemote(AccessTokenID tokenID, HapTokenInfoForSyncParcel& hapSyncParcel) override; diff --git a/interfaces/innerkits/accesstoken/src/perm_state_callback_customize.cpp b/interfaces/innerkits/accesstoken/src/perm_state_callback_customize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3cd2d65813330a9d341a977beb544ded2b1d2f7 --- /dev/null +++ b/interfaces/innerkits/accesstoken/src/perm_state_callback_customize.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "perm_state_callback_customize.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +PermStateChangeCbCustomize::PermStateChangeCbCustomize() +{} + +PermStateChangeCbCustomize::PermStateChangeCbCustomize( + const PermStateChangeScope &scopeInfo) : scopeInfo_(scopeInfo) +{} + +PermStateChangeCbCustomize::~PermStateChangeCbCustomize() +{} + +void PermStateChangeCbCustomize::GetScope(PermStateChangeScope &scopeInfo) const +{ + scopeInfo = scopeInfo_; +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/interfaces/innerkits/accesstoken/src/permission_state_change_callback.cpp b/interfaces/innerkits/accesstoken/src/permission_state_change_callback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..170e9446cf6db3f1acd9918557bc38f198b2fa8c --- /dev/null +++ b/interfaces/innerkits/accesstoken/src/permission_state_change_callback.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_change_callback.h" + +#include "access_token.h" +#include "accesstoken_log.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { + LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "PermissionStateChangeCallback" +}; +PermissionStateCallback::PermissionStateCallback( + const std::shared_ptr &customizedCallback) + : customizedCallback_(customizedCallback) +{} + +PermissionStateCallback::~PermissionStateCallback() +{} + +void PermissionStateCallback::PermStateChangeCallback(PermStateChangeInfo& result) +{ + if (customizedCallback_ == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "customizedCallback_ is nullptr"); + return; + } + + customizedCallback_->PermStateChangeCallback(result); +} + +void PermissionStateCallback::Stop() +{} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/interfaces/innerkits/accesstoken/src/permission_state_change_callback.h b/interfaces/innerkits/accesstoken/src/permission_state_change_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..a7d43c270be38640a8b063bb417521d458b6eeb9 --- /dev/null +++ b/interfaces/innerkits/accesstoken/src/permission_state_change_callback.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STATE_CHANGE_CALLBACK_H +#define PERMISSION_STATE_CHANGE_CALLBACK_H + + +#include "permission_state_change_callback_stub.h" +#include "perm_state_callback_customize.h" + + +namespace OHOS { +namespace Security { +namespace AccessToken { +class PermissionStateCallback : public PermissionStateCallbackStub { +public: + explicit PermissionStateCallback(const std::shared_ptr &subscriber); + ~PermissionStateCallback() override; + + void PermStateChangeCallback(PermStateChangeInfo& result) override; + + void Stop(); + +private: + std::shared_ptr customizedCallback_; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_STATE_CHANGE_CALLBACK_H diff --git a/interfaces/innerkits/accesstoken/src/permission_state_change_callback_stub.cpp b/interfaces/innerkits/accesstoken/src/permission_state_change_callback_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e56edb215923338209f203b142e0b0d4b18f4e9 --- /dev/null +++ b/interfaces/innerkits/accesstoken/src/permission_state_change_callback_stub.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_change_callback_stub.h" + +#include "access_token.h" +#include "accesstoken_log.h" +#include "permission_state_change_info_parcel.h" +#include "string_ex.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { + LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "PermissionStateChangeCallbackStub" +}; +} + +int32_t PermissionStateCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) +{ + ACCESSTOKEN_LOG_DEBUG(LABEL, "Entry, code: 0x%{public}x", code); + std::u16string descriptor = data.ReadInterfaceToken(); + if (descriptor != IPermissionStateCallback::GetDescriptor()) { + ACCESSTOKEN_LOG_ERROR(LABEL, "get unexpect descriptor: %{public}s", Str16ToStr8(descriptor).c_str()); + return RET_FAILED; + } + + int32_t msgCode = static_cast(code); + if (msgCode == IPermissionStateCallback::PERMISSION_STATE_CHANGE) { + PermStateChangeInfo result; + sptr resultSptr = data.ReadParcelable(); + if (resultSptr == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ReadParcelable fail"); + return RET_FAILED; + } + + PermStateChangeCallback(resultSptr->changeInfo); + } else { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + return RET_SUCCESS; +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/interfaces/innerkits/accesstoken/src/permission_state_change_callback_stub.h b/interfaces/innerkits/accesstoken/src/permission_state_change_callback_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..3be58ca5560b9e82c4d13dbc88afa0efca7593e6 --- /dev/null +++ b/interfaces/innerkits/accesstoken/src/permission_state_change_callback_stub.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STATE_CHANGE_CALLBACK_STUB_H +#define PERMISSION_STATE_CHANGE_CALLBACK_STUB_H + + +#include "i_permission_state_callback.h" + +#include "iremote_stub.h" +#include "nocopyable.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +class PermissionStateCallbackStub : public IRemoteStub { +public: + PermissionStateCallbackStub() = default; + virtual ~PermissionStateCallbackStub() = default; + + int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_STATE_CHANGE_CALLBACK_STUB_H diff --git a/interfaces/innerkits/accesstoken/test/BUILD.gn b/interfaces/innerkits/accesstoken/test/BUILD.gn index 8120ebb50ec1fffe3ebb0a2515f00a2c719c9e28..b99e33ac6ed43e6f130511ff5e1f19745c7a5cb6 100644 --- a/interfaces/innerkits/accesstoken/test/BUILD.gn +++ b/interfaces/innerkits/accesstoken/test/BUILD.gn @@ -42,6 +42,7 @@ ohos_unittest("libaccesstoken_sdk_test") { external_deps = [ "dsoftbus:softbus_client", "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", ] if (token_sync_enable == true) { cflags_cc += [ "-DTOKEN_SYNC_ENABLE" ] diff --git a/interfaces/innerkits/accesstoken/test/unittest/src/accesstoken_kit_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/src/accesstoken_kit_test.cpp index d0373c59c2c87dcc7e87bcdc9e3de24a014be732..8a8f4975da2c349cb9153fca32ba459036940907 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/src/accesstoken_kit_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/src/accesstoken_kit_test.cpp @@ -2411,6 +2411,361 @@ HWTEST_F(AccessTokenKitTest, GetTokenTypeFlag003, TestSize.Level1) ASSERT_EQ(RET_SUCCESS, res); } +class CbCustomizeTest : public PermStateChangeCbCustomize { +public: + explicit CbCustomizeTest(const PermStateChangeScope &scopeInfo) + : PermStateChangeCbCustomize(scopeInfo) + { + GTEST_LOG_(INFO) << "CbCustomizeTest create"; + } + + ~CbCustomizeTest() + {} + + virtual void PermStateChangeCallback(PermStateChangeInfo& result) + { + ready_ = true; + GTEST_LOG_(INFO) << "CbCustomizeTest PermStateChangeCallback"; + GTEST_LOG_(INFO) << "tokenid" << result.tokenID; + GTEST_LOG_(INFO) << "permissionName" << result.permissionName; + } + + bool ready_; +}; + +/** + * @tc.name: RegisterPermStateChangeCallback001 + * @tc.desc: RegisterPermStateChangeCallback permList + * @tc.type: FUNC + * @tc.require:AR000GK6TD + */ +HWTEST_F(AccessTokenKitTest, RegisterPermStateChangeCallback001, TestSize.Level1) +{ + PermStateChangeScope scopeInfo; + scopeInfo.permList = {"ohos.permission.CAMERA"}; + scopeInfo.tokenIDs = {}; + auto callbackPtr = std::make_shared(scopeInfo); + callbackPtr->ready_ = false; + + int32_t res = AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr); + + static PermissionStateFull infoManagerTestStateA = { + .permissionName = "ohos.permission.CAMERA", + .grantFlags = {1}, + .grantStatus = {PERMISSION_DENIED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static HapPolicyParams infoManagerTestPolicyPrams = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = {}, + .permStateList = {infoManagerTestStateA} + }; + + AccessTokenIDEx tokenIdEx = {0}; + AccessTokenID tokenID; + tokenIdEx = AccessTokenKit::AllocHapToken(g_infoManagerTestInfoParms, infoManagerTestPolicyPrams); + + tokenID = tokenIdEx.tokenIdExStruct.tokenID; + ASSERT_NE(0, tokenID); + + ATokenTypeEnum ret = AccessTokenKit::GetTokenTypeFlag(tokenID); + ASSERT_EQ(ret, TOKEN_HAP); + + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_DENIED, res); + + res = AccessTokenKit::GrantPermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_GRANTED, res); + + ASSERT_EQ(true, callbackPtr->ready_); + + callbackPtr->ready_ = false; + + res = AccessTokenKit::RevokePermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + + ASSERT_EQ(true, callbackPtr->ready_); + + res = AccessTokenKit::UnRegisterPermStateChangeCallback(callbackPtr); + ASSERT_EQ(RET_SUCCESS, res); + + callbackPtr->ready_ = false; + + res = AccessTokenKit::GrantPermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + + ASSERT_EQ(false, callbackPtr->ready_); + + callbackPtr->ready_ = false; + + res = AccessTokenKit::RevokePermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + + ASSERT_EQ(false, callbackPtr->ready_); + + res = AccessTokenKit::DeleteToken(tokenID); + ASSERT_EQ(RET_SUCCESS, res); + +} + +/** + * @tc.name: RegisterPermStateChangeCallback002 + * @tc.desc: RegisterPermStateChangeCallback permList + * @tc.type: FUNC + * @tc.require:AR000GK6TD + */ +HWTEST_F(AccessTokenKitTest, RegisterPermStateChangeCallback002, TestSize.Level1) +{ + PermStateChangeScope scopeInfo; + scopeInfo.permList = {"ohos.permission.GET_BUNDLE_INFO"}; + scopeInfo.tokenIDs = {}; + auto callbackPtr = std::make_shared(scopeInfo); + callbackPtr->ready_ = false; + + int32_t res = AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr); + + static PermissionStateFull infoManagerTestStateA = { + .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .grantFlags = {1}, + .grantStatus = {PERMISSION_GRANTED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static PermissionStateFull infoManagerTestStateB = { + .permissionName = "ohos.permission.CAMERA", + .grantFlags = {1}, + .grantStatus = {PERMISSION_GRANTED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static HapPolicyParams infoManagerTestPolicyPrams = { + .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = {}, + .permStateList = {infoManagerTestStateA, infoManagerTestStateB} + }; + + AccessTokenIDEx tokenIdEx = {0}; + tokenIdEx = AccessTokenKit::AllocHapToken(g_infoManagerTestInfoParms, infoManagerTestPolicyPrams); + + AccessTokenID tokenID = tokenIdEx.tokenIdExStruct.tokenID; + + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_GRANTED, res); + + res = AccessTokenKit::GrantPermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + + ASSERT_EQ(false, callbackPtr->ready_); + + res = AccessTokenKit::DeleteToken(tokenID); + ASSERT_EQ(RET_SUCCESS, res); + + res = AccessTokenKit::UnRegisterPermStateChangeCallback(callbackPtr); + ASSERT_EQ(RET_SUCCESS, res); +} + +/** + * @tc.name: RegisterPermStateChangeCallback003 + * @tc.desc: RegisterPermStateChangeCallback permList + * @tc.type: FUNC + * @tc.require:AR000GK6TD + */ +HWTEST_F(AccessTokenKitTest, RegisterPermStateChangeCallback003, TestSize.Level1) +{ + PermStateChangeScope scopeInfo; + scopeInfo.permList = {}; + scopeInfo.tokenIDs = {}; + auto callbackPtr = std::make_shared(scopeInfo); + callbackPtr->ready_ = false; + + int32_t res = AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr); + + static PermissionStateFull infoManagerTestStateA = { + .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .grantFlags = {1}, + .grantStatus = {PERMISSION_DENIED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static PermissionStateFull infoManagerTestStateB = { + .permissionName = "ohos.permission.CAMERA", + .grantFlags = {1}, + .grantStatus = {PERMISSION_DENIED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static HapPolicyParams infoManagerTestPolicyPrams = { + .apl = APL_SYSTEM_CORE, + .domain = "test.domain", + .permList = {}, + .permStateList = {infoManagerTestStateA, infoManagerTestStateB} + }; + + AccessTokenIDEx tokenIdEx = {0}; + tokenIdEx = AccessTokenKit::AllocHapToken(g_infoManagerTestInfoParms, infoManagerTestPolicyPrams); + + AccessTokenID tokenID = tokenIdEx.tokenIdExStruct.tokenID; + + callbackPtr->ready_ = false; + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_DENIED, res); + res = AccessTokenKit::GrantPermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_GRANTED, res); + ASSERT_EQ(true, callbackPtr->ready_); + + callbackPtr->ready_ = false; + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.GET_BUNDLE_INFO"); + ASSERT_EQ(PERMISSION_DENIED, res); + res = AccessTokenKit::GrantPermission(tokenID, "ohos.permission.GET_BUNDLE_INFO", 2); + ASSERT_EQ(RET_SUCCESS, res); + + ASSERT_EQ(true, callbackPtr->ready_); + + res = AccessTokenKit::DeleteToken(tokenID); + ASSERT_EQ(RET_SUCCESS, res); + + res = AccessTokenKit::UnRegisterPermStateChangeCallback(callbackPtr); + ASSERT_EQ(RET_SUCCESS, res); +} + +/** + * @tc.name: RegisterPermStateChangeCallback004 + * @tc.desc: RegisterPermStateChangeCallback permList + * @tc.type: FUNC + * @tc.require:AR000GK6TD + */ +HWTEST_F(AccessTokenKitTest, RegisterPermStateChangeCallback004, TestSize.Level1) +{ + PermStateChangeScope scopeInfo; + scopeInfo.permList = {"ohos.permission.GET_BUNDLE_INFO", "ohos.permission.CAMERA"}; + scopeInfo.tokenIDs = {555555}; // 555555为模拟的tokenid + auto callbackPtr = std::make_shared(scopeInfo); + callbackPtr->ready_ = false; + + int32_t res = AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr); + + static PermissionStateFull infoManagerTestStateA = { + .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .grantFlags = {1}, + .grantStatus = {PERMISSION_GRANTED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static PermissionStateFull infoManagerTestStateB = { + .permissionName = "ohos.permission.CAMERA", + .grantFlags = {1}, + .grantStatus = {PERMISSION_GRANTED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static HapPolicyParams infoManagerTestPolicyPrams = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = {}, + .permStateList = {infoManagerTestStateA, infoManagerTestStateB} + }; + + AccessTokenIDEx tokenIdEx = {0}; + tokenIdEx = AccessTokenKit::AllocHapToken(g_infoManagerTestInfoParms, infoManagerTestPolicyPrams); + + AccessTokenID tokenID = tokenIdEx.tokenIdExStruct.tokenID; + + callbackPtr->ready_ = false; + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_GRANTED, res); + res = AccessTokenKit::RevokePermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_DENIED, res); + ASSERT_EQ(false, callbackPtr->ready_); + + callbackPtr->ready_ = false; + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.GET_BUNDLE_INFO"); + ASSERT_EQ(PERMISSION_GRANTED, res); + res = AccessTokenKit::RevokePermission(tokenID, "ohos.permission.GET_BUNDLE_INFO", 2); + ASSERT_EQ(RET_SUCCESS, res); + + ASSERT_EQ(false, callbackPtr->ready_); + + res = AccessTokenKit::DeleteToken(tokenID); + ASSERT_EQ(RET_SUCCESS, res); + + res = AccessTokenKit::UnRegisterPermStateChangeCallback(callbackPtr); + ASSERT_EQ(RET_SUCCESS, res); +} + +/** + * @tc.name: RegisterPermStateChangeCallback005 + * @tc.desc: RegisterPermStateChangeCallback permList + * @tc.type: FUNC + * @tc.require:AR000GK6TD + */ +HWTEST_F(AccessTokenKitTest, RegisterPermStateChangeCallback005, TestSize.Level1) +{ + static PermissionStateFull infoManagerTestStateA = { + .permissionName = "ohos.permission.CAMERA", + .grantFlags = {1}, + .grantStatus = {PERMISSION_DENIED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static PermissionStateFull infoManagerTestStateB = { + .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .grantFlags = {1}, + .grantStatus = {PERMISSION_GRANTED}, + .isGeneral = true, + .resDeviceID = {"local"} + }; + static HapPolicyParams infoManagerTestPolicyPrams = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = {}, + .permStateList = {infoManagerTestStateA, infoManagerTestStateB} + }; + + AccessTokenIDEx tokenIdEx = {0}; + tokenIdEx = AccessTokenKit::AllocHapToken(g_infoManagerTestInfoParms, infoManagerTestPolicyPrams); + + AccessTokenID tokenID = tokenIdEx.tokenIdExStruct.tokenID; + + PermStateChangeScope scopeInfo; + scopeInfo.permList = {"ohos.permission.GET_BUNDLE_INFO", "ohos.permission.CAMERA"}; + scopeInfo.tokenIDs = {tokenID, 0}; + auto callbackPtr = std::make_shared(scopeInfo); + callbackPtr->ready_ = false; + + int32_t res = AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr); + + callbackPtr->ready_ = false; + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.CAMERA"); + ASSERT_EQ(PERMISSION_DENIED, res); + res = AccessTokenKit::GrantPermission(tokenID, "ohos.permission.CAMERA", 2); + ASSERT_EQ(RET_SUCCESS, res); + ASSERT_EQ(true, callbackPtr->ready_); + + callbackPtr->ready_ = false; + res = AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.GET_BUNDLE_INFO"); + ASSERT_EQ(PERMISSION_GRANTED, res); + res = AccessTokenKit::GrantPermission(tokenID, "ohos.permission.GET_BUNDLE_INFO", 2); + ASSERT_EQ(RET_SUCCESS, res); + + ASSERT_EQ(false, callbackPtr->ready_); + + res = AccessTokenKit::DeleteToken(tokenID); + ASSERT_EQ(RET_SUCCESS, res); + + res = AccessTokenKit::UnRegisterPermStateChangeCallback(callbackPtr); + ASSERT_EQ(RET_SUCCESS, res); +} + #ifdef TOKEN_SYNC_ENABLE /** * @tc.name: SetRemoteHapTokenInfo001 diff --git a/services/accesstokenmanager/BUILD.gn b/services/accesstokenmanager/BUILD.gn index 0fca1e5918a9466f0d8c6810d58daf583e908374..ee5405bd255909effaa8863bfe30e2a0620709f3 100644 --- a/services/accesstokenmanager/BUILD.gn +++ b/services/accesstokenmanager/BUILD.gn @@ -26,6 +26,7 @@ ohos_shared_library("accesstoken_manager_service") { part_name = "access_token" include_dirs = [ + "main/cpp/include/callback", "main/cpp/include/service", "main/cpp/include/token", "main/cpp/include/permission", @@ -58,6 +59,9 @@ ohos_shared_library("accesstoken_manager_service") { "main/cpp/src/token/hap_token_info_inner.cpp", "main/cpp/src/token/native_token_info_inner.cpp", "main/cpp/src/token/native_token_receptor.cpp", + "main/cpp/src/callback/callback_manager.cpp", + "main/cpp/src/callback/permission_state_change_callback_proxy.cpp", + "main/cpp/src/callback/perm_state_callback_death_recipient.cpp", ] cflags_cc = [ "-DHILOG_ENABLE" ] diff --git a/services/accesstokenmanager/main/cpp/include/callback/callback_manager.h b/services/accesstokenmanager/main/cpp/include/callback/callback_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..70f5528b9feeeb4812db75a176a774d06692d7fa --- /dev/null +++ b/services/accesstokenmanager/main/cpp/include/callback/callback_manager.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACCESS_TOKEN_PERMISSION_CALLBACK_MANAGER_H +#define ACCESS_TOKEN_PERMISSION_CALLBACK_MANAGER_H + +#include +#include + +#include "access_token.h" +#include "accesstoken_log.h" +#include "i_permission_state_callback.h" +#include "permission_state_change_info.h" +#include "permission_state_change_callback_proxy.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +enum PermStateChangeType { + REVOKED = 0, + GRANTED = 1, +}; +struct CallbackRecord { + CallbackRecord() : scopePtr_(nullptr), callbackObject_(nullptr) + {} + CallbackRecord(std::shared_ptr callbackScopePtr, sptr callback) + : scopePtr_(callbackScopePtr), callbackObject_(callback) + {} + + std::shared_ptr scopePtr_; + sptr callbackObject_; +}; + +class CallbackManager{ +public: + virtual ~CallbackManager(); + CallbackManager(); + static CallbackManager& GetInstance(); + + int32_t AddCallback( + const std::shared_ptr& callbackScopePtr, const sptr& callback); + int32_t RemoveCallback(const sptr& callback); + bool CalledAccordingToTokenIdLlist( const std::vector& tokenIDList, AccessTokenID tokenID); + bool CalledAccordingToPermLlist(const std::vector& permList, const std::string& permName); + void ExcuteCallbackAsync(AccessTokenID tokenID, const std::string& permName, int32_t changeType); + +private: + std::mutex mutex_; + std::vector callbackInfoList_; + sptr callbackDeathRecipient_; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif // ACCESS_TOKEN_PERMISSION_CALLBACK_MANAGER_H diff --git a/services/accesstokenmanager/main/cpp/include/callback/perm_state_callback_death_recipient.h b/services/accesstokenmanager/main/cpp/include/callback/perm_state_callback_death_recipient.h new file mode 100644 index 0000000000000000000000000000000000000000..09f131f37c31fe6e4ba5054fa3ab90176f53e099 --- /dev/null +++ b/services/accesstokenmanager/main/cpp/include/callback/perm_state_callback_death_recipient.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERM_STATE_CALLBACK_DEATH_RECIPIENT_H +#define PERM_STATE_CALLBACK_DEATH_RECIPIENT_H + + +#include "iremote_object.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +class PermStateCallbackDeathRecipient : public IRemoteObject::DeathRecipient { +public: + PermStateCallbackDeathRecipient() = default; + virtual ~PermStateCallbackDeathRecipient() = default; + + virtual void OnRemoteDied(const wptr &remote); +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif // PERM_STATE_CALLBACK_DEATH_RECIPIENT_H diff --git a/services/accesstokenmanager/main/cpp/include/callback/permission_state_change_callback_proxy.h b/services/accesstokenmanager/main/cpp/include/callback/permission_state_change_callback_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..19598c47e052ae750164783dfe444eab1ea35b13 --- /dev/null +++ b/services/accesstokenmanager/main/cpp/include/callback/permission_state_change_callback_proxy.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STATE_CHANGE_CALLBACK_PROXY_H +#define PERMISSION_STATE_CHANGE_CALLBACK_PROXY_H + + +#include "i_permission_state_callback.h" + +#include "iremote_proxy.h" +#include "nocopyable.h" +#include "permission_state_change_info.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +class PermissionStateCallbackProxy : public IRemoteProxy { +public: + explicit PermissionStateCallbackProxy(const sptr& impl); + ~PermissionStateCallbackProxy() override; + virtual void PermStateChangeCallback(PermStateChangeInfo& result) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_STATE_CHANGE_CALLBACK_PROXY_H diff --git a/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h b/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h index aa829f33340167f3ecbd8f5b5a470b1f3a19c7b2..db527aecb1d7a5364078b06622cfe501c53f3a64 100644 --- a/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h +++ b/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h @@ -21,8 +21,10 @@ #include "access_token.h" #include "hap_token_info_inner.h" +#include "i_permission_state_callback.h" #include "permission_def.h" #include "permission_list_state.h" +#include "permission_state_change_info.h" #include "permission_state_full.h" #include "rwlock.h" @@ -53,6 +55,10 @@ public: void ClearUserGrantedPermissionState(AccessTokenID tokenID); void GetSelfPermissionState( std::vector permsList, PermissionListState &permState); + int32_t AddPermStateChangeCallback( + const PermStateChangeScope& scope, const sptr& callback); + int32_t RemovePermStateChangeCallback(const sptr& callback); + private: PermissionManager(); void UpdateTokenPermissionState( diff --git a/services/accesstokenmanager/main/cpp/include/permission/permission_policy_set.h b/services/accesstokenmanager/main/cpp/include/permission/permission_policy_set.h index b90de396837f43de12e6a60daa826c5f45460914..d18e301a105a24344c64240ca37a8f74f9b809f3 100644 --- a/services/accesstokenmanager/main/cpp/include/permission/permission_policy_set.h +++ b/services/accesstokenmanager/main/cpp/include/permission/permission_policy_set.h @@ -45,7 +45,7 @@ public: void GetDefPermissions(std::vector& permList); void GetPermissionStateFulls(std::vector& permList); int QueryPermissionFlag(const std::string& permissionName); - void UpdatePermissionStatus(const std::string& permissionName, bool isGranted, uint32_t flag); + bool UpdatePermissionStatus(const std::string& permissionName, bool isGranted, uint32_t flag); void ToString(std::string& info); bool IsPermissionReqValid(int32_t tokenApl, const std::string& permissionName, const std::vector& nativeAcls); diff --git a/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h b/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h index a6bb3c284efaab290193c6e2723788b67143fa6d..ebc754ad1142266180ed602e445f71b3551fccec 100644 --- a/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h +++ b/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h @@ -62,6 +62,9 @@ public: int GetHapTokenInfo(AccessTokenID tokenID, HapTokenInfoParcel& InfoParcel) override; int UpdateHapToken(AccessTokenID tokenID, const std::string& appIDDesc, const HapPolicyParcel& policyParcel) override; + int32_t RegisterPermStateChangeCallback( + const PermStateChangeScopeParcel& scope, const sptr& callback) override; + int32_t UnRegisterPermStateChangeCallback(const sptr& callback) override; #ifdef TOKEN_SYNC_ENABLE int GetHapTokenInfoFromRemote(AccessTokenID tokenID, HapTokenInfoForSyncParcel& hapSyncParcel) override; diff --git a/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_stub.h b/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_stub.h index 6bd9a3ec2a6e8fbf9aa3026dff4b477cd5eadf33..cbc45c2beaf56f40810e05a8f8c800dcf94682ce 100644 --- a/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_stub.h +++ b/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_stub.h @@ -54,6 +54,8 @@ private: void GetHapTokenIDInner(MessageParcel& data, MessageParcel& reply); void CheckNativeDCapInner(MessageParcel& data, MessageParcel& reply); void GetTokenTypeInner(MessageParcel& data, MessageParcel& reply); + void RegisterPermStateChangeCallbackInner(MessageParcel& data, MessageParcel& reply); + void UnRegisterPermStateChangeCallbackInner(MessageParcel& data, MessageParcel& reply); #ifdef TOKEN_SYNC_ENABLE void GetHapTokenInfoFromRemoteInner(MessageParcel& data, MessageParcel& reply); diff --git a/services/accesstokenmanager/main/cpp/src/callback/callback_manager.cpp b/services/accesstokenmanager/main/cpp/src/callback/callback_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2de14b4fc0ebd80f3a2a532b6f21c8fa6d3817f4 --- /dev/null +++ b/services/accesstokenmanager/main/cpp/src/callback/callback_manager.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "callback_manager.h" + +#include +#include +#include + +#include "access_token.h" +#include "perm_state_callback_death_recipient.h" + + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "CallbackManager"}; +const time_t MAX_TIMEOUT_SEC = 30; +} + +CallbackManager& CallbackManager::GetInstance() +{ + static CallbackManager instance; + return instance; +} + +CallbackManager::CallbackManager() : callbackDeathRecipient_(sptr( + new (std::nothrow) PermStateCallbackDeathRecipient())) +{ +} + +CallbackManager::~CallbackManager() +{ +} + +int32_t CallbackManager::AddCallback(const std::shared_ptr& callbackScopePtr, const sptr& callback) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "callback %{public}p ", (IRemoteObject *)callback); + if ((callbackScopePtr == nullptr) || (callback == nullptr)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "input is nullptr"); + return RET_FAILED; + } + + callback->AddDeathRecipient(callbackDeathRecipient_); //这个this指的是当前实例本身 + + CallbackRecord recordInstance; + recordInstance.callbackObject_ = callback; + recordInstance.scopePtr_ = callbackScopePtr; + + std::lock_guard lock(mutex_); + callbackInfoList_.emplace_back(recordInstance); + + ACCESSTOKEN_LOG_INFO(LABEL, "recordInstance is added"); + return RET_SUCCESS; +} + +int32_t CallbackManager::RemoveCallback(const sptr& callback) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "called"); + if (callback == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "callback is nullptr"); + return RET_FAILED; + } + + std::lock_guard lock(mutex_); + + for (auto it = callbackInfoList_.begin(); it != callbackInfoList_.end(); ++it) { + if (callback == (*it).callbackObject_) { + ACCESSTOKEN_LOG_INFO(LABEL, "find callback"); + if (callbackDeathRecipient_ != nullptr) { + callback->RemoveDeathRecipient(callbackDeathRecipient_); + } + (*it).callbackObject_ = nullptr; + callbackInfoList_.erase(it); + break; + } + } + ACCESSTOKEN_LOG_INFO(LABEL, "callbackInfoList_ %{public}lu", callbackInfoList_.size()); + return RET_SUCCESS; +} + + +bool CallbackManager::CalledAccordingToTokenIdLlist( + const std::vector& tokenIDList, AccessTokenID tokenID) +{ + if (tokenIDList.empty()) { + return true; + } + for (const auto& id : tokenIDList) { + if (id == tokenID) { + return true; + } + } + return false; +} + +bool CallbackManager::CalledAccordingToPermLlist(const std::vector& permList, const std::string& permName) +{ + if (permList.empty()) { + return true; + } + for (const auto& perm : permList) { + if (perm == permName) { + return true; + } + } + return false; +} + +void CallbackManager::ExcuteCallbackAsync(AccessTokenID tokenID, const std::string& permName, int32_t changeType) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "entry"); + + auto callbackStart = [&]() { + ACCESSTOKEN_LOG_INFO(LABEL, "callbackStart"); + std::lock_guard lock(mutex_); + ACCESSTOKEN_LOG_INFO(LABEL, "callbackInfoList_ %{public}lu", callbackInfoList_.size()); + for (auto it = callbackInfoList_.begin(); it != callbackInfoList_.end(); ++it) { + ACCESSTOKEN_LOG_INFO(LABEL, "callbackStart scopePtr_"); + std::shared_ptr scopePtr_ = (*it).scopePtr_; + if (scopePtr_ == nullptr) { //关注下,我们的callbackInfoList_里面是结构体,而非结构体指针,看是否会有问题 + ACCESSTOKEN_LOG_ERROR(LABEL, "scopePtr_ is nullptr"); + continue; + } + if (!CalledAccordingToTokenIdLlist(scopePtr_->tokenIDs, tokenID) || + !CalledAccordingToPermLlist(scopePtr_->permList, permName)) { + ACCESSTOKEN_LOG_INFO(LABEL, "tokenID is %{public}u, permName is %{public}s", tokenID, permName.c_str()); + continue; + } + auto callback = iface_cast((*it).callbackObject_); + if (callback != nullptr) { + ACCESSTOKEN_LOG_INFO(LABEL, "callback excute"); + PermStateChangeInfo resInfo; + resInfo.PermStateChangeType = changeType; + resInfo.permissionName = permName; + resInfo.tokenID = tokenID; + callback->PermStateChangeCallback(resInfo); + } + } + }; + + std::packaged_task callbackTask(callbackStart); + std::future fut = callbackTask.get_future(); + std::make_unique(std::move(callbackTask))->detach(); + + ACCESSTOKEN_LOG_INFO(LABEL, "Waiting for the callback execution complete..."); + std::future_status status = fut.wait_for(std::chrono::seconds(MAX_TIMEOUT_SEC)); + if (status == std::future_status::timeout) { + ACCESSTOKEN_LOG_WARN(LABEL, "callbackTask callback execution timeout"); + } + ACCESSTOKEN_LOG_INFO(LABEL, "The callback execution is complete"); + +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/services/accesstokenmanager/main/cpp/src/callback/perm_state_callback_death_recipient.cpp b/services/accesstokenmanager/main/cpp/src/callback/perm_state_callback_death_recipient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27b14b5bd0eb9518cb9ef934c15311fa5262eb3a --- /dev/null +++ b/services/accesstokenmanager/main/cpp/src/callback/perm_state_callback_death_recipient.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "perm_state_callback_death_recipient.h" + +#include "access_token.h" +#include "callback_manager.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { + LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "PermStateCallbackDeathRecipient" +}; +} +void PermStateCallbackDeathRecipient::OnRemoteDied(const wptr &remote) +{ + ACCESSTOKEN_LOG_ERROR(LABEL, "enter"); + if (remote == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "remote object is nullptr"); + return; + } + + sptr object = remote.promote(); + if (object == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "object is nullptr"); + return; + } + CallbackManager::GetInstance().RemoveCallback(object); + ACCESSTOKEN_LOG_ERROR(LABEL, "end"); +} + +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/services/accesstokenmanager/main/cpp/src/callback/permission_state_change_callback_proxy.cpp b/services/accesstokenmanager/main/cpp/src/callback/permission_state_change_callback_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e963d48d9b298b159eaa8dbe6c88c755e444d53 --- /dev/null +++ b/services/accesstokenmanager/main/cpp/src/callback/permission_state_change_callback_proxy.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_change_callback_proxy.h" + +#include "access_token.h" +#include "accesstoken_log.h" +#include "permission_state_change_info_parcel.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { + LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "PermissionStateChangeCallbackProxy" +}; +} + +PermissionStateCallbackProxy::PermissionStateCallbackProxy(const sptr& impl) + : IRemoteProxy(impl) { +} + +PermissionStateCallbackProxy::~PermissionStateCallbackProxy() +{} + +void PermissionStateCallbackProxy::PermStateChangeCallback(PermStateChangeInfo& info) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionStateCallback::GetDescriptor()); + + PermissionStateChangeInfoParcel resultParcel; + resultParcel.changeInfo = info; + if (!data.WriteParcelable(&resultParcel)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to WriteParcelable(result)"); + return; + } + + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + sptr remote = Remote(); + if (remote == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "remote service null."); + return; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionStateCallback::PERMISSION_STATE_CHANGE), data, reply, option); + if (requestResult != NO_ERROR) { + ACCESSTOKEN_LOG_ERROR(LABEL, "send request fail, result: %{public}d", requestResult); + return; + } + + ACCESSTOKEN_LOG_DEBUG(LABEL, "SendRequest success"); +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp b/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp index 595f386a0ba0ba6999d0465b681d4acb4c140184..84a77d8e6590f02ed6a723eaac4172707f5ef09c 100644 --- a/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp +++ b/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp @@ -18,6 +18,7 @@ #include "accesstoken_id_manager.h" #include "accesstoken_info_manager.h" #include "accesstoken_log.h" +#include "callback_manager.h" #ifdef SUPPORT_SANDBOX_APP #include "dlp_permission_set_manager.h" #endif @@ -333,7 +334,13 @@ void PermissionManager::UpdateTokenPermissionState( } } #endif - permPolicySet->UpdatePermissionStatus(permissionName, isGranted, static_cast(flag)); + bool isUpdated = permPolicySet->UpdatePermissionStatus(permissionName, isGranted, static_cast(flag)); + + if (isUpdated) { + ACCESSTOKEN_LOG_INFO(LABEL, "isUpdated"); + int32_t changeType = isGranted ? GRANTED : REVOKED; + CallbackManager::GetInstance().ExcuteCallbackAsync(tokenID, permissionName, changeType); + } #ifdef TOKEN_SYNC_ENABLE TokenModifyNotifier::GetInstance().NotifyTokenModify(tokenID); @@ -382,6 +389,23 @@ void PermissionManager::RevokePermission(AccessTokenID tokenID, const std::strin UpdateTokenPermissionState(tokenID, permissionName, false, flag); } +int32_t PermissionManager::AddPermStateChangeCallback( + const PermStateChangeScope& scope, const sptr& callback) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "called"); + auto callbackScopePtr = std::make_shared(scope); //关注这么写是不是OK + if (callbackScopePtr == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "callbackScopePtr is nullptr"); + } + + return CallbackManager::GetInstance().AddCallback(callbackScopePtr, callback); +} + +int32_t PermissionManager::RemovePermStateChangeCallback(const sptr& callback) +{ + return CallbackManager::GetInstance().RemoveCallback(callback); +} + void PermissionManager::ClearUserGrantedPermissionState(AccessTokenID tokenID) { ACCESSTOKEN_LOG_INFO(LABEL, "%{public}s called, tokenID: %{public}u", __func__, tokenID); diff --git a/services/accesstokenmanager/main/cpp/src/permission/permission_policy_set.cpp b/services/accesstokenmanager/main/cpp/src/permission/permission_policy_set.cpp index f2144a11ae37cc6a7081dd383236b63a95b1ab5b..51a4e058c89b1177c83685d87332444c07ac81d4 100644 --- a/services/accesstokenmanager/main/cpp/src/permission/permission_policy_set.cpp +++ b/services/accesstokenmanager/main/cpp/src/permission/permission_policy_set.cpp @@ -180,21 +180,31 @@ int PermissionPolicySet::QueryPermissionFlag(const std::string& permissionName) return PERMISSION_DEFAULT_FLAG; } -void PermissionPolicySet::UpdatePermissionStatus(const std::string& permissionName, bool isGranted, uint32_t flag) +bool PermissionPolicySet::UpdatePermissionStatus(const std::string& permissionName, bool isGranted, uint32_t flag) { + ACCESSTOKEN_LOG_INFO(LABEL, "permissionName %{public}s.", permissionName.c_str()); + int32_t oldStatus = 1; + int32_t newStatus = isGranted ? PERMISSION_GRANTED : PERMISSION_DENIED;; Utils::UniqueWriteGuard infoGuard(this->permPolicySetLock_); for (auto& perm : permStateList_) { if (perm.permissionName == permissionName) { + ACCESSTOKEN_LOG_INFO(LABEL, "ZZ permissionName %{public}s.", permissionName.c_str()); if (perm.isGeneral) { - perm.grantStatus[0] = isGranted ? PERMISSION_GRANTED : PERMISSION_DENIED; + oldStatus = perm.grantStatus[0]; + perm.grantStatus[0] = newStatus; uint32_t currFlag = static_cast(perm.grantFlags[0]); uint32_t newFlag = flag | (currFlag & PERMISSION_GRANTED_BY_POLICY); perm.grantFlags[0] = static_cast(newFlag); - } else { - return; } + ACCESSTOKEN_LOG_INFO(LABEL, "oldStatus %{public}d newStatus %{public}d.", oldStatus, newStatus); + if (oldStatus == newStatus) { + return false; + } + return true; } } + + return false; } void PermissionPolicySet::ResetUserGrantPermissionStatus(void) diff --git a/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp b/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp index 9229bd58fdb2b746cd35189c88ee808de7903af5..79027dcccb49c3115e157227ae0ab47a23a89e12 100644 --- a/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp +++ b/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp @@ -206,6 +206,19 @@ int AccessTokenManagerService::ClearUserGrantedPermissionState(AccessTokenID tok return RET_SUCCESS; } +int32_t AccessTokenManagerService::RegisterPermStateChangeCallback( + const PermStateChangeScopeParcel& scope, const sptr& callback) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Entry"); + return PermissionManager::GetInstance().AddPermStateChangeCallback(scope.scope, callback); +} + +int32_t AccessTokenManagerService::UnRegisterPermStateChangeCallback(const sptr& callback) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Entry"); + return PermissionManager::GetInstance().RemovePermStateChangeCallback(callback); +} + AccessTokenIDEx AccessTokenManagerService::AllocHapToken(const HapInfoParcel& info, const HapPolicyParcel& policy) { ACCESSTOKEN_LOG_INFO(LABEL, "called!"); diff --git a/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_stub.cpp b/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_stub.cpp index 8d621da61b8ad6fab150eb7a9707739dcad0c39c..3df99af34ca5779be00d1e4321ed1ded14a5723c 100644 --- a/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_stub.cpp +++ b/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_stub.cpp @@ -320,6 +320,33 @@ void AccessTokenManagerStub::GetNativeTokenInfoInner(MessageParcel& data, Messag reply.WriteInt32(result); } +void AccessTokenManagerStub::RegisterPermStateChangeCallbackInner(MessageParcel& data, MessageParcel& reply) +{ + ACCESSTOKEN_LOG_ERROR(LABEL, "called"); + sptr scopeParcel = data.ReadParcelable(); + if (scopeParcel == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "read scopeParcel fail"); + reply.WriteInt32(RET_FAILED); + return; + } + sptr callback = data.ReadRemoteObject(); + ACCESSTOKEN_LOG_ERROR(LABEL, "callback %{public}p ", (IRemoteObject *)callback); + int32_t result = this->RegisterPermStateChangeCallback(*scopeParcel, callback); + reply.WriteInt32(result); +} +void AccessTokenManagerStub::UnRegisterPermStateChangeCallbackInner(MessageParcel& data, MessageParcel& reply) +{ + ACCESSTOKEN_LOG_ERROR(LABEL, "called"); + sptr callback = data.ReadRemoteObject(); + if (callback == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "read scopeParcel fail"); + reply.WriteInt32(RET_FAILED); + return; + } + int32_t result = this->UnRegisterPermStateChangeCallback(callback); + reply.WriteInt32(result); +} + #ifdef TOKEN_SYNC_ENABLE void AccessTokenManagerStub::GetHapTokenInfoFromRemoteInner(MessageParcel& data, MessageParcel& reply) { @@ -528,6 +555,11 @@ AccessTokenManagerStub::AccessTokenManagerStub() &AccessTokenManagerStub::DumpTokenInfoInner; requestFuncMap_[static_cast(IAccessTokenManager::InterfaceCode::GET_PERMISSION_OPER_STATE)] = &AccessTokenManagerStub::GetSelfPermissionsStateInner; + + requestFuncMap_[static_cast(IAccessTokenManager::InterfaceCode::REGISTER_PERMISSION_STATE_CHANGE_CALLBACK)] = + &AccessTokenManagerStub::RegisterPermStateChangeCallbackInner; + requestFuncMap_[static_cast(IAccessTokenManager::InterfaceCode::UNREGISTER_PERMISSION_STATE_CHANGE_CALLBACK)] = + &AccessTokenManagerStub::UnRegisterPermStateChangeCallbackInner; } AccessTokenManagerStub::~AccessTokenManagerStub()