From 499cf76fecb7d2e84aa81aafef0342a07d6506ba Mon Sep 17 00:00:00 2001 From: chennian Date: Mon, 16 Mar 2026 20:57:41 +0800 Subject: [PATCH] add add startUsingWithBundle Co-Authored-By: Agent Signed-off-by: chennian Change-Id: I9ad63b8a72ed9cf7911df35ee05869fca5bd8833 --- access_token.gni | 7 + .../src/active_change_response_parcel.cpp | 3 + .../test/unittest/privacy_parcel_test.cpp | 24 +- .../include/active_change_response_info.h | 34 +- .../innerkits/privacy/include/privacy_kit.h | 18 +- .../innerkits/privacy/include/privacy_param.h | 5 + .../innerkits/privacy/libprivacy_sdk.map | 6 +- .../innerkits/privacy/src/privacy_kit.cpp | 37 +- .../privacy/src/privacy_manager_client.cpp | 93 ++- .../privacy/src/privacy_manager_client.h | 25 +- interfaces/innerkits/privacy/test/BUILD.gn | 4 + .../privacy_mock_test/privacy_kit_test.cpp | 47 ++ .../src/privacy_bundle_using_test.cpp | 767 ++++++++++++++++++ .../unittest/src/privacy_bundle_using_test.h | 35 + .../src/privacy_kit_coverage_test.cpp | 85 ++ .../test/unittest/src/privacy_kit_test.cpp | 203 +++-- .../privacymanager/idl/IPrivacyManager.idl | 6 +- .../active/active_status_callback_manager.h | 15 +- .../record/permission_record_manager.h | 14 +- .../include/service/privacy_manager_service.h | 8 +- .../active/active_status_callback_manager.cpp | 28 +- .../src/record/permission_record_manager.cpp | 267 ++++-- .../src/service/privacy_manager_service.cpp | 75 +- ...ermission_record_manager_coverage_test.cpp | 3 +- .../active_status_callback_manager_test.cpp | 97 ++- .../record/permission_record_manager_test.cpp | 385 +++++++-- .../service/privacy_manager_service_test.cpp | 298 ++++++- test/fuzztest/innerkits/privacy/BUILD.gn | 1 + .../BUILD.gn | 36 + .../corpus/init | 14 + .../project.xml | 25 + .../startusingpermissionbundle_fuzzer.cpp | 44 + .../startusingpermissionbundle_fuzzer.h | 22 + .../stopusingpermissionbundle_fuzzer/BUILD.gn | 36 + .../corpus/init | 14 + .../project.xml | 25 + .../stopusingpermissionbundle_fuzzer.cpp | 44 + .../stopusingpermissionbundle_fuzzer.h | 22 + test/fuzztest/services/privacy/BUILD.gn | 2 + .../startremoteusingpermissionstub_fuzzer.cpp | 2 +- .../BUILD.gn | 36 + .../corpus/init | 14 + .../project.xml | 25 + .../startusingpermissionbundlestub_fuzzer.cpp | 69 ++ .../startusingpermissionbundlestub_fuzzer.h | 22 + ...tartusingpermissioncallbackstub_fuzzer.cpp | 2 +- .../startusingpermissionstub_fuzzer.cpp | 2 +- .../BUILD.gn | 35 + .../corpus/init | 14 + .../project.xml | 25 + .../stopusingpermissionbundlestub_fuzzer.cpp | 64 ++ .../stopusingpermissionbundlestub_fuzzer.h | 22 + 52 files changed, 2967 insertions(+), 239 deletions(-) create mode 100644 interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.cpp create mode 100644 interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.h create mode 100644 test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/BUILD.gn create mode 100644 test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/corpus/init create mode 100644 test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/project.xml create mode 100644 test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.cpp create mode 100644 test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.h create mode 100644 test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/BUILD.gn create mode 100644 test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/corpus/init create mode 100644 test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/project.xml create mode 100644 test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.cpp create mode 100644 test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.h create mode 100644 test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/BUILD.gn create mode 100644 test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/corpus/init create mode 100644 test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/project.xml create mode 100644 test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.cpp create mode 100644 test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.h create mode 100644 test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/BUILD.gn create mode 100644 test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/corpus/init create mode 100644 test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/project.xml create mode 100644 test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.cpp create mode 100644 test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.h diff --git a/access_token.gni b/access_token.gni index bc2601ef0..b5ad9b46b 100644 --- a/access_token.gni +++ b/access_token.gni @@ -203,3 +203,10 @@ if ("${target_platform}" == "pc" || "${target_platform}" == "tablet" || use_libf } else { access_token_manage_user_policy_enable = false } + +if ("${target_platform}" == "phone" || "${target_platform}" == "tablet" || "${target_platform}" == "pc") { + privacy_bundle_start_stop_enable = true + access_token_cflags_cc += [ "-DPRIVACY_BUNDLE_START_STOP_ENABLE" ] +} else { + privacy_bundle_start_stop_enable = false +} diff --git a/frameworks/privacy/src/active_change_response_parcel.cpp b/frameworks/privacy/src/active_change_response_parcel.cpp index b63251b59..d09266a93 100644 --- a/frameworks/privacy/src/active_change_response_parcel.cpp +++ b/frameworks/privacy/src/active_change_response_parcel.cpp @@ -31,6 +31,7 @@ bool ActiveChangeResponseParcel::Marshalling(Parcel& out) const RETURN_IF_FALSE(out.WriteString(this->changeResponse.deviceId)); RETURN_IF_FALSE(out.WriteString(this->changeResponse.remoteDeviceName)); RETURN_IF_FALSE(out.WriteString(this->changeResponse.extra)); + RETURN_IF_FALSE(out.WriteString(this->changeResponse.bundleName)); return true; } @@ -61,6 +62,8 @@ ActiveChangeResponseParcel* ActiveChangeResponseParcel::Unmarshalling(Parcel& in RELEASE_IF_FALSE( in.ReadString(activeChangeResponseParcel->changeResponse.remoteDeviceName), activeChangeResponseParcel); RELEASE_IF_FALSE(in.ReadString(activeChangeResponseParcel->changeResponse.extra), activeChangeResponseParcel); + RELEASE_IF_FALSE( + in.ReadString(activeChangeResponseParcel->changeResponse.bundleName), activeChangeResponseParcel); return activeChangeResponseParcel; } } // namespace AccessToken diff --git a/frameworks/test/unittest/privacy_parcel_test.cpp b/frameworks/test/unittest/privacy_parcel_test.cpp index e4584da5f..51c1167b7 100644 --- a/frameworks/test/unittest/privacy_parcel_test.cpp +++ b/frameworks/test/unittest/privacy_parcel_test.cpp @@ -164,18 +164,17 @@ HWTEST_F(PrivacyParcelTest, ActiveChangeResponseParcel001, TestSize.Level1) { ActiveChangeResponseParcel activeChangeResponseParcel; - activeChangeResponseParcel.changeResponse = { - .callingTokenID = 100, - .tokenID = 100, - .permissionName = "ohos.permission.CAMERA", - .type = PERM_INACTIVE, - .usedType = NORMAL_TYPE, - .pid = -1, - .isRemote = false, - .deviceId = "device", - .remoteDeviceName = "name", - .extra = "perm_add", - }; + activeChangeResponseParcel.changeResponse.callingTokenID = 100; + activeChangeResponseParcel.changeResponse.tokenID = 100; + activeChangeResponseParcel.changeResponse.permissionName = "ohos.permission.CAMERA"; + activeChangeResponseParcel.changeResponse.type = PERM_INACTIVE; + activeChangeResponseParcel.changeResponse.usedType = NORMAL_TYPE; + activeChangeResponseParcel.changeResponse.pid = -1; + activeChangeResponseParcel.changeResponse.isRemote = false; + activeChangeResponseParcel.changeResponse.deviceId = "device"; + activeChangeResponseParcel.changeResponse.remoteDeviceName = "name"; + activeChangeResponseParcel.changeResponse.extra = "perm_add"; + activeChangeResponseParcel.changeResponse.bundleName = "com.ohos.permissionmanager"; Parcel parcel; EXPECT_EQ(true, activeChangeResponseParcel.Marshalling(parcel)); @@ -193,6 +192,7 @@ HWTEST_F(PrivacyParcelTest, ActiveChangeResponseParcel001, TestSize.Level1) EXPECT_EQ(activeChangeResponseParcel.changeResponse.deviceId, readedData->changeResponse.deviceId); EXPECT_EQ(activeChangeResponseParcel.changeResponse.remoteDeviceName, readedData->changeResponse.remoteDeviceName); EXPECT_EQ(activeChangeResponseParcel.changeResponse.extra, readedData->changeResponse.extra); + EXPECT_EQ(activeChangeResponseParcel.changeResponse.bundleName, readedData->changeResponse.bundleName); } /** diff --git a/interfaces/innerkits/privacy/include/active_change_response_info.h b/interfaces/innerkits/privacy/include/active_change_response_info.h index d21129004..3075bd9ea 100644 --- a/interfaces/innerkits/privacy/include/active_change_response_info.h +++ b/interfaces/innerkits/privacy/include/active_change_response_info.h @@ -68,21 +68,47 @@ enum LockScreenStatusChangeType { * @brief Permission active state change response struct */ struct ActiveChangeResponse { - AccessTokenID callingTokenID = 0; - AccessTokenID tokenID = 0; + AccessTokenID callingTokenID = INVALID_TOKENID; + AccessTokenID tokenID = INVALID_TOKENID; std::string permissionName; /** * permission active change type, for details about the valid values, * see the definition above. */ - ActiveChangeType type; - PermissionUsedType usedType; + ActiveChangeType type = PERM_INACTIVE; + PermissionUsedType usedType = NORMAL_TYPE; int32_t pid = -1; bool isRemote = false; std::string deviceId; std::string remoteDeviceName; /** extra info propagated from AddPermParamInfo::extra for PERM_ADD callback */ std::string extra = ""; + /** + * This field is only filled in callbacks triggered by bundle-based start/stop using permission. + * The callback contains the bundle name, permission name of this access. + */ + std::string bundleName; + + ActiveChangeResponse() = default; + + // Used by token-based active records and current-using queries. + ActiveChangeResponse(AccessTokenID callingTokenID, AccessTokenID tokenID, const std::string& permissionName, + ActiveChangeType type, PermissionUsedType usedType, int32_t pid = -1) + : callingTokenID(callingTokenID), tokenID(tokenID), permissionName(permissionName), type(type), + usedType(usedType), pid(pid) + {} + + // Used by bundle-based current-using queries. + ActiveChangeResponse(const std::string& bundleName, const std::string& permissionName) + : permissionName(permissionName), type(PERM_ACTIVE_IN_FOREGROUND), bundleName(bundleName) + {} + + // Used by remote permission active records and callbacks. + ActiveChangeResponse(const std::string& permissionName, const std::string& deviceId, + const std::string& remoteDeviceName) + : permissionName(permissionName), type(PERM_REMOTE_USING), isRemote(true), deviceId(deviceId), + remoteDeviceName(remoteDeviceName) + {} }; typedef ActiveChangeResponse CurrUsingPermInfo; diff --git a/interfaces/innerkits/privacy/include/privacy_kit.h b/interfaces/innerkits/privacy/include/privacy_kit.h index 107268bb6..95f8b1954 100644 --- a/interfaces/innerkits/privacy/include/privacy_kit.h +++ b/interfaces/innerkits/privacy/include/privacy_kit.h @@ -117,6 +117,20 @@ public: * @return error code, see privacy_error.h */ static int32_t StopUsingPermission(AccessTokenID tokenID, const std::string& permissionName, int32_t pid = -1); + /** + * @brief Input bundleName start using input permission. + * @param bundleName bundle name + * @param permissionName permission name + * @return error code, see privacy_error.h + */ + static int32_t StartUsingPermission(const std::string& bundleName, const std::string& permissionName); + /** + * @brief Input bundleName stop using input permission. + * @param bundleName bundle name + * @param permissionName permission name + * @return error code, see privacy_error.h + */ + static int32_t StopUsingPermission(const std::string& bundleName, const std::string& permissionName); /** * @brief Input info start remote using input permission. * @param info caller info @@ -178,9 +192,11 @@ public: /** * @brief Register sensitive permission active status change callback. * @param callback PermActiveStatusCustomizedCbk smark pointer quote + * @param type callback register type, default is TOKEN_ONLY * @return error code, see privacy_error.h */ - static int32_t RegisterPermActiveStatusCallback(const std::shared_ptr& callback); + static int32_t RegisterPermActiveStatusCallback(const std::shared_ptr& callback, + CallbackRegisterType type = CallbackRegisterType::TOKEN_ONLY); /** * @brief Unregister sensitive permission active status change callback. * @param callback PermActiveStatusCustomizedCbk smark pointer quote diff --git a/interfaces/innerkits/privacy/include/privacy_param.h b/interfaces/innerkits/privacy/include/privacy_param.h index 99c105f6f..13df92380 100644 --- a/interfaces/innerkits/privacy/include/privacy_param.h +++ b/interfaces/innerkits/privacy/include/privacy_param.h @@ -58,6 +58,11 @@ enum CallerType { MICROPHONE = 0, CAMERA = 1 }; + +enum class CallbackRegisterType { + ALL = 0, + TOKEN_ONLY, +}; } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/interfaces/innerkits/privacy/libprivacy_sdk.map b/interfaces/innerkits/privacy/libprivacy_sdk.map index e92811cce..066f39c11 100644 --- a/interfaces/innerkits/privacy/libprivacy_sdk.map +++ b/interfaces/innerkits/privacy/libprivacy_sdk.map @@ -22,13 +22,15 @@ "OHOS::Security::AccessToken::PrivacyKit::GetPermissionUsedRecordToggleStatus(int, bool&)"; "OHOS::Security::AccessToken::PrivacyKit::StartUsingPermission(unsigned int, std::__h::basic_string, std::__h::allocator> const&, int, OHOS::Security::AccessToken::PermissionUsedTypeValue)"; "OHOS::Security::AccessToken::PrivacyKit::StopUsingPermission(unsigned int, std::__h::basic_string, std::__h::allocator> const&, int)"; + "OHOS::Security::AccessToken::PrivacyKit::StartUsingPermission(std::__h::basic_string, std::__h::allocator> const&, std::__h::basic_string, std::__h::allocator> const&)"; + "OHOS::Security::AccessToken::PrivacyKit::StopUsingPermission(std::__h::basic_string, std::__h::allocator> const&, std::__h::basic_string, std::__h::allocator> const&)"; "OHOS::Security::AccessToken::PrivacyKit::StartRemoteUsingPermission(OHOS::Security::AccessToken::RemoteCallerInfo const&, std::__h::basic_string, std::__h::allocator> const&)"; "OHOS::Security::AccessToken::PrivacyKit::StopRemoteUsingPermission(OHOS::Security::AccessToken::RemoteCallerInfo const&, std::__h::basic_string, std::__h::allocator> const&)"; "OHOS::Security::AccessToken::PrivacyKit::GetPermissionUsedRecords(OHOS::Security::AccessToken::PermissionUsedRequest const&, OHOS::Security::AccessToken::PermissionUsedResult&)"; "OHOS::Security::AccessToken::PrivacyKit::AddRemotePermissionUsedRecord(OHOS::Security::AccessToken::RemoteCallerInfo const&, std::__h::basic_string, std::__h::allocator> const&, int, int, bool)"; "OHOS::Security::AccessToken::PrivacyKit::GetRemotePermissionUsedRecords(OHOS::Security::AccessToken::PermissionUsedRequest const&, OHOS::Security::AccessToken::PermissionUsedResult&)"; "OHOS::Security::AccessToken::PermActiveStatusCustomizedCbk::GetPermList(std::__h::vector, std::__h::allocator>, std::__h::allocator, std::__h::allocator>>>&) const"; - "OHOS::Security::AccessToken::PrivacyKit::RegisterPermActiveStatusCallback(std::__h::shared_ptr const&)"; + "OHOS::Security::AccessToken::PrivacyKit::RegisterPermActiveStatusCallback(std::__h::shared_ptr const&, OHOS::Security::AccessToken::CallbackRegisterType)"; "OHOS::Security::AccessToken::PrivacyKit::UnRegisterPermActiveStatusCallback(std::__h::shared_ptr const&)"; "OHOS::Security::AccessToken::PrivacyKit::RemovePermissionUsedRecords(unsigned int)"; "OHOS::Security::AccessToken::StateCustomizedCbk::StateCustomizedCbk()"; @@ -38,7 +40,7 @@ "OHOS::Security::AccessToken::StateCustomizedCbk::~StateCustomizedCbk()"; "OHOS::Security::AccessToken::OnPermissionUsedRecordCallbackStub::OnRemoteRequest(unsigned int, OHOS::MessageParcel&, OHOS::MessageParcel&, OHOS::MessageOption&)"; "OHOS::Security::AccessToken::PrivacyManagerClient::GetInstance()"; - "OHOS::Security::AccessToken::PrivacyManagerClient::RegisterPermActiveStatusCallback(std::__h::shared_ptr const&)"; + "OHOS::Security::AccessToken::PrivacyManagerClient::RegisterPermActiveStatusCallback(std::__h::shared_ptr const&, OHOS::Security::AccessToken::CallbackRegisterType)"; "OHOS::Security::AccessToken::StateChangeCallbackStub::OnRemoteRequest(unsigned int, OHOS::MessageParcel&, OHOS::MessageParcel&, OHOS::MessageOption&)"; "OHOS::Security::AccessToken::PermActiveStatusChangeCallbackStub::OnRemoteRequest(unsigned int, OHOS::MessageParcel&, OHOS::MessageParcel&, OHOS::MessageOption&)"; "OHOS::Security::AccessToken::PermActiveStatusChangeCallback::PermActiveStatusChangeCallback(std::__h::shared_ptr const&)"; diff --git a/interfaces/innerkits/privacy/src/privacy_kit.cpp b/interfaces/innerkits/privacy/src/privacy_kit.cpp index 99a9b4c85..f5eeece17 100644 --- a/interfaces/innerkits/privacy/src/privacy_kit.cpp +++ b/interfaces/innerkits/privacy/src/privacy_kit.cpp @@ -29,6 +29,11 @@ namespace Security { namespace AccessToken { namespace { constexpr const int64_t MERGE_TIMESTAMP = 200; // 200ms +bool IsValidCallbackRegisterType(CallbackRegisterType type) +{ + return (type == CallbackRegisterType::ALL) || (type == CallbackRegisterType::TOKEN_ONLY); +} + std::mutex g_lockCache; struct RecordCache { int32_t successCount = 0; @@ -162,6 +167,30 @@ int32_t PrivacyKit::StopUsingPermission(AccessTokenID tokenID, const std::string return PrivacyManagerClient::GetInstance().StopUsingPermission(tokenID, pid, permissionName); } +int32_t PrivacyKit::StartUsingPermission(const std::string& bundleName, const std::string& permissionName) +{ +#ifndef PRIVACY_BUNDLE_START_STOP_ENABLE + return PrivacyError::ERR_CAPABILITY_NOT_SUPPORT; +#else + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName)) { + return PrivacyError::ERR_PARAM_INVALID; + } + return PrivacyManagerClient::GetInstance().StartUsingPermission(bundleName, permissionName); +#endif +} + +int32_t PrivacyKit::StopUsingPermission(const std::string& bundleName, const std::string& permissionName) +{ +#ifndef PRIVACY_BUNDLE_START_STOP_ENABLE + return PrivacyError::ERR_CAPABILITY_NOT_SUPPORT; +#else + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName)) { + return PrivacyError::ERR_PARAM_INVALID; + } + return PrivacyManagerClient::GetInstance().StopUsingPermission(bundleName, permissionName); +#endif +} + int32_t PrivacyKit::RemovePermissionUsedRecords(AccessTokenID tokenID) { if (!DataValidator::IsTokenIDValid(tokenID)) { @@ -306,9 +335,13 @@ int32_t PrivacyKit::GetRemotePermissionUsedRecords( } #endif -int32_t PrivacyKit::RegisterPermActiveStatusCallback(const std::shared_ptr& callback) +int32_t PrivacyKit::RegisterPermActiveStatusCallback( + const std::shared_ptr& callback, CallbackRegisterType type) { - return PrivacyManagerClient::GetInstance().RegisterPermActiveStatusCallback(callback); + if (!IsValidCallbackRegisterType(type)) { + return PrivacyError::ERR_PARAM_INVALID; + } + return PrivacyManagerClient::GetInstance().RegisterPermActiveStatusCallback(callback, type); } int32_t PrivacyKit::UnRegisterPermActiveStatusCallback(const std::shared_ptr& callback) diff --git a/interfaces/innerkits/privacy/src/privacy_manager_client.cpp b/interfaces/innerkits/privacy/src/privacy_manager_client.cpp index b884b1d7f..9b289d890 100644 --- a/interfaces/innerkits/privacy/src/privacy_manager_client.cpp +++ b/interfaces/innerkits/privacy/src/privacy_manager_client.cpp @@ -155,6 +155,9 @@ void PrivacyManagerClient::OnAddPrivacySa(void) { LOGI(PRI_DOMAIN, PRI_TAG, "Enter."); ReStartUsing(); +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + ReStartUsingBundle(); +#endif #ifdef REMOTE_PRIVACY_ENABLE ReStartRemoteUsing(); #endif @@ -492,6 +495,92 @@ int32_t PrivacyManagerClient::GetRemotePermissionUsedRecords(const PermissionUse } #endif +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +void PrivacyManagerClient::ReStartUsingBundle() +{ + auto proxy = GetProxy(); + if (proxy == nullptr) { + LOGE(PRI_DOMAIN, PRI_TAG, "Proxy is null."); + return; + } + auto anonyStub = GetAnonyStub(); + if (anonyStub == nullptr) { + LOGE(PRI_DOMAIN, PRI_TAG, "Proxy death recipent is null."); + return; + } + std::lock_guard lock(startUsingBundlePermInputMutex_); + LOGI(PRI_DOMAIN, PRI_TAG, "Bundle cache size=%{public}zu.", bundleCacheList_.size()); + for (const auto& info : bundleCacheList_) { + int32_t ret = proxy->StartUsingPermission( + info.bundleName, info.permissionName, anonyStub->AsObject()); + ret = ConvertResult(ret); + LOGI(PRI_DOMAIN, PRI_TAG, "Recover bundle start ret=%{public}d.", ret); + } +} + +void PrivacyManagerClient::SetBundleInputCache(const std::string& bundleName, const std::string& permissionName) +{ + std::lock_guard lock(startUsingBundlePermInputMutex_); + for (const auto& info : bundleCacheList_) { + if ((info.bundleName == bundleName) && (info.permissionName == permissionName)) { + LOGE(PRI_DOMAIN, PRI_TAG, "It already exists in bundle cache."); + return; + } + } + bundleCacheList_.emplace_back(StartUsingBundlePermInputInfo { bundleName, permissionName }); +} + +void PrivacyManagerClient::DeleteBundleInputCache(const std::string& bundleName, const std::string& permissionName) +{ + std::lock_guard lock(startUsingBundlePermInputMutex_); + for (auto it = bundleCacheList_.begin(); it != bundleCacheList_.end(); ++it) { + if ((it->bundleName == bundleName) && (it->permissionName == permissionName)) { + bundleCacheList_.erase(it); + return; + } + } +} + +int32_t PrivacyManagerClient::StartUsingPermission(const std::string& bundleName, const std::string& permissionName) +{ + auto proxy = GetProxy(); + if (proxy == nullptr) { + LOGE(PRI_DOMAIN, PRI_TAG, "Proxy is null."); + return PrivacyError::ERR_SERVICE_ABNORMAL; + } + + auto anonyStub = GetAnonyStub(); + if (anonyStub == nullptr) { + LOGE(PRI_DOMAIN, PRI_TAG, "Proxy death recipent is null."); + return PrivacyError::ERR_MALLOC_FAILED; + } + + int32_t ret = proxy->StartUsingPermission(bundleName, permissionName, anonyStub->AsObject()); + ret = ConvertResult(ret); + LOGI(PRI_DOMAIN, PRI_TAG, "Bundle start ret=%{public}d.", ret); + if (ret == RET_SUCCESS) { + SetBundleInputCache(bundleName, permissionName); + } + return ret; +} + +int32_t PrivacyManagerClient::StopUsingPermission(const std::string& bundleName, const std::string& permissionName) +{ + DeleteBundleInputCache(bundleName, permissionName); + + auto proxy = GetProxy(); + if (proxy == nullptr) { + LOGE(PRI_DOMAIN, PRI_TAG, "Proxy is null."); + return PrivacyError::ERR_SERVICE_ABNORMAL; + } + + int32_t ret = proxy->StopUsingPermission(bundleName, permissionName); + ret = ConvertResult(ret); + LOGI(PRI_DOMAIN, PRI_TAG, "Bundle stop ret=%{public}d.", ret); + return ret; +} +#endif + int32_t PrivacyManagerClient::RemovePermissionUsedRecords(AccessTokenID tokenID) { auto proxy = GetProxy(); @@ -567,7 +656,7 @@ int32_t PrivacyManagerClient::CreateActiveStatusChangeCbk( } int32_t PrivacyManagerClient::RegisterPermActiveStatusCallback( - const std::shared_ptr& callback) + const std::shared_ptr& callback, CallbackRegisterType type) { if (callback == nullptr) { LOGE(PRI_DOMAIN, PRI_TAG, "CustomizedCb is nullptr."); @@ -592,7 +681,7 @@ int32_t PrivacyManagerClient::RegisterPermActiveStatusCallback( return PrivacyError::ERR_PARAM_INVALID; } - result = proxy->RegisterPermActiveStatusCallback(permList, callbackWrap->AsObject()); + result = proxy->RegisterPermActiveStatusCallback(permList, callbackWrap->AsObject(), static_cast(type)); if (result == RET_SUCCESS) { std::lock_guard lock(activeCbkMutex_); activeCbkMap_[callback] = callbackWrap; diff --git a/interfaces/innerkits/privacy/src/privacy_manager_client.h b/interfaces/innerkits/privacy/src/privacy_manager_client.h index adfe1d0e9..ce51dd8f8 100644 --- a/interfaces/innerkits/privacy/src/privacy_manager_client.h +++ b/interfaces/innerkits/privacy/src/privacy_manager_client.h @@ -27,6 +27,7 @@ #include "perm_active_status_customized_cbk.h" #include "perm_disable_policy_change_callback.h" #include "privacy_death_recipient.h" +#include "privacy_param.h" #include "proxy_death_callback.h" #ifdef REMOTE_PRIVACY_ENABLE #include "remote_caller_info.h" @@ -43,6 +44,14 @@ struct StartUsingPermInputInfo { PermissionUsedTypeInfo input; bool hasCbk; }; + +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +struct StartUsingBundlePermInputInfo { + std::string bundleName; + std::string permissionName; +}; +#endif + class PrivacyManagerClient final { public: static PrivacyManagerClient& GetInstance(); @@ -66,12 +75,18 @@ public: int32_t successCount, int32_t failCount, bool asyncMode = false); int32_t GetRemotePermissionUsedRecords(const PermissionUsedRequest& request, PermissionUsedResult& result); void ReStartRemoteUsing(); +#endif +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + int32_t StartUsingPermission(const std::string& bundleName, const std::string& permissionName); + int32_t StopUsingPermission(const std::string& bundleName, const std::string& permissionName); + void ReStartUsingBundle(); #endif int32_t RemovePermissionUsedRecords(AccessTokenID tokenID); int32_t GetPermissionUsedRecords(const PermissionUsedRequest& request, PermissionUsedResult& result); int32_t GetPermissionUsedRecords( const PermissionUsedRequest& request, const sptr& callback); - int32_t RegisterPermActiveStatusCallback(const std::shared_ptr& callback); + int32_t RegisterPermActiveStatusCallback( + const std::shared_ptr& callback, CallbackRegisterType type); int32_t UnRegisterPermActiveStatusCallback(const std::shared_ptr& callback); int32_t CreateActiveStatusChangeCbk( const std::shared_ptr& callback, @@ -113,6 +128,10 @@ private: void SetRemoteInputCache(const RemotePermissionUsedInfo& info); void DeleteRemoteInputCache(const RemoteCallerInfo& info, const std::string& permissionName); #endif +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + void SetBundleInputCache(const std::string& bundleName, const std::string& permissionName); + void DeleteBundleInputCache(const std::string& bundleName, const std::string& permissionName); +#endif private: std::mutex activeCbkMutex_; @@ -130,6 +149,10 @@ private: std::mutex startRemoteUsingPermInputMutex_; std::vector remoteCacheList_; #endif +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + std::mutex startUsingBundlePermInputMutex_; + std::vector bundleCacheList_; +#endif }; } // namespace AccessToken } // namespace Security diff --git a/interfaces/innerkits/privacy/test/BUILD.gn b/interfaces/innerkits/privacy/test/BUILD.gn index 49fac92c7..5c17bfb93 100644 --- a/interfaces/innerkits/privacy/test/BUILD.gn +++ b/interfaces/innerkits/privacy/test/BUILD.gn @@ -44,6 +44,10 @@ ohos_unittest("libprivacy_sdk_test") { "unittest/src/privacy_test_common.cpp", ] + if (privacy_bundle_start_stop_enable) { + sources += [ "unittest/src/privacy_bundle_using_test.cpp" ] + } + cflags_cc = access_token_cflags_cc configs = [ "${access_token_path}/config:coverage_flags" ] diff --git a/interfaces/innerkits/privacy/test/unittest/privacy_mock_test/privacy_kit_test.cpp b/interfaces/innerkits/privacy/test/unittest/privacy_mock_test/privacy_kit_test.cpp index 1087b6028..32e5f5b60 100644 --- a/interfaces/innerkits/privacy/test/unittest/privacy_mock_test/privacy_kit_test.cpp +++ b/interfaces/innerkits/privacy/test/unittest/privacy_mock_test/privacy_kit_test.cpp @@ -63,6 +63,24 @@ HWTEST_F(PrivacyKitTest, AddPermissionUsedRecord001, TestSize.Level0) ASSERT_EQ(PrivacyError::ERR_SERVICE_ABNORMAL, ret); } +/** + * @tc.name: AddPermissionUsedRecord002 + * @tc.desc: AddPermissionUsedRecord with AddPermParamInfo and proxy is null. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, AddPermissionUsedRecord002, TestSize.Level0) +{ + AddPermParamInfo info; + info.tokenId = 0xff; + info.permissionName = "ohos.permission.CAMERA"; + info.successCount = 1; + info.failCount = 0; + + int32_t ret = PrivacyKit::AddPermissionUsedRecord(info); + ASSERT_EQ(PrivacyError::ERR_SERVICE_ABNORMAL, ret); +} + #ifdef REMOTE_PRIVACY_ENABLE /** * @tc.name: AddRemotePermissionUsedRecord001 @@ -170,6 +188,22 @@ HWTEST_F(PrivacyKitTest, StartUsingPermission002, TestSize.Level0) PrivacyKit::StartUsingPermission(g_TokenId_A, permissionName, callbackPtr)); } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +/** + * @tc.name: BundleUsingProxyTest001 + * @tc.desc: Bundle start/stop using permission with proxy is null. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, BundleUsingProxyTest001, TestSize.Level0) +{ + std::string bundleName = "ohos.test.bundle"; + std::string permissionName = "ohos.permission.CAMERA"; + ASSERT_EQ(PrivacyError::ERR_SERVICE_ABNORMAL, PrivacyKit::StartUsingPermission(bundleName, permissionName)); + ASSERT_EQ(PrivacyError::ERR_SERVICE_ABNORMAL, PrivacyKit::StopUsingPermission(bundleName, permissionName)); +} +#endif + /** * @tc.name: StopUsingPermission001 * @tc.desc: StopUsingPermission proxy is null. @@ -416,6 +450,19 @@ HWTEST_F(PrivacyKitTest, GetCurrUsingPermInfo001, TestSize.Level0) std::vector results; EXPECT_EQ(PrivacyError::ERR_SERVICE_ABNORMAL, PrivacyKit::GetCurrUsingPermInfo(results)); } + +/** + * @tc.name: CheckPermissionInUse001 + * @tc.desc: CheckPermissionInUse proxy is null. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, CheckPermissionInUse001, TestSize.Level0) +{ + bool isUsing = true; + EXPECT_EQ(PrivacyError::ERR_SERVICE_ABNORMAL, + PrivacyKit::CheckPermissionInUse("ohos.permission.CAMERA", isUsing)); +} } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.cpp b/interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.cpp new file mode 100644 index 000000000..2829246d3 --- /dev/null +++ b/interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.cpp @@ -0,0 +1,767 @@ +/* + * Copyright (c) 2026 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 "privacy_bundle_using_test.h" + +#include +#include + +#include "parameter.h" +#include "privacy_error.h" +#include "privacy_kit.h" +#include "privacy_test_common.h" + +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +constexpr int32_t VALUE_MAX_LEN = 32; +uint64_t g_selfTokenId = 0; +constexpr const char* PERMISSION_USED_STATS = "ohos.permission.PERMISSION_USED_STATS"; +constexpr const char* TEST_BUNDLE_NAME = "ohos.test.bundle"; +constexpr const char* TEST_PERMISSION_NAME = "ohos.permission.CAMERA"; +constexpr const char* EDM_CAMERA_MUTE_KEY = "persist.edm.camera_disable"; +constexpr size_t INVALID_NAME_LENGTH = 257; + +AccessTokenID CreateGrantedHapToken(const std::string& bundleName, const std::string& permissionName) +{ + HapInfoParams infoParams = { + .userID = 0, + .bundleName = bundleName, + .instIndex = 0, + .appIDDesc = "AccessTokenBundleUsingTestAppID", + .apiVersion = PrivacyTestCommon::DEFAULT_API_VERSION, + .isSystemApp = true, + .appDistributionType = "", + }; + + HapPolicyParams policyParams = { + .apl = APL_NORMAL, + .domain = "accesstoken_test_domain", + }; + + PermissionDef permDefResult; + if (AccessTokenKit::GetDefPermission(permissionName, permDefResult) == RET_SUCCESS) { + PermissionStateFull permState = { + .permissionName = permissionName, + .isGeneral = true, + .resDeviceID = {"local_test_device"}, + .grantStatus = {PermissionState::PERMISSION_GRANTED}, + .grantFlags = {PermissionFlag::PERMISSION_SYSTEM_FIXED} + }; + policyParams.permStateList.emplace_back(permState); + if (permDefResult.availableLevel > policyParams.apl) { + policyParams.aclRequestedList.emplace_back(permissionName); + } + } + + AccessTokenIDEx tokenIdEx = PrivacyTestCommon::AllocTestHapToken(infoParams, policyParams); + return tokenIdEx.tokenIdExStruct.tokenID; +} + +const CurrUsingPermInfo* FindUsingInfo( + const std::vector& infoList, AccessTokenID tokenID, const std::string& permissionName) +{ + for (const auto& info : infoList) { + if ((info.tokenID == tokenID) && (info.permissionName == permissionName)) { + return &info; + } + } + return nullptr; +} + +const CurrUsingPermInfo* FindBundleUsingInfo( + const std::vector& infoList, const std::string& bundleName, const std::string& permissionName) +{ + for (const auto& info : infoList) { + if ((info.bundleName == bundleName) && (info.permissionName == permissionName)) { + return &info; + } + } + return nullptr; +} + +const CurrUsingPermInfo* FindRemoteUsingInfo(const std::vector& infoList, + const std::string& deviceId, const std::string& permissionName) +{ + for (const auto& info : infoList) { + if (info.isRemote && (info.deviceId == deviceId) && (info.permissionName == permissionName)) { + return &info; + } + } + return nullptr; +} + +int32_t SetDisablePolicyAsEdm(const std::string& permissionName, bool isDisable) +{ + MockNativeToken mock("edm"); + return PrivacyKit::SetDisablePolicy(permissionName, isDisable); +} + +class BundleActiveStatusCallbackTest : public PermActiveStatusCustomizedCbk { +public: + explicit BundleActiveStatusCallbackTest(const std::vector& permList) + : PermActiveStatusCustomizedCbk(permList) + {} + + ~BundleActiveStatusCallbackTest() override = default; + + void ActiveStatusChangeCallback(ActiveChangeResponse& result) override + { + callTimes_++; + type_ = result.type; + callingTokenID_ = result.callingTokenID; + tokenID_ = result.tokenID; + permissionName_ = result.permissionName; + bundleName_ = result.bundleName; + } + + int32_t callTimes_ = 0; + ActiveChangeType type_ = PERM_INACTIVE; + AccessTokenID callingTokenID_ = INVALID_TOKENID; + AccessTokenID tokenID_ = INVALID_TOKENID; + std::string permissionName_; + std::string bundleName_; +}; +} + +void BundleUsingTest::SetUpTestCase() +{ + g_selfTokenId = GetSelfTokenID(); + PrivacyTestCommon::SetTestEvironment(g_selfTokenId); +} + +void BundleUsingTest::TearDownTestCase() +{ + SetSelfTokenID(g_selfTokenId); + PrivacyTestCommon::ResetTestEvironment(); +} +void BundleUsingTest::SetUp() {} +void BundleUsingTest::TearDown() +{ + (void)PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME); +} + +/** + * @tc.name: BundleUsingtest001 + * @tc.desc: Verify bundle using interfaces with invalid parameters. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest001, TestSize.Level1) +{ + std::string longBundle(INVALID_NAME_LENGTH, 'a'); + std::string longPerm(INVALID_NAME_LENGTH, 'a'); + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StartUsingPermission("", TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StartUsingPermission(longBundle, TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, "")); + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, longPerm)); + + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StopUsingPermission("", TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StopUsingPermission(longBundle, TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, "")); + EXPECT_EQ(ERR_PARAM_INVALID, PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, longPerm)); +} + +/** + * @tc.name: BundleUsingtest002 + * @tc.desc: Verify bundle start and stop succeed for system app with permission. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest002, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest002", reqPerm, true); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingtest003 + * @tc.desc: Verify bundle start and stop are rejected for non-system app. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest003, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest003", reqPerm, false); + + EXPECT_EQ(ERR_NOT_SYSTEM_APP, PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_NOT_SYSTEM_APP, PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingtest004 + * @tc.desc: Verify bundle start and stop are denied without permission. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest004, TestSize.Level1) +{ + std::vector reqPerm; + MockHapToken mock("BundleUsingtest004", reqPerm, true); + + EXPECT_EQ(ERR_PERMISSION_DENIED, PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_PERMISSION_DENIED, PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingtest005 + * @tc.desc: Verify bundle repeat start and repeat stop return expected errors. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest005, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest005", reqPerm, true); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_PERMISSION_ALREADY_START_USING, + PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); + EXPECT_EQ(ERR_PERMISSION_NOT_START_USING, + PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingtest006 + * @tc.desc: Verify bundle start and stop return permission not exist for unsupported permission name. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest006, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest006", reqPerm, true); + const std::string noexistPerm = "ohos.permission.TEST"; + + EXPECT_EQ(ERR_PERMISSION_NOT_EXIST, PrivacyKit::StartUsingPermission(TEST_BUNDLE_NAME, noexistPerm)); + EXPECT_EQ(ERR_PERMISSION_NOT_EXIST, PrivacyKit::StopUsingPermission(TEST_BUNDLE_NAME, noexistPerm)); +} + +/** + * @tc.name: BundleUsingtest007 + * @tc.desc: Verify bundle callback is not triggered by mute and restart is blocked by EDM policy after stop. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest007, TestSize.Level1) +{ + char value[VALUE_MAX_LEN] = {0}; + GetParameter(EDM_CAMERA_MUTE_KEY, "", value, VALUE_MAX_LEN - 1); + std::string muteState(value); + + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest007", reqPerm, true); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleName = "ohos.test.bundle.callback.mute"; + AccessTokenID callingTokenID = static_cast(GetSelfTokenID()); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(1, callbackPtr->callTimes_); + EXPECT_EQ(PERM_ACTIVE_IN_FOREGROUND, callbackPtr->type_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ(bundleName, callbackPtr->bundleName_); + + ASSERT_EQ(0, SetParameter(EDM_CAMERA_MUTE_KEY, "true")); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(1, callbackPtr->callTimes_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(2, callbackPtr->callTimes_); + EXPECT_EQ(PERM_INACTIVE, callbackPtr->type_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ(bundleName, callbackPtr->bundleName_); + + EXPECT_EQ(ERR_EDM_POLICY_CHECK_FAILED, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(2, callbackPtr->callTimes_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); + + EXPECT_EQ(0, SetParameter(EDM_CAMERA_MUTE_KEY, muteState.c_str())); +} + +/** + * @tc.name: BundleUsingtest008 + * @tc.desc: Verify bundle callback is not triggered by disable policy and restart is blocked after stop. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest008, TestSize.Level1) +{ + bool disableBackup = false; + { + MockNativeToken mock("accesstoken_service"); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::GetDisablePolicy(TEST_PERMISSION_NAME, disableBackup)); + } + + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest008", reqPerm, true); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleName = "ohos.test.bundle.callback.disable"; + AccessTokenID callingTokenID = static_cast(GetSelfTokenID()); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(1, callbackPtr->callTimes_); + EXPECT_EQ(PERM_ACTIVE_IN_FOREGROUND, callbackPtr->type_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ(bundleName, callbackPtr->bundleName_); + + ASSERT_EQ(RET_SUCCESS, SetDisablePolicyAsEdm(TEST_PERMISSION_NAME, true)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(1, callbackPtr->callTimes_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(2, callbackPtr->callTimes_); + EXPECT_EQ(PERM_INACTIVE, callbackPtr->type_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ(bundleName, callbackPtr->bundleName_); + + EXPECT_EQ(ERR_EDM_POLICY_CHECK_FAILED, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(2, callbackPtr->callTimes_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); + + ASSERT_EQ(RET_SUCCESS, SetDisablePolicyAsEdm(TEST_PERMISSION_NAME, disableBackup)); +} + +/** + * @tc.name: BundleUsingtest009 + * @tc.desc: Verify GetCurrUsingPermInfo does not return bundle records when nothing is started. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest009, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest009", reqPerm, true); + + std::vector infoList; + { + MockNativeToken mockQuery("audio_server"); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::GetCurrUsingPermInfo(infoList)); + } + EXPECT_EQ(nullptr, FindBundleUsingInfo(infoList, TEST_BUNDLE_NAME, TEST_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingtest010 + * @tc.desc: Verify bundle only start/stop affects GetCurrUsingPermInfo and CheckPermissionInUse. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest010, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest010", reqPerm, true); + const std::string bundleName = "ohos.test.bundle.query"; + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + + std::vector infoList; + { + MockNativeToken mockQuery("audio_server"); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::GetCurrUsingPermInfo(infoList)); + } + const CurrUsingPermInfo* info = FindBundleUsingInfo(infoList, bundleName, TEST_PERMISSION_NAME); + ASSERT_NE(nullptr, info); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), info->permissionName); + EXPECT_EQ(bundleName, info->bundleName); + + bool isUsing = false; + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_TRUE(isUsing); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + + infoList.clear(); + { + MockNativeToken mockQuery("audio_server"); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::GetCurrUsingPermInfo(infoList)); + } + EXPECT_EQ(nullptr, FindBundleUsingInfo(infoList, bundleName, TEST_PERMISSION_NAME)); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_FALSE(isUsing); +} + +/** + * @tc.name: BundleUsingtest011 + * @tc.desc: Verify CheckPermissionInUse with token only start and stop. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest011, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest011", reqPerm, true); + AccessTokenID tokenID = CreateGrantedHapToken("ohos.test.bundle.token.only", TEST_PERMISSION_NAME); + ASSERT_NE(INVALID_TOKENID, tokenID); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(tokenID, TEST_PERMISSION_NAME)); + + bool isUsing = false; + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_TRUE(isUsing); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(tokenID, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_FALSE(isUsing); + + EXPECT_EQ(RET_SUCCESS, PrivacyTestCommon::DeleteTestHapToken(tokenID)); +} + +/** + * @tc.name: BundleUsingtest012 + * @tc.desc: Verify bundle and token together affect GetCurrUsingPermInfo and CheckPermissionInUse. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest012, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest012", reqPerm, true); + AccessTokenID callingTokenID = static_cast(GetSelfTokenID()); + + AccessTokenID tokenID = CreateGrantedHapToken("ohos.test.bundle.token", TEST_PERMISSION_NAME); + ASSERT_NE(INVALID_TOKENID, tokenID); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission("ohos.test.bundle.mixed", TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(tokenID, TEST_PERMISSION_NAME)); + + std::vector infoList; + { + MockNativeToken mockQuery("audio_server"); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::GetCurrUsingPermInfo(infoList)); + } + const CurrUsingPermInfo* bundleInfo = FindBundleUsingInfo( + infoList, "ohos.test.bundle.mixed", TEST_PERMISSION_NAME); + ASSERT_NE(nullptr, bundleInfo); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), bundleInfo->permissionName); + EXPECT_EQ("ohos.test.bundle.mixed", bundleInfo->bundleName); + EXPECT_EQ(PERM_ACTIVE_IN_FOREGROUND, bundleInfo->type); + const CurrUsingPermInfo* info = FindUsingInfo(infoList, tokenID, TEST_PERMISSION_NAME); + EXPECT_NE(nullptr, info); + if (info != nullptr) { + EXPECT_EQ(callingTokenID, info->callingTokenID); + EXPECT_EQ(tokenID, info->tokenID); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), info->permissionName); + EXPECT_EQ(-1, info->pid); // -1: bundle start does not carry pid + EXPECT_EQ("", info->deviceId); + EXPECT_EQ(NORMAL_TYPE, info->usedType); + EXPECT_FALSE(info->isRemote); + } + + bool isUsing = false; + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_TRUE(isUsing); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(tokenID, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_TRUE(isUsing); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission("ohos.test.bundle.mixed", TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_FALSE(isUsing); + + EXPECT_EQ(RET_SUCCESS, PrivacyTestCommon::DeleteTestHapToken(tokenID)); +} + +#ifdef REMOTE_PRIVACY_ENABLE +/** + * @tc.name: BundleUsingtest013 + * @tc.desc: Verify bundle, token and remote together affect GetCurrUsingPermInfo and CheckPermissionInUse. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest013, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest013", reqPerm, true); + AccessTokenID callingTokenID = static_cast(GetSelfTokenID()); + AccessTokenID tokenID = CreateGrantedHapToken("ohos.test.bundle.token.remote", TEST_PERMISSION_NAME); + ASSERT_NE(INVALID_TOKENID, tokenID); + const std::string bundleName = "ohos.test.bundle.remote.mixed"; + RemoteCallerInfo remoteInfo = {"remote_device_id", "remote_device_name"}; + auto startRemote = [&remoteInfo]() { MockNativeToken mockRemote("camera_service"); + return PrivacyKit::StartRemoteUsingPermission(remoteInfo, TEST_PERMISSION_NAME); }; + auto stopRemote = [&remoteInfo]() { MockNativeToken mockRemote("camera_service"); + return PrivacyKit::StopRemoteUsingPermission(remoteInfo, TEST_PERMISSION_NAME); }; + auto checkInfo = [&](const std::vector& infoList) { + const CurrUsingPermInfo* bundleInfo = FindBundleUsingInfo(infoList, bundleName, TEST_PERMISSION_NAME); + ASSERT_NE(nullptr, bundleInfo); + EXPECT_EQ(bundleName, bundleInfo->bundleName); + const CurrUsingPermInfo* tokenInfo = FindUsingInfo(infoList, tokenID, TEST_PERMISSION_NAME); + ASSERT_NE(nullptr, tokenInfo); + EXPECT_EQ(callingTokenID, tokenInfo->callingTokenID); + const CurrUsingPermInfo* remoteUsingInfo = + FindRemoteUsingInfo(infoList, remoteInfo.remoteDeviceId, TEST_PERMISSION_NAME); + ASSERT_NE(nullptr, remoteUsingInfo); + EXPECT_TRUE(remoteUsingInfo->isRemote); + }; + auto checkUsing = [](bool expected) { + bool isUsing = false; + EXPECT_EQ(RET_SUCCESS, PrivacyKit::CheckPermissionInUse(TEST_PERMISSION_NAME, isUsing)); + EXPECT_EQ(expected, isUsing); + }; + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(tokenID, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, startRemote()); + std::vector infoList; + { MockNativeToken mockQuery("audio_server"); EXPECT_EQ(RET_SUCCESS, PrivacyKit::GetCurrUsingPermInfo(infoList)); } + checkInfo(infoList); + checkUsing(true); + EXPECT_EQ(RET_SUCCESS, stopRemote()); + checkUsing(true); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(tokenID, TEST_PERMISSION_NAME)); + checkUsing(true); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + checkUsing(false); + EXPECT_EQ(RET_SUCCESS, PrivacyTestCommon::DeleteTestHapToken(tokenID)); +} +#endif + +/** + * @tc.name: BundleUsingtest014 + * @tc.desc: Verify register callback receives bundle start active status change. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest014, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest014", reqPerm, true); + AccessTokenID callingTokenID = static_cast(GetSelfTokenID()); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission("ohos.test.bundle.callback", TEST_PERMISSION_NAME)); + + usleep(1000000); // 1000000: 1s + EXPECT_EQ(1, callbackPtr->callTimes_); + EXPECT_EQ(PERM_ACTIVE_IN_FOREGROUND, callbackPtr->type_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ("ohos.test.bundle.callback", callbackPtr->bundleName_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission("ohos.test.bundle.callback", TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); +} + +/** + * @tc.name: BundleUsingtest015 + * @tc.desc: Verify register callback receives bundle stop active status change. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest015, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest015", reqPerm, true); + AccessTokenID callingTokenID = static_cast(GetSelfTokenID()); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleName = "ohos.test.bundle.callback.stop"; + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(2, callbackPtr->callTimes_); + EXPECT_EQ(PERM_INACTIVE, callbackPtr->type_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ(bundleName, callbackPtr->bundleName_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); +} + +/** + * @tc.name: BundleUsingtest016 + * @tc.desc: Verify TOKEN_ONLY callback does not receive bundle start and stop active status change. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest016, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest016", reqPerm, true); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleName = "ohos.test.bundle.callback.tokenonly"; + + ASSERT_EQ(RET_SUCCESS, + PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::TOKEN_ONLY)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(0, callbackPtr->callTimes_); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(0, callbackPtr->callTimes_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); +} + +/** + * @tc.name: BundleUsingtest017 + * @tc.desc: Verify callback does not receive bundle start and stop when permission does not match. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest017, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest017", reqPerm, true); + std::vector permList = {"ohos.permission.MICROPHONE"}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleName = "ohos.test.bundle.callback.mismatch"; + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(0, callbackPtr->callTimes_); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(0, callbackPtr->callTimes_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); +} + +/** + * @tc.name: BundleUsingtest018 + * @tc.desc: Verify callback does not receive bundle start and stop after unregister. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest018, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest018", reqPerm, true); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleName = "ohos.test.bundle.callback.unregister"; + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(0, callbackPtr->callTimes_); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(0, callbackPtr->callTimes_); +} + +/** + * @tc.name: BundleUsingtest019 + * @tc.desc: Verify callback bundleName matches the actual bundle for multiple bundles. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest019, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest019", reqPerm, true); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleNameA = "ohos.test.bundle.callback.multi.a"; + const std::string bundleNameB = "ohos.test.bundle.callback.multi.b"; + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleNameA, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(1, callbackPtr->callTimes_); + EXPECT_EQ(bundleNameA, callbackPtr->bundleName_); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleNameB, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(2, callbackPtr->callTimes_); + EXPECT_EQ(bundleNameB, callbackPtr->bundleName_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleNameA, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleNameB, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); +} + +/** + * @tc.name: BundleUsingtest020 + * @tc.desc: Verify ALL callback receives both bundle start and token start active status change. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(BundleUsingTest, BundleUsingtest020, TestSize.Level1) +{ + std::vector reqPerm = {PERMISSION_USED_STATS}; + MockHapToken mock("BundleUsingtest020", reqPerm, true); + std::vector permList = {TEST_PERMISSION_NAME}; + auto callbackPtr = std::make_shared(permList); + const std::string bundleName = "ohos.test.bundle.callback.all"; + AccessTokenID callingTokenID = static_cast(GetSelfTokenID()); + AccessTokenID tokenID = CreateGrantedHapToken("ohos.test.bundle.callback.token", TEST_PERMISSION_NAME); + ASSERT_NE(INVALID_TOKENID, tokenID); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr, CallbackRegisterType::ALL)); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(bundleName, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(1, callbackPtr->callTimes_); + EXPECT_EQ(PERM_ACTIVE_IN_FOREGROUND, callbackPtr->type_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(INVALID_TOKENID, callbackPtr->tokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ(bundleName, callbackPtr->bundleName_); + + ASSERT_EQ(RET_SUCCESS, PrivacyKit::StartUsingPermission(tokenID, TEST_PERMISSION_NAME)); + usleep(1000000); // 1000000: 1s + EXPECT_EQ(2, callbackPtr->callTimes_); + EXPECT_EQ(callingTokenID, callbackPtr->callingTokenID_); + EXPECT_EQ(tokenID, callbackPtr->tokenID_); + EXPECT_EQ(std::string(TEST_PERMISSION_NAME), callbackPtr->permissionName_); + EXPECT_EQ("", callbackPtr->bundleName_); + + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(tokenID, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::StopUsingPermission(bundleName, TEST_PERMISSION_NAME)); + EXPECT_EQ(RET_SUCCESS, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); + EXPECT_EQ(RET_SUCCESS, PrivacyTestCommon::DeleteTestHapToken(tokenID)); +} + +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.h b/interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.h new file mode 100644 index 000000000..91259c415 --- /dev/null +++ b/interfaces/innerkits/privacy/test/unittest/src/privacy_bundle_using_test.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2026 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 PRIVACY_BUNDLE_USING_TEST_H +#define PRIVACY_BUNDLE_USING_TEST_H + +#include + +namespace OHOS { +namespace Security { +namespace AccessToken { +class BundleUsingTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +#endif // PRIVACY_BUNDLE_USING_TEST_H diff --git a/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_coverage_test.cpp b/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_coverage_test.cpp index 2cde6447d..15df33f74 100644 --- a/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_coverage_test.cpp +++ b/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_coverage_test.cpp @@ -372,3 +372,88 @@ HWTEST_F(PrivacyKitTest, OnAddPrivacySa003, TestSize.Level0) EXPECT_EQ(PrivacyManagerClient::GetInstance().remoteCacheList_.size(), 0); } #endif + +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +/** + * @tc.name: SystemAbilityStatusChangeListener004 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, OnAddPrivacySa004, TestSize.Level0) +{ + const std::string bundleName = g_infoParmsE.bundleName; + const std::string permissionName = "ohos.permission.CAMERA"; + + EXPECT_EQ(0, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + EXPECT_EQ(0, PrivacyKit::StartUsingPermission(bundleName, permissionName)); + EXPECT_EQ(1, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + EXPECT_EQ(ERR_PERMISSION_ALREADY_START_USING, PrivacyKit::StartUsingPermission(bundleName, permissionName)); + EXPECT_EQ(1, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + + PrivacyManagerClient::GetInstance().OnAddPrivacySa(); + PrivacyManagerClient::GetInstance().OnRemoteDiedHandle(); + PrivacyManagerClient::GetInstance().OnAddPrivacySa(); + + EXPECT_EQ(0, PrivacyKit::StopUsingPermission(bundleName, permissionName)); + EXPECT_EQ(0, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); +} + +/** + * @tc.name: BundleClientCache001 + * @tc.desc: Verify bundle cache is created after successful bundle start. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, BundleClientCache001, TestSize.Level0) +{ + const std::string bundleName = g_infoParmsE.bundleName; + const std::string permissionName = "ohos.permission.CAMERA"; + + PrivacyManagerClient::GetInstance().bundleCacheList_.clear(); + EXPECT_EQ(0, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + EXPECT_EQ(0, PrivacyKit::StartUsingPermission(bundleName, permissionName)); + EXPECT_EQ(1, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + EXPECT_EQ(0, PrivacyKit::StopUsingPermission(bundleName, permissionName)); +} + +/** + * @tc.name: BundleClientCache002 + * @tc.desc: Verify bundle cache is removed after bundle stop. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, BundleClientCache002, TestSize.Level0) +{ + const std::string bundleName = g_infoParmsE.bundleName; + const std::string permissionName = "ohos.permission.CAMERA"; + + PrivacyManagerClient::GetInstance().bundleCacheList_.clear(); + EXPECT_EQ(0, PrivacyKit::StartUsingPermission(bundleName, permissionName)); + EXPECT_EQ(1, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + EXPECT_EQ(0, PrivacyKit::StopUsingPermission(bundleName, permissionName)); + EXPECT_EQ(0, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); +} + +/** + * @tc.name: BundleClientRetry003 + * @tc.desc: Verify OnAddPrivacySa replays bundle cache without duplicating entries. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, BundleClientRetry003, TestSize.Level0) +{ + const std::string bundleName = g_infoParmsE.bundleName; + const std::string permissionName = "ohos.permission.CAMERA"; + + PrivacyManagerClient::GetInstance().bundleCacheList_.clear(); + EXPECT_EQ(0, PrivacyKit::StartUsingPermission(bundleName, permissionName)); + EXPECT_EQ(1, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + + PrivacyManagerClient::GetInstance().OnAddPrivacySa(); + EXPECT_EQ(1, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); + + EXPECT_EQ(0, PrivacyKit::StopUsingPermission(bundleName, permissionName)); + EXPECT_EQ(0, PrivacyManagerClient::GetInstance().bundleCacheList_.size()); +} +#endif diff --git a/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_test.cpp b/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_test.cpp index 6b1f801a8..2b9963954 100644 --- a/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_test.cpp +++ b/interfaces/innerkits/privacy/test/unittest/src/privacy_kit_test.cpp @@ -727,9 +727,7 @@ HWTEST_F(PrivacyKitTest, AddRemotePermissionUsedRecordTest001, TestSize.Level0) uint32_t selfUid = getuid(); setuid(USER_100_UID); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; info.remoteDeviceId = ""; @@ -772,9 +770,7 @@ HWTEST_F(PrivacyKitTest, AddRemotePermissionUsedRecordTest002, TestSize.Level0) uint32_t selfUid = getuid(); setuid(USER_100_UID); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::AddRemotePermissionUsedRecord(info, permissionName, 1, 0)); @@ -817,9 +813,7 @@ HWTEST_F(PrivacyKitTest, AddRecordWithToggleFalseTest001, TestSize.Level1) uint32_t selfUid = getuid(); setuid(USER_100_UID); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::AddRemotePermissionUsedRecord(info, permissionName, 1, 0)); @@ -860,9 +854,7 @@ HWTEST_F(PrivacyKitTest, GetRemotePermissionUsedRecordTest001, TestSize.Level0) uint32_t selfUid = getuid(); setuid(USER_100_UID); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::AddRemotePermissionUsedRecord(info, permissionName, 1, 0)); @@ -908,9 +900,7 @@ HWTEST_F(PrivacyKitTest, GetRemotePermissionUsedRecordTest002, TestSize.Level0) uint32_t selfUid = getuid(); setuid(USER_100_UID); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::AddRemotePermissionUsedRecord(info, permissionName, 1, 0)); @@ -953,9 +943,7 @@ HWTEST_F(PrivacyKitTest, GetRemotePermissionUsedRecordTest003, TestSize.Level0) uint32_t selfUid = getuid(); setuid(USER_100_UID); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::AddRemotePermissionUsedRecord(info, permissionName, 1, 0)); @@ -1006,9 +994,7 @@ HWTEST_F(PrivacyKitTest, GetRemotePermissionUsedRecordTest004, TestSize.Level0) uint32_t selfUid = getuid(); setuid(USER_100_UID); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::AddRemotePermissionUsedRecord(info, permissionName, 1, 0)); @@ -1049,9 +1035,7 @@ HWTEST_F(PrivacyKitTest, GetRemotePermissionUsedRecordTest004, TestSize.Level0) */ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission001, TestSize.Level0) { - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; info.remoteDeviceId = ""; EXPECT_EQ(PrivacyError::ERR_PARAM_INVALID, PrivacyKit::StartRemoteUsingPermission(info, "ohos.permission.CAMERA")); @@ -1111,9 +1095,7 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission002, TestSize.Level1) auto callbackPtr = std::make_shared(permList); EXPECT_EQ(RET_NO_ERROR, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr)); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::StartRemoteUsingPermission(info, "ohos.permission.CAMERA")); usleep(1000000); // 1000000us = 1s EXPECT_EQ(callbackPtr->callTimes, 0); @@ -1133,17 +1115,14 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission002, TestSize.Level1) */ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission003, TestSize.Level1) { - AccessTokenID cameraToken = PrivacyTestCommon::GetNativeTokenIdFromProcess("camera_service"); - SetSelfTokenID(cameraToken); + MockNativeToken mock("camera_service"); EXPECT_EQ(RET_NO_ERROR, SetDisablePolicy("ohos.permission.MICROPHONE", false)); std::vector permList = {"ohos.permission.CAMERA"}; auto callbackPtr = std::make_shared(permList); EXPECT_EQ(RET_NO_ERROR, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr)); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::StartRemoteUsingPermission(info, "ohos.permission.CAMERA")); usleep(1000000); // 1000000us = 1s EXPECT_EQ(callbackPtr->type_, PERM_REMOTE_USING); @@ -1153,8 +1132,7 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission003, TestSize.Level1) EXPECT_EQ(callbackPtr->callTimes, 1); info.remoteDeviceId = "ididid2222"; - EXPECT_EQ(PrivacyError::ERR_REMOTE_USING_CONFLICT, - PrivacyKit::StartRemoteUsingPermission(info, "ohos.permission.CAMERA")); + EXPECT_EQ(ERR_REMOTE_USING_CONFLICT, PrivacyKit::StartRemoteUsingPermission(info, "ohos.permission.CAMERA")); info.remoteDeviceId = "ididid"; usleep(1000000); // 1000000us = 1s EXPECT_EQ(callbackPtr->callTimes, 1); @@ -1168,8 +1146,7 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission003, TestSize.Level1) EXPECT_EQ(callbackPtr->callTimes, 2); info.remoteDeviceId = "ididid2222"; - EXPECT_EQ(PrivacyError::ERR_PERMISSION_NOT_START_USING, - PrivacyKit::StopRemoteUsingPermission(info, "ohos.permission.CAMERA")); + EXPECT_EQ(ERR_PERMISSION_NOT_START_USING, PrivacyKit::StopRemoteUsingPermission(info, "ohos.permission.CAMERA")); usleep(1000000); // 1000000us = 1s EXPECT_EQ(callbackPtr->callTimes, 2); info.remoteDeviceId = "ididid"; @@ -1186,12 +1163,13 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission003, TestSize.Level1) usleep(1000000); // 1000000us = 1s EXPECT_EQ(callbackPtr->callTimes, 4); - EXPECT_EQ(PrivacyError::ERR_PERMISSION_NOT_START_USING, + EXPECT_EQ(ERR_PERMISSION_NOT_START_USING, PrivacyKit::StopRemoteUsingPermission(info, "ohos.permission.CAMERA")); - EXPECT_EQ(RET_NO_ERROR, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); + EXPECT_EQ(RET_NO_ERROR, PrivacyKit::StopRemoteUsingPermission(info, "ohos.permission.MICROPHONE")); + EXPECT_EQ(RET_NO_ERROR, PrivacyKit::StopRemoteUsingPermission(info, "ohos.permission.MICROPHONE")); - SetSelfTokenID(g_selfTokenId); + EXPECT_EQ(RET_NO_ERROR, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); } /** @@ -1202,17 +1180,14 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission003, TestSize.Level1) */ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission004, TestSize.Level1) { - AccessTokenID cameraToken = PrivacyTestCommon::GetNativeTokenIdFromProcess("camera_service"); - SetSelfTokenID(cameraToken); + MockNativeToken mock("camera_service"); EXPECT_EQ(RET_NO_ERROR, SetDisablePolicy("ohos.permission.MICROPHONE", false)); std::vector permList; auto callbackPtr = std::make_shared(permList); EXPECT_EQ(RET_NO_ERROR, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr)); - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; EXPECT_EQ(RET_NO_ERROR, PrivacyKit::StartRemoteUsingPermission(info, "ohos.permission.CAMERA")); usleep(1000000); // 1000000us = 1s EXPECT_EQ(callbackPtr->type_, PERM_REMOTE_USING); @@ -1234,8 +1209,6 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission004, TestSize.Level1) EXPECT_EQ(callbackPtr->callTimes, 4); EXPECT_EQ(RET_NO_ERROR, PrivacyKit::UnRegisterPermActiveStatusCallback(callbackPtr)); - - SetSelfTokenID(g_selfTokenId); } #else /** @@ -1246,9 +1219,7 @@ HWTEST_F(PrivacyKitTest, StartRemoteUsingPermission004, TestSize.Level1) */ HWTEST_F(PrivacyKitTest, RemotePrivacyLiteTest001, TestSize.Level0) { - RemoteCallerInfo info; - info.remoteDeviceId = "ididid"; - info.remoteDeviceName = "namename"; + RemoteCallerInfo info = {"ididid", "namename"}; std::string permissionName = "ohos.permission.CAMERA"; EXPECT_EQ(PrivacyError::ERR_CAPABILITY_NOT_SUPPORT, PrivacyKit::StartRemoteUsingPermission(info, permissionName)); EXPECT_EQ(PrivacyError::ERR_CAPABILITY_NOT_SUPPORT, PrivacyKit::StopRemoteUsingPermission(info, permissionName)); @@ -1809,6 +1780,13 @@ HWTEST_F(PrivacyKitTest, RegisterPermActiveStatusCallback003, TestSize.Level0) permList.emplace_back("ohos.permission.MICROPHONE"); auto callbackPtr = std::make_shared(permList); EXPECT_EQ(PrivacyError::ERR_PARAM_INVALID, PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr)); + + std::vector validPermList = {"ohos.permission.CAMERA"}; + auto callbackPtr2 = std::make_shared(validPermList); + EXPECT_EQ(PrivacyError::ERR_PARAM_INVALID, + PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr2, static_cast(-1))); + EXPECT_EQ(PrivacyError::ERR_PARAM_INVALID, + PrivacyKit::RegisterPermActiveStatusCallback(callbackPtr2, static_cast(2))); } /** @@ -1932,7 +1910,8 @@ HWTEST_F(PrivacyKitTest, RegisterPermActiveStatusCallback009, TestSize.Level0) { std::shared_ptr callback = nullptr; EXPECT_EQ(nullptr, callback); - PrivacyManagerClient::GetInstance().RegisterPermActiveStatusCallback(callback); // callback is null + PrivacyManagerClient::GetInstance().RegisterPermActiveStatusCallback( + callback, CallbackRegisterType::TOKEN_ONLY); // callback is null } /** @@ -2763,12 +2742,11 @@ public: */ HWTEST_F(PrivacyKitTest, OnRemoteRequest003, TestSize.Level0) { - ActiveChangeResponse response = { - .tokenID = 123, - .permissionName = "ohos.permission.CAMERA", - .deviceId = "I don't know", - .type = ActiveChangeType::PERM_INACTIVE - }; + ActiveChangeResponse response; + response.tokenID = 123; + response.permissionName = "ohos.permission.CAMERA"; + response.deviceId = "I don't know"; + response.type = ActiveChangeType::PERM_INACTIVE; ActiveChangeResponseParcel responseParcel; responseParcel.changeResponse = response; @@ -2798,12 +2776,11 @@ HWTEST_F(PrivacyKitTest, OnRemoteRequest003, TestSize.Level0) */ HWTEST_F(PrivacyKitTest, ActiveStatusChangeCallback001, TestSize.Level0) { - ActiveChangeResponse response = { - .tokenID = 123, - .permissionName = "ohos.permission.CAMERA", - .deviceId = "I don't know", - .type = ActiveChangeType::PERM_INACTIVE - }; + ActiveChangeResponse response; + response.tokenID = 123; + response.permissionName = "ohos.permission.CAMERA"; + response.deviceId = "I don't know"; + response.type = ActiveChangeType::PERM_INACTIVE; std::vector permList = {"ohos.permission.CAMERA"}; std::shared_ptr callbackPtr = std::make_shared(permList); OHOS::sptr callback = new ( @@ -3724,6 +3701,108 @@ HWTEST_F(PrivacyKitTest, SetPermissionUsedRecordToggleStatus004, TestSize.Level0 EXPECT_EQ(PrivacyError::ERR_NOT_SYSTEM_APP, PrivacyKit::GetPermissionUsedRecordToggleStatus(USER_ID_2, status)); } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +/** + * @tc.name: BundleUsingPermissionCacheKeyTest001 + * @tc.desc: Verify bundle start keeps different permissions for the same bundle observable from kit results. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, BundleUsingPermissionCacheKeyTest001, TestSize.Level0) +{ + std::vector reqPerm = {"ohos.permission.PERMISSION_USED_STATS"}; + MockHapToken mock("BundleUsingPermissionCacheKeyTest001", reqPerm, true); + const std::string bundleName = g_infoParmsE.bundleName; + const std::string cameraPermission = "ohos.permission.CAMERA"; + const std::string microphonePermission = "ohos.permission.MICROPHONE"; + + auto findBundleInfo = [](const std::vector& infoList, + const std::string& targetBundle, const std::string& targetPermission) { + for (const auto& info : infoList) { + if ((info.bundleName == targetBundle) && (info.permissionName == targetPermission)) { + return true; + } + } + return false; + }; + + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StartUsingPermission(bundleName, cameraPermission)); + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StartUsingPermission(bundleName, microphonePermission)); + + MockNativeToken queryToken("audio_server"); + std::vector infoList; + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::GetCurrUsingPermInfo(infoList)); + EXPECT_TRUE(findBundleInfo(infoList, bundleName, cameraPermission)); + EXPECT_TRUE(findBundleInfo(infoList, bundleName, microphonePermission)); + + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StopUsingPermission(bundleName, cameraPermission)); + infoList.clear(); + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::GetCurrUsingPermInfo(infoList)); + EXPECT_FALSE(findBundleInfo(infoList, bundleName, cameraPermission)); + EXPECT_TRUE(findBundleInfo(infoList, bundleName, microphonePermission)); + + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StopUsingPermission(bundleName, microphonePermission)); +} + +/** + * @tc.name: BundleUsingPermissionCacheKeyTest002 + * @tc.desc: Verify bundle start keeps different bundles for the same permission observable from kit results. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, BundleUsingPermissionCacheKeyTest002, TestSize.Level0) +{ + std::vector reqPerm = {"ohos.permission.PERMISSION_USED_STATS"}; + MockHapToken mock("BundleUsingPermissionCacheKeyTest002", reqPerm, true); + const std::string bundleNameA = g_infoParmsE.bundleName; + const std::string bundleNameB = g_infoParmsF.bundleName; + const std::string permissionName = "ohos.permission.CAMERA"; + + auto findBundleInfo = [](const std::vector& infoList, + const std::string& targetBundle, const std::string& targetPermission) { + for (const auto& info : infoList) { + if ((info.bundleName == targetBundle) && (info.permissionName == targetPermission)) { + return true; + } + } + return false; + }; + + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StartUsingPermission(bundleNameA, permissionName)); + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StartUsingPermission(bundleNameB, permissionName)); + + MockNativeToken queryToken("audio_server"); + std::vector infoList; + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::GetCurrUsingPermInfo(infoList)); + EXPECT_TRUE(findBundleInfo(infoList, bundleNameA, permissionName)); + EXPECT_TRUE(findBundleInfo(infoList, bundleNameB, permissionName)); + + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StopUsingPermission(bundleNameA, permissionName)); + infoList.clear(); + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::GetCurrUsingPermInfo(infoList)); + EXPECT_FALSE(findBundleInfo(infoList, bundleNameA, permissionName)); + EXPECT_TRUE(findBundleInfo(infoList, bundleNameB, permissionName)); + + ASSERT_EQ(RET_NO_ERROR, PrivacyKit::StopUsingPermission(bundleNameB, permissionName)); +} +#endif + +#ifndef PRIVACY_BUNDLE_START_STOP_ENABLE +/** + * @tc.name: BundleUsingCapabilityTest001 + * @tc.desc: Verify bundle start and stop return capability not support when feature is disabled. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyKitTest, BundleUsingCapabilityTest001, TestSize.Level0) +{ + EXPECT_EQ(PrivacyError::ERR_CAPABILITY_NOT_SUPPORT, + PrivacyKit::StartUsingPermission("ohos.privacy_test.bundle.unsupport", "ohos.permission.CAMERA")); + EXPECT_EQ(PrivacyError::ERR_CAPABILITY_NOT_SUPPORT, + PrivacyKit::StopUsingPermission("ohos.privacy_test.bundle.unsupport", "ohos.permission.CAMERA")); +} +#endif + int32_t PrivacyKitTest::SetDisablePolicy(const std::string& permissionName, bool isDisable) { MockNativeToken mock("edm"); diff --git a/services/privacymanager/idl/IPrivacyManager.idl b/services/privacymanager/idl/IPrivacyManager.idl index 4eec509f6..0c24a6f39 100644 --- a/services/privacymanager/idl/IPrivacyManager.idl +++ b/services/privacymanager/idl/IPrivacyManager.idl @@ -33,7 +33,8 @@ interface OHOS.Security.AccessToken.IPrivacyManager { [ipccode 6] void RemovePermissionUsedRecords([in] unsigned int tokenID); [ipccode 7] void GetPermissionUsedRecords([in] PermissionUsedRequestParcel request, [out] PermissionUsedResultParcel resultParcel); [ipccode 8] void GetPermissionUsedRecordsAsync([in] PermissionUsedRequestParcel request, [in] OnPermissionUsedRecordCallback cb); - [ipccode 9] void RegisterPermActiveStatusCallback([in] List permList, [in] IRemoteObject cb); + [ipccode 9] void RegisterPermActiveStatusCallback([in] List permList, [in] IRemoteObject cb, + [in] int type); [ipccode 10] void UnRegisterPermActiveStatusCallback([in] IRemoteObject cb); [ipccode 11] boolean IsAllowedUsingPermission([in] unsigned int tokenID, [in] String permissionName, [in] int pid); [ipccode 12] void GetPermissionUsedTypeInfos([in] unsigned int tokenId, [in] String permissionName, [out] List resultsParcel); @@ -52,4 +53,7 @@ interface OHOS.Security.AccessToken.IPrivacyManager { [ipccode 25, macrodef REMOTE_PRIVACY_ENABLE] void AddRemotePermissionUsedRecord([in] RemoteAddPermParamInfoParcel infoParcel); [ipccode 26, oneway, macrodef REMOTE_PRIVACY_ENABLE] void AddRemotePermissionUsedRecordAsync([in] RemoteAddPermParamInfoParcel infoParcel); [ipccode 27, macrodef REMOTE_PRIVACY_ENABLE] void GetRemotePermissionUsedRecords([in] PermissionUsedRequestParcel request, [out] PermissionUsedResultParcel resultParcel); + [ipccode 28, macrodef PRIVACY_BUNDLE_START_STOP_ENABLE] void StartUsingPermission([in] String bundleName, [in] String permissionName, + [in] IRemoteObject anonyStub); + [ipccode 29, macrodef PRIVACY_BUNDLE_START_STOP_ENABLE] void StopUsingPermission([in] String bundleName, [in] String permissionName); } diff --git a/services/privacymanager/include/active/active_status_callback_manager.h b/services/privacymanager/include/active/active_status_callback_manager.h index d52d73d0a..eb2bf375d 100644 --- a/services/privacymanager/include/active/active_status_callback_manager.h +++ b/services/privacymanager/include/active/active_status_callback_manager.h @@ -27,6 +27,7 @@ #include "active_change_response_info.h" #include "perm_active_status_callback_death_recipient.h" #include "perm_active_status_change_callback_proxy.h" +#include "privacy_param.h" namespace OHOS { namespace Security { @@ -34,13 +35,15 @@ namespace AccessToken { struct CallbackData { CallbackData() : permList_(), callbackObject_(nullptr) {} - CallbackData(const std::vector& permList, sptr callback) - : permList_(permList), callbackObject_(callback) + CallbackData(AccessTokenID tokenId, const std::vector& permList, sptr callback, + int32_t type) + : registerTokenId(tokenId), permList_(permList), callbackObject_(callback), registerType_(type) {} AccessTokenID registerTokenId {0}; std::vector permList_; sptr callbackObject_; + int32_t registerType_; }; class ActiveStatusCallbackManager { @@ -50,11 +53,13 @@ public: static ActiveStatusCallbackManager& GetInstance(); int32_t AddCallback( - AccessTokenID regiterTokenId, const std::vector& permList, const sptr& callback); + AccessTokenID regiterTokenId, const std::vector& permList, const sptr& callback, + int32_t registerType); int32_t RemoveCallback(const sptr& callback); bool NeedCalled(const std::vector& permList, const std::string& permName); - void ExecuteCallbackAsync(ActiveChangeResponse& info); - void ActiveStatusChange(ActiveChangeResponse& info); + bool NeedNotify(CallbackRegisterType registerType, CallbackRegisterType sourceType) const; + void ExecuteCallbackAsync(ActiveChangeResponse& info, CallbackRegisterType sourceType); + void ActiveStatusChange(ActiveChangeResponse& info, CallbackRegisterType sourceType); private: std::mutex mutex_; std::vector callbackDataList_; diff --git a/services/privacymanager/include/record/permission_record_manager.h b/services/privacymanager/include/record/permission_record_manager.h index 81c1d6e55..51ed345c3 100644 --- a/services/privacymanager/include/record/permission_record_manager.h +++ b/services/privacymanager/include/record/permission_record_manager.h @@ -90,7 +90,6 @@ public: int32_t callerPid); int32_t StopUsingPermission(AccessTokenID tokenId, int32_t pid, const std::string& permissionName, int32_t callerPid); - bool HasCallerInStartList(int32_t callerPid); #ifdef REMOTE_PRIVACY_ENABLE int32_t StartRemoteUsingPermission(const RemotePermissionUsedInfo &info, int32_t callerPid); int32_t StopRemoteUsingPermission(const std::string& remoteDeviceId, const std::string& remoteDeviceName, @@ -100,8 +99,13 @@ public: int32_t AddRemotePermissionUsedRecord(const RemoteAddPermParamInfo& info); int32_t GetRemotePermissionUsedRecords(const PermissionUsedRequest& request, PermissionUsedResult& result); #endif - int32_t RegisterPermActiveStatusCallback( - AccessTokenID regiterTokenId, const std::vector& permList, const sptr& callback); +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + int32_t StartUsingPermission(const std::string& bundleName, const std::string& permissionName, int32_t callerPid); + int32_t StopUsingPermission(const std::string& bundleName, const std::string& permissionName, int32_t callerPid); +#endif + bool HasCallerInStartList(int32_t callerPid); + int32_t RegisterPermActiveStatusCallback(AccessTokenID regiterTokenId, const std::vector& permList, + const sptr& callback, int32_t type); int32_t UnRegisterPermActiveStatusCallback(const sptr& callback); void CallbackExecute(const ContinuousPermissionRecord& record, const std::string& permissionName, @@ -312,6 +316,10 @@ private: std::mutex remotePermUsedRecMutex_; std::vector remotePermUsedRecList_; #endif +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + std::mutex bundleStartRecordListMutex_; + std::unordered_map>> bundleStartRecordMap_; +#endif }; } // namespace AccessToken } // namespace Security diff --git a/services/privacymanager/include/service/privacy_manager_service.h b/services/privacymanager/include/service/privacy_manager_service.h index 49c414b0a..38fd5ebc9 100644 --- a/services/privacymanager/include/service/privacy_manager_service.h +++ b/services/privacymanager/include/service/privacy_manager_service.h @@ -41,6 +41,12 @@ public: int32_t AddPermissionUsedRecordAsync(const AddPermParamInfoParcel& infoParcel) override; int32_t StartUsingPermission(const PermissionUsedTypeInfoParcel &infoParcel, const sptr& anonyStub) override; +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + int32_t StartUsingPermission( + const std::string& bundleName, const std::string& permissionName, + const sptr& anonyStub) override; + int32_t StopUsingPermission(const std::string& bundleName, const std::string& permissionName) override; +#endif int32_t StartUsingPermissionCallback(const PermissionUsedTypeInfoParcel &infoParcel, const sptr& callback, const sptr& anonyStub) override; int32_t SetPermissionUsedRecordToggleStatus(int32_t userID, bool status) override; @@ -62,7 +68,7 @@ public: int32_t GetPermissionUsedRecordsAsync( const PermissionUsedRequestParcel& request, const sptr& callback) override; int32_t RegisterPermActiveStatusCallback( - const std::vector& permList, const sptr& callback) override; + const std::vector& permList, const sptr& callback, int32_t type) override; int32_t UnRegisterPermActiveStatusCallback(const sptr& callback) override; int32_t IsAllowedUsingPermission( AccessTokenID tokenId, const std::string& permissionName, int32_t pid, bool& isAllowed) override; diff --git a/services/privacymanager/src/active/active_status_callback_manager.cpp b/services/privacymanager/src/active/active_status_callback_manager.cpp index 0026ba302..4b1e5b053 100644 --- a/services/privacymanager/src/active/active_status_callback_manager.cpp +++ b/services/privacymanager/src/active/active_status_callback_manager.cpp @@ -79,7 +79,8 @@ std::shared_ptr ActiveStatusCallbackManager::GetEventHandler #endif int32_t ActiveStatusCallbackManager::AddCallback( - AccessTokenID registerTokenId, const std::vector& permList, const sptr& callback) + AccessTokenID registerTokenId, const std::vector& permList, const sptr& callback, + int32_t registerType) { if (callback == nullptr) { LOGE(PRI_DOMAIN, PRI_TAG, "Input is nullptr"); @@ -97,12 +98,7 @@ int32_t ActiveStatusCallbackManager::AddCallback( return PrivacyError::ERR_ADD_DEATH_RECIPIENT_FAILED; } - CallbackData recordInstance; - recordInstance.registerTokenId = registerTokenId; - recordInstance.callbackObject_ = callback; - recordInstance.permList_ = permList; - - callbackDataList_.emplace_back(recordInstance); + callbackDataList_.emplace_back(registerTokenId, permList, callback, registerType); LOGI(PRI_DOMAIN, PRI_TAG, "RecordInstance is added"); return RET_SUCCESS; @@ -141,13 +137,23 @@ bool ActiveStatusCallbackManager::NeedCalled(const std::vector& per [permName](const std::string& perm) { return perm == permName; }); } +bool ActiveStatusCallbackManager::NeedNotify(CallbackRegisterType registerType, CallbackRegisterType sourceType) const +{ + if (registerType == CallbackRegisterType::ALL) { + return true; + } + return registerType == sourceType; +} -void ActiveStatusCallbackManager::ActiveStatusChange(ActiveChangeResponse& info) +void ActiveStatusCallbackManager::ActiveStatusChange(ActiveChangeResponse& info, CallbackRegisterType sourceType) { std::vector> list; { std::lock_guard lock(mutex_); for (auto it = callbackDataList_.begin(); it != callbackDataList_.end(); ++it) { + if (!NeedNotify(static_cast(it->registerType_), sourceType)) { + continue; + } std::vector permList = (*it).permList_; if (!NeedCalled(permList, info.permissionName)) { LOGI(PRI_DOMAIN, PRI_TAG, "TokenId %{public}u, perm %{public}s", info.tokenID, @@ -173,7 +179,7 @@ void ActiveStatusCallbackManager::ActiveStatusChange(ActiveChangeResponse& info) } } -void ActiveStatusCallbackManager::ExecuteCallbackAsync(ActiveChangeResponse& info) +void ActiveStatusCallbackManager::ExecuteCallbackAsync(ActiveChangeResponse& info, CallbackRegisterType sourceType) { #ifdef EVENTHANDLER_ENABLE auto eventHandler = GetEventHandler(); @@ -184,8 +190,8 @@ void ActiveStatusCallbackManager::ExecuteCallbackAsync(ActiveChangeResponse& inf std::string taskName = info.permissionName + std::to_string(info.tokenID); LOGI(PRI_DOMAIN, PRI_TAG, "Add permission task name:%{public}s", taskName.c_str()); - std::function task = ([info]() mutable { - ActiveStatusCallbackManager::GetInstance().ActiveStatusChange(info); + std::function task = ([info, sourceType]() mutable { + ActiveStatusCallbackManager::GetInstance().ActiveStatusChange(info, sourceType); LOGI(PRI_DOMAIN, PRI_TAG, "deviceId: %{public}s, " "token: %{public}u, pid: %{public}d, permName: %{public}s, changeType: %{public}d, ActiveStatusChange end", ConstantCommon::EncryptDevId(info.deviceId).c_str(), diff --git a/services/privacymanager/src/record/permission_record_manager.cpp b/services/privacymanager/src/record/permission_record_manager.cpp index 6344e3849..fb9460612 100644 --- a/services/privacymanager/src/record/permission_record_manager.cpp +++ b/services/privacymanager/src/record/permission_record_manager.cpp @@ -63,7 +63,6 @@ namespace Security { namespace AccessToken { namespace { static const int32_t VALUE_MAX_LEN = 32; -static constexpr int32_t MAX_PERMISSION_NAME_LENGTH = 256; constexpr const char* CAMERA_PERMISSION_NAME = "ohos.permission.CAMERA"; constexpr const char* CAMERA_BACKGROUND_PERMISSION_NAME = "ohos.permission.CAMERA_BACKGROUND"; constexpr const char* MICROPHONE_PERMISSION_NAME = "ohos.permission.MICROPHONE"; @@ -92,12 +91,13 @@ static const uint32_t MAX_PERMISSION_USED_TYPE_SIZE = 20; #endif constexpr const char* EDM_PROCESS_NAME = "edm"; std::recursive_mutex g_instanceMutex; +} -bool IsPermAddCallbackSupported(const std::string& permissionName) +static bool IsPermAddCallbackSupported(const std::string& permissionName) { return g_supportAddCallbackPermList.find(permissionName) != g_supportAddCallbackPermList.end(); } -} + PermissionRecordManager& PermissionRecordManager::GetInstance() { static PermissionRecordManager* instance = nullptr; @@ -927,7 +927,7 @@ void PermissionRecordManager::CallbackRemoteExecute(const RemoteContinuousPermis info.remoteDeviceName = remoteDeviceName; info.type = type; - ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(info); + ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(info, CallbackRegisterType::TOKEN_ONLY); } int32_t PermissionRecordManager::AddRecordToStartRemoteList( @@ -1039,7 +1039,7 @@ bool PermissionRecordManager::ToRemoveRemoteRecord( for (auto it = startRemoteRecordList_.begin(); it != startRemoteRecordList_.end();) { if (((*it).*isEqualFunc)(targetRecord)) { std::string perm; - Constant::TransferOpcodeToPermission(it->opCode, perm); + (void)Constant::TransferOpcodeToPermission(it->opCode, perm); RemoteContinuousPermissionRecord newRecord = { .opCode = it->opCode, .callerPid = it->callerPid, @@ -1065,6 +1065,7 @@ bool PermissionRecordManager::ToRemoveRemoteRecord( } return res; } + #endif int32_t PermissionRecordManager::SetPermissionUsedRecordToggleStatus(int32_t userID, bool status) @@ -1595,40 +1596,41 @@ void PermissionRecordManager::GetCurrUsingPermInfo(std::vector lock(startRecordListMutex_); - for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) { + for (const auto& record : startRecordList_) { std::string perm; - Constant::TransferOpcodeToPermission(it->opCode, perm); - ActiveChangeResponse info; - info.callingTokenID = it->callertokenId; - info.tokenID = it->tokenId; - info.permissionName = perm; - info.deviceId = ""; - info.type = static_cast(it->status); - info.usedType = it->usedType; - info.pid = it->pid; - infoList.emplace_back(info); + (void)Constant::TransferOpcodeToPermission(record.opCode, perm); + infoList.emplace_back(record.callertokenId, record.tokenId, perm, + static_cast(record.status), record.usedType, record.pid); LOGI(PRI_DOMAIN, PRI_TAG, "TokenId %{public}d using permission %{public}s, " - "status %{public}d, type %{public}d, pid %{public}d, callerPid %{public}d.", it->tokenId, - perm.c_str(), it->status, it->usedType, it->pid, it->callerPid); + "status %{public}d, type %{public}d, pid %{public}d, callerPid %{public}d.", record.tokenId, + perm.c_str(), record.status, record.usedType, record.pid, record.callerPid); } } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + { + std::lock_guard lock(bundleStartRecordListMutex_); + for (const auto& item : bundleStartRecordMap_) { + for (const auto& record : item.second) { + std::string perm; + (void)Constant::TransferOpcodeToPermission(record.first, perm); + infoList.emplace_back(item.first, perm); + LOGI(PRI_DOMAIN, PRI_TAG, "Bundle %{public}s using permission %{public}s, callerPid %{public}d.", + item.first.c_str(), perm.c_str(), record.second); + } + } + } +#endif #ifdef REMOTE_PRIVACY_ENABLE { std::lock_guard lock(startRemoteRecordListMutex_); - for (auto it = startRemoteRecordList_.begin(); it != startRemoteRecordList_.end(); ++it) { + for (const auto& record : startRemoteRecordList_) { std::string perm; - Constant::TransferOpcodeToPermission(it->opCode, perm); - ActiveChangeResponse info; - info.permissionName = perm; - info.type = ActiveChangeType::PERM_REMOTE_USING; - info.isRemote = true; - info.deviceId = uniqueDeviceId_; - info.remoteDeviceName = uniqueDeviceName_; - - infoList.emplace_back(info); + (void)Constant::TransferOpcodeToPermission(record.opCode, perm); + infoList.emplace_back(perm, uniqueDeviceId_, uniqueDeviceName_); LOGI(PRI_DOMAIN, PRI_TAG, "deviceId: %{public}s, " "using permission %{public}s, type %{public}d, callerPid %{public}d.", - ConstantCommon::EncryptDevId(info.deviceId).c_str(), perm.c_str(), info.type, it->callerPid); + ConstantCommon::EncryptDevId(uniqueDeviceId_).c_str(), perm.c_str(), + ActiveChangeType::PERM_REMOTE_USING, record.callerPid); } } #endif @@ -1636,31 +1638,51 @@ void PermissionRecordManager::GetCurrUsingPermInfo(std::vector lock(startRecordListMutex_); - - // Validate permission name parameter - if (permissionName.empty() || permissionName.length() > MAX_PERMISSION_NAME_LENGTH) { - LOGE(PRI_DOMAIN, PRI_TAG, "Permission name is empty or exceeds max length: %{public}zu.", - permissionName.length()); - return PrivacyError::ERR_PARAM_INVALID; - } - - // Check if permission exists int32_t opCode; if (!Constant::TransferPermissionToOpcode(permissionName, opCode)) { LOGE(PRI_DOMAIN, PRI_TAG, "Permission(%{public}s) is not exist", permissionName.c_str()); return PrivacyError::ERR_PERMISSION_NOT_EXIST; } - // Iterate and check if opcode is in use - for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) { - if (it->opCode == opCode && it->status != PERM_INACTIVE) { - isUsing = true; - LOGI(PRI_DOMAIN, PRI_TAG, "Permission %{public}s (opcode %{public}d) isUsing: %{public}d", - permissionName.c_str(), opCode, isUsing); - return RET_SUCCESS; + { + std::lock_guard lock(startRecordListMutex_); + for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) { + if (it->opCode == opCode && it->status != PERM_INACTIVE) { + isUsing = true; + LOGI(PRI_DOMAIN, PRI_TAG, "Permission %{public}s (opcode %{public}d) isUsing: %{public}d", + permissionName.c_str(), opCode, isUsing); + return RET_SUCCESS; + } } } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + { + std::lock_guard lock(bundleStartRecordListMutex_); + for (const auto& item : bundleStartRecordMap_) { + for (const auto& record : item.second) { + if (record.first == opCode) { + isUsing = true; + LOGI(PRI_DOMAIN, PRI_TAG, "Bundle permission %{public}s (opcode %{public}d) isUsing: %{public}d", + permissionName.c_str(), opCode, isUsing); + return RET_SUCCESS; + } + } + } + } +#endif +#ifdef REMOTE_PRIVACY_ENABLE + { + std::lock_guard lock(startRemoteRecordListMutex_); + for (const auto& record : startRemoteRecordList_) { + if (record.opCode == opCode) { + isUsing = true; + LOGI(PRI_DOMAIN, PRI_TAG, "Remote permission %{public}s (opcode %{public}d) isUsing: %{public}d", + permissionName.c_str(), opCode, isUsing); + return RET_SUCCESS; + } + } + } +#endif isUsing = false; LOGI(PRI_DOMAIN, PRI_TAG, "Permission %{public}s (opcode %{public}d) isUsing: %{public}d", @@ -1676,7 +1698,7 @@ void PermissionRecordManager::ExecuteAndUpdateRecord(uint32_t tokenId, int32_t p for (auto it = startRecordList_.begin(); it != startRecordList_.end();) { if ((it->tokenId == tokenId) && ((it->status) != PERM_INACTIVE) && ((it->status) != status)) { std::string perm; - Constant::TransferOpcodeToPermission(it->opCode, perm); + (void)Constant::TransferOpcodeToPermission(it->opCode, perm); if ((GetMuteStatus(perm, EDM)) || (!GetGlobalSwitchStatus(perm))) { ++it; continue; @@ -1809,6 +1831,24 @@ void PermissionRecordManager::RemoveRecordFromStartListByCallerPid(int32_t calle ContinuousPermissionRecord record = {0}; record.callerPid = callerPid; (void) ToRemoveRecord(record, &ContinuousPermissionRecord::IsEqualCallerPid); + +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + { + std::lock_guard lock(bundleStartRecordListMutex_); + for (auto mapIt = bundleStartRecordMap_.begin(); mapIt != bundleStartRecordMap_.end();) { + auto& records = mapIt->second; + records.erase(std::remove_if(records.begin(), records.end(), + [callerPid](const std::pair& recordInfo) { + return recordInfo.second == callerPid; + }), records.end()); + if (records.empty()) { + mapIt = bundleStartRecordMap_.erase(mapIt); + continue; + } + ++mapIt; + } + } +#endif #ifdef REMOTE_PRIVACY_ENABLE RemoteContinuousPermissionRecord targetRecord; targetRecord.callerPid = callerPid; @@ -1831,7 +1871,7 @@ bool PermissionRecordManager::ToRemoveRecord(const ContinuousPermissionRecord& t } PermissionRecordSet::GetInActiveUniqueRecord(startRecordList_, removeList, inactiveList); for (const auto& record: inactiveList) { - Constant::TransferOpcodeToPermission(record.opCode, perm); + (void)Constant::TransferOpcodeToPermission(record.opCode, perm); ContinuousPermissionRecord newRecord; newRecord.tokenId = record.tokenId; newRecord.status = PERM_INACTIVE; @@ -1869,7 +1909,8 @@ void PermissionRecordManager::CallbackExecute( info.usedType = type; info.pid = record.pid; - ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(info); + ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync( + info, CallbackRegisterType::TOKEN_ONLY); } void PermissionRecordManager::ExecutePermAddCallbackAsync( @@ -1890,7 +1931,7 @@ void PermissionRecordManager::ExecutePermAddCallbackAsync( callbackInfo.deviceId = ""; callbackInfo.remoteDeviceName = ""; callbackInfo.extra = info.extra; - ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(callbackInfo); + ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(callbackInfo, CallbackRegisterType::TOKEN_ONLY); } bool PermissionRecordManager::GetGlobalSwitchStatus(const std::string& permissionName) @@ -2156,21 +2197,131 @@ int32_t PermissionRecordManager::StopUsingPermission( return RemoveRecordFromStartList(tokenId, pid, permissionName, callerPid); } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +int32_t PermissionRecordManager::StartUsingPermission( + const std::string& bundleName, const std::string& permissionName, int32_t callerPid) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName)) { + return PrivacyError::ERR_PARAM_INVALID; + } + + int32_t opCode = 0; + if (!Constant::TransferPermissionToOpcode(permissionName, opCode)) { + LOGE(PRI_DOMAIN, PRI_TAG, "Invalid permission(%{public}s)", permissionName.c_str()); + return PrivacyError::ERR_PERMISSION_NOT_EXIST; + } + + InitializeMuteState(permissionName); + if (IsEdmMuteOrDisable(permissionName)) { + LOGE(PRI_DOMAIN, PRI_TAG, "EDM not allow."); + return PrivacyError::ERR_EDM_POLICY_CHECK_FAILED; + } + if (!Register()) { + return PrivacyError::ERR_MALLOC_FAILED; + } + + std::lock_guard lock(bundleStartRecordListMutex_); + auto mapIt = bundleStartRecordMap_.find(bundleName); + if (mapIt == bundleStartRecordMap_.end()) { + mapIt = bundleStartRecordMap_.emplace(bundleName, std::vector> {}).first; + } + auto& records = mapIt->second; + const auto isSameRecord = [opCode, callerPid](const std::pair& record) { + return (record.first == opCode) && (record.second == callerPid); + }; + if (std::find_if(records.begin(), records.end(), isSameRecord) != records.end()) { + LOGE(PRI_DOMAIN, PRI_TAG, "Bundle in use: %{public}s, op=%{public}d, caller=%{public}d", + bundleName.c_str(), opCode, callerPid); + return PrivacyError::ERR_PERMISSION_ALREADY_START_USING; + } + records.emplace_back(opCode, callerPid); + + ActiveChangeResponse info; + info.callingTokenID = IPCSkeleton::GetCallingTokenID(); + info.permissionName = permissionName; + info.type = ActiveChangeType::PERM_ACTIVE_IN_FOREGROUND; + info.usedType = NORMAL_TYPE; + info.bundleName = bundleName; + ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(info, CallbackRegisterType::ALL); + return Constant::SUCCESS; +} + +int32_t PermissionRecordManager::StopUsingPermission( + const std::string& bundleName, const std::string& permissionName, int32_t callerPid) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName)) { + return PrivacyError::ERR_PARAM_INVALID; + } + + int32_t opCode = 0; + if (!Constant::TransferPermissionToOpcode(permissionName, opCode)) { + LOGE(PRI_DOMAIN, PRI_TAG, "Invalid permission(%{public}s)", permissionName.c_str()); + return PrivacyError::ERR_PERMISSION_NOT_EXIST; + } + + std::lock_guard lock(bundleStartRecordListMutex_); + auto mapIt = bundleStartRecordMap_.find(bundleName); + if (mapIt == bundleStartRecordMap_.end()) { + LOGE(PRI_DOMAIN, PRI_TAG, "Bundle not started: %{public}s, op=%{public}d, caller=%{public}d", + bundleName.c_str(), opCode, callerPid); + return PrivacyError::ERR_PERMISSION_NOT_START_USING; + } + + auto& records = mapIt->second; + auto recordIt = std::find_if(records.begin(), records.end(), + [opCode, callerPid](const std::pair& record) { + return (record.first == opCode) && (record.second == callerPid); + }); + if (recordIt == records.end()) { + LOGE(PRI_DOMAIN, PRI_TAG, "Bundle not started: %{public}s, op=%{public}d, caller=%{public}d", + bundleName.c_str(), opCode, callerPid); + return PrivacyError::ERR_PERMISSION_NOT_START_USING; + } + + records.erase(recordIt); + if (records.empty()) { + bundleStartRecordMap_.erase(mapIt); + } + + ActiveChangeResponse info; + info.callingTokenID = IPCSkeleton::GetCallingTokenID(); + info.permissionName = permissionName; + info.type = ActiveChangeType::PERM_INACTIVE; + info.usedType = NORMAL_TYPE; + info.bundleName = bundleName; + ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(info, CallbackRegisterType::ALL); + return Constant::SUCCESS; +} + +#endif + bool PermissionRecordManager::HasCallerInStartList(int32_t callerPid) { { std::lock_guard lock(startRecordListMutex_); - for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) { - if (it->callerPid == callerPid) { + for (const auto& record : startRecordList_) { + if (record.callerPid == callerPid) { return true; } } } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + { + std::lock_guard lock(bundleStartRecordListMutex_); + for (const auto& item : bundleStartRecordMap_) { + for (const auto& record : item.second) { + if (record.second == callerPid) { + return true; + } + } + } + } +#endif #ifdef REMOTE_PRIVACY_ENABLE { std::lock_guard lock(startRemoteRecordListMutex_); - for (auto it = startRemoteRecordList_.begin(); it != startRemoteRecordList_.end(); ++it) { - if (it->callerPid == callerPid) { + for (const auto& record : startRemoteRecordList_) { + if (record.callerPid == callerPid) { return true; } } @@ -2404,14 +2555,15 @@ bool PermissionRecordManager::GetMuteStatus(const std::string& permissionName, i } int32_t PermissionRecordManager::RegisterPermActiveStatusCallback( - AccessTokenID regiterTokenId, const std::vector& permList, const sptr& callback) + AccessTokenID regiterTokenId, const std::vector& permList, const sptr& callback, + int32_t type) { std::vector permListRes; int32_t res = PermissionListFilter(permList, permListRes); if (res != Constant::SUCCESS) { return res; } - return ActiveStatusCallbackManager::GetInstance().AddCallback(regiterTokenId, permListRes, callback); + return ActiveStatusCallbackManager::GetInstance().AddCallback(regiterTokenId, permListRes, callback, type); } int32_t PermissionRecordManager::UnRegisterPermActiveStatusCallback(const sptr& callback) @@ -2424,7 +2576,8 @@ void PermissionRecordManager::AddDataValueToResults(const GenericValues value, { PermissionUsedTypeInfo info; info.tokenId = static_cast(value.GetInt(PrivacyFiledConst::FIELD_TOKEN_ID)); - Constant::TransferOpcodeToPermission(value.GetInt(PrivacyFiledConst::FIELD_PERMISSION_CODE), info.permissionName); + (void)Constant::TransferOpcodeToPermission(value.GetInt(PrivacyFiledConst::FIELD_PERMISSION_CODE), + info.permissionName); uint32_t type = static_cast(value.GetInt(PrivacyFiledConst::FIELD_USED_TYPE)); if ((type & NORMAL_TYPE_ADD_VALUE) == NORMAL_TYPE_ADD_VALUE) { // normal first info.type = PermissionUsedType::NORMAL_TYPE; diff --git a/services/privacymanager/src/service/privacy_manager_service.cpp b/services/privacymanager/src/service/privacy_manager_service.cpp index 3ef262dd7..372696034 100644 --- a/services/privacymanager/src/service/privacy_manager_service.cpp +++ b/services/privacymanager/src/service/privacy_manager_service.cpp @@ -55,8 +55,15 @@ constexpr const char* SET_MUTE_POLICY = "ohos.permission.SET_MUTE_POLICY"; constexpr const char* MANAGE_EDM_POLICY = "ohos.permission.MANAGE_EDM_POLICY"; constexpr const char* GET_PERMISSION_POLICY = "ohos.permission.GET_PERMISSION_POLICY"; static const int32_t SA_ID_PRIVACY_MANAGER_SERVICE = 3505; +static constexpr int32_t MAX_PERMISSION_NAME_LENGTH = 256; static const uint32_t PERM_LIST_SIZE_MAX = 1024; static const int32_t RETRY_COUNT = 128; +bool IsValidCallbackRegisterType(int32_t type) +{ + return (type == static_cast(CallbackRegisterType::ALL)) || + (type == static_cast(CallbackRegisterType::TOKEN_ONLY)); +} + static const int32_t RETRY_TIMES_MS = 500; // 0.5s static const int32_t ASYNC_RETRY_COUNT = 43200; // 30d * 24h * 60m static const int32_t ASYNC_RETRY_TIMES_MS = 60 * 1000; // 1min @@ -188,6 +195,10 @@ void PrivacyManagerService::ProcessProxyDeathStub(const sptr& ano void PrivacyManagerService::ReleaseDeathStub(int32_t callerPid) { + if (PermissionRecordManager::GetInstance().HasCallerInStartList(callerPid)) { + return; + } + LOGI(PRI_DOMAIN, PRI_TAG, "No permission record from caller = %{public}d", callerPid); std::shared_ptr param = std::make_shared(callerPid); if (param == nullptr) { LOGE(PRI_DOMAIN, PRI_TAG, "Create param failed."); @@ -256,10 +267,7 @@ int32_t PrivacyManagerService::StopUsingPermission( if (ret != Constant::SUCCESS) { return ret; } - if (!PermissionRecordManager::GetInstance().HasCallerInStartList(callerPid)) { - LOGI(PRI_DOMAIN, PRI_TAG, "No permission record from caller = %{public}d", callerPid); - ReleaseDeathStub(callerPid); - } + ReleaseDeathStub(callerPid); return ret; } @@ -300,10 +308,7 @@ int32_t PrivacyManagerService::StopRemoteUsingPermission(const std::string& remo if (ret != Constant::SUCCESS) { return ret; } - if (!PermissionRecordManager::GetInstance().HasCallerInStartList(callerPid)) { - LOGI(PRI_DOMAIN, PRI_TAG, "No permission record from caller = %{public}d", callerPid); - ReleaseDeathStub(callerPid); - } + ReleaseDeathStub(callerPid); return ret; } @@ -360,6 +365,50 @@ int32_t PrivacyManagerService::GetRemotePermissionUsedRecords( } #endif +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +int32_t PrivacyManagerService::StartUsingPermission( + const std::string& bundleName, const std::string& permissionName, const sptr& anonyStub) +{ + uint32_t callingTokenID = IPCSkeleton::GetCallingTokenID(); + if ((AccessTokenKit::GetTokenTypeFlag(callingTokenID) == TOKEN_HAP) && (!IsSystemAppCalling())) { + return PrivacyError::ERR_NOT_SYSTEM_APP; + } + if (!VerifyPermission(PERMISSION_USED_STATS)) { + return PrivacyError::ERR_PERMISSION_DENIED; + } + + int32_t callerPid = IPCSkeleton::GetCallingPid(); + LOGI(PRI_DOMAIN, PRI_TAG, "Bundle start: %{public}s, %{public}s, %{public}d.", + bundleName.c_str(), permissionName.c_str(), callerPid); + ProcessProxyDeathStub(anonyStub, callerPid); + return PermissionRecordManager::GetInstance().StartUsingPermission(bundleName, permissionName, callerPid); +} +#endif + +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +int32_t PrivacyManagerService::StopUsingPermission( + const std::string& bundleName, const std::string& permissionName) +{ + uint32_t callingTokenID = IPCSkeleton::GetCallingTokenID(); + if ((AccessTokenKit::GetTokenTypeFlag(callingTokenID) == TOKEN_HAP) && (!IsSystemAppCalling())) { + return PrivacyError::ERR_NOT_SYSTEM_APP; + } + if (!VerifyPermission(PERMISSION_USED_STATS)) { + return PrivacyError::ERR_PERMISSION_DENIED; + } + + int32_t callerPid = IPCSkeleton::GetCallingPid(); + LOGI(PRI_DOMAIN, PRI_TAG, "Bundle stop: %{public}s, %{public}s, %{public}d.", + bundleName.c_str(), permissionName.c_str(), callerPid); + int32_t ret = PermissionRecordManager::GetInstance().StopUsingPermission(bundleName, permissionName, callerPid); + if (ret != Constant::SUCCESS) { + return ret; + } + ReleaseDeathStub(callerPid); + return ret; +} +#endif + int32_t PrivacyManagerService::RemovePermissionUsedRecords(AccessTokenID tokenId) { uint32_t callingTokenID = IPCSkeleton::GetCallingTokenID(); @@ -417,7 +466,7 @@ int32_t PrivacyManagerService::GetPermissionUsedRecordsAsync( } int32_t PrivacyManagerService::RegisterPermActiveStatusCallback( - const std::vector& permList, const sptr& callback) + const std::vector& permList, const sptr& callback, int32_t type) { uint32_t callingTokenID = IPCSkeleton::GetCallingTokenID(); if ((AccessTokenKit::GetTokenTypeFlag(callingTokenID) == TOKEN_HAP) && (!IsSystemAppCalling())) { @@ -431,9 +480,12 @@ int32_t PrivacyManagerService::RegisterPermActiveStatusCallback( LOGE(PRI_DOMAIN, PRI_TAG, "PermList oversize"); return PrivacyError::ERR_OVERSIZE; } + if (!IsValidCallbackRegisterType(type)) { + return PrivacyError::ERR_PARAM_INVALID; + } return PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - IPCSkeleton::GetCallingTokenID(), permList, callback); + IPCSkeleton::GetCallingTokenID(), permList, callback, type); } int32_t PrivacyManagerService::ResponseDumpCommand(int32_t fd, const std::vector& args) @@ -654,6 +706,9 @@ int32_t PrivacyManagerService::CheckPermissionInUse(const std::string& permissio if (!VerifyPermission(PERMISSION_USED_STATS)) { return PrivacyError::ERR_PERMISSION_DENIED; } + if (permissionName.empty() || permissionName.length() > MAX_PERMISSION_NAME_LENGTH) { + return PrivacyError::ERR_PARAM_INVALID; + } return PermissionRecordManager::GetInstance().CheckPermissionInUse(permissionName, isUsing); } diff --git a/services/privacymanager/test/coverage/record/permission_record_manager_coverage_test.cpp b/services/privacymanager/test/coverage/record/permission_record_manager_coverage_test.cpp index 400a6ba64..12ff86c3d 100644 --- a/services/privacymanager/test/coverage/record/permission_record_manager_coverage_test.cpp +++ b/services/privacymanager/test/coverage/record/permission_record_manager_coverage_test.cpp @@ -420,7 +420,8 @@ HWTEST_F(PermissionRecordManagerTest, OnRemoteDied001, TestSize.Level4) permList.emplace_back("ohos.permission.CAMERA"); wptr remote = new (std::nothrow) PermActiveStatusChangeCallbackTest(); callback = remote.promote(); - ActiveStatusCallbackManager::GetInstance().AddCallback(GetSelfTokenID(), permList, callback); + ActiveStatusCallbackManager::GetInstance().AddCallback( + GetSelfTokenID(), permList, callback, static_cast(CallbackRegisterType::TOKEN_ONLY)); ASSERT_EQ(static_cast(1), ActiveStatusCallbackManager::GetInstance().callbackDataList_.size()); recipient->OnRemoteDied(remote); // remote is not nullptr ASSERT_EQ(static_cast(0), ActiveStatusCallbackManager::GetInstance().callbackDataList_.size()); diff --git a/services/privacymanager/test/unittest/active/active_status_callback_manager_test.cpp b/services/privacymanager/test/unittest/active/active_status_callback_manager_test.cpp index 6e4520b18..a1d957c39 100644 --- a/services/privacymanager/test/unittest/active/active_status_callback_manager_test.cpp +++ b/services/privacymanager/test/unittest/active/active_status_callback_manager_test.cpp @@ -88,6 +88,21 @@ void PermActiveStatusChangeCallbackTest1::ActiveStatusChangeCallback(ActiveChang { } +class PermActiveStatusCountCallbackTest : public PermActiveStatusChangeCallbackStub { +public: + PermActiveStatusCountCallbackTest() = default; + virtual ~PermActiveStatusCountCallbackTest() = default; + + void ActiveStatusChangeCallback(ActiveChangeResponse& result) override + { + ++count_; + type_ = result.type; + } + + int32_t count_ = 0; + ActiveChangeType type_ = PERM_INACTIVE; +}; + /* * @tc.name: AddCallback001 * @tc.desc: AddCallback mock function test @@ -105,16 +120,19 @@ HWTEST_F(ActiveStatusCallbackManagerTest, AddCallback001, TestSize.Level0) std::vector permList; permList.emplace_back("ohos.permission.CAMERA"); - int32_t ret = ActiveStatusCallbackManager::GetInstance().AddCallback(GetSelfTokenID(), permList, callback); + int32_t ret = ActiveStatusCallbackManager::GetInstance().AddCallback( + GetSelfTokenID(), permList, callback, static_cast(CallbackRegisterType::TOKEN_ONLY)); EXPECT_EQ(ret, ERR_PARAM_INVALID); wptr remote = new (std::nothrow) PermActiveStatusChangeCallbackTest(); callback = remote.promote(); - ret = ActiveStatusCallbackManager::GetInstance().AddCallback(GetSelfTokenID(), permList, callback); + ret = ActiveStatusCallbackManager::GetInstance().AddCallback( + GetSelfTokenID(), permList, callback, static_cast(CallbackRegisterType::TOKEN_ONLY)); EXPECT_EQ(ret, RET_SUCCESS); g_isAddSucc = false; - ret = ActiveStatusCallbackManager::GetInstance().AddCallback(GetSelfTokenID(), permList, callback); + ret = ActiveStatusCallbackManager::GetInstance().AddCallback( + GetSelfTokenID(), permList, callback, static_cast(CallbackRegisterType::TOKEN_ONLY)); EXPECT_EQ(ret, ERR_ADD_DEATH_RECIPIENT_FAILED); // recovery @@ -140,12 +158,83 @@ HWTEST_F(ActiveStatusCallbackManagerTest, AddCallback002, TestSize.Level0) wptr remote = new (std::nothrow) PermActiveStatusChangeCallbackTest1(); callback = remote.promote(); - int32_t ret = ActiveStatusCallbackManager::GetInstance().AddCallback(GetSelfTokenID(), permList, callback); + int32_t ret = ActiveStatusCallbackManager::GetInstance().AddCallback( + GetSelfTokenID(), permList, callback, static_cast(CallbackRegisterType::TOKEN_ONLY)); EXPECT_EQ(ret, RET_SUCCESS); // recovery ActiveStatusCallbackManager::GetInstance().callbackDataList_ = callbackDataList; } + +/* + * @tc.name: AddCallback003 + * @tc.desc: AddCallback stores ALL register type correctly. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ActiveStatusCallbackManagerTest, AddCallback003, TestSize.Level0) +{ + std::vector callbackDataList = ActiveStatusCallbackManager::GetInstance().callbackDataList_; + ActiveStatusCallbackManager::GetInstance().callbackDataList_.clear(); + + sptr callback; + std::vector permList; + permList.emplace_back("ohos.permission.CAMERA"); + + wptr remote = new (std::nothrow) PermActiveStatusChangeCallbackTest1(); + callback = remote.promote(); + int32_t ret = ActiveStatusCallbackManager::GetInstance().AddCallback( + GetSelfTokenID(), permList, callback, static_cast(CallbackRegisterType::ALL)); + ASSERT_EQ(ret, RET_SUCCESS); + ASSERT_EQ(1, ActiveStatusCallbackManager::GetInstance().callbackDataList_.size()); + EXPECT_EQ(static_cast(CallbackRegisterType::ALL), + ActiveStatusCallbackManager::GetInstance().callbackDataList_[0].registerType_); + + ActiveStatusCallbackManager::GetInstance().callbackDataList_ = callbackDataList; +} + +/* + * @tc.name: ActiveStatusChangeByRegisterType001 + * @tc.desc: Verify TOKEN_ONLY only receives token events and ALL receives supported source events. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ActiveStatusCallbackManagerTest, ActiveStatusChangeByRegisterType001, TestSize.Level0) +{ + std::vector callbackDataList = ActiveStatusCallbackManager::GetInstance().callbackDataList_; + ActiveStatusCallbackManager::GetInstance().callbackDataList_.clear(); + + std::vector permList = {"ohos.permission.CAMERA"}; + sptr tokenCallback = new (std::nothrow) PermActiveStatusCountCallbackTest(); + sptr allCallback = new (std::nothrow) PermActiveStatusCountCallbackTest(); + ASSERT_NE(nullptr, tokenCallback); + ASSERT_NE(nullptr, allCallback); + + auto& manager = ActiveStatusCallbackManager::GetInstance(); + ASSERT_EQ(RET_SUCCESS, manager.AddCallback( + GetSelfTokenID(), permList, tokenCallback->AsObject(), + static_cast(CallbackRegisterType::TOKEN_ONLY))); + ASSERT_EQ(RET_SUCCESS, manager.AddCallback( + GetSelfTokenID(), permList, allCallback->AsObject(), + static_cast(CallbackRegisterType::ALL))); + + ActiveChangeResponse info; + info.permissionName = "ohos.permission.CAMERA"; + info.type = PERM_ACTIVE_IN_FOREGROUND; + + manager.ActiveStatusChange(info, CallbackRegisterType::TOKEN_ONLY); + EXPECT_EQ(1, tokenCallback->count_); + EXPECT_EQ(1, allCallback->count_); + +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE + // Bundle-level active status changes are dispatched with the ALL source type. + manager.ActiveStatusChange(info, CallbackRegisterType::ALL); + EXPECT_EQ(1, tokenCallback->count_); + EXPECT_EQ(2, allCallback->count_); +#endif + + ActiveStatusCallbackManager::GetInstance().callbackDataList_ = callbackDataList; +} } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/services/privacymanager/test/unittest/record/permission_record_manager_test.cpp b/services/privacymanager/test/unittest/record/permission_record_manager_test.cpp index d70e588e4..b12c5edae 100644 --- a/services/privacymanager/test/unittest/record/permission_record_manager_test.cpp +++ b/services/privacymanager/test/unittest/record/permission_record_manager_test.cpp @@ -295,7 +295,7 @@ HWTEST_F(PermissionRecordManagerTest, RegisterPermActiveStatusCallback001, TestS { std::vector permList = {"ohos.permission.CAMERA"}; ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, nullptr)); + GetSelfTokenID(), permList, nullptr, static_cast(CallbackRegisterType::TOKEN_ONLY))); } @@ -340,7 +340,8 @@ HWTEST_F(PermissionRecordManagerTest, RegisterPermActiveStatusCallback002, TestS sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), + static_cast(CallbackRegisterType::TOKEN_ONLY))); callbacks.emplace_back(callback); } @@ -348,7 +349,8 @@ HWTEST_F(PermissionRecordManagerTest, RegisterPermActiveStatusCallback002, TestS ASSERT_NE(nullptr, callback); ASSERT_EQ(PrivacyError::ERR_CALLBACKS_EXCEED_LIMITATION, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), + static_cast(CallbackRegisterType::TOKEN_ONLY))); for (size_t i = 0; i < callbacks.size(); ++i) { ASSERT_EQ(RET_SUCCESS, @@ -366,7 +368,7 @@ HWTEST_F(PermissionRecordManagerTest, UnRegisterPermActiveStatusCallback001, Tes { std::vector permList = {"ohos.permission.CAMERA"}; ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, nullptr)); + GetSelfTokenID(), permList, nullptr, static_cast(CallbackRegisterType::TOKEN_ONLY))); } /* @@ -439,8 +441,7 @@ HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionTest003, TestSize.Leve AccessTokenID tokenId = tokenIdEx.tokenIdExStruct.tokenID; ASSERT_NE(INVALID_TOKENID, tokenId); std::string permissionName = "ohos.permission.MICROPHONE"; - ASSERT_EQ(PrivacyError::ERR_EDM_POLICY_CHECK_FAILED, - PermissionRecordManager::GetInstance().StartUsingPermission( + ASSERT_EQ(PrivacyError::ERR_EDM_POLICY_CHECK_FAILED, PermissionRecordManager::GetInstance().StartUsingPermission( MakeInfo(tokenId, PID, permissionName), CALLER_PID)); std::string str = isMute ? "true" : "false"; SetParameter(EDM_MIC_MUTE_KEY, str.c_str()); @@ -468,7 +469,7 @@ HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionTest004, TestSize.Leve sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, g_InfoParms1.bundleName, g_InfoParms1.instIndex); @@ -508,7 +509,7 @@ HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionTest005, TestSize.Leve sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, g_InfoParms1.bundleName, g_InfoParms1.instIndex); @@ -549,7 +550,7 @@ HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionTest006, TestSize.Leve sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); EXPECT_NE(nullptr, callback); EXPECT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, g_InfoParms1.bundleName, g_InfoParms1.instIndex); @@ -608,7 +609,7 @@ HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionTest008, TestSize.Leve sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, g_InfoParms1.bundleName, g_InfoParms1.instIndex); @@ -715,7 +716,7 @@ HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionTest010, TestSize.Leve sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, g_InfoParms1.bundleName, g_InfoParms1.instIndex); @@ -825,7 +826,7 @@ HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionTest012, TestSize.Leve sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, g_InfoParms1.bundleName, g_InfoParms1.instIndex); AccessTokenID tokenId = tokenIdEx.tokenIdExStruct.tokenID; @@ -1237,7 +1238,7 @@ HWTEST_F(PermissionRecordManagerTest, RegisterPermActiveStatusCallback003, TestS permList.emplace_back("com.ohos.TEST"); // GetDefPermission != Constant::SUCCESS && listRes is empty && listSrc is not empty ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, nullptr)); + GetSelfTokenID(), permList, nullptr, static_cast(CallbackRegisterType::TOKEN_ONLY))); } /* @@ -1663,7 +1664,7 @@ HWTEST_F(PermissionRecordManagerTest, ProxyDeathTest002, TestSize.Level0) } /* - * @tc.name: PermissionRecordManagerTest + * @tc.name: HasCallerInStartList001 * @tc.desc: HasCallerInStartList test * @tc.type: FUNC * @tc.require: @@ -1688,6 +1689,247 @@ HWTEST_F(PermissionRecordManagerTest, HasCallerInStartList001, TestSize.Level0) ASSERT_FALSE(PermissionRecordManager::GetInstance().HasCallerInStartList(CALLER_PID)); } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +/* + * @tc.name: StartUsingPermissionBundle001 + * @tc.desc: StartUsingPermission bundle function test + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionBundle001, TestSize.Level0) +{ + const std::string bundleName = g_InfoParms1.bundleName; + const std::string permissionName = "ohos.permission.CAMERA"; + + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission(bundleName, permissionName, CALLER_PID)); + ASSERT_EQ(1, manager.bundleStartRecordMap_.size()); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID)); + + ASSERT_EQ(PrivacyError::ERR_PERMISSION_ALREADY_START_USING, + manager.StartUsingPermission(bundleName, permissionName, CALLER_PID)); + ASSERT_EQ(1, manager.bundleStartRecordMap_[bundleName].size()); + + ASSERT_EQ(RET_SUCCESS, manager.StopUsingPermission(bundleName, permissionName, CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); + ASSERT_FALSE(manager.HasCallerInStartList(CALLER_PID)); +} + +/* + * @tc.name: StartUsingPermissionBundle002 + * @tc.desc: StartUsingPermission bundle validates bundle and permission parameters + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionBundle002, TestSize.Level0) +{ + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, manager.StartUsingPermission("", "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, manager.StartUsingPermission(g_InfoParms1.bundleName, "", CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); +} + +/* + * @tc.name: StartUsingPermissionBundle003 + * @tc.desc: StartUsingPermission bundle returns ERR_PERMISSION_NOT_EXIST for unsupported permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionBundle003, TestSize.Level0) +{ + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(PrivacyError::ERR_PERMISSION_NOT_EXIST, + manager.StartUsingPermission(g_InfoParms1.bundleName, "ohos.permission.TEST", CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); +} + +/* + * @tc.name: StartUsingPermissionBundle004 + * @tc.desc: StartUsingPermission bundle returns EDM policy error when camera is muted by EDM policy + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionBundle004, TestSize.Level0) +{ + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + char value[VALUE_MAX_LEN] = {0}; + GetParameter(EDM_CAMERA_MUTE_KEY, "", value, VALUE_MAX_LEN - 1); + std::string muteState(value); + + ASSERT_EQ(0, SetParameter(EDM_CAMERA_MUTE_KEY, "true")); + ASSERT_EQ(PrivacyError::ERR_EDM_POLICY_CHECK_FAILED, + manager.StartUsingPermission(g_InfoParms1.bundleName, "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); + + ASSERT_EQ(0, SetParameter(EDM_CAMERA_MUTE_KEY, muteState.c_str())); +} + +/* + * @tc.name: StartUsingPermissionBundle005 + * @tc.desc: StartUsingPermission bundle appends a new record when the bundle bucket already exists + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StartUsingPermissionBundle005, TestSize.Level0) +{ + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission(g_InfoParms1.bundleName, "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_EQ(1, manager.bundleStartRecordMap_.size()); + ASSERT_EQ(1, manager.bundleStartRecordMap_[g_InfoParms1.bundleName].size()); + + ASSERT_EQ(RET_SUCCESS, + manager.StartUsingPermission(g_InfoParms1.bundleName, "ohos.permission.CAMERA", CALLER_PID2)); + ASSERT_EQ(1, manager.bundleStartRecordMap_.size()); + ASSERT_EQ(2, manager.bundleStartRecordMap_[g_InfoParms1.bundleName].size()); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID)); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID2)); + + ASSERT_EQ(RET_SUCCESS, manager.StopUsingPermission(g_InfoParms1.bundleName, "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_EQ(RET_SUCCESS, manager.StopUsingPermission(g_InfoParms1.bundleName, "ohos.permission.CAMERA", CALLER_PID2)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); +} + +/* + * @tc.name: StopUsingPermissionBundle001 + * @tc.desc: StopUsingPermission bundle returns ERR_PERMISSION_NOT_START_USING when bundle was never started + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StopUsingPermissionBundle001, TestSize.Level0) +{ + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(PrivacyError::ERR_PERMISSION_NOT_START_USING, + manager.StopUsingPermission(g_InfoParms1.bundleName, "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); +} + +/* + * @tc.name: StopUsingPermissionBundle002 + * @tc.desc: StopUsingPermission bundle validates bundle and permission parameters + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StopUsingPermissionBundle002, TestSize.Level0) +{ + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, manager.StopUsingPermission("", "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, manager.StopUsingPermission(g_InfoParms1.bundleName, "", CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); +} + +/* + * @tc.name: StopUsingPermissionBundle003 + * @tc.desc: StopUsingPermission bundle returns ERR_PERMISSION_NOT_EXIST for unsupported permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StopUsingPermissionBundle003, TestSize.Level0) +{ + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(PrivacyError::ERR_PERMISSION_NOT_EXIST, + manager.StopUsingPermission(g_InfoParms1.bundleName, "ohos.permission.TEST", CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); +} + +/* + * @tc.name: StopUsingPermissionBundle004 + * @tc.desc: StopUsingPermission bundle keeps record when permission does not match + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StopUsingPermissionBundle004, TestSize.Level0) +{ + const std::string bundleName = g_InfoParms1.bundleName; + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission(bundleName, "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_EQ(PrivacyError::ERR_PERMISSION_NOT_START_USING, + manager.StopUsingPermission(bundleName, "ohos.permission.MICROPHONE", CALLER_PID)); + ASSERT_EQ(1, manager.bundleStartRecordMap_.size()); + ASSERT_EQ(1, manager.bundleStartRecordMap_[bundleName].size()); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID)); + + ASSERT_EQ(RET_SUCCESS, manager.StopUsingPermission(bundleName, "ohos.permission.CAMERA", CALLER_PID)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); + ASSERT_FALSE(manager.HasCallerInStartList(CALLER_PID)); +} + +/* + * @tc.name: StopUsingPermissionBundle005 + * @tc.desc: StopUsingPermission bundle retains other caller records in the same bundle bucket + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, StopUsingPermissionBundle005, TestSize.Level0) +{ + const std::string bundleName = g_InfoParms1.bundleName; + const std::string permissionName = "ohos.permission.CAMERA"; + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission(bundleName, permissionName, CALLER_PID)); + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission(bundleName, permissionName, CALLER_PID2)); + ASSERT_EQ(2, manager.bundleStartRecordMap_[bundleName].size()); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID)); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID2)); + + ASSERT_EQ(RET_SUCCESS, manager.StopUsingPermission(bundleName, permissionName, CALLER_PID)); + ASSERT_EQ(1, manager.bundleStartRecordMap_.size()); + ASSERT_EQ(1, manager.bundleStartRecordMap_[bundleName].size()); + ASSERT_FALSE(manager.HasCallerInStartList(CALLER_PID)); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID2)); + + ASSERT_EQ(RET_SUCCESS, manager.StopUsingPermission(bundleName, permissionName, CALLER_PID2)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); + ASSERT_FALSE(manager.HasCallerInStartList(CALLER_PID2)); +} + +/* + * @tc.name: CallerPidCleanup001 + * @tc.desc: RemoveRecordFromStartListByCallerPid clears bundle records for the specified caller only + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, CallerPidCleanup001, TestSize.Level0) +{ + const std::string permissionName = "ohos.permission.CAMERA"; + auto& manager = PermissionRecordManager::GetInstance(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission(g_InfoParms1.bundleName, permissionName, CALLER_PID)); + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission(g_InfoParms1.bundleName, permissionName, CALLER_PID2)); + ASSERT_EQ(RET_SUCCESS, manager.StartUsingPermission("ohos.privacy_test.bundleB", permissionName, CALLER_PID)); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID)); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID2)); + + manager.RemoveRecordFromStartListByCallerPid(CALLER_PID); + ASSERT_FALSE(manager.HasCallerInStartList(CALLER_PID)); + ASSERT_TRUE(manager.HasCallerInStartList(CALLER_PID2)); + ASSERT_EQ(1, manager.bundleStartRecordMap_.size()); + ASSERT_EQ(1, manager.bundleStartRecordMap_[g_InfoParms1.bundleName].size()); + + ASSERT_EQ(RET_SUCCESS, manager.StopUsingPermission(g_InfoParms1.bundleName, permissionName, CALLER_PID2)); + ASSERT_TRUE(manager.bundleStartRecordMap_.empty()); +} +#endif + /* * @tc.name: AddPermissionUsedRecordTest001 * @tc.desc: AddPermissionUsedRecord function test @@ -1829,7 +2071,7 @@ HWTEST_F(PermissionRecordManagerTest, AddPermissionUsedRecordTest004, TestSize.L sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AddPermParamInfo info; info.tokenId = tokenId; @@ -1868,7 +2110,7 @@ HWTEST_F(PermissionRecordManagerTest, AddPermissionUsedRecordTest005, TestSize.L sptr callback = new (std::nothrow) PermActiveStatusChangeCallback(); ASSERT_NE(nullptr, callback); ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().RegisterPermActiveStatusCallback( - GetSelfTokenID(), permList, callback->AsObject())); + GetSelfTokenID(), permList, callback->AsObject(), static_cast(CallbackRegisterType::TOKEN_ONLY))); AddPermParamInfo info; info.tokenId = tokenId; @@ -1961,40 +2203,11 @@ HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse004, TestSize.Level1) /** * @tc.name: CheckPermissionInUse005 - * @tc.desc: Test CheckPermissionInUse with empty permission name. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse005, TestSize.Level1) -{ - // Empty permission name should return error code - bool isUsing = false; - EXPECT_EQ(PrivacyError::ERR_PARAM_INVALID, - PermissionRecordManager::GetInstance().CheckPermissionInUse("", isUsing)); -} - -/** - * @tc.name: CheckPermissionInUse006 - * @tc.desc: Test CheckPermissionInUse with permission name exceeding 256 characters. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse006, TestSize.Level1) -{ - // Permission name exceeding 256 characters should return error code - std::string longPermissionName(257, 'a'); // 257 characters, exceeds MAX_PERMISSION_NAME_LENGTH (256) - bool isUsing = false; - EXPECT_EQ(PrivacyError::ERR_PARAM_INVALID, PermissionRecordManager::GetInstance().CheckPermissionInUse( - longPermissionName, isUsing)); -} - -/** - * @tc.name: CheckPermissionInUse007 * @tc.desc: Test CheckPermissionInUse with multiple permissions. * @tc.type: FUNC * @tc.require: */ -HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse007, TestSize.Level1) +HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse005, TestSize.Level1) { // Get HAP token from bundle AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, @@ -2029,6 +2242,55 @@ HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse007, TestSize.Level1) tokenId, PID, "ohos.permission.CAMERA", CALLER_PID)); } +/** + * @tc.name: CheckPermissionInUse006 + * @tc.desc: Test CheckPermissionInUse with target permission not started while another permission is in use. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse006, TestSize.Level1) +{ + AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle(g_InfoParms1.userID, + g_InfoParms1.bundleName, g_InfoParms1.instIndex); + AccessTokenID tokenId = tokenIdEx.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenId); + + ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().StartUsingPermission( + MakeInfo(tokenId, PID, "ohos.permission.CAMERA"), CALLER_PID)); + + bool isUsing = true; + EXPECT_EQ(RET_SUCCESS, + PermissionRecordManager::GetInstance().CheckPermissionInUse("ohos.permission.MICROPHONE", isUsing)); + EXPECT_FALSE(isUsing); + + ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().StopUsingPermission( + tokenId, PID, "ohos.permission.CAMERA", CALLER_PID)); +} + +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +/** + * @tc.name: CheckPermissionInUse007 + * @tc.desc: Test CheckPermissionInUse with bundle start and stop. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse007, TestSize.Level1) +{ + const std::string bundleName = "ohos.permission.record.bundle"; + + ASSERT_EQ(RET_SUCCESS, + PermissionRecordManager::GetInstance().StartUsingPermission(bundleName, "ohos.permission.CAMERA", CALLER_PID)); + + bool isUsing = false; + EXPECT_EQ(RET_SUCCESS, + PermissionRecordManager::GetInstance().CheckPermissionInUse("ohos.permission.CAMERA", isUsing)); + EXPECT_TRUE(isUsing); + + ASSERT_EQ(RET_SUCCESS, + PermissionRecordManager::GetInstance().StopUsingPermission(bundleName, "ohos.permission.CAMERA", CALLER_PID)); +} +#endif + /** * @tc.name: CheckPermissionInUse008 * @tc.desc: Test CheckPermissionInUse after removing permission record. @@ -2109,6 +2371,37 @@ HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse009, TestSize.Level1) tokenId, PID, "ohos.permission.CAMERA", CALLER_PID)); } +#ifdef REMOTE_PRIVACY_ENABLE +/** + * @tc.name: CheckPermissionInUse010 + * @tc.desc: Test CheckPermissionInUse with remote permission start and stop. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionRecordManagerTest, CheckPermissionInUse010, TestSize.Level1) +{ + RemotePermissionUsedInfo info; + info.permissionName = "ohos.permission.CAMERA"; + info.remoteDeviceId = "ididid"; + info.remoteDeviceName = "namename"; + + ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().StartRemoteUsingPermission(info, CALLER_PID)); + + bool isUsing = false; + EXPECT_EQ(RET_SUCCESS, + PermissionRecordManager::GetInstance().CheckPermissionInUse("ohos.permission.CAMERA", isUsing)); + EXPECT_TRUE(isUsing); + + ASSERT_EQ(RET_SUCCESS, PermissionRecordManager::GetInstance().StopRemoteUsingPermission( + info.remoteDeviceId, info.remoteDeviceName, info.permissionName, CALLER_PID)); + + isUsing = false; + EXPECT_EQ(RET_SUCCESS, + PermissionRecordManager::GetInstance().CheckPermissionInUse("ohos.permission.CAMERA", isUsing)); + EXPECT_FALSE(isUsing); +} +#endif + #ifdef MAX_COUNT_TEST class DisablePolicyChangeCallbackTest : public DisablePolicyChangeCallback { public: diff --git a/services/privacymanager/test/unittest/service/privacy_manager_service_test.cpp b/services/privacymanager/test/unittest/service/privacy_manager_service_test.cpp index f60392587..5d33ff1fe 100644 --- a/services/privacymanager/test/unittest/service/privacy_manager_service_test.cpp +++ b/services/privacymanager/test/unittest/service/privacy_manager_service_test.cpp @@ -15,15 +15,18 @@ #include #include +#include #include "accesstoken_kit.h" #include "constant.h" #include "iprivacy_manager.h" #include "on_permission_used_record_callback_stub.h" #define private public +#include "proxy_death_handler.h" #include "permission_record_manager.h" #include "privacy_manager_service.h" #undef private +#include "parameter.h" #include "perm_active_status_change_callback_stub.h" #include "perm_active_status_change_callback.h" #include "privacy_error.h" @@ -834,6 +837,246 @@ HWTEST_F(PrivacyManagerServiceTest, StartUsingPermissionInner003, TestSize.Level ASSERT_EQ(PrivacyError::ERR_PERMISSION_DENIED, privacyManagerService_->StartUsingPermission(parcel, nullptr)); } +#ifdef PRIVACY_BUNDLE_START_STOP_ENABLE +/** + * @tc.name: BundleUsingServiceTest001 + * @tc.desc: Verify bundle start enters business branch for native caller. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest001, TestSize.Level0) +{ + MockNativeToken mock("privacy_service"); + + int32_t ret = privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest001", CAMERA_PERMISSION_NAME, nullptr); + EXPECT_NE(PrivacyError::ERR_NOT_SYSTEM_APP, ret); + EXPECT_NE(PrivacyError::ERR_PERMISSION_DENIED, ret); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest001", CAMERA_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingServiceTest002 + * @tc.desc: Verify bundle start returns ERR_NOT_SYSTEM_APP for normal hap caller. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest002, TestSize.Level0) +{ + std::vector reqPerm; + MockHapToken mock("BundleUsingServiceTest002", reqPerm, false); + + ASSERT_EQ(PrivacyError::ERR_NOT_SYSTEM_APP, privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest002", CAMERA_PERMISSION_NAME, nullptr)); +} + +/** + * @tc.name: BundleUsingServiceTest003 + * @tc.desc: Verify bundle start returns ERR_PERMISSION_DENIED without permission. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest003, TestSize.Level0) +{ + std::vector reqPerm; + MockHapToken mock("BundleUsingServiceTest003", reqPerm, true); + + ASSERT_EQ(PrivacyError::ERR_PERMISSION_DENIED, privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest003", CAMERA_PERMISSION_NAME, nullptr)); +} + +/** + * @tc.name: BundleUsingServiceTest004 + * @tc.desc: Verify bundle start succeeds for system hap with PERMISSION_USED_STATS. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest004, TestSize.Level0) +{ + std::vector reqPerm = {"ohos.permission.PERMISSION_USED_STATS"}; + MockHapToken mock("BundleUsingServiceTest004", reqPerm, true); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest004", CAMERA_PERMISSION_NAME, nullptr)); + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest004", CAMERA_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingServiceTest005 + * @tc.desc: Verify bundle stop enters business branch for native caller. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest005, TestSize.Level0) +{ + MockNativeToken mock("privacy_service"); + + int32_t ret = privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest005", CAMERA_PERMISSION_NAME); + EXPECT_NE(PrivacyError::ERR_NOT_SYSTEM_APP, ret); + EXPECT_NE(PrivacyError::ERR_PERMISSION_DENIED, ret); +} + +/** + * @tc.name: BundleUsingServiceTest006 + * @tc.desc: Verify bundle stop returns ERR_NOT_SYSTEM_APP for normal hap caller. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest006, TestSize.Level0) +{ + std::vector reqPerm; + MockHapToken mock("BundleUsingServiceTest006", reqPerm, false); + + ASSERT_EQ(PrivacyError::ERR_NOT_SYSTEM_APP, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest006", CAMERA_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingServiceTest007 + * @tc.desc: Verify bundle stop returns ERR_PERMISSION_DENIED without permission. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest007, TestSize.Level0) +{ + std::vector reqPerm; + MockHapToken mock("BundleUsingServiceTest007", reqPerm, true); + + ASSERT_EQ(PrivacyError::ERR_PERMISSION_DENIED, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest007", CAMERA_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingServiceTest008 + * @tc.desc: Verify bundle stop succeeds for system hap with PERMISSION_USED_STATS. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest008, TestSize.Level0) +{ + std::vector reqPerm = {"ohos.permission.PERMISSION_USED_STATS"}; + MockHapToken mock("BundleUsingServiceTest008", reqPerm, true); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest008", CAMERA_PERMISSION_NAME, nullptr)); + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest008", CAMERA_PERMISSION_NAME)); +} + +/** + * @tc.name: BundleUsingServiceTest009 + * @tc.desc: Verify caller remains in bundle start list when another bundle record is still active after stop. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest009, TestSize.Level0) +{ + std::vector reqPerm = {"ohos.permission.PERMISSION_USED_STATS"}; + MockHapToken mock("BundleUsingServiceTest009", reqPerm, true); + auto& manager = PermissionRecordManager::GetInstance(); + int32_t callerPid = getpid(); + manager.bundleStartRecordMap_.clear(); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest009", CAMERA_PERMISSION_NAME, nullptr)); + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StartUsingPermission( + g_InfoParms1.bundleName, CAMERA_PERMISSION_NAME, nullptr)); + ASSERT_TRUE(manager.HasCallerInStartList(callerPid)); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest009", CAMERA_PERMISSION_NAME)); + ASSERT_TRUE(manager.HasCallerInStartList(callerPid)); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + g_InfoParms1.bundleName, CAMERA_PERMISSION_NAME)); + ASSERT_FALSE(manager.HasCallerInStartList(callerPid)); +} + +/** + * @tc.name: BundleUsingServiceTest010 + * @tc.desc: Verify stopping the last bundle record releases the death proxy for the caller. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest010, TestSize.Level0) +{ + std::vector reqPerm = {"ohos.permission.PERMISSION_USED_STATS"}; + MockHapToken mock("BundleUsingServiceTest010", reqPerm, true); + auto& manager = PermissionRecordManager::GetInstance(); + int32_t callerPid = getpid(); + manager.bundleStartRecordMap_.clear(); + + sptr callback = new (std::nothrow) ProxyDeathCallBackStub(); + ASSERT_NE(nullptr, callback); + + auto handler = privacyManagerService_->GetProxyDeathHandler(); + ASSERT_NE(nullptr, handler); + handler->proxyStubAndRecipientMap_.clear(); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest010", CAMERA_PERMISSION_NAME, callback->AsObject())); + ASSERT_TRUE(manager.HasCallerInStartList(callerPid)); + ASSERT_EQ(1, static_cast(handler->proxyStubAndRecipientMap_.size())); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest010", CAMERA_PERMISSION_NAME)); + ASSERT_FALSE(manager.HasCallerInStartList(callerPid)); + ASSERT_TRUE(handler->proxyStubAndRecipientMap_.empty()); +} + +/** + * @tc.name: BundleUsingServiceTest011 + * @tc.desc: Verify stopping bundle record does not release death proxy while token record of the same caller remains. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, BundleUsingServiceTest011, TestSize.Level0) +{ + std::vector reqPerm = {"ohos.permission.PERMISSION_USED_STATS"}; + MockHapToken mock("BundleUsingServiceTest011", reqPerm, true); + auto& manager = PermissionRecordManager::GetInstance(); + int32_t callerPid = getpid(); + manager.bundleStartRecordMap_.clear(); + + AccessTokenIDEx tokenIdEx = PrivacyTestCommon::GetHapTokenIdFromBundle( + g_InfoParms1.userID, g_InfoParms1.bundleName, g_InfoParms1.instIndex); + ASSERT_NE(INVALID_TOKENID, tokenIdEx.tokenIdExStruct.tokenID); + + sptr callback = new (std::nothrow) ProxyDeathCallBackStub(); + ASSERT_NE(nullptr, callback); + + auto handler = privacyManagerService_->GetProxyDeathHandler(); + ASSERT_NE(nullptr, handler); + handler->proxyStubAndRecipientMap_.clear(); + + PermissionUsedTypeInfoParcel parcel; + parcel.info.tokenId = tokenIdEx.tokenIdExStruct.tokenID; + parcel.info.pid = -1; + parcel.info.permissionName = CAMERA_PERMISSION_NAME; + parcel.info.type = PermissionUsedType::NORMAL_TYPE; + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StartUsingPermission(parcel, callback->AsObject())); + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StartUsingPermission( + "BundleUsingServiceTest011", CAMERA_PERMISSION_NAME, callback->AsObject())); + ASSERT_EQ(1, static_cast(handler->proxyStubAndRecipientMap_.size())); + ASSERT_TRUE(manager.HasCallerInStartList(callerPid)); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + "BundleUsingServiceTest011", CAMERA_PERMISSION_NAME)); + ASSERT_EQ(1, static_cast(handler->proxyStubAndRecipientMap_.size())); + ASSERT_TRUE(manager.HasCallerInStartList(callerPid)); + + ASSERT_EQ(RET_SUCCESS, privacyManagerService_->StopUsingPermission( + tokenIdEx.tokenIdExStruct.tokenID, -1, CAMERA_PERMISSION_NAME)); + ASSERT_FALSE(manager.HasCallerInStartList(callerPid)); + ASSERT_TRUE(handler->proxyStubAndRecipientMap_.empty()); +} +#endif + /** * @tc.name: StartUsingPermissionCallbackInner001 * @tc.desc: StartUsingPermissionCallbackInner test. @@ -1150,7 +1393,14 @@ HWTEST_F(PrivacyManagerServiceTest, RegisterPermActiveStatusCallbackInner001, Te // permList size oversize ASSERT_EQ(PrivacyError::ERR_OVERSIZE, - privacyManagerService_->RegisterPermActiveStatusCallback(permList, nullptr)); + privacyManagerService_->RegisterPermActiveStatusCallback( + permList, nullptr, static_cast(CallbackRegisterType::TOKEN_ONLY))); + + permList.clear(); + ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, + privacyManagerService_->RegisterPermActiveStatusCallback(permList, nullptr, -1)); + ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, + privacyManagerService_->RegisterPermActiveStatusCallback(permList, nullptr, 2)); } /** @@ -1168,7 +1418,8 @@ HWTEST_F(PrivacyManagerServiceTest, RegisterPermActiveStatusCallbackInner002, Te // callingTokenID is normal hap without need permission ASSERT_EQ(PrivacyError::ERR_NOT_SYSTEM_APP, - privacyManagerService_->RegisterPermActiveStatusCallback(permList, nullptr)); + privacyManagerService_->RegisterPermActiveStatusCallback( + permList, nullptr, static_cast(CallbackRegisterType::TOKEN_ONLY))); } /** @@ -1186,7 +1437,8 @@ HWTEST_F(PrivacyManagerServiceTest, RegisterPermActiveStatusCallbackInner003, Te // callingTokenID is system hap without need permission ASSERT_EQ(PrivacyError::ERR_PERMISSION_DENIED, - privacyManagerService_->RegisterPermActiveStatusCallback(permList, nullptr)); + privacyManagerService_->RegisterPermActiveStatusCallback( + permList, nullptr, static_cast(CallbackRegisterType::TOKEN_ONLY))); } /** @@ -1200,7 +1452,13 @@ HWTEST_F(PrivacyManagerServiceTest, RegisterPermActiveStatusCallbackInner004, Te std::vector permList; // systemapp with need permission - int32_t ret = privacyManagerService_->RegisterPermActiveStatusCallback(permList, nullptr); + int32_t ret = privacyManagerService_->RegisterPermActiveStatusCallback( + permList, nullptr, static_cast(CallbackRegisterType::TOKEN_ONLY)); + EXPECT_NE(PrivacyError::ERR_NOT_SYSTEM_APP, ret); + EXPECT_NE(PrivacyError::ERR_PERMISSION_DENIED, ret); + + ret = privacyManagerService_->RegisterPermActiveStatusCallback( + permList, nullptr, static_cast(CallbackRegisterType::ALL)); EXPECT_NE(PrivacyError::ERR_NOT_SYSTEM_APP, ret); EXPECT_NE(PrivacyError::ERR_PERMISSION_DENIED, ret); } @@ -1607,7 +1865,7 @@ HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse004, TestSize.Level0) /** * @tc.name: CheckPermissionInUse005 - * @tc.desc: Test CheckPermissionInUse after stopping permission use. + * @tc.desc: Test CheckPermissionInUse with permission name exceeding 256 characters. * @tc.type: FUNC * @tc.require: */ @@ -1617,6 +1875,24 @@ HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse005, TestSize.Level0) reqPerm.emplace_back("ohos.permission.PERMISSION_USED_STATS"); MockHapToken mock("CheckPermissionInUse005", reqPerm, true); // set self tokenID to system app + std::string longPermissionName(257, 'a'); + bool isUsing = false; + ASSERT_EQ(PrivacyError::ERR_PARAM_INVALID, + privacyManagerService_->CheckPermissionInUse(longPermissionName, isUsing)); +} + +/** + * @tc.name: CheckPermissionInUse006 + * @tc.desc: Test CheckPermissionInUse after stopping permission use. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse006, TestSize.Level0) +{ + std::vector reqPerm; + reqPerm.emplace_back("ohos.permission.PERMISSION_USED_STATS"); + MockHapToken mock("CheckPermissionInUse006", reqPerm, true); // set self tokenID to system app + // Start using permission PermissionUsedTypeInfoParcel parcel; AccessTokenID tokenID = 123; // use local tokenID variable @@ -1639,16 +1915,16 @@ HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse005, TestSize.Level0) } /** - * @tc.name: CheckPermissionInUse006 + * @tc.name: CheckPermissionInUse007 * @tc.desc: Test CheckPermissionInUse caller is not system app. * @tc.type: FUNC * @tc.require: */ -HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse006, TestSize.Level0) +HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse007, TestSize.Level0) { std::vector reqPerm; reqPerm.emplace_back("ohos.permission.PERMISSION_USED_STATS"); - MockHapToken mock("CheckPermissionInUse006", reqPerm, false); + MockHapToken mock("CheckPermissionInUse007", reqPerm, false); bool isUsing = false; ASSERT_EQ(PrivacyError::ERR_NOT_SYSTEM_APP, @@ -1656,15 +1932,15 @@ HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse006, TestSize.Level0) } /** - * @tc.name: CheckPermissionInUse007 + * @tc.name: CheckPermissionInUse008 * @tc.desc: Test CheckPermissionInUse caller is system app without PERMISSION_USED_STATS permission. * @tc.type: FUNC * @tc.require: */ -HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse007, TestSize.Level0) +HWTEST_F(PrivacyManagerServiceTest, CheckPermissionInUse008, TestSize.Level0) { std::vector reqPerm; // empty permission list - no PERMISSION_USED_STATS - MockHapToken mock("CheckPermissionInUse007", reqPerm, true); // isSystemApp = true + MockHapToken mock("CheckPermissionInUse008", reqPerm, true); // isSystemApp = true bool isUsing = false; ASSERT_EQ(PrivacyError::ERR_PERMISSION_DENIED, diff --git a/test/fuzztest/innerkits/privacy/BUILD.gn b/test/fuzztest/innerkits/privacy/BUILD.gn index 52df4664c..42bcbb15c 100644 --- a/test/fuzztest/innerkits/privacy/BUILD.gn +++ b/test/fuzztest/innerkits/privacy/BUILD.gn @@ -31,6 +31,7 @@ group("fuzztest") { "setpermissionusedrecordtogglestatus_fuzzer:SetPermissionUsedRecordToggleStatusFuzzTest", "startusingpermission001_fuzzer:StartUsingPermission001FuzzTest", "startusingpermission_fuzzer:StartUsingPermissionFuzzTest", + "startusingpermissionbundle_fuzzer:StartUsingPermissionBundleFuzzTest", "stopusingpermission_fuzzer:StopUsingPermissionFuzzTest", "unregisterpermactivestatuscallback_fuzzer:UnRegisterPermActiveStatusCallbackFuzzTest", ] diff --git a/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/BUILD.gn b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/BUILD.gn new file mode 100644 index 000000000..45ba5bda8 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2026 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. + +import("//base/security/access_token/access_token.gni") +import("//build/config/features.gni") +import("//build/test.gni") +import("../privacy_fuzzer.gni") + +ohos_fuzztest("StartUsingPermissionBundleFuzzTest") { + module_out_path = module_output_path_interface_privacy + fuzz_config_file = "." + include_dirs = privacy_fuzzer_include_dirs + + [ "${access_token_path}/frameworks/common/include" ] + cflags = privacy_fuzzer_cflags + sources = [ "startusingpermissionbundle_fuzzer.cpp" ] + + deps = [ + "${access_token_path}/frameworks/common:accesstoken_common_cxx", + "${access_token_path}/interfaces/innerkits/accesstoken:libaccesstoken_sdk", + "${access_token_path}/interfaces/innerkits/privacy:libprivacy_sdk", + ] + + configs = privacy_fuzzer_configs + + external_deps = privacy_fuzzer_external_deps +} diff --git a/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/corpus/init b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/corpus/init new file mode 100644 index 000000000..bc2e78765 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2026 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. + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/project.xml b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/project.xml new file mode 100644 index 000000000..d3de054d3 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.cpp b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.cpp new file mode 100644 index 000000000..e569de179 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2026 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 "startusingpermissionbundle_fuzzer.h" + +#include + +#include "accesstoken_fuzzdata.h" +#include "fuzzer/FuzzedDataProvider.h" +#undef private +#include "privacy_kit.h" + +using namespace OHOS::Security::AccessToken; + +namespace OHOS { +bool StartUsingPermissionBundleFuzzTest(const uint8_t* data, size_t size) +{ + if ((data == nullptr) || (size == 0)) { + return false; + } + + FuzzedDataProvider provider(data, size); + return PrivacyKit::StartUsingPermission( + provider.ConsumeRandomLengthString(), ConsumePermissionName(provider)) == 0; +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + OHOS::StartUsingPermissionBundleFuzzTest(data, size); + return 0; +} diff --git a/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.h b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.h new file mode 100644 index 000000000..9aaa99cf2 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/startusingpermissionbundle_fuzzer/startusingpermissionbundle_fuzzer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 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 START_USING_PERMISSION_BUNDLE_FUZZER_H +#define START_USING_PERMISSION_BUNDLE_FUZZER_H + +#include +#include + +#endif // START_USING_PERMISSION_BUNDLE_FUZZER_H diff --git a/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/BUILD.gn b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/BUILD.gn new file mode 100644 index 000000000..b8cc76f98 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2026 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. + +import("//base/security/access_token/access_token.gni") +import("//build/config/features.gni") +import("//build/test.gni") +import("../privacy_fuzzer.gni") + +ohos_fuzztest("StopUsingPermissionBundleFuzzTest") { + module_out_path = module_output_path_interface_privacy + fuzz_config_file = "." + include_dirs = privacy_fuzzer_include_dirs + + [ "${access_token_path}/frameworks/common/include" ] + cflags = privacy_fuzzer_cflags + sources = [ "stopusingpermissionbundle_fuzzer.cpp" ] + + deps = [ + "${access_token_path}/frameworks/common:accesstoken_common_cxx", + "${access_token_path}/interfaces/innerkits/accesstoken:libaccesstoken_sdk", + "${access_token_path}/interfaces/innerkits/privacy:libprivacy_sdk", + ] + + configs = privacy_fuzzer_configs + + external_deps = privacy_fuzzer_external_deps +} diff --git a/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/corpus/init b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/corpus/init new file mode 100644 index 000000000..bc2e78765 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2026 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. + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/project.xml b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/project.xml new file mode 100644 index 000000000..d3de054d3 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.cpp b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.cpp new file mode 100644 index 000000000..984328828 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2026 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 "stopusingpermissionbundle_fuzzer.h" + +#include + +#include "accesstoken_fuzzdata.h" +#include "fuzzer/FuzzedDataProvider.h" +#undef private +#include "privacy_kit.h" + +using namespace OHOS::Security::AccessToken; + +namespace OHOS { +bool StopUsingPermissionBundleFuzzTest(const uint8_t* data, size_t size) +{ + if ((data == nullptr) || (size == 0)) { + return false; + } + + FuzzedDataProvider provider(data, size); + return PrivacyKit::StopUsingPermission( + provider.ConsumeRandomLengthString(), ConsumePermissionName(provider)) == 0; +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + OHOS::StopUsingPermissionBundleFuzzTest(data, size); + return 0; +} diff --git a/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.h b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.h new file mode 100644 index 000000000..7fc618ab3 --- /dev/null +++ b/test/fuzztest/innerkits/privacy/stopusingpermissionbundle_fuzzer/stopusingpermissionbundle_fuzzer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 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 STOP_USING_PERMISSION_BUNDLE_FUZZER_H +#define STOP_USING_PERMISSION_BUNDLE_FUZZER_H + +#include +#include + +#endif // STOP_USING_PERMISSION_BUNDLE_FUZZER_H diff --git a/test/fuzztest/services/privacy/BUILD.gn b/test/fuzztest/services/privacy/BUILD.gn index 451103308..c26ca4576 100644 --- a/test/fuzztest/services/privacy/BUILD.gn +++ b/test/fuzztest/services/privacy/BUILD.gn @@ -32,7 +32,9 @@ group("fuzztest") { "setmutepolicystub_fuzzer:SetMutePolicyStubFuzzTest", "setpermissionusedrecordtogglestatusstub_fuzzer:SetPermissionUsedRecordToggleStatusStubFuzzTest", "startusingpermissioncallbackstub_fuzzer:StartUsingPermissionCallbackStubFuzzTest", + "startusingpermissionbundlestub_fuzzer:StartUsingPermissionBundleStubFuzzTest", "startusingpermissionstub_fuzzer:StartUsingPermissionStubFuzzTest", + "stopusingpermissionbundlestub_fuzzer:StopUsingPermissionBundleStubFuzzTest", "stopusingpermissionstub_fuzzer:StopUsingPermissionStubFuzzTest", "unregisterpermactivestatuscallbackstub_fuzzer:UnRegisterPermActiveStatusCallbackStubFuzzTest", ] diff --git a/test/fuzztest/services/privacy/startremoteusingpermissionstub_fuzzer/startremoteusingpermissionstub_fuzzer.cpp b/test/fuzztest/services/privacy/startremoteusingpermissionstub_fuzzer/startremoteusingpermissionstub_fuzzer.cpp index 79e6392a3..ef116980c 100644 --- a/test/fuzztest/services/privacy/startremoteusingpermissionstub_fuzzer/startremoteusingpermissionstub_fuzzer.cpp +++ b/test/fuzztest/services/privacy/startremoteusingpermissionstub_fuzzer/startremoteusingpermissionstub_fuzzer.cpp @@ -90,7 +90,7 @@ bool StartRemoteUsingPermissionStubFuzzTest(const uint8_t* data, size_t size) FuzzedDataProvider provider(data, size); std::string permissionName; int32_t opCode = provider.ConsumeIntegral() % g_permSize; - Constant::TransferOpcodeToPermission(opCode, permissionName); + (void)Constant::TransferOpcodeToPermission(opCode, permissionName); std::string remoteDeviceId = provider.ConsumeRandomLengthString(); std::string remoteDeviceName = provider.ConsumeRandomLengthString(); diff --git a/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/BUILD.gn b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/BUILD.gn new file mode 100644 index 000000000..eb82268f4 --- /dev/null +++ b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2026 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. + +import("//build/config/features.gni") +import("//build/test.gni") +import("../privacy_service_fuzz.gni") + +ohos_fuzztest("StartUsingPermissionBundleStubFuzzTest") { + module_out_path = module_output_path_service_privacy + fuzz_config_file = "." + + sources = [ "startusingpermissionbundlestub_fuzzer.cpp" ] + sources += [ "${access_token_path}/services/common/proxy_death/src/proxy_death_callback_stub.cpp" ] + sources += privacy_stub_fuzz_sources + + include_dirs = privacy_stub_fuzz_include_dirs + + deps = privacy_stub_fuzz_deps + + configs = privacy_stub_fuzz_configs + + external_deps = privacy_stub_fuzz_external_deps + + cflags_cc = privacy_stub_fuzz_cflags_cc + cflags = privacy_stub_fuzz_cflags +} diff --git a/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/corpus/init b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/corpus/init new file mode 100644 index 000000000..bc2e78765 --- /dev/null +++ b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2026 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. + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/project.xml b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/project.xml new file mode 100644 index 000000000..d3de054d3 --- /dev/null +++ b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.cpp b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.cpp new file mode 100644 index 000000000..7146a2218 --- /dev/null +++ b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026 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 "startusingpermissionbundlestub_fuzzer.h" + +#include + +#include "accesstoken_fuzzdata.h" +#include "fuzzer/FuzzedDataProvider.h" +#include "iprivacy_manager.h" +#include "privacy_manager_service.h" +#include "proxy_death_callback_stub.h" + +using namespace OHOS::Security::AccessToken; + +namespace OHOS { +void StartUsingPermissionBundleStub(const std::string& bundleName, const std::string& permissionName) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(IPrivacyManager::GetDescriptor())) { + return; + } + auto anonyStub = sptr::MakeSptr(); + if (!data.WriteString(bundleName)) { + return; + } + if (!data.WriteString(permissionName)) { + return; + } + if (!data.WriteRemoteObject(anonyStub)) { + return; + } + + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + DelayedSingleton::GetInstance()->OnRemoteRequest( + static_cast(IPrivacyManagerIpcCode::COMMAND_START_USING_PERMISSION), + data, reply, option); +} + +bool StartUsingPermissionBundleStubFuzzTest(const uint8_t* data, size_t size) +{ + if ((data == nullptr) || (size == 0)) { + return false; + } + + FuzzedDataProvider provider(data, size); + StartUsingPermissionBundleStub(provider.ConsumeRandomLengthString(), ConsumePermissionName(provider)); + return true; +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + OHOS::StartUsingPermissionBundleStubFuzzTest(data, size); + return 0; +} diff --git a/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.h b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.h new file mode 100644 index 000000000..e6574a5c8 --- /dev/null +++ b/test/fuzztest/services/privacy/startusingpermissionbundlestub_fuzzer/startusingpermissionbundlestub_fuzzer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 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 START_USING_PERMISSION_BUNDLE_STUB_FUZZER_H +#define START_USING_PERMISSION_BUNDLE_STUB_FUZZER_H + +#include +#include + +#endif // START_USING_PERMISSION_BUNDLE_STUB_FUZZER_H diff --git a/test/fuzztest/services/privacy/startusingpermissioncallbackstub_fuzzer/startusingpermissioncallbackstub_fuzzer.cpp b/test/fuzztest/services/privacy/startusingpermissioncallbackstub_fuzzer/startusingpermissioncallbackstub_fuzzer.cpp index e390a6e2f..e5d013a52 100644 --- a/test/fuzztest/services/privacy/startusingpermissioncallbackstub_fuzzer/startusingpermissioncallbackstub_fuzzer.cpp +++ b/test/fuzztest/services/privacy/startusingpermissioncallbackstub_fuzzer/startusingpermissioncallbackstub_fuzzer.cpp @@ -118,7 +118,7 @@ bool StartUsingPermissionCallbackStubFuzzTest(const uint8_t* data, size_t size) int32_t pid = provider.ConsumeIntegral(); std::string permissionName; int32_t opCode = provider.ConsumeIntegral() % g_permSize; - Constant::TransferOpcodeToPermission(opCode, permissionName); + (void)Constant::TransferOpcodeToPermission(opCode, permissionName); StartUsingPermissionCallbackStub(tokenID, pid, permissionName); StopUsingPermissionStub(tokenID, pid, permissionName); diff --git a/test/fuzztest/services/privacy/startusingpermissionstub_fuzzer/startusingpermissionstub_fuzzer.cpp b/test/fuzztest/services/privacy/startusingpermissionstub_fuzzer/startusingpermissionstub_fuzzer.cpp index e52e7b191..abb370684 100644 --- a/test/fuzztest/services/privacy/startusingpermissionstub_fuzzer/startusingpermissionstub_fuzzer.cpp +++ b/test/fuzztest/services/privacy/startusingpermissionstub_fuzzer/startusingpermissionstub_fuzzer.cpp @@ -88,7 +88,7 @@ bool StartUsingPermissionStubFuzzTest(const uint8_t* data, size_t size) int32_t pid = provider.ConsumeIntegral(); std::string permissionName; int32_t opCode = provider.ConsumeIntegral() % g_permSize; - Constant::TransferOpcodeToPermission(opCode, permissionName); + (void)Constant::TransferOpcodeToPermission(opCode, permissionName); StartUsingPermissionStub(tokenID, pid, permissionName); StopUsingPermissionStub(tokenID, pid, permissionName); diff --git a/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/BUILD.gn b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/BUILD.gn new file mode 100644 index 000000000..515706dfa --- /dev/null +++ b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2026 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. + +import("//build/config/features.gni") +import("//build/test.gni") +import("../privacy_service_fuzz.gni") + +ohos_fuzztest("StopUsingPermissionBundleStubFuzzTest") { + module_out_path = module_output_path_service_privacy + fuzz_config_file = "." + + sources = [ "stopusingpermissionbundlestub_fuzzer.cpp" ] + sources += privacy_stub_fuzz_sources + + include_dirs = privacy_stub_fuzz_include_dirs + + deps = privacy_stub_fuzz_deps + + configs = privacy_stub_fuzz_configs + + external_deps = privacy_stub_fuzz_external_deps + + cflags_cc = privacy_stub_fuzz_cflags_cc + cflags = privacy_stub_fuzz_cflags +} diff --git a/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/corpus/init b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/corpus/init new file mode 100644 index 000000000..bc2e78765 --- /dev/null +++ b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2026 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. + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/project.xml b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/project.xml new file mode 100644 index 000000000..d3de054d3 --- /dev/null +++ b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.cpp b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.cpp new file mode 100644 index 000000000..906de7c31 --- /dev/null +++ b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2026 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 "stopusingpermissionbundlestub_fuzzer.h" + +#include + +#include "accesstoken_fuzzdata.h" +#include "fuzzer/FuzzedDataProvider.h" +#include "iprivacy_manager.h" +#include "privacy_manager_service.h" + +using namespace OHOS::Security::AccessToken; + +namespace OHOS { +void StopUsingPermissionBundleStub(const std::string& bundleName, const std::string& permissionName) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(IPrivacyManager::GetDescriptor())) { + return; + } + if (!data.WriteString(bundleName)) { + return; + } + if (!data.WriteString(permissionName)) { + return; + } + + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + DelayedSingleton::GetInstance()->OnRemoteRequest( + static_cast(IPrivacyManagerIpcCode::COMMAND_STOP_USING_PERMISSION), + data, reply, option); +} + +bool StopUsingPermissionBundleStubFuzzTest(const uint8_t* data, size_t size) +{ + if ((data == nullptr) || (size == 0)) { + return false; + } + + FuzzedDataProvider provider(data, size); + StopUsingPermissionBundleStub(provider.ConsumeRandomLengthString(), ConsumePermissionName(provider)); + return true; +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + OHOS::StopUsingPermissionBundleStubFuzzTest(data, size); + return 0; +} diff --git a/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.h b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.h new file mode 100644 index 000000000..055a0abe8 --- /dev/null +++ b/test/fuzztest/services/privacy/stopusingpermissionbundlestub_fuzzer/stopusingpermissionbundlestub_fuzzer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 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 STOP_USING_PERMISSION_BUNDLE_STUB_FUZZER_H +#define STOP_USING_PERMISSION_BUNDLE_STUB_FUZZER_H + +#include +#include + +#endif // STOP_USING_PERMISSION_BUNDLE_STUB_FUZZER_H