1 /*
2  * Copyright (c) 2024 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 "ability_manager_interface.h"
17 #include "ability_manager_client.h"
18 #include "bundle_mgr_proxy.h"
19 #include "iremote_stub.h"
20 #include "iservice_registry.h"
21 #include "array_wrapper.h"
22 #include "string_wrapper.h"
23 #include "want_params_wrapper.h"
24 #include "system_ability_definition.h"
25 
26 #include "avsession_dynamic_insight.h"
27 #include "avsession_errors.h"
28 #include "avsession_log.h"
29 
30 namespace OHOS::AVSession {
31 
InsightAdapter()32 InsightAdapter::InsightAdapter()
33 {
34     SLOGI("construct");
35 }
36 
~InsightAdapter()37 InsightAdapter::~InsightAdapter()
38 {
39     SLOGI("destroy");
40 }
41 
GetInsightAdapterInstance()42 InsightAdapter& InsightAdapter::GetInsightAdapterInstance()
43 {
44     static InsightAdapter insightAdapter;
45     return insightAdapter;
46 }
47 
CheckBundleSupport(std::string & profile)48 bool InsightAdapter::CheckBundleSupport(std::string& profile)
49 {
50     nlohmann::json profileValues = nlohmann::json::parse(profile, nullptr, false);
51     CHECK_AND_RETURN_RET_LOG(!profileValues.is_discarded(), false, "json object is null");
52     CHECK_AND_RETURN_RET_LOG(profileValues.contains("insightIntents"), false, "json do not contains insightIntents");
53     for (const auto& value : profileValues["insightIntents"]) {
54         std::string insightName = value["intentName"];
55         CHECK_AND_RETURN_RET_LOG(value.contains("uiAbility"), false, "json do not contains uiAbility");
56         nlohmann::json abilityValue = value["uiAbility"];
57         if (insightName != PLAY_MUSICLIST && insightName != PLAY_AUDIO) {
58             continue;
59         }
60         if (abilityValue.is_discarded()) {
61             SLOGE("uiability discarded=%{public}d", abilityValue.is_discarded());
62             return false;
63         }
64         CHECK_AND_RETURN_RET_LOG(abilityValue.contains("executeMode"), false, "json do not contains executeMode");
65         auto modeValues = abilityValue["executeMode"];
66         if (modeValues.is_discarded()) {
67             SLOGE("executeMode discarded=%{public}d", modeValues.is_discarded());
68             return false;
69         }
70         auto mode = std::find(modeValues.begin(), modeValues.end(), "background");
71         return (mode != modeValues.end());
72     }
73     return false;
74 }
75 
IsSupportPlayIntent(const std::string & bundleName,std::string & supportModule,std::string & profile)76 __attribute__((no_sanitize("cfi"))) bool InsightAdapter::IsSupportPlayIntent(const std::string& bundleName,
77     std::string& supportModule, std::string& profile)
78 {
79     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
80     if (!systemAbilityManager) {
81         SLOGI("fail to get system ability mgr");
82         return false;
83     }
84 
85     auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
86     if (!remoteObject) {
87         SLOGI("fail to get bundle manager proxy");
88         return false;
89     }
90 
91     sptr<AppExecFwk::BundleMgrProxy> bundleMgrProxy = iface_cast<AppExecFwk::BundleMgrProxy>(remoteObject);
92     if (bundleMgrProxy == nullptr) {
93         return false;
94     }
95     SLOGI("get bundle manager proxy success");
96 
97     AppExecFwk::BundleInfo bundleInfo;
98     if (!bundleMgrProxy->GetBundleInfo(bundleName, getBundleInfoWithHapModule, bundleInfo, startUserId)) {
99         SLOGE("GetBundleInfo=%{public}s fail", bundleName.c_str());
100         return false;
101     }
102     bool isSupportIntent = false;
103     for (const std::string& module : bundleInfo.moduleNames) {
104         auto ret = bundleMgrProxy->GetJsonProfile(AppExecFwk::ProfileType::INTENT_PROFILE, bundleName, module,
105             profile, startUserId);
106         if (ret == 0) {
107             SLOGI("GetJsonProfile success, profile=%{public}s", profile.c_str());
108             isSupportIntent = true;
109             supportModule = module;
110             break;
111         }
112     }
113     if (!isSupportIntent) {
114         SLOGE("Bundle=%{public}s does not support insight", bundleName.c_str());
115         return false;
116     }
117     return CheckBundleSupport(profile);
118 }
119 
GetPlayIntentParam(const std::string & bundleName,const std::string & assetId,AppExecFwk::InsightIntentExecuteParam & executeParam)120 bool InsightAdapter::GetPlayIntentParam(const std::string& bundleName, const std::string& assetId,
121     AppExecFwk::InsightIntentExecuteParam &executeParam)
122 {
123     std::string supportModule;
124     std::string profile;
125     if (!IsSupportPlayIntent(bundleName, supportModule, profile)) {
126         SLOGE("bundle=%{public}s does not support play insights", bundleName.c_str());
127         return false;
128     }
129     SLOGD("GetJsonProfile profile=%{public}s", profile.c_str());
130     nlohmann::json profileValues = nlohmann::json::parse(profile, nullptr, false);
131     CHECK_AND_RETURN_RET_LOG(!profileValues.is_discarded(), false, "json object is null");
132     CHECK_AND_RETURN_RET_LOG(profileValues.contains("insightIntents"), false, "json do not contains insightIntents");
133     auto res = false;
134     for (const auto& value : profileValues["insightIntents"]) {
135         std::string insightName = value["intentName"];
136         nlohmann::json abilityValue = value["uiAbility"];
137         SLOGD(" insightName=%{public}s", insightName.c_str());
138         if (insightName != PLAY_MUSICLIST && insightName != PLAY_AUDIO) {
139             continue;
140         }
141         if (!value.contains("uiAbility") || abilityValue.is_discarded()) {
142             SLOGE("uiability discarded=%{public}d", abilityValue.is_discarded());
143             continue;
144         }
145         SLOGD("insightName=%{public}s", insightName.c_str());
146         executeParam.bundleName_ = bundleName;
147         executeParam.moduleName_ = supportModule;
148         executeParam.abilityName_ = abilityValue["ability"];
149         executeParam.insightIntentName_ = insightName;
150         executeParam.executeMode_ = AppExecFwk::ExecuteMode::UI_ABILITY_BACKGROUND;
151         std::shared_ptr<AppExecFwk::WantParams> wantParam = std::make_shared<AppExecFwk::WantParams>();
152         if (insightName == PLAY_MUSICLIST) {
153             // construct items array
154             AppExecFwk::WantParams innerParams;
155             innerParams.SetParam("entityId", OHOS::AAFwk::String::Box(assetId));
156             sptr<OHOS::AAFwk::IArray> array = new (std::nothrow) OHOS::AAFwk::Array(1, OHOS::AAFwk::g_IID_IWantParams);
157             array->Set(0, OHOS::AAFwk::WantParamWrapper::Box(innerParams));
158             wantParam->SetParam("items", array);
159             res = true;
160         }
161         if (insightName == PLAY_AUDIO) {
162             wantParam->SetParam("entityId", AppExecFwk::WantParams::GetInterfaceByType(interfaceType, assetId));
163             res = true;
164         }
165         executeParam.insightIntentParam_ = wantParam;
166     }
167     return res;
168 }
169 
StartAVPlayback(AppExecFwk::InsightIntentExecuteParam & executeParam)170 int32_t InsightAdapter::StartAVPlayback(AppExecFwk::InsightIntentExecuteParam &executeParam)
171 {
172     SLOGI("bundleName=%{public}s abilityName=%{public}s moduleName=%{public}s IntentName=%{public}s",
173         executeParam.bundleName_.c_str(), executeParam.abilityName_.c_str(),
174         executeParam.moduleName_.c_str(), executeParam.insightIntentName_.c_str());
175 
176     sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
177     if (systemManager == nullptr) {
178         SLOGE("Fail to get registry");
179         return AVSESSION_ERROR;
180     }
181     sptr<IRemoteObject> remote = systemManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
182     if (remote == nullptr) {
183         SLOGE("Fail to connect ability manager service");
184         return AVSESSION_ERROR;
185     }
186 
187     auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteIntent((uint64_t) AVSESSION_SERVICE_ID,
188         remote, executeParam);
189     if (ret != AVSESSION_SUCCESS) {
190         SLOGE("ExecuteIntent insightIntent=%{public}s fail", executeParam.insightIntentName_.c_str());
191         return AVSESSION_ERROR;
192     }
193     return AVSESSION_SUCCESS;
194 }
195 
IsSupportPlayIntent(const std::string & bundleName,const std::string & assetId)196 extern "C" bool IsSupportPlayIntent(const std::string& bundleName, const std::string& assetId)
197 {
198     AppExecFwk::InsightIntentExecuteParam executeParam;
199     return InsightAdapter::GetInsightAdapterInstance().GetPlayIntentParam(bundleName, assetId, executeParam);
200 }
201 
StartAVPlayback(const std::string & bundleName,const std::string & assetId)202 extern "C" int32_t StartAVPlayback(const std::string& bundleName, const std::string& assetId)
203 {
204     AppExecFwk::InsightIntentExecuteParam executeParam;
205     bool isSupport = InsightAdapter::GetInsightAdapterInstance().GetPlayIntentParam(bundleName, assetId, executeParam);
206     if (isSupport) {
207         return InsightAdapter::GetInsightAdapterInstance().StartAVPlayback(executeParam);
208     }
209     return AVSESSION_SUCCESS;
210 }
211 }
212