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