• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "nlohmann/json.hpp"
22 #include "want.h"
23 #include "want_params_wrapper.h"
24 #include "string_wrapper.h"
25 #include "array_wrapper.h"
26 
27 namespace OHOS::AVSession {
BundleStatusAdapter()28 BundleStatusAdapter::BundleStatusAdapter()
29 {
30     SLOGI("construct");
31 }
32 
~BundleStatusAdapter()33 BundleStatusAdapter::~BundleStatusAdapter()
34 {
35     SLOGI("destroy");
36 }
37 
GetInstance()38 BundleStatusAdapter& BundleStatusAdapter::GetInstance()
39 {
40     static BundleStatusAdapter bundleStatusAdapter;
41     return bundleStatusAdapter;
42 }
43 
Init()44 void BundleStatusAdapter::Init()
45 {
46     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
47     if (!systemAbilityManager) {
48         SLOGI("fail to get system ability mgr");
49         return;
50     }
51 
52     auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
53     if (!remoteObject) {
54         SLOGI("fail to get bundle manager proxy");
55         return;
56     }
57 
58     std::lock_guard bundleMgrProxyLockGuard(bundleMgrProxyLock_);
59     SLOGI("get bundle manager proxy success");
60     bundleMgrProxy = iface_cast<AppExecFwk::BundleMgrProxy>(remoteObject);
61     bundleResourceProxy = bundleMgrProxy->GetBundleResourceProxy();
62 }
63 
GetBundleIcon(const std::string bundleName,std::string & icon)64 bool BundleStatusAdapter::GetBundleIcon(const std::string bundleName, std::string& icon)
65 {
66     SLOGI("GetBundleIcon with bundleName:%{public}s", bundleName.c_str());
67 
68     if (bundleMgrProxy == nullptr || bundleResourceProxy == nullptr) {
69         SLOGE("GetBundleIcon with bundleMgrProxy:%{public}d, bundleResourceProxy:%{public}d",
70             static_cast<int>(bundleMgrProxy != nullptr), static_cast<int>(bundleResourceProxy != nullptr));
71         return false;
72     }
73     AppExecFwk::BundleInfo bundleInfo;
74     if (!bundleMgrProxy->GetBundleInfo(bundleName, getBundleInfoWithHapModule, bundleInfo, startUserId)) {
75         SLOGE("GetBundleInfo of bundleName:%{public}s fail!", bundleName.c_str());
76         return false;
77     }
78     std::vector<AppExecFwk::LauncherAbilityResourceInfo> LauncherAbilityResourceInfoList;
79     ErrCode ret = bundleResourceProxy->GetLauncherAbilityResourceInfo(bundleName, 0, LauncherAbilityResourceInfoList);
80     if (ret != ERR_OK) {
81         SLOGE("GetLauncherAbilityResourceInfo of bundleName:%{public}s fail for errCode:%{public}d",
82             bundleName.c_str(), ret);
83         return false;
84     }
85 
86     icon = LauncherAbilityResourceInfoList[0].icon;
87     return true;
88 }
89 
SubscribeBundleStatusEvent(const std::string bundleName,const std::function<void (const std::string,const int32_t userId)> & callback,int32_t userId)90 bool BundleStatusAdapter::SubscribeBundleStatusEvent(const std::string bundleName,
91     const std::function<void(const std::string, const int32_t userId)>& callback, int32_t userId)
92 {
93     SLOGI("Bundle status adapter subscribe bundle status event, bundleName=%{public}s, userId=%{public}d",
94         bundleName.c_str(), userId);
95     auto bundleStatusListener = bundleStatusListeners_.find(std::make_pair(bundleName, userId));
96     if (bundleStatusListener != bundleStatusListeners_.end()) {
97         SLOGE("bundle status has already register");
98         return false;
99     }
100     auto bundleStatusCallback = [this](std::string bundleName, int32_t userId) {
101         NotifyBundleRemoved(bundleName, userId);
102     };
103     sptr<BundleStatusCallbackImpl> bundleStatusCallbackImpl =
104             new(std::nothrow) BundleStatusCallbackImpl(bundleStatusCallback, userId);
105     if (bundleStatusCallbackImpl == nullptr) {
106         SLOGE("no memory");
107         return false;
108     }
109     std::lock_guard bundleMgrProxyLockGuard(bundleMgrProxyLock_);
110     if (bundleMgrProxy == nullptr) {
111         SLOGE("SubscribeBundleStatusEvent with proxy null!");
112         Init();
113         if (bundleMgrProxy == nullptr) {
114             SLOGE("SubscribeBundleStatusEvent with proxy null after init!");
115             return false;
116         }
117     }
118     bundleStatusCallbackImpl->SetBundleName(bundleName);
119     bundleStatusCallbackImpl->SetUserId(userId);
120     if (bundleMgrProxy->RegisterBundleStatusCallback(bundleStatusCallbackImpl)) {
121         bundleStatusListeners_.insert(std::make_pair(std::make_pair(bundleName, userId), callback));
122         return true;
123     } else {
124         SLOGE("Register bundle status callback failed, bundleName=%{public}s", bundleName.c_str());
125         return false;
126     }
127 }
128 
IsAudioPlayback(const std::string & bundleName,const std::string & abilityName)129 bool BundleStatusAdapter::IsAudioPlayback(const std::string& bundleName, const std::string& abilityName)
130 {
131     SLOGI("Estimate bundle audio playback status, bundleName=%{public}s", bundleName.c_str());
132     AppExecFwk::AbilityInfo abilityInfo;
133     bool flag = false;
134     if (bundleMgrProxy->GetAbilityInfo(bundleName, abilityName, abilityInfo)) {
135         flag = static_cast<int32_t>(abilityInfo.backgroundModes) == backgroundModeDemand ? true : false;
136     }
137     return flag;
138 }
139 
NotifyBundleRemoved(const std::string bundleName,const int32_t userId)140 void BundleStatusAdapter::NotifyBundleRemoved(const std::string bundleName, const int32_t userId)
141 {
142     auto bundleStatusListener = bundleStatusListeners_.find(std::make_pair(bundleName, userId));
143     if (bundleStatusListener == bundleStatusListeners_.end()) {
144         return;
145     }
146     bundleStatusListener->second(bundleName, userId);
147     // BMS will keep callbackImpl for the bundleName & userId until avsession do ClearBundleStatusCallback
148     SLOGI("notify bundle status callback without erase, bundleName=%{public}s, userId=%{public}d",
149         bundleName.c_str(), userId);
150 }
151 
GetBundleNameFromUid(const int32_t uid)152 std::string BundleStatusAdapter::GetBundleNameFromUid(const int32_t uid)
153 {
154     std::string bundleName {""};
155     if (bundleMgrProxy != nullptr) {
156         bundleMgrProxy->GetNameForUid(uid, bundleName);
157     }
158     return bundleName;
159 }
160 
CheckBundleSupport(std::string & profile)161 bool BundleStatusAdapter::CheckBundleSupport(std::string& profile)
162 {
163     // check bundle support background mode & playmusiclist intent
164     nlohmann::json profileValues = nlohmann::json::parse(profile, nullptr, false);
165     CHECK_AND_RETURN_RET_LOG(!profileValues.is_discarded(), false, "json object is null");
166     CHECK_AND_RETURN_RET_LOG(profileValues.contains("insightIntents"), false, "json do not contains insightIntents");
167     for (const auto& value : profileValues["insightIntents"]) {
168         std::string insightName = value["intentName"];
169         CHECK_AND_RETURN_RET_LOG(value.contains("uiAbility"), false, "json do not contains uiAbility");
170         nlohmann::json abilityValue = value["uiAbility"];
171         if (insightName != PLAY_MUSICLIST && insightName != PLAY_AUDIO) {
172             continue;
173         }
174         if (abilityValue.is_discarded()) {
175             SLOGE("uiability discarded=%{public}d", abilityValue.is_discarded());
176             return false;
177         }
178         CHECK_AND_RETURN_RET_LOG(abilityValue.contains("executeMode"), false, "json do not contains executeMode");
179         auto modeValues = abilityValue["executeMode"];
180         if (modeValues.is_discarded()) {
181             SLOGE("executeMode discarded=%{public}d", modeValues.is_discarded());
182             return false;
183         }
184         auto mode = std::find(modeValues.begin(), modeValues.end(), "background");
185         return (mode != modeValues.end());
186     }
187     return false;
188 }
189 
IsSupportPlayIntent(const std::string & bundleName,std::string & supportModule,std::string & profile)190 __attribute__((no_sanitize("cfi"))) bool BundleStatusAdapter::IsSupportPlayIntent(const std::string& bundleName,
191     std::string& supportModule, std::string& profile)
192 {
193     if (bundleMgrProxy == nullptr) {
194         return false;
195     }
196     AppExecFwk::BundleInfo bundleInfo;
197     if (!bundleMgrProxy->GetBundleInfo(bundleName, getBundleInfoWithHapModule, bundleInfo, startUserId)) {
198         SLOGE("GetBundleInfo=%{public}s fail", bundleName.c_str());
199         return false;
200     }
201     bool isSupportIntent = false;
202     for (std::string module : bundleInfo.moduleNames) {
203         auto ret = bundleMgrProxy->GetJsonProfile(AppExecFwk::ProfileType::INTENT_PROFILE, bundleName, module,
204             profile, startUserId);
205         if (ret == 0) {
206             SLOGI("GetJsonProfile success, profile=%{public}s", profile.c_str());
207             isSupportIntent = true;
208             supportModule = module;
209             break;
210         }
211     }
212     if (!isSupportIntent) {
213         SLOGE("Bundle=%{public}s does not support insight", bundleName.c_str());
214         return false;
215     }
216     return CheckBundleSupport(profile);
217 }
218 
BundleStatusCallbackImpl(const std::function<void (const std::string,const int32_t userId)> & callback,int32_t userId)219 BundleStatusCallbackImpl::BundleStatusCallbackImpl(
220     const std::function<void(const std::string, const int32_t userId)>& callback, int32_t userId)
221 {
222     SLOGI("Create bundle status instance with userId %{public}d", userId);
223     callback_ = callback;
224     userId_ = userId;
225 }
226 
~BundleStatusCallbackImpl()227 BundleStatusCallbackImpl::~BundleStatusCallbackImpl()
228 {
229     SLOGI("Destroy bundle status instance");
230 }
231 
OnBundleStateChanged(const uint8_t installType,const int32_t resultCode,const std::string & resultMsg,const std::string & bundleName)232 void BundleStatusCallbackImpl::OnBundleStateChanged(const uint8_t installType, const int32_t resultCode,
233     const std::string &resultMsg, const std::string &bundleName)
234 {
235     if (installType == static_cast<uint8_t>(AppExecFwk::InstallType::UNINSTALL_CALLBACK)) {
236         callback_(bundleName, userId_);
237     }
238 }
239 }
240