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