• 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 "want.h"
22 #include "want_params_wrapper.h"
23 #include "string_wrapper.h"
24 #include "array_wrapper.h"
25 
26 namespace OHOS::AVSession {
BundleStatusAdapter()27 BundleStatusAdapter::BundleStatusAdapter()
28 {
29     SLOGI("construct");
30 }
31 
~BundleStatusAdapter()32 BundleStatusAdapter::~BundleStatusAdapter()
33 {
34     SLOGI("destroy");
35 }
36 
GetInstance()37 BundleStatusAdapter& BundleStatusAdapter::GetInstance()
38 {
39     static BundleStatusAdapter bundleStatusAdapter;
40     return bundleStatusAdapter;
41 }
42 
Init()43 void 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     SLOGI("get bundle manager proxy success");
58     bundleMgrProxy = iface_cast<AppExecFwk::BundleMgrProxy>(remoteObject);
59 }
60 
SubscribeBundleStatusEvent(const std::string bundleName,const std::function<void (const std::string)> & callback)61 bool BundleStatusAdapter::SubscribeBundleStatusEvent(const std::string bundleName,
62     const std::function<void(const std::string)>& callback)
63 {
64     SLOGI("Bundle status adapter subscribe bundle status event, bundleName=%{public}s", bundleName.c_str());
65     auto bundleStatusCallback = [this](std::string bundleName) {
66         NotifyBundleRemoved(bundleName);
67     };
68     sptr<BundleStatusCallbackImpl> bundleStatusCallbackImpl =
69             new(std::nothrow) BundleStatusCallbackImpl(bundleStatusCallback);
70     if (bundleStatusCallbackImpl == nullptr) {
71         SLOGE("no memory");
72         return false;
73     }
74     if (bundleMgrProxy == nullptr) {
75         SLOGE("SubscribeBundleStatusEvent with proxy null!");
76         Init();
77         if (bundleMgrProxy == nullptr) {
78             SLOGE("SubscribeBundleStatusEvent with proxy null after init!");
79             return false;
80         }
81     }
82     bundleStatusCallbackImpl->SetBundleName(bundleName);
83     if (bundleMgrProxy->RegisterBundleStatusCallback(bundleStatusCallbackImpl)) {
84         bundleStatusListeners_.insert(std::pair<std::string, std::function<void(const std::string)>>(bundleName,
85             callback));
86         return true;
87     } else {
88         SLOGE("Register bundle status callback failed, bundleName=%{public}s", bundleName.c_str());
89         return false;
90     }
91 }
92 
IsAudioPlayback(const std::string & bundleName,const std::string & abilityName)93 bool BundleStatusAdapter::IsAudioPlayback(const std::string& bundleName, const std::string& abilityName)
94 {
95     SLOGI("Estimate bundle audio playback status, bundleName=%{public}s", bundleName.c_str());
96     AppExecFwk::AbilityInfo abilityInfo;
97     bool flag = false;
98     if (bundleMgrProxy->GetAbilityInfo(bundleName, abilityName, abilityInfo)) {
99         flag = static_cast<int32_t>(abilityInfo.backgroundModes) == backgroundModeDemand ? true : false;
100     }
101     return flag;
102 }
103 
NotifyBundleRemoved(const std::string bundleName)104 void BundleStatusAdapter::NotifyBundleRemoved(const std::string bundleName)
105 {
106     auto bundleStatusListener = bundleStatusListeners_.find(bundleName);
107     if (bundleStatusListener == bundleStatusListeners_.end()) {
108         return;
109     }
110     bundleStatusListener->second(bundleName);
111     SLOGI("erase bundle status callback, bundleName=%{public}s", bundleName.c_str());
112     bundleStatusListeners_.erase(bundleName);
113 }
114 
GetBundleNameFromUid(const int32_t uid)115 std::string BundleStatusAdapter::GetBundleNameFromUid(const int32_t uid)
116 {
117     std::string bundleName {""};
118     if (bundleMgrProxy != nullptr) {
119         bundleMgrProxy->GetNameForUid(uid, bundleName);
120     }
121     return bundleName;
122 }
123 
IsSupportPlayIntent(const std::string & bundleName,std::string & supportModule,std::string & profile)124 bool BundleStatusAdapter::IsSupportPlayIntent(const std::string& bundleName, std::string& supportModule,
125                                               std::string& profile)
126 {
127     if (bundleMgrProxy == nullptr) {
128         return false;
129     }
130     AppExecFwk::BundleInfo bundleInfo;
131     if (!bundleMgrProxy->GetBundleInfo(bundleName, getBundleInfoWithHapModule, bundleInfo, startUserId)) {
132         SLOGE("GetBundleInfo=%{public}s fail", bundleName.c_str());
133         return false;
134     }
135     bool isSupportIntent = false;
136     for (std::string module : bundleInfo.moduleNames) {
137         auto ret = bundleMgrProxy->GetJsonProfile(AppExecFwk::ProfileType::INTENT_PROFILE, bundleName, module,
138             profile, startUserId);
139         if (ret == 0) {
140             SLOGI("GetJsonProfile success, profile=%{public}s", profile.c_str());
141             isSupportIntent = true;
142             supportModule = module;
143             break;
144         }
145     }
146     if (!isSupportIntent) {
147         SLOGE("Bundle=%{public}s does not support insight", bundleName.c_str());
148         return false;
149     }
150     // check bundle support background mode & playmusiclist intent
151     nlohmann::json profileValues = nlohmann::json::parse(profile, nullptr, false);
152     CHECK_AND_RETURN_RET_LOG(!profileValues.is_discarded(), false, "json object is null");
153     for (const auto& value : profileValues["insightIntents"]) {
154         std::string insightName = value["intentName"];
155         nlohmann::json abilityValue = value["uiAbility"];
156         if (insightName != PLAY_MUSICLIST) {
157             continue;
158         }
159         if (!value.contains("uiAbility") || abilityValue.is_discarded()) {
160             SLOGE("PLAY_MUSICLIST uiability discarded=%{public}d", abilityValue.is_discarded());
161             return false;
162         }
163         auto modeValues = abilityValue["executeMode"];
164         if (!abilityValue.contains("executeMode") || modeValues.is_discarded()) {
165             SLOGE("PLAY_MUSICLIST executeMode discarded=%{public}d", modeValues.is_discarded());
166             return false;
167         }
168         auto mode = std::find(modeValues.begin(), modeValues.end(), "background");
169         return (mode != modeValues.end());
170     }
171     return false;
172 }
173 
GetPlayIntentParam(const std::string & bundleName,const std::string & assetId,AppExecFwk::InsightIntentExecuteParam & executeParam)174 bool BundleStatusAdapter::GetPlayIntentParam(const std::string& bundleName, const std::string& assetId,
175                                              AppExecFwk::InsightIntentExecuteParam &executeParam)
176 {
177     if (bundleMgrProxy == nullptr) {
178         return false;
179     }
180     std::string supportModule;
181     std::string profile;
182     if (!IsSupportPlayIntent(bundleName, supportModule, profile)) {
183         SLOGE("bundle=%{public}s does not support play insights", bundleName.c_str());
184         return false;
185     }
186     SLOGD("GetJsonProfile profile=%{public}s", profile.c_str());
187     nlohmann::json profileValues = nlohmann::json::parse(profile, nullptr, false);
188     CHECK_AND_RETURN_RET_LOG(!profileValues.is_discarded(), false, "json object is null");
189     for (const auto& value : profileValues["insightIntents"]) {
190         std::string insightName = value["intentName"];
191         nlohmann::json abilityValue = value["uiAbility"];
192         SLOGD(" insightName=%{public}s", insightName.c_str());
193         if (insightName == PLAY_MUSICLIST) {
194             if (!value.contains("uiAbility") || abilityValue.is_discarded()) {
195                 SLOGE("PLAY_MUSICLIST uiability discarded=%{public}d", abilityValue.is_discarded());
196                 return false;
197             }
198             executeParam.bundleName_ = bundleName;
199             executeParam.moduleName_ = supportModule;
200             executeParam.abilityName_ = abilityValue["ability"];
201             executeParam.insightIntentName_ = insightName;
202             executeParam.executeMode_ = AppExecFwk::ExecuteMode::UI_ABILITY_BACKGROUND;
203             // construct items array
204             AppExecFwk::WantParams innerParams;
205             innerParams.SetParam("entityId", OHOS::AAFwk::String::Box(assetId));
206             sptr<OHOS::AAFwk::IArray> array = new (std::nothrow) OHOS::AAFwk::Array(1, OHOS::AAFwk::g_IID_IWantParams);
207             array->Set(0, OHOS::AAFwk::WantParamWrapper::Box(innerParams));
208             std::shared_ptr<AppExecFwk::WantParams> wantParam = std::make_shared<AppExecFwk::WantParams>();
209             wantParam->SetParam("items", array);
210             executeParam.insightIntentParam_ = wantParam;
211             return true;
212         }
213     }
214 
215     return false;
216 }
217 
BundleStatusCallbackImpl(const std::function<void (const std::string)> & callback)218 BundleStatusCallbackImpl::BundleStatusCallbackImpl(const std::function<void(const std::string)>& callback)
219 {
220     SLOGI("Create bundle status instance");
221     callback_ = callback;
222 }
223 
~BundleStatusCallbackImpl()224 BundleStatusCallbackImpl::~BundleStatusCallbackImpl()
225 {
226     SLOGI("Destroy bundle status instance");
227 }
228 
OnBundleStateChanged(const uint8_t installType,const int32_t resultCode,const std::string & resultMsg,const std::string & bundleName)229 void BundleStatusCallbackImpl::OnBundleStateChanged(const uint8_t installType, const int32_t resultCode,
230     const std::string &resultMsg, const std::string &bundleName)
231 {
232     if (installType == static_cast<uint8_t>(AppExecFwk::InstallType::UNINSTALL_CALLBACK)) {
233         callback_(bundleName);
234     }
235 }
236 }