1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "bundle_status_adapter.h" 17 18#include "avsession_log.h" 19#include "iservice_registry.h" 20#include "system_ability_definition.h" 21#include "want.h" 22#include "want_params_wrapper.h" 23#include "string_wrapper.h" 24#include "array_wrapper.h" 25 26namespace OHOS::AVSession { 27BundleStatusAdapter::BundleStatusAdapter() 28{ 29 SLOGI("construct"); 30} 31 32BundleStatusAdapter::~BundleStatusAdapter() 33{ 34 SLOGI("destroy"); 35} 36 37BundleStatusAdapter& BundleStatusAdapter::GetInstance() 38{ 39 static BundleStatusAdapter bundleStatusAdapter; 40 return bundleStatusAdapter; 41} 42 43void BundleStatusAdapter::Init() 44{ 45 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 46 if (!systemAbilityManager) { 47 SLOGI("fail to get system ability mgr"); 48 return; 49 } 50 51 auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 52 if (!remoteObject) { 53 SLOGI("fail to get bundle manager proxy"); 54 return; 55 } 56 57 std::lock_guard bundleMgrProxyLockGuard(bundleMgrProxyLock_); 58 SLOGI("get bundle manager proxy success"); 59 bundleMgrProxy = iface_cast<AppExecFwk::BundleMgrProxy>(remoteObject); 60} 61 62bool BundleStatusAdapter::SubscribeBundleStatusEvent(const std::string bundleName, 63 const std::function<void(const std::string, const int32_t userId)>& callback, int32_t userId) 64{ 65 SLOGI("Bundle status adapter subscribe bundle status event, bundleName=%{public}s, userId=%{public}d", 66 bundleName.c_str(), userId); 67 auto bundleStatusListener = bundleStatusListeners_.find(std::make_pair(bundleName, userId)); 68 if (bundleStatusListener != bundleStatusListeners_.end()) { 69 SLOGE("bundle status has already register"); 70 return false; 71 } 72 auto bundleStatusCallback = [this](std::string bundleName, int32_t userId) { 73 NotifyBundleRemoved(bundleName, userId); 74 }; 75 sptr<BundleStatusCallbackImpl> bundleStatusCallbackImpl = 76 new(std::nothrow) BundleStatusCallbackImpl(bundleStatusCallback, userId); 77 if (bundleStatusCallbackImpl == nullptr) { 78 SLOGE("no memory"); 79 return false; 80 } 81 std::lock_guard bundleMgrProxyLockGuard(bundleMgrProxyLock_); 82 if (bundleMgrProxy == nullptr) { 83 SLOGE("SubscribeBundleStatusEvent with proxy null!"); 84 Init(); 85 if (bundleMgrProxy == nullptr) { 86 SLOGE("SubscribeBundleStatusEvent with proxy null after init!"); 87 return false; 88 } 89 } 90 bundleStatusCallbackImpl->SetBundleName(bundleName); 91 bundleStatusCallbackImpl->SetUserId(userId); 92 if (bundleMgrProxy->RegisterBundleStatusCallback(bundleStatusCallbackImpl)) { 93 bundleStatusListeners_.insert(std::make_pair(std::make_pair(bundleName, userId), callback)); 94 return true; 95 } else { 96 SLOGE("Register bundle status callback failed, bundleName=%{public}s", bundleName.c_str()); 97 return false; 98 } 99} 100 101bool BundleStatusAdapter::IsAudioPlayback(const std::string& bundleName, const std::string& abilityName) 102{ 103 SLOGI("Estimate bundle audio playback status, bundleName=%{public}s", bundleName.c_str()); 104 AppExecFwk::AbilityInfo abilityInfo; 105 bool flag = false; 106 if (bundleMgrProxy->GetAbilityInfo(bundleName, abilityName, abilityInfo)) { 107 flag = static_cast<int32_t>(abilityInfo.backgroundModes) == backgroundModeDemand ? true : false; 108 } 109 return flag; 110} 111 112void BundleStatusAdapter::NotifyBundleRemoved(const std::string bundleName, const int32_t userId) 113{ 114 auto bundleStatusListener = bundleStatusListeners_.find(std::make_pair(bundleName, userId)); 115 if (bundleStatusListener == bundleStatusListeners_.end()) { 116 return; 117 } 118 bundleStatusListener->second(bundleName, userId); 119 SLOGI("erase bundle status callback, bundleName=%{public}s, userId=%{public}d", bundleName.c_str(), userId); 120 bundleStatusListeners_.erase(bundleStatusListener); 121} 122 123std::string BundleStatusAdapter::GetBundleNameFromUid(const int32_t uid) 124{ 125 std::string bundleName {""}; 126 if (bundleMgrProxy != nullptr) { 127 bundleMgrProxy->GetNameForUid(uid, bundleName); 128 } 129 return bundleName; 130} 131 132bool BundleStatusAdapter::CheckBundleSupport(std::string& profile) 133{ 134 nlohmann::json profileValues = nlohmann::json::parse(profile, nullptr, false); 135 CHECK_AND_RETURN_RET_LOG(!profileValues.is_discarded(), false, "json object is null"); 136 CHECK_AND_RETURN_RET_LOG(profileValues.contains("insightIntents"), false, "json do not contains insightIntents"); 137 for (const auto& value : profileValues["insightIntents"]) { 138 std::string insightName = value["intentName"]; 139 CHECK_AND_RETURN_RET_LOG(value.contains("uiAbility"), false, "json do not contains uiAbility"); 140 nlohmann::json abilityValue = value["uiAbility"]; 141 if (insightName != PLAY_MUSICLIST && insightName != PLAY_AUDIO) { 142 continue; 143 } 144 if (abilityValue.is_discarded()) { 145 SLOGE("uiability discarded=%{public}d", abilityValue.is_discarded()); 146 return false; 147 } 148 CHECK_AND_RETURN_RET_LOG(abilityValue.contains("executeMode"), false, "json do not contains executeMode"); 149 auto modeValues = abilityValue["executeMode"]; 150 if (modeValues.is_discarded()) { 151 SLOGE("executeMode discarded=%{public}d", modeValues.is_discarded()); 152 return false; 153 } 154 auto mode = std::find(modeValues.begin(), modeValues.end(), "background"); 155 return (mode != modeValues.end()); 156 } 157 return false; 158} 159 160__attribute__((no_sanitize("cfi"))) bool BundleStatusAdapter::IsSupportPlayIntent(const std::string& bundleName, 161 std::string& supportModule, std::string& profile) 162{ 163 if (bundleMgrProxy == nullptr) { 164 return false; 165 } 166 AppExecFwk::BundleInfo bundleInfo; 167 if (!bundleMgrProxy->GetBundleInfo(bundleName, getBundleInfoWithHapModule, bundleInfo, startUserId)) { 168 SLOGE("GetBundleInfo=%{public}s fail", bundleName.c_str()); 169 return false; 170 } 171 bool isSupportIntent = false; 172 for (std::string module : bundleInfo.moduleNames) { 173 auto ret = bundleMgrProxy->GetJsonProfile(AppExecFwk::ProfileType::INTENT_PROFILE, bundleName, module, 174 profile, startUserId); 175 if (ret == 0) { 176 SLOGI("GetJsonProfile success, profile=%{public}s", profile.c_str()); 177 isSupportIntent = true; 178 supportModule = module; 179 break; 180 } 181 } 182 if (!isSupportIntent) { 183 SLOGE("Bundle=%{public}s does not support insight", bundleName.c_str()); 184 return false; 185 } 186 return CheckBundleSupport(profile); 187} 188 189BundleStatusCallbackImpl::BundleStatusCallbackImpl( 190 const std::function<void(const std::string, const int32_t userId)>& callback, int32_t userId) 191{ 192 SLOGI("Create bundle status instance with userId %{public}d", userId); 193 callback_ = callback; 194 userId_ = userId; 195} 196 197BundleStatusCallbackImpl::~BundleStatusCallbackImpl() 198{ 199 SLOGI("Destroy bundle status instance"); 200} 201 202void BundleStatusCallbackImpl::OnBundleStateChanged(const uint8_t installType, const int32_t resultCode, 203 const std::string &resultMsg, const std::string &bundleName) 204{ 205 if (installType == static_cast<uint8_t>(AppExecFwk::InstallType::UNINSTALL_CALLBACK)) { 206 callback_(bundleName, userId_); 207 } 208} 209} 210