1 /*
2  * Copyright (c) 2022-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 #include "bundle_mgr_client_impl.h"
16 
17 #include <cerrno>
18 #include <fstream>
19 #include <unistd.h>
20 
21 #include "app_log_wrapper.h"
22 #include "app_log_tag_wrapper.h"
23 #include "bundle_constants.h"
24 #include "bundle_mgr_interface.h"
25 #include "bundle_mgr_proxy.h"
26 #include "bundle_mgr_service_death_recipient.h"
27 #include "iservice_registry.h"
28 #include "nlohmann/json.hpp"
29 #include "system_ability_definition.h"
30 
31 #ifdef GLOBAL_RESMGR_ENABLE
32 using namespace OHOS::Global::Resource;
33 #endif
34 
35 namespace OHOS {
36 namespace AppExecFwk {
37 namespace {
38 const char* BUNDLE_MAP_CODE_PATH = "/data/storage/el1/bundle";
39 const char* DATA_APP_PATH = "/data/app";
40 #ifdef GLOBAL_RESMGR_ENABLE
41 constexpr const char* PROFILE_FILE_PREFIX = "$profile:";
42 #endif
43 const char* PATH_SEPARATOR = "/";
44 } // namespace
45 
BundleMgrClientImpl()46 BundleMgrClientImpl::BundleMgrClientImpl()
47 {
48     APP_LOGD("create bundleMgrClientImpl");
49 }
50 
~BundleMgrClientImpl()51 BundleMgrClientImpl::~BundleMgrClientImpl()
52 {
53     APP_LOGD("destroy bundleMgrClientImpl");
54     std::unique_lock<std::shared_mutex> lock(mutex_);
55     if (bundleMgr_ != nullptr && deathRecipient_ != nullptr) {
56         bundleMgr_->AsObject()->RemoveDeathRecipient(deathRecipient_);
57     }
58 }
59 
GetNameForUid(const int uid,std::string & name)60 ErrCode BundleMgrClientImpl::GetNameForUid(const int uid, std::string &name)
61 {
62     if (Connect() != ERR_OK) {
63         APP_LOGE("failed to connect");
64         return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR;
65     }
66     std::shared_lock<std::shared_mutex> lock(mutex_);
67     return bundleMgr_->GetNameForUid(uid, name);
68 }
69 
GetBundleInfo(const std::string & bundleName,const BundleFlag flag,BundleInfo & bundleInfo,int32_t userId)70 bool BundleMgrClientImpl::GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo,
71     int32_t userId)
72 {
73     LOG_D(BMS_TAG_QUERY, "GetBundleInfo begin");
74 
75     ErrCode result = Connect();
76     if (result != ERR_OK) {
77         LOG_E(BMS_TAG_QUERY, "failed to connect");
78         return false;
79     }
80 
81     std::shared_lock<std::shared_mutex> lock(mutex_);
82     return bundleMgr_->GetBundleInfo(bundleName, flag, bundleInfo, userId);
83 }
84 
GetBundlePackInfo(const std::string & bundleName,const BundlePackFlag flag,BundlePackInfo & bundlePackInfo,int32_t userId)85 ErrCode BundleMgrClientImpl::GetBundlePackInfo(
86     const std::string &bundleName, const BundlePackFlag flag, BundlePackInfo &bundlePackInfo, int32_t userId)
87 {
88     APP_LOGD("enter");
89     ErrCode result = Connect();
90     if (result != ERR_OK) {
91         APP_LOGE("failed to connect");
92         return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR;
93     }
94     std::shared_lock<std::shared_mutex> lock(mutex_);
95     return bundleMgr_->GetBundlePackInfo(bundleName, flag, bundlePackInfo, userId);
96 }
97 
CreateBundleDataDir(int32_t userId)98 ErrCode BundleMgrClientImpl::CreateBundleDataDir(int32_t userId)
99 {
100     APP_LOGD("enter");
101     ErrCode result = Connect();
102     if (result != ERR_OK) {
103         APP_LOGE("failed to connect");
104         return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR;
105     }
106     std::shared_lock<std::shared_mutex> lock(mutex_);
107     return bundleMgr_->CreateBundleDataDir(userId);
108 }
109 
GetHapModuleInfo(const std::string & bundleName,const std::string & hapName,HapModuleInfo & hapModuleInfo)110 bool BundleMgrClientImpl::GetHapModuleInfo(const std::string &bundleName, const std::string &hapName,
111     HapModuleInfo &hapModuleInfo)
112 {
113     ErrCode result = Connect();
114     if (result != ERR_OK) {
115         APP_LOGE("failed to connect");
116         return false;
117     }
118 
119     AbilityInfo info;
120     info.bundleName = bundleName;
121     info.package = hapName;
122     std::shared_lock<std::shared_mutex> lock(mutex_);
123     return bundleMgr_->GetHapModuleInfo(info, hapModuleInfo);
124 }
125 
GetResConfigFile(const HapModuleInfo & hapModuleInfo,const std::string & metadataName,std::vector<std::string> & profileInfos) const126 bool BundleMgrClientImpl::GetResConfigFile(const HapModuleInfo &hapModuleInfo, const std::string &metadataName,
127     std::vector<std::string> &profileInfos) const
128 {
129     bool isCompressed = !hapModuleInfo.hapPath.empty();
130     std::string resourcePath = isCompressed ? hapModuleInfo.hapPath : hapModuleInfo.resourcePath;
131     if (!GetResProfileByMetadata(hapModuleInfo.metadata, metadataName, resourcePath, isCompressed, profileInfos)) {
132         APP_LOGE("GetResProfileByMetadata failed");
133         return false;
134     }
135     if (profileInfos.empty()) {
136         APP_LOGE("no valid file can be obtained");
137         return false;
138     }
139     int32_t InfoSize = static_cast<int32_t>(profileInfos.size());
140     APP_LOGD("The size of the profile info is : %{public}d", InfoSize);
141     return true;
142 }
143 
GetResConfigFile(const ExtensionAbilityInfo & extensionInfo,const std::string & metadataName,std::vector<std::string> & profileInfos) const144 bool BundleMgrClientImpl::GetResConfigFile(const ExtensionAbilityInfo &extensionInfo, const std::string &metadataName,
145     std::vector<std::string> &profileInfos) const
146 {
147     bool isCompressed = !extensionInfo.hapPath.empty();
148     std::string resourcePath = isCompressed ? extensionInfo.hapPath : extensionInfo.resourcePath;
149     if (!GetResProfileByMetadata(extensionInfo.metadata, metadataName, resourcePath, isCompressed, profileInfos)) {
150         APP_LOGE("GetResProfileByMetadata failed");
151         return false;
152     }
153     if (profileInfos.empty()) {
154         APP_LOGE("no valid file can be obtained");
155         return false;
156     }
157     int32_t InfoSize = static_cast<int32_t>(profileInfos.size());
158     APP_LOGD("The size of the profile info is : %{public}d", InfoSize);
159     return true;
160 }
161 
GetResConfigFile(const AbilityInfo & abilityInfo,const std::string & metadataName,std::vector<std::string> & profileInfos) const162 bool BundleMgrClientImpl::GetResConfigFile(const AbilityInfo &abilityInfo, const std::string &metadataName,
163     std::vector<std::string> &profileInfos) const
164 {
165     bool isCompressed = !abilityInfo.hapPath.empty();
166     std::string resourcePath = isCompressed ? abilityInfo.hapPath : abilityInfo.resourcePath;
167     if (!GetResProfileByMetadata(abilityInfo.metadata, metadataName, resourcePath, isCompressed, profileInfos)) {
168         APP_LOGE("GetResProfileByMetadata failed");
169         return false;
170     }
171     if (profileInfos.empty()) {
172         APP_LOGE("no valid file can be obtained");
173         return false;
174     }
175     return true;
176 }
177 
GetProfileFromExtension(const ExtensionAbilityInfo & extensionInfo,const std::string & metadataName,std::vector<std::string> & profileInfos) const178 bool BundleMgrClientImpl::GetProfileFromExtension(const ExtensionAbilityInfo &extensionInfo,
179     const std::string &metadataName, std::vector<std::string> &profileInfos) const
180 {
181     APP_LOGD("get extension config file from extension dir begin");
182     bool isCompressed = !extensionInfo.hapPath.empty();
183     std::string resPath = isCompressed ? extensionInfo.hapPath : extensionInfo.resourcePath;
184     if (!ConvertResourcePath(extensionInfo.bundleName, resPath, isCompressed)) {
185         APP_LOGE("ConvertResourcePath failed %{public}s", resPath.c_str());
186         return false;
187     }
188     ExtensionAbilityInfo innerExtension = extensionInfo;
189     if (isCompressed) {
190         innerExtension.hapPath = resPath;
191     } else {
192         innerExtension.resourcePath = resPath;
193     }
194     return GetResConfigFile(innerExtension, metadataName, profileInfos);
195 }
196 
GetProfileFromAbility(const AbilityInfo & abilityInfo,const std::string & metadataName,std::vector<std::string> & profileInfos) const197 bool BundleMgrClientImpl::GetProfileFromAbility(const AbilityInfo &abilityInfo, const std::string &metadataName,
198     std::vector<std::string> &profileInfos) const
199 {
200     APP_LOGD("get ability config file from ability begin");
201     bool isCompressed = !abilityInfo.hapPath.empty();
202     std::string resPath = isCompressed ? abilityInfo.hapPath : abilityInfo.resourcePath;
203     if (!ConvertResourcePath(abilityInfo.bundleName, resPath, isCompressed)) {
204         APP_LOGE("ConvertResourcePath failed %{public}s", resPath.c_str());
205         return false;
206     }
207     AbilityInfo innerAbilityInfo = abilityInfo;
208     if (isCompressed) {
209         innerAbilityInfo.hapPath = resPath;
210     } else {
211         innerAbilityInfo.resourcePath = resPath;
212     }
213     return GetResConfigFile(innerAbilityInfo, metadataName, profileInfos);
214 }
215 
GetProfileFromHap(const HapModuleInfo & hapModuleInfo,const std::string & metadataName,std::vector<std::string> & profileInfos) const216 bool BundleMgrClientImpl::GetProfileFromHap(const HapModuleInfo &hapModuleInfo, const std::string &metadataName,
217     std::vector<std::string> &profileInfos) const
218 {
219     APP_LOGD("get hap module config file from hap begin");
220     bool isCompressed = !hapModuleInfo.hapPath.empty();
221     std::string resPath = isCompressed ? hapModuleInfo.hapPath : hapModuleInfo.resourcePath;
222     if (!ConvertResourcePath(hapModuleInfo.bundleName, resPath, isCompressed)) {
223         APP_LOGE("ConvertResourcePath failed %{public}s", resPath.c_str());
224         return false;
225     }
226     HapModuleInfo innerHapModuleInfo = hapModuleInfo;
227     if (isCompressed) {
228         innerHapModuleInfo.hapPath = resPath;
229     } else {
230         innerHapModuleInfo.resourcePath = resPath;
231     }
232     return GetResConfigFile(innerHapModuleInfo, metadataName, profileInfos);
233 }
234 
ConvertResourcePath(const std::string & bundleName,std::string & resPath,bool isCompressed) const235 bool BundleMgrClientImpl::ConvertResourcePath(
236     const std::string &bundleName, std::string &resPath, bool isCompressed) const
237 {
238     if (resPath.empty()) {
239         APP_LOGE("res path is empty");
240         return false;
241     }
242     if (isCompressed && (resPath.find(DATA_APP_PATH) != 0)) {
243         APP_LOGD("no need to convert to sandbox path");
244         return true;
245     }
246     std::string innerStr = std::string(Constants::BUNDLE_CODE_DIR) + std::string(PATH_SEPARATOR) + bundleName;
247     if (resPath.find(innerStr) == std::string::npos) {
248         APP_LOGE("res path is incorrect");
249         return false;
250     }
251     resPath.replace(0, innerStr.length(), BUNDLE_MAP_CODE_PATH);
252     return true;
253 }
254 
GetResProfileByMetadata(const std::vector<Metadata> & metadata,const std::string & metadataName,const std::string & resourcePath,bool isCompressed,std::vector<std::string> & profileInfos) const255 bool BundleMgrClientImpl::GetResProfileByMetadata(const std::vector<Metadata> &metadata,
256     const std::string &metadataName, const std ::string &resourcePath, bool isCompressed,
257     std::vector<std::string> &profileInfos) const
258 {
259 #ifdef GLOBAL_RESMGR_ENABLE
260     if (metadata.empty()) {
261         APP_LOGE("GetResProfileByMetadata failed due to empty metadata");
262         return false;
263     }
264     if (resourcePath.empty()) {
265         APP_LOGE("GetResProfileByMetadata failed due to empty resourcePath");
266         return false;
267     }
268     std::shared_ptr<ResourceManager> resMgr = InitResMgr(resourcePath);
269     if (resMgr == nullptr) {
270         APP_LOGE("GetResProfileByMetadata init resMgr failed");
271         return false;
272     }
273 
274     if (metadataName.empty()) {
275         for_each(metadata.begin(), metadata.end(),
276             [this, &resMgr, isCompressed, &profileInfos](const Metadata& data)->void {
277             if (!GetResFromResMgr(data.resource, resMgr, isCompressed, profileInfos)) {
278                 APP_LOGW("GetResFromResMgr failed");
279             }
280         });
281     } else {
282         for_each(metadata.begin(), metadata.end(),
283             [this, &resMgr, &metadataName, isCompressed, &profileInfos](const Metadata& data)->void {
284             if ((metadataName.compare(data.name) == 0)
285                 && (!GetResFromResMgr(data.resource, resMgr, isCompressed, profileInfos))) {
286                 APP_LOGW("GetResFromResMgr failed");
287             }
288         });
289     }
290 
291     return true;
292 #else
293     APP_LOGW("GLOBAL_RESMGR_ENABLE is false");
294     return false;
295 #endif
296 }
297 
298 #ifdef GLOBAL_RESMGR_ENABLE
InitResMgr(const std::string & resourcePath) const299 std::shared_ptr<ResourceManager> BundleMgrClientImpl::InitResMgr(const std::string &resourcePath) const
300 {
301     APP_LOGD("InitResMgr begin");
302     if (resourcePath.empty()) {
303         APP_LOGE("InitResMgr failed due to invalid param");
304         return nullptr;
305     }
306     std::shared_ptr<ResourceManager> resMgr(CreateResourceManager());
307     if (!resMgr) {
308         APP_LOGE("InitResMgr resMgr is nullptr");
309         return nullptr;
310     }
311 
312     std::unique_ptr<ResConfig> resConfig(CreateResConfig());
313     if (!resConfig) {
314         APP_LOGE("InitResMgr resConfig is nullptr");
315         return nullptr;
316     }
317     resMgr->UpdateResConfig(*resConfig);
318 
319     APP_LOGD("resourcePath is %{private}s", resourcePath.c_str());
320     if (!resourcePath.empty() && !resMgr->AddResource(resourcePath.c_str())) {
321         APP_LOGE("InitResMgr AddResource failed");
322         return nullptr;
323     }
324     return resMgr;
325 }
326 
GetResFromResMgr(const std::string & resName,const std::shared_ptr<ResourceManager> & resMgr,bool isCompressed,std::vector<std::string> & profileInfos) const327 bool BundleMgrClientImpl::GetResFromResMgr(const std::string &resName, const std::shared_ptr<ResourceManager> &resMgr,
328     bool isCompressed, std::vector<std::string> &profileInfos) const
329 {
330     APP_LOGD("GetResFromResMgr begin");
331     if (resName.empty()) {
332         APP_LOGE("GetResFromResMgr res name is empty");
333         return false;
334     }
335 
336     size_t pos = resName.rfind(PROFILE_FILE_PREFIX);
337     if ((pos == std::string::npos) || (pos == resName.length() - strlen(PROFILE_FILE_PREFIX))) {
338         APP_LOGE("GetResFromResMgr res name %{public}s invalid", resName.c_str());
339         return false;
340     }
341     std::string profileName = resName.substr(pos + strlen(PROFILE_FILE_PREFIX));
342     // hap is compressed status, get file content.
343     if (isCompressed) {
344         APP_LOGD("compressed status");
345         std::unique_ptr<uint8_t[]> fileContentPtr = nullptr;
346         size_t len = 0;
347         if (resMgr->GetProfileDataByName(profileName.c_str(), len, fileContentPtr) != SUCCESS) {
348             APP_LOGE("GetProfileDataByName failed");
349             return false;
350         }
351         if (fileContentPtr == nullptr || len == 0) {
352             APP_LOGE("invalid data");
353             return false;
354         }
355         std::string rawData(fileContentPtr.get(), fileContentPtr.get() + len);
356         nlohmann::json profileJson = nlohmann::json::parse(rawData, nullptr, false);
357         if (profileJson.is_discarded()) {
358             APP_LOGE("bad profile file");
359             return false;
360         }
361         profileInfos.emplace_back(profileJson.dump());
362         return true;
363     }
364     // hap is decompressed status, get file path then read file.
365     std::string resPath;
366     if (resMgr->GetProfileByName(profileName.c_str(), resPath) != SUCCESS) {
367         APP_LOGE("GetResFromResMgr profileName cannot be found");
368         return false;
369     }
370     APP_LOGD("GetResFromResMgr resPath is %{private}s", resPath.c_str());
371     std::string profile;
372     if (!TransformFileToJsonString(resPath, profile)) {
373         return false;
374     }
375     profileInfos.emplace_back(profile);
376     return true;
377 }
378 #endif
379 
IsFileExisted(const std::string & filePath) const380 bool BundleMgrClientImpl::IsFileExisted(const std::string &filePath) const
381 {
382     if (filePath.empty()) {
383         APP_LOGE("the file is not existed due to empty file path");
384         return false;
385     }
386 
387     if (access(filePath.c_str(), F_OK) != 0) {
388         APP_LOGE("not access file: %{private}s errno: %{public}d", filePath.c_str(), errno);
389         return false;
390     }
391     return true;
392 }
393 
TransformFileToJsonString(const std::string & resPath,std::string & profile) const394 bool BundleMgrClientImpl::TransformFileToJsonString(const std::string &resPath, std::string &profile) const
395 {
396     if (!IsFileExisted(resPath)) {
397         APP_LOGE("the file is not existed");
398         return false;
399     }
400     std::fstream in;
401     char errBuf[256];
402     errBuf[0] = '\0';
403     in.open(resPath, std::ios_base::in | std::ios_base::binary);
404     if (!in.is_open()) {
405         strerror_r(errno, errBuf, sizeof(errBuf));
406         APP_LOGE("file open fail due to %{public}s errno:%{public}d", errBuf, errno);
407         return false;
408     }
409     in.seekg(0, std::ios::end);
410     int64_t size = in.tellg();
411     if (size <= 0) {
412         APP_LOGE("file empty err %{public}d", errno);
413         in.close();
414         return false;
415     }
416     in.seekg(0, std::ios::beg);
417     nlohmann::json profileJson = nlohmann::json::parse(in, nullptr, false);
418     if (profileJson.is_discarded()) {
419         APP_LOGE("bad profile file");
420         in.close();
421         return false;
422     }
423     profile = profileJson.dump();
424     in.close();
425     return true;
426 }
427 
InstallSandboxApp(const std::string & bundleName,int32_t dlpType,int32_t userId,int32_t & appIndex)428 ErrCode BundleMgrClientImpl::InstallSandboxApp(const std::string &bundleName, int32_t dlpType, int32_t userId,
429     int32_t &appIndex)
430 {
431     APP_LOGD("InstallSandboxApp begin");
432     if (bundleName.empty()) {
433         APP_LOGE("InstallSandboxApp bundleName is empty");
434         return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
435     }
436     ErrCode result = Connect();
437     if (result != ERR_OK) {
438         APP_LOGE("failed to connect");
439         return ERR_APPEXECFWK_SANDBOX_INSTALL_INTERNAL_ERROR;
440     }
441 
442     std::shared_lock<std::shared_mutex> lock(mutex_);
443     return bundleInstaller_->InstallSandboxApp(bundleName, dlpType, userId, appIndex);
444 }
445 
UninstallSandboxApp(const std::string & bundleName,int32_t appIndex,int32_t userId)446 ErrCode BundleMgrClientImpl::UninstallSandboxApp(const std::string &bundleName, int32_t appIndex, int32_t userId)
447 {
448     APP_LOGD("UninstallSandboxApp begin");
449     if (bundleName.empty() || appIndex <= Constants::INITIAL_SANDBOX_APP_INDEX) {
450         APP_LOGE("UninstallSandboxApp params are invalid");
451         return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
452     }
453     ErrCode result = Connect();
454     if (result != ERR_OK) {
455         APP_LOGE("failed to connect");
456         return ERR_APPEXECFWK_SANDBOX_INSTALL_INTERNAL_ERROR;
457     }
458 
459     std::shared_lock<std::shared_mutex> lock(mutex_);
460     return bundleInstaller_->UninstallSandboxApp(bundleName, appIndex, userId);
461 }
462 
GetSandboxBundleInfo(const std::string & bundleName,int32_t appIndex,int32_t userId,BundleInfo & info)463 ErrCode BundleMgrClientImpl::GetSandboxBundleInfo(
464     const std::string &bundleName, int32_t appIndex, int32_t userId, BundleInfo &info)
465 {
466     APP_LOGD("GetSandboxBundleInfo begin");
467     if (bundleName.empty() || appIndex <= Constants::INITIAL_SANDBOX_APP_INDEX) {
468         APP_LOGE("UninstallSandboxApp params are invalid");
469         return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
470     }
471 
472     ErrCode result = Connect();
473     if (result != ERR_OK) {
474         APP_LOGE("failed to connect");
475         return ERR_APPEXECFWK_SANDBOX_INSTALL_INTERNAL_ERROR;
476     }
477     std::shared_lock<std::shared_mutex> lock(mutex_);
478     return bundleMgr_->GetSandboxBundleInfo(bundleName, appIndex, userId, info);
479 }
480 
GetSandboxAbilityInfo(const Want & want,int32_t appIndex,int32_t flags,int32_t userId,AbilityInfo & abilityInfo)481 ErrCode BundleMgrClientImpl::GetSandboxAbilityInfo(const Want &want, int32_t appIndex, int32_t flags, int32_t userId,
482     AbilityInfo &abilityInfo)
483 {
484     APP_LOGD("GetSandboxAbilityInfo begin");
485     if (appIndex <= Constants::INITIAL_SANDBOX_APP_INDEX || appIndex > Constants::MAX_SANDBOX_APP_INDEX) {
486         APP_LOGE("GetSandboxAbilityInfo params are invalid");
487         return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
488     }
489     ErrCode result = Connect();
490     if (result != ERR_OK) {
491         APP_LOGE("failed to connect");
492         return ERR_APPEXECFWK_SANDBOX_INSTALL_INTERNAL_ERROR;
493     }
494 
495     std::shared_lock<std::shared_mutex> lock(mutex_);
496     return bundleMgr_->GetSandboxAbilityInfo(want, appIndex, flags, userId, abilityInfo);
497 }
498 
GetSandboxExtAbilityInfos(const Want & want,int32_t appIndex,int32_t flags,int32_t userId,std::vector<ExtensionAbilityInfo> & extensionInfos)499 ErrCode BundleMgrClientImpl::GetSandboxExtAbilityInfos(const Want &want, int32_t appIndex, int32_t flags,
500     int32_t userId, std::vector<ExtensionAbilityInfo> &extensionInfos)
501 {
502     APP_LOGD("GetSandboxExtensionAbilityInfos begin");
503     if (appIndex <= Constants::INITIAL_SANDBOX_APP_INDEX || appIndex > Constants::MAX_SANDBOX_APP_INDEX) {
504         APP_LOGE("GetSandboxExtensionAbilityInfos params are invalid");
505         return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
506     }
507     ErrCode result = Connect();
508     if (result != ERR_OK) {
509         APP_LOGE("failed to connect");
510         return ERR_APPEXECFWK_SANDBOX_INSTALL_INTERNAL_ERROR;
511     }
512 
513     std::shared_lock<std::shared_mutex> lock(mutex_);
514     return bundleMgr_->GetSandboxExtAbilityInfos(want, appIndex, flags, userId, extensionInfos);
515 }
516 
GetSandboxHapModuleInfo(const AbilityInfo & abilityInfo,int32_t appIndex,int32_t userId,HapModuleInfo & hapModuleInfo)517 ErrCode BundleMgrClientImpl::GetSandboxHapModuleInfo(const AbilityInfo &abilityInfo, int32_t appIndex, int32_t userId,
518     HapModuleInfo &hapModuleInfo)
519 {
520     APP_LOGD("GetSandboxHapModuleInfo begin");
521     if (appIndex <= Constants::INITIAL_SANDBOX_APP_INDEX || appIndex > Constants::MAX_SANDBOX_APP_INDEX) {
522         APP_LOGE("GetSandboxHapModuleInfo params are invalid");
523         return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
524     }
525     ErrCode result = Connect();
526     if (result != ERR_OK) {
527         APP_LOGE("failed to connect");
528         return ERR_APPEXECFWK_SANDBOX_INSTALL_INTERNAL_ERROR;
529     }
530 
531     std::shared_lock<std::shared_mutex> lock(mutex_);
532     return bundleMgr_->GetSandboxHapModuleInfo(abilityInfo, appIndex, userId, hapModuleInfo);
533 }
534 
GetDirByBundleNameAndAppIndex(const std::string & bundleName,const int32_t appIndex,std::string & dataDir)535 ErrCode BundleMgrClientImpl::GetDirByBundleNameAndAppIndex(const std::string &bundleName, const int32_t appIndex,
536     std::string &dataDir)
537 {
538     APP_LOGD("GetDir begin");
539     Connect();
540     if (bundleMgr_ == nullptr) {
541         APP_LOGE("connect fail");
542         return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR;
543     }
544     std::shared_lock<std::shared_mutex> lock(mutex_);
545     return bundleMgr_->GetDirByBundleNameAndAppIndex(bundleName, appIndex, dataDir);
546 }
547 
GetAllBundleDirs(int32_t userId,std::vector<BundleDir> & bundleDirs)548 ErrCode BundleMgrClientImpl::GetAllBundleDirs(int32_t userId, std::vector<BundleDir> &bundleDirs)
549 {
550     APP_LOGD("GetAllBundleDirs begin");
551     ErrCode result = Connect();
552     if (result != ERR_OK) {
553         APP_LOGE("connect fail");
554         return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR;
555     }
556     std::shared_lock<std::shared_mutex> lock(mutex_);
557     return bundleMgr_->GetAllBundleDirs(userId, bundleDirs);
558 }
559 
Connect()560 ErrCode BundleMgrClientImpl::Connect()
561 {
562     APP_LOGD("connect begin");
563     std::unique_lock<std::shared_mutex> lock(mutex_);
564     if (bundleMgr_ == nullptr) {
565         sptr<ISystemAbilityManager> systemAbilityManager =
566             SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
567         if (systemAbilityManager == nullptr) {
568             APP_LOGE("failed to get system ability manager");
569             return ERR_APPEXECFWK_SERVICE_NOT_CONNECTED;
570         }
571 
572         sptr<IRemoteObject> remoteObject_ = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
573         if (remoteObject_ == nullptr || (bundleMgr_ = iface_cast<IBundleMgr>(remoteObject_)) == nullptr) {
574             APP_LOGE("failed to get bundle mgr service remote object");
575             return ERR_APPEXECFWK_SERVICE_NOT_CONNECTED;
576         }
577         std::weak_ptr<BundleMgrClientImpl> weakPtr = shared_from_this();
578         auto deathCallback = [weakPtr](const wptr<IRemoteObject>& object) {
579             auto sharedPtr = weakPtr.lock();
580             if (sharedPtr != nullptr) {
581                 sharedPtr->OnDeath();
582             }
583         };
584         deathRecipient_ = new (std::nothrow) BundleMgrServiceDeathRecipient(deathCallback);
585         bundleMgr_->AsObject()->AddDeathRecipient(deathRecipient_);
586     }
587 
588     if (bundleInstaller_ == nullptr) {
589         bundleInstaller_ = bundleMgr_->GetBundleInstaller();
590         if ((bundleInstaller_ == nullptr) || (bundleInstaller_->AsObject() == nullptr)) {
591             APP_LOGE("failed to get bundle installer proxy");
592             return ERR_APPEXECFWK_SERVICE_NOT_CONNECTED;
593         }
594     }
595     APP_LOGD("connect end");
596     return ERR_OK;
597 }
598 
OnDeath()599 void BundleMgrClientImpl::OnDeath()
600 {
601     APP_LOGD("BundleManagerService dead");
602     std::unique_lock<std::shared_mutex> lock(mutex_);
603     bundleMgr_ = nullptr;
604     bundleInstaller_ = nullptr;
605 }
606 }  // namespace AppExecFwk
607 }  // namespace OHOS