1 /*
2 * Copyright (c) 2022-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_distributed_manager.h"
17
18 #include "bundle_manager_callback.h"
19 #include "bundle_memory_guard.h"
20 #include "bundle_mgr_service.h"
21 #include "syscap_interface.h"
22
23 #ifdef BMS_DEVICE_INFO_MANAGER_ENABLE
24 #include "distributed_device_profile_client.h"
25 #endif // BMS_DEVICE_INFO_MANAGER_ENABLE
26
27 namespace OHOS {
28 namespace AppExecFwk {
29 using namespace ffrt;
30 namespace {
31 const int32_t CHECK_ABILITY_ENABLE_INSTALL = 1;
32 const uint32_t OUT_TIME = 3000;
33 const std::string DISTRIBUTED_MANAGER_QUEUE = "DistributedManagerQueue";
34 const std::u16string DMS_BUNDLE_MANAGER_CALLBACK_TOKEN = u"ohos.DistributedSchedule.IDmsBundleManagerCallback";
35 const std::u16string SERVICE_CENTER_TOKEN = u"abilitydispatcherhm.openapi.hapinstall.IHapInstall";
36 // syscap
37 constexpr const char* CHARACTER_OS_SYSCAP = "ossyscap";
38 constexpr const char* CHARACTER_PRIVATE_SYSCAP = "privatesyscap";
39 }
40
BundleDistributedManager()41 BundleDistributedManager::BundleDistributedManager()
42 {
43 APP_LOGD("create BundleDistributedManager");
44 serialQueue_ = std::make_shared<SerialQueue>(DISTRIBUTED_MANAGER_QUEUE);
45 }
46
~BundleDistributedManager()47 BundleDistributedManager::~BundleDistributedManager()
48 {
49 APP_LOGD("destroy BundleDistributedManager");
50 }
51
ConvertTargetAbilityInfo(const Want & want,TargetAbilityInfo & targetAbilityInfo)52 bool BundleDistributedManager::ConvertTargetAbilityInfo(const Want &want, TargetAbilityInfo &targetAbilityInfo)
53 {
54 auto elementName = want.GetElement();
55 std::string bundleName = elementName.GetBundleName();
56 std::string moduleName = elementName.GetModuleName();
57 std::string abilityName = elementName.GetAbilityName();
58 APP_LOGI("ConvertTargetAbilityInfo %{public}s, %{public}s, %{public}s",
59 bundleName.c_str(), moduleName.c_str(), abilityName.c_str());
60 AppExecFwk::TargetInfo targetInfo;
61 targetInfo.transactId = std::to_string(this->GetTransactId());
62 targetInfo.bundleName = bundleName;
63 targetInfo.moduleName = moduleName;
64 targetInfo.abilityName = abilityName;
65 targetAbilityInfo.targetInfo = targetInfo;
66 return true;
67 }
68
ComparePcIdString(const Want & want,const RpcIdResult & rpcIdResult)69 int32_t BundleDistributedManager::ComparePcIdString(const Want &want, const RpcIdResult &rpcIdResult)
70 {
71 #ifdef BMS_DEVICE_INFO_MANAGER_ENABLE
72 DistributedDeviceProfile::DeviceProfile profile;
73 int32_t result = DistributedDeviceProfile::DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(
74 want.GetElement().GetDeviceID(), profile);
75 if (result != 0) {
76 APP_LOGE("GetDeviceProfile failed %{public}d", result);
77 return ErrorCode::GET_DEVICE_PROFILE_FAILED;
78 }
79 std::string jsonData = profile.GetOsSysCap();
80 APP_LOGI("CharacteristicProfileJson:%{public}s", jsonData.c_str());
81 nlohmann::json jsonObject = nlohmann::json::parse(jsonData, nullptr, false);
82 if (jsonObject.is_discarded()) {
83 APP_LOGE("jsonObject is_discarded");
84 return ErrorCode::DECODE_SYS_CAP_FAILED;
85 }
86 if ((jsonObject.find(CHARACTER_OS_SYSCAP) == jsonObject.end()) ||
87 (jsonObject.find(CHARACTER_PRIVATE_SYSCAP) == jsonObject.end())) {
88 APP_LOGE("ossyscap no exist ");
89 return ErrorCode::DECODE_SYS_CAP_FAILED;
90 }
91 std::vector<int> values = jsonObject[CHARACTER_OS_SYSCAP].get<std::vector<int>>();
92 std::string pcId;
93 for (int value : values) {
94 pcId = pcId + std::to_string(value) + ",";
95 }
96 std::string capabilities = jsonObject[CHARACTER_PRIVATE_SYSCAP];
97 if (capabilities.empty()) {
98 pcId.resize(pcId.length() - 1);
99 } else {
100 pcId = pcId + capabilities;
101 }
102 APP_LOGD("sysCap pcId:%{public}s", pcId.c_str());
103 for (auto &rpcId : rpcIdResult.abilityInfo.rpcId) {
104 APP_LOGD("sysCap rpcId:%{public}s", rpcId.c_str());
105 CompareError compareError = {{0}, 0, 0};
106 int32_t ret = ComparePcidString(pcId.c_str(), rpcId.c_str(), &compareError);
107 if (ret != 0) {
108 APP_LOGE("ComparePcIdString failed err %{public}d", ret);
109 return ErrorCode::COMPARE_PC_ID_FAILED;
110 }
111 }
112 return ErrorCode::NO_ERROR;
113 #else
114 APP_LOGW("BMS_DEVICE_INFO_MANAGER_ENABLE is false");
115 return ErrorCode::ERR_BMS_DEVICE_INFO_MANAGER_ENABLE_DISABLED;
116 #endif
117 }
118
CheckAbilityEnableInstall(const Want & want,int32_t missionId,int32_t userId,const sptr<IRemoteObject> & callback)119 bool BundleDistributedManager::CheckAbilityEnableInstall(
120 const Want &want, int32_t missionId, int32_t userId, const sptr<IRemoteObject> &callback)
121 {
122 APP_LOGI("BundleDistributedManager::CheckAbilityEnableInstall");
123 AppExecFwk::TargetAbilityInfo targetAbilityInfo;
124 if (!ConvertTargetAbilityInfo(want, targetAbilityInfo)) {
125 return false;
126 }
127 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
128 if (dataMgr == nullptr) {
129 APP_LOGE("fail to get data mgr");
130 return false;
131 }
132 ApplicationInfo applicationInfo;
133 if (!dataMgr->GetApplicationInfo(
134 targetAbilityInfo.targetInfo.bundleName, 0, userId, applicationInfo)) {
135 APP_LOGE("fail get bundleName %{public}s", targetAbilityInfo.targetInfo.bundleName.c_str());
136 return false;
137 }
138 sptr<QueryRpcIdParams> queryRpcIdParams = new(std::nothrow) QueryRpcIdParams();
139 if (queryRpcIdParams == nullptr) {
140 APP_LOGE("queryRpcIdParams is nullptr");
141 return false;
142 }
143 queryRpcIdParams->missionId = missionId;
144 queryRpcIdParams->callback = callback;
145 queryRpcIdParams->want = want;
146 queryRpcIdParams->versionCode = applicationInfo.versionCode;
147 {
148 std::unique_lock<std::shared_mutex> lock(mutex_);
149 auto ret = queryAbilityParamsMap_.emplace(targetAbilityInfo.targetInfo.transactId, *queryRpcIdParams);
150 if (!ret.second) {
151 APP_LOGE("BundleDistributedManager::QueryAbilityInfo map emplace error");
152 return false;
153 }
154 }
155 auto queryRpcIdByAbilityFunc = [this, targetAbilityInfo]() {
156 BundleMemoryGuard memoryGuard;
157 auto res = this->QueryRpcIdByAbilityToServiceCenter(targetAbilityInfo);
158 if (!res) {
159 SendCallbackRequest(ErrorCode::WAITING_TIMEOUT, targetAbilityInfo.targetInfo.transactId);
160 }
161 };
162 ffrt::submit(queryRpcIdByAbilityFunc);
163 return true;
164 }
165
QueryRpcIdByAbilityToServiceCenter(const TargetAbilityInfo & targetAbilityInfo)166 bool BundleDistributedManager::QueryRpcIdByAbilityToServiceCenter(const TargetAbilityInfo &targetAbilityInfo)
167 {
168 APP_LOGI("QueryRpcIdByAbilityToServiceCenter");
169 auto connectAbility = DelayedSingleton<BundleMgrService>::GetInstance()->GetConnectAbility();
170 if (connectAbility == nullptr) {
171 APP_LOGE("fail to connect ServiceCenter");
172 return false;
173 }
174 std::shared_ptr<BundleMgrService> bms = DelayedSingleton<BundleMgrService>::GetInstance();
175 std::shared_ptr<BundleDataMgr> bundleDataMgr_ = bms->GetDataMgr();
176 if (bundleDataMgr_ == nullptr) {
177 APP_LOGE("GetDataMgr failed, bundleDataMgr_ is nullptr");
178 SendCallbackRequest(ErrorCode::WAITING_TIMEOUT, targetAbilityInfo.targetInfo.transactId);
179 return true;
180 }
181 std::string bundleName;
182 std::string abilityName;
183 if (!(bundleDataMgr_->QueryAppGalleryAbilityName(bundleName, abilityName))) {
184 APP_LOGE("Fail to query ServiceCenter ability and bundle name");
185 SendCallbackRequest(ErrorCode::CONNECT_FAILED, targetAbilityInfo.targetInfo.transactId);
186 return true;
187 }
188 Want serviceCenterWant;
189 serviceCenterWant.SetElementName(bundleName, abilityName);
190 bool ret = connectAbility->ConnectAbility(serviceCenterWant, nullptr);
191 if (!ret) {
192 APP_LOGE("fail to connect ServiceCenter");
193 SendCallbackRequest(ErrorCode::CONNECT_FAILED, targetAbilityInfo.targetInfo.transactId);
194 return true;
195 }
196 const std::string targetInfo = GetJsonStrFromInfo(targetAbilityInfo);
197 APP_LOGI("queryRpcId param %{public}s", targetInfo.c_str());
198 MessageParcel data;
199 MessageParcel reply;
200 MessageOption option(MessageOption::TF_ASYNC);
201 if (!data.WriteInterfaceToken(SERVICE_CENTER_TOKEN)) {
202 APP_LOGE("failed to sendCallback due to write MessageParcel fail");
203 return false;
204 }
205 if (!data.WriteString16(Str8ToStr16(targetInfo))) {
206 APP_LOGE("WriteString16 failed");
207 return false;
208 }
209 sptr<BundleManagerCallback> bundleManagerCallback = new(std::nothrow) BundleManagerCallback(weak_from_this());
210 if (bundleManagerCallback == nullptr) {
211 APP_LOGE("bundleManagerCallback is nullptr");
212 return false;
213 }
214 if (!data.WriteRemoteObject(bundleManagerCallback)) {
215 APP_LOGE("failed to write remote object");
216 return false;
217 }
218 ret = connectAbility->SendRequest(ServiceCenterFunction::CONNECT_QUERY_RPCID, data, reply);
219 if (!ret) {
220 APP_LOGE("send request to serviceCenter failed");
221 SendCallbackRequest(ErrorCode::SEND_REQUEST_FAILED, targetAbilityInfo.targetInfo.transactId);
222 return true;
223 }
224 OutTimeMonitor(targetAbilityInfo.targetInfo.transactId);
225 return true;
226 }
227
OutTimeMonitor(const std::string transactId)228 void BundleDistributedManager::OutTimeMonitor(const std::string transactId)
229 {
230 APP_LOGI("BundleDistributedManager::OutTimeMonitor");
231 auto registerEventListenerFunc = [this, transactId]() {
232 BundleMemoryGuard memoryGuard;
233 APP_LOGI("RegisterEventListenerFunc transactId:%{public}s", transactId.c_str());
234 this->SendCallbackRequest(ErrorCode::WAITING_TIMEOUT, transactId);
235 };
236 serialQueue_->ScheduleDelayTask(transactId, OUT_TIME, registerEventListenerFunc);
237 }
238
OnQueryRpcIdFinished(const std::string & queryRpcIdResult)239 void BundleDistributedManager::OnQueryRpcIdFinished(const std::string &queryRpcIdResult)
240 {
241 RpcIdResult rpcIdResult;
242 APP_LOGI("queryRpcIdResult:%{public}s", queryRpcIdResult.c_str());
243 if (!ParseInfoFromJsonStr(queryRpcIdResult.c_str(), rpcIdResult)) {
244 APP_LOGE("Parse info from json fail");
245 return;
246 }
247 Want want;
248 {
249 std::shared_lock<std::shared_mutex> lock(mutex_);
250 auto queryAbilityParams = queryAbilityParamsMap_.find(rpcIdResult.transactId);
251 if (queryAbilityParams == queryAbilityParamsMap_.end()) {
252 APP_LOGE("no node");
253 return;
254 }
255 want = queryAbilityParams->second.want;
256 }
257 serialQueue_->CancelDelayTask(rpcIdResult.transactId);
258 if (rpcIdResult.retCode != 0) {
259 APP_LOGE("query RpcId fail%{public}d", rpcIdResult.retCode);
260 SendCallbackRequest(rpcIdResult.retCode, rpcIdResult.transactId);
261 return;
262 }
263 int32_t ret = ComparePcIdString(want, rpcIdResult);
264 if (ret != 0) {
265 APP_LOGE("Compare pcId fail%{public}d", ret);
266 }
267 SendCallbackRequest(ret, rpcIdResult.transactId);
268 }
269
SendCallbackRequest(int32_t resultCode,const std::string & transactId)270 void BundleDistributedManager::SendCallbackRequest(int32_t resultCode, const std::string &transactId)
271 {
272 APP_LOGI("sendCallbackRequest resultCode:%{public}d, transactId:%{public}s", resultCode, transactId.c_str());
273 QueryRpcIdParams queryRpcIdParams;
274 {
275 std::shared_lock<std::shared_mutex> lock(mutex_);
276 auto queryAbilityParams = queryAbilityParamsMap_.find(transactId);
277 if (queryAbilityParams == queryAbilityParamsMap_.end()) {
278 APP_LOGE("Can not find transactId:%{public}s in queryAbilityParamsMap", transactId.c_str());
279 return;
280 }
281 queryRpcIdParams = queryAbilityParams->second;
282 }
283 SendCallback(resultCode, queryRpcIdParams);
284
285 uint32_t mapSize;
286 {
287 std::unique_lock<std::shared_mutex> lock(mutex_);
288 queryAbilityParamsMap_.erase(transactId);
289 mapSize = queryAbilityParamsMap_.size();
290 }
291
292 if (mapSize == 0) {
293 auto connectAbility = DelayedSingleton<BundleMgrService>::GetInstance()->GetConnectAbility();
294 if (connectAbility == nullptr) {
295 APP_LOGW("fail to connect ServiceCenter");
296 return;
297 }
298 connectAbility->DisconnectAbility();
299 }
300 }
301
SendCallback(int32_t resultCode,const QueryRpcIdParams & queryRpcIdParams)302 void BundleDistributedManager::SendCallback(int32_t resultCode, const QueryRpcIdParams &queryRpcIdParams)
303 {
304 auto remoteObject = queryRpcIdParams.callback;
305 if (remoteObject == nullptr) {
306 APP_LOGW("sendCallbackRequest remoteObject is invalid");
307 return;
308 }
309 MessageParcel data;
310 if (!data.WriteInterfaceToken(DMS_BUNDLE_MANAGER_CALLBACK_TOKEN)) {
311 APP_LOGE("failed to sendCallback due to write MessageParcel fail");
312 return;
313 }
314 if (!data.WriteInt32(resultCode)) {
315 APP_LOGE("fail to sendCallback due to write resultCode fail");
316 return;
317 }
318 if (!data.WriteUint32(queryRpcIdParams.versionCode)) {
319 APP_LOGE("fail to sendCallback due to write versionCode fail");
320 return;
321 }
322 if (!data.WriteInt32(queryRpcIdParams.missionId)) {
323 APP_LOGE("fail to sendCallback due to write missionId fail");
324 return;
325 }
326 MessageParcel reply;
327 MessageOption option(MessageOption::TF_SYNC);
328 int32_t result = remoteObject->SendRequest(CHECK_ABILITY_ENABLE_INSTALL, data, reply, option);
329 if (result != 0) {
330 APP_LOGE("failed send request code %{public}d", result);
331 }
332 }
333 } // namespace AppExecFwk
334 } // namespace OHOS
335