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 "bundle_mgr_proxy.h"
17 #include "iremote_stub.h"
18 #include "iservice_registry.h"
19 #include "array_wrapper.h"
20 #include "string_wrapper.h"
21 #include "want_params_wrapper.h"
22 #include "system_ability_definition.h"
23
24 #include "avsession_dynamic_insight.h"
25 #include "avsession_errors.h"
26 #include "avsession_log.h"
27
28 namespace OHOS::AVSession {
29
InsightAdapter()30 InsightAdapter::InsightAdapter()
31 {
32 SLOGI("construct");
33 }
34
~InsightAdapter()35 InsightAdapter::~InsightAdapter()
36 {
37 SLOGI("destroy");
38 }
39
GetInsightAdapterInstance()40 InsightAdapter& InsightAdapter::GetInsightAdapterInstance()
41 {
42 static InsightAdapter insightAdapter;
43 return insightAdapter;
44 }
45
CheckBundleSupport(std::string & profile)46 bool InsightAdapter::CheckBundleSupport(std::string& profile)
47 {
48 cJSON* profileValues = cJSON_Parse(profile.c_str());
49 CHECK_AND_RETURN_RET_LOG(profileValues != nullptr, false, "parse profile fail");
50 if (cJSON_IsInvalid(profileValues)) {
51 SLOGE("parse profile not valid json");
52 cJSON_Delete(profileValues);
53 return false;
54 }
55 cJSON* insightIntentsArray = cJSON_GetObjectItem(profileValues, "insightIntents");
56 if (insightIntentsArray == nullptr || !cJSON_IsArray(insightIntentsArray)) {
57 SLOGE("json do not contain insightIntentsArray");
58 cJSON_Delete(profileValues);
59 return false;
60 }
61
62 cJSON* insightIntentsItem = nullptr;
63 cJSON_ArrayForEach(insightIntentsItem, insightIntentsArray) {
64 cJSON* intentNameItem = cJSON_GetObjectItem(insightIntentsItem, "intentName");
65 if (intentNameItem == nullptr || !cJSON_IsString(intentNameItem)) {
66 SLOGE("json do not contain intentName");
67 continue;
68 }
69 const char* insightName = intentNameItem->valuestring;
70 if (insightName != nullptr &&
71 strcmp(insightName, PLAY_MUSICLIST.c_str()) != 0 && strcmp(insightName, PLAY_AUDIO.c_str()) != 0) {
72 continue;
73 }
74
75 cJSON* uiAbilityItem = cJSON_GetObjectItem(insightIntentsItem, "uiAbility");
76 if (uiAbilityItem == nullptr) {
77 SLOGE("json do not contain uiAbility");
78 cJSON_Delete(profileValues);
79 return false;
80 }
81 cJSON* executeModeArray = cJSON_GetObjectItem(uiAbilityItem, "executeMode");
82 if (executeModeArray == nullptr || !cJSON_IsArray(executeModeArray)) {
83 SLOGE("json do not contain executeMode");
84 cJSON_Delete(profileValues);
85 return false;
86 }
87 cJSON* modeItem = nullptr;
88 cJSON_ArrayForEach(modeItem, executeModeArray) {
89 if (cJSON_IsString(modeItem) && modeItem->valuestring != nullptr &&
90 strcmp(modeItem->valuestring, "background") == 0) {
91 cJSON_Delete(profileValues);
92 return true;
93 }
94 }
95 }
96 cJSON_Delete(profileValues);
97 return false;
98 }
99
IsSupportPlayIntent(const std::string & bundleName,std::string & supportModule,std::string & profile)100 __attribute__((no_sanitize("cfi"))) bool InsightAdapter::IsSupportPlayIntent(const std::string& bundleName,
101 std::string& supportModule, std::string& profile)
102 {
103 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
104 if (!systemAbilityManager) {
105 SLOGI("fail to get system ability mgr");
106 return false;
107 }
108
109 auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
110 if (!remoteObject) {
111 SLOGI("fail to get bundle manager proxy");
112 return false;
113 }
114
115 sptr<AppExecFwk::BundleMgrProxy> bundleMgrProxy = iface_cast<AppExecFwk::BundleMgrProxy>(remoteObject);
116 if (bundleMgrProxy == nullptr) {
117 return false;
118 }
119 SLOGI("get bundle manager proxy success");
120
121 AppExecFwk::BundleInfo bundleInfo;
122 if (!bundleMgrProxy->GetBundleInfo(bundleName, getBundleInfoWithHapModule, bundleInfo, startUserId)) {
123 SLOGE("GetBundleInfo=%{public}s fail", bundleName.c_str());
124 return false;
125 }
126 bool isSupportIntent = false;
127 for (const std::string& module : bundleInfo.moduleNames) {
128 auto ret = bundleMgrProxy->GetJsonProfile(AppExecFwk::ProfileType::INTENT_PROFILE, bundleName, module,
129 profile, startUserId);
130 if (ret == 0) {
131 SLOGI("GetJsonProfile success, profile=%{public}s", profile.c_str());
132 isSupportIntent = true;
133 supportModule = module;
134 break;
135 }
136 }
137 if (!isSupportIntent) {
138 SLOGE("Bundle=%{public}s does not support insight", bundleName.c_str());
139 return false;
140 }
141 return CheckBundleSupport(profile);
142 }
143
SetStartPlayInfoToParam(const StartPlayInfo startPlayInfo,StartPlayType startPlayType,std::shared_ptr<AppExecFwk::WantParams> & wantParam)144 void InsightAdapter::SetStartPlayInfoToParam(const StartPlayInfo startPlayInfo, StartPlayType startPlayType,
145 std::shared_ptr<AppExecFwk::WantParams> &wantParam)
146 {
147 AppExecFwk::WantParams startPlayInfoParam;
148 startPlayInfoParam.SetParam("startPlayBundleName", OHOS::AAFwk::String::Box(startPlayInfo.getBundleName()));
149 startPlayInfoParam.SetParam("deviceId", OHOS::AAFwk::String::Box(startPlayInfo.getDeviceId()));
150
151 if (wantParam == nullptr) {
152 SLOGE("wantParam is null when SetStartPlayInfoToParam");
153 return;
154 }
155 wantParam->SetParam("startPlayInfo", OHOS::AAFwk::WantParamWrapper::Box(startPlayInfoParam));
156 wantParam->SetParam("startPlayType", OHOS::AAFwk::String::Box(StartPlayTypeToString.at(startPlayType)));
157 }
158
GetPlayIntentParamWithWantProcess(std::string & insightName,const std::string & assetId,const StartPlayInfo startPlayInfo,StartPlayType startPlayType,bool & res)159 std::shared_ptr<AppExecFwk::WantParams> InsightAdapter::GetPlayIntentParamWithWantProcess(std::string& insightName,
160 const std::string& assetId, const StartPlayInfo startPlayInfo, StartPlayType startPlayType, bool& res)
161 {
162 std::shared_ptr<AppExecFwk::WantParams> wantParam = std::make_shared<AppExecFwk::WantParams>();
163 if (insightName == PLAY_MUSICLIST) {
164 AppExecFwk::WantParams innerParams; // construct items array
165 innerParams.SetParam("entityId", OHOS::AAFwk::String::Box(assetId));
166 sptr<OHOS::AAFwk::IArray> array = new (std::nothrow) OHOS::AAFwk::Array(1, OHOS::AAFwk::g_IID_IWantParams);
167 CHECK_AND_RETURN_RET_LOG(array != nullptr, wantParam, "new Array is null");
168 array->Set(0, OHOS::AAFwk::WantParamWrapper::Box(innerParams));
169 wantParam->SetParam("items", array);
170 SetStartPlayInfoToParam(startPlayInfo, startPlayType, wantParam);
171 res = true;
172 }
173 if (insightName == PLAY_AUDIO) {
174 wantParam->SetParam("entityId", AppExecFwk::WantParams::GetInterfaceByType(interfaceType, assetId));
175 SetStartPlayInfoToParam(startPlayInfo, startPlayType, wantParam);
176 res = true;
177 }
178 return wantParam;
179 }
180
GetPlayIntentParam(const std::string & bundleName,const std::string & assetId,AppExecFwk::InsightIntentExecuteParam & executeParam,const StartPlayInfo startPlayInfo,StartPlayType startPlayType)181 bool InsightAdapter::GetPlayIntentParam(const std::string& bundleName, const std::string& assetId,
182 AppExecFwk::InsightIntentExecuteParam &executeParam, const StartPlayInfo startPlayInfo, StartPlayType startPlayType)
183 {
184 std::string supportModule;
185 std::string profile;
186 if (!IsSupportPlayIntent(bundleName, supportModule, profile)) {
187 SLOGE("bundle=%{public}s does not support play insights", bundleName.c_str());
188 return false;
189 }
190 SLOGD("GetJsonProfile profile=%{public}s", profile.c_str());
191 cJSON* profileValues = cJSON_Parse(profile.c_str());
192 CHECK_AND_RETURN_RET_LOG(profileValues != nullptr && !cJSON_IsInvalid(profileValues), false, "parse profile fail");
193 cJSON* insightIntentsArray = cJSON_GetObjectItem(profileValues, "insightIntents");
194 if (insightIntentsArray == nullptr || !cJSON_IsArray(insightIntentsArray)) {
195 SLOGE("json do not contain insightIntentsArray");
196 cJSON_Delete(profileValues);
197 return false;
198 }
199 bool res = false;
200 cJSON* insightIntentsItem = nullptr;
201 cJSON_ArrayForEach(insightIntentsItem, insightIntentsArray) {
202 cJSON* intentNameItem = cJSON_GetObjectItem(insightIntentsItem, "intentName");
203 if (intentNameItem == nullptr || !cJSON_IsString(intentNameItem)) {
204 SLOGE("json do not contain intentName");
205 continue;
206 }
207 std::string insightName(intentNameItem->valuestring);
208 if (insightName != PLAY_MUSICLIST && insightName != PLAY_AUDIO) {
209 continue;
210 }
211 cJSON* uiAbilityItem = cJSON_GetObjectItem(insightIntentsItem, "uiAbility");
212 if (uiAbilityItem == nullptr) {
213 SLOGE("json do not contain uiAbility");
214 continue;
215 }
216 cJSON* abilityItem = cJSON_GetObjectItem(uiAbilityItem, "ability");
217 if (abilityItem == nullptr || !cJSON_IsString(abilityItem)) {
218 SLOGE("json do not contain ability");
219 continue;
220 }
221 executeParam.bundleName_ = bundleName;
222 executeParam.moduleName_ = supportModule;
223 executeParam.abilityName_.assign(abilityItem->valuestring);
224 executeParam.insightIntentName_ = insightName;
225 executeParam.executeMode_ = AppExecFwk::ExecuteMode::UI_ABILITY_BACKGROUND;
226 std::shared_ptr<AppExecFwk::WantParams> wantParam =
227 GetPlayIntentParamWithWantProcess(insightName, assetId, startPlayInfo, startPlayType, res);
228 executeParam.insightIntentParam_ = wantParam;
229 }
230 cJSON_Delete(profileValues);
231 return res;
232 }
233
ExecuteIntentFromAVSession(uint64_t key,const sptr<IRemoteObject> & callerToken,AppExecFwk::InsightIntentExecuteParam & param)234 bool InsightAdapter::ExecuteIntentFromAVSession(uint64_t key, const sptr<IRemoteObject> &callerToken,
235 AppExecFwk::InsightIntentExecuteParam ¶m)
236 {
237 MessageParcel data;
238 MessageParcel reply;
239 MessageOption option;
240 if (!data.WriteInterfaceToken(ABILITY_MANAGER_INTERFACE_TOKEN)) {
241 SLOGE("write interface token failed");
242 return false;
243 }
244 if (!data.WriteUint64(key)) {
245 SLOGE("write key fail");
246 return false;
247 }
248 if (!data.WriteRemoteObject(callerToken)) {
249 SLOGE("write callerToken fail");
250 return false;
251 }
252 if (!data.WriteParcelable(¶m)) {
253 SLOGE("write param fail");
254 return false;
255 }
256
257 sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
258 if (systemManager == nullptr) {
259 SLOGE("Fail to get registry");
260 return false;
261 }
262 sptr<IRemoteObject> remote = systemManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
263 if (remote == nullptr) {
264 SLOGE("Fail to connect ability manager service");
265 return false;
266 }
267 SLOGI("Connect ability manager service success");
268
269 if (remote->SendRequest(static_cast<uint32_t>(AVSESSION_EXECUTE_INTENT_CODE),
270 data, reply, option) != 0) {
271 SLOGE("Send request error");
272 return false;
273 }
274 return reply.ReadInt32() == ERR_OK;
275 }
276
StartAVPlayback(AppExecFwk::InsightIntentExecuteParam & executeParam)277 int32_t InsightAdapter::StartAVPlayback(AppExecFwk::InsightIntentExecuteParam &executeParam)
278 {
279 SLOGI("bundleName=%{public}s abilityName=%{public}s moduleName=%{public}s IntentName=%{public}s",
280 executeParam.bundleName_.c_str(), executeParam.abilityName_.c_str(),
281 executeParam.moduleName_.c_str(), executeParam.insightIntentName_.c_str());
282
283 sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
284 if (systemManager == nullptr) {
285 SLOGE("Fail to get registry");
286 return AVSESSION_ERROR;
287 }
288 sptr<IRemoteObject> remote = systemManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
289 if (remote == nullptr) {
290 SLOGE("Fail to connect ability manager service");
291 return AVSESSION_ERROR;
292 }
293
294 bool ret = ExecuteIntentFromAVSession((uint64_t) AVSESSION_SERVICE_ID, remote, executeParam);
295 if (!ret) {
296 SLOGE("ExecuteIntent insightIntent=%{public}s fail", executeParam.insightIntentName_.c_str());
297 return AVSESSION_ERROR;
298 }
299 return AVSESSION_SUCCESS;
300 }
301
IsSupportPlayIntent(const std::string & bundleName,const std::string & assetId)302 extern "C" bool IsSupportPlayIntent(const std::string& bundleName, const std::string& assetId)
303 {
304 AppExecFwk::InsightIntentExecuteParam executeParam;
305 return InsightAdapter::GetInsightAdapterInstance().GetPlayIntentParam(bundleName, assetId, executeParam);
306 }
307
StartAVPlaybackWithId(const std::string & bundleName,const std::string & assetId,const StartPlayInfo startPlayInfo,StartPlayType startPlayType)308 extern "C" int32_t StartAVPlaybackWithId(const std::string& bundleName, const std::string& assetId,
309 const StartPlayInfo startPlayInfo, StartPlayType startPlayType)
310 {
311 AppExecFwk::InsightIntentExecuteParam executeParam;
312 bool isSupport = InsightAdapter::GetInsightAdapterInstance().GetPlayIntentParam(bundleName, assetId,
313 executeParam, startPlayInfo, startPlayType);
314 if (isSupport) {
315 return InsightAdapter::GetInsightAdapterInstance().StartAVPlayback(executeParam);
316 }
317 return AVSESSION_SUCCESS;
318 }
319
StartAVPlayback(const std::string & bundleName,const std::string & assetId)320 extern "C" int32_t StartAVPlayback(const std::string& bundleName, const std::string& assetId)
321 {
322 AppExecFwk::InsightIntentExecuteParam executeParam;
323 bool isSupport = InsightAdapter::GetInsightAdapterInstance().GetPlayIntentParam(bundleName, assetId, executeParam);
324 if (isSupport) {
325 return InsightAdapter::GetInsightAdapterInstance().StartAVPlayback(executeParam);
326 }
327 return AVSESSION_SUCCESS;
328 }
329 }
330