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