* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "distributed_bms.h"
#include <fstream>
#include <vector>
#include "accesstoken_kit.h"
#include "account_manager_helper.h"
#include "app_log_wrapper.h"
#include "appexecfwk_errors.h"
#include "bundle_mgr_interface.h"
#include "bundle_mgr_proxy.h"
#include "distributed_bms_proxy.h"
#include "distributed_data_storage.h"
#include "event_report.h"
#include "iservice_registry.h"
#include "if_system_ability_manager.h"
#include "locale_config.h"
#include "locale_info.h"
#include "image_compress.h"
#ifdef DISTRIBUTED_BUNDLE_IMAGE_ENABLE
#include "image_packer.h"
#include "image_source.h"
#endif
#include "ipc_skeleton.h"
#include "system_ability_definition.h"
#include "tokenid_kit.h"
#ifdef HICOLLIE_ENABLE
#include "xcollie/xcollie.h"
#include "xcollie/xcollie_define.h"
#endif
namespace OHOS {
namespace AppExecFwk {
namespace {
#ifdef HICOLLIE_ENABLE
const unsigned int LOCAL_TIME_OUT_SECONDS = 5;
const unsigned int REMOTE_TIME_OUT_SECONDS = 10;
#endif
const uint8_t DECODE_VALUE_ONE = 1;
const uint8_t DECODE_VALUE_TWO = 2;
const uint8_t DECODE_VALUE_THREE = 3;
const unsigned char DECODE_VALUE_CHAR_THREE = 3;
const uint8_t DECODE_VALUE_FOUR = 4;
const uint8_t DECODE_VALUE_SIX = 6;
const unsigned char DECODE_VALUE_CHAR_FIFTEEN = 15;
const unsigned char DECODE_VALUE_CHAR_SIXTY_THREE = 63;
const std::vector<char> DECODE_TABLE = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
const std::string POSTFIX = "_Compress.";
#ifdef HISYSEVENT_ENABLE
DBMSEventInfo GetEventInfo(
const std::vector<ElementName> &elements, const std::string &localeInfo, int32_t resultCode)
{
DBMSEventInfo eventInfo;
if (elements.empty()) {
return eventInfo;
}
eventInfo.deviceID = elements[0].GetDeviceID();
eventInfo.localeInfo = localeInfo;
for (auto element : elements) {
if (eventInfo.bundleName.empty()) {
eventInfo.bundleName.append(element.GetBundleName());
} else {
eventInfo.bundleName.append(";").append(element.GetBundleName());
}
if (eventInfo.abilityName.empty()) {
eventInfo.abilityName.append(element.GetAbilityName());
} else {
eventInfo.abilityName.append(";").append(element.GetAbilityName());
}
}
eventInfo.resultCode = resultCode;
return eventInfo;
}
DBMSEventInfo GetEventInfo(
const ElementName &element, const std::string &localeInfo, int32_t resultCode)
{
DBMSEventInfo eventInfo;
eventInfo.bundleName = element.GetBundleName();
eventInfo.abilityName = element.GetAbilityName();
eventInfo.deviceID = element.GetDeviceID();
eventInfo.localeInfo = localeInfo;
eventInfo.resultCode = resultCode;
return eventInfo;
}
#endif
}
const bool REGISTER_RESULT =
SystemAbility::MakeAndRegisterAbility(DelayedSingleton<DistributedBms>::GetInstance().get());
DistributedBms::DistributedBms() : SystemAbility(DISTRIBUTED_BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, true)
{
APP_LOGI("DistributedBms :%{public}s call", __func__);
}
DistributedBms::~DistributedBms()
{
APP_LOGI("DistributedBms: DBundleMgrService");
}
void DistributedBms::OnStart()
{
APP_LOGI("DistributedBms: OnStart");
Init();
bool res = Publish(this);
if (!res) {
APP_LOGE("DistributedBms: OnStart failed");
}
APP_LOGI("DistributedBms: OnStart end");
}
void DistributedBms::OnStop()
{
APP_LOGI("DistributedBms: OnStop");
if (distributedSub_ != nullptr) {
EventFwk::CommonEventManager::UnSubscribeCommonEvent(distributedSub_);
}
}
void DistributedBms::Init()
{
APP_LOGI("DistributedBms: Init");
InitDeviceManager();
DistributedDataStorage::GetInstance();
if (distributedSub_ == nullptr) {
EventFwk::MatchingSkills matchingSkills;
matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED);
matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED);
matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
distributedSub_ = std::make_shared<DistributedMonitor>(subscribeInfo);
EventFwk::CommonEventManager::SubscribeCommonEvent(distributedSub_);
}
int32_t userId = AccountManagerHelper::GetCurrentActiveUserId();
if (userId == Constants::INVALID_USERID) {
APP_LOGW("get user id failed");
return;
}
DistributedDataStorage::GetInstance()->UpdateDistributedData(userId);
}
void DistributedBms::InitDeviceManager()
{
if (dbmsDeviceManager_ == nullptr) {
std::lock_guard<std::mutex> lock(dbmsDeviceManagerMutex_);
if (dbmsDeviceManager_ == nullptr) {
APP_LOGI("Create device manager");
dbmsDeviceManager_ = std::make_shared<DbmsDeviceManager>();
}
}
}
OHOS::sptr<OHOS::AppExecFwk::IBundleMgr> DistributedBms::GetBundleMgr()
{
if (bundleMgr_ == nullptr) {
std::lock_guard<std::mutex> lock(bundleMgrMutex_);
if (bundleMgr_ == nullptr) {
auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (systemAbilityManager == nullptr) {
APP_LOGE("GetBundleMgr GetSystemAbilityManager is null");
return nullptr;
}
auto bundleMgrSa = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
if (bundleMgrSa == nullptr) {
APP_LOGE("GetBundleMgr GetSystemAbility is null");
return nullptr;
}
bundleMgr_ = OHOS::iface_cast<IBundleMgr>(bundleMgrSa);
}
}
return bundleMgr_;
}
int32_t DistributedBms::GetUdidByNetworkId(const std::string &networkId, std::string &udid)
{
if (dbmsDeviceManager_ == nullptr) {
APP_LOGI("deviceManager_ is nullptr");
InitDeviceManager();
}
return dbmsDeviceManager_->GetUdidByNetworkId(networkId, udid);
}
int32_t DistributedBms::GetUuidByNetworkId(const std::string &networkId, std::string &uuid)
{
if (dbmsDeviceManager_ == nullptr) {
APP_LOGI("deviceManager_ is nullptr");
InitDeviceManager();
}
return dbmsDeviceManager_->GetUuidByNetworkId(networkId, uuid);
}
bool DistributedBms::GetLocalDevice(DistributedHardware::DmDeviceInfo& dmDeviceInfo)
{
if (dbmsDeviceManager_ == nullptr) {
APP_LOGI("deviceManager_ is nullptr");
InitDeviceManager();
}
return dbmsDeviceManager_->GetLocalDevice(dmDeviceInfo);
}
static OHOS::sptr<OHOS::AppExecFwk::IDistributedBms> GetDistributedBundleMgr(const std::string &deviceId)
{
auto samgr = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (samgr == nullptr) {
APP_LOGE("GetSystemAbilityManager failed");
return nullptr;
}
OHOS::sptr<OHOS::IRemoteObject> remoteObject;
if (deviceId.empty()) {
APP_LOGW("GetDistributedBundleMgr deviceId is empty");
return nullptr;
} else {
APP_LOGI("GetDistributedBundleMgr get remote d-bms");
remoteObject = samgr->CheckSystemAbility(OHOS::DISTRIBUTED_BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, deviceId);
}
return OHOS::iface_cast<IDistributedBms>(remoteObject);
}
int32_t DistributedBms::GetRemoteAbilityInfo(
const OHOS::AppExecFwk::ElementName &elementName, RemoteAbilityInfo &remoteAbilityInfo)
{
return GetRemoteAbilityInfo(elementName, "", remoteAbilityInfo);
}
int32_t DistributedBms::GetRemoteAbilityInfo(const OHOS::AppExecFwk::ElementName &elementName,
const std::string &localeInfo, RemoteAbilityInfo &remoteAbilityInfo)
{
if (!VerifySystemApp()) {
APP_LOGE("verify system app failed");
return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
}
if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
auto iDistBundleMgr = GetDistributedBundleMgr(elementName.GetDeviceID());
int32_t resultCode = 0;
if (!iDistBundleMgr) {
APP_LOGE("GetDistributedBundle object failed");
resultCode = ERR_BUNDLE_MANAGER_DEVICE_ID_NOT_EXIST;
} else {
#ifdef HICOLLIE_ENABLE
int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetRemoteAbilityInfo", REMOTE_TIME_OUT_SECONDS,
nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
#endif
APP_LOGD("GetDistributedBundleMgr get remote d-bms");
DistributedBmsAclInfo info = BuildDistributedBmsAclInfo();
resultCode = iDistBundleMgr->GetAbilityInfo(elementName, localeInfo, remoteAbilityInfo, &info);
}
#ifdef HISYSEVENT_ENABLE
EventReport::SendSystemEvent(
DBMSEventType::GET_REMOTE_ABILITY_INFO, GetEventInfo(elementName, localeInfo, resultCode));
#endif
return resultCode;
}
int32_t DistributedBms::GetRemoteAbilityInfos(
const std::vector<ElementName> &elementNames, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
{
return GetRemoteAbilityInfos(elementNames, "", remoteAbilityInfos);
}
int32_t DistributedBms::GetRemoteAbilityInfos(const std::vector<ElementName> &elementNames,
const std::string &localeInfo, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
{
if (!VerifySystemApp()) {
APP_LOGE("verify system app failed");
return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
}
if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
if (elementNames.empty()) {
APP_LOGE("GetDistributedBundle failed due to elementNames empty");
return ERR_BUNDLE_MANAGER_PARAM_ERROR;
}
auto iDistBundleMgr = GetDistributedBundleMgr(elementNames[0].GetDeviceID());
int32_t resultCode = 0;
if (!iDistBundleMgr) {
APP_LOGE("GetDistributedBundle object failed");
resultCode = ERR_BUNDLE_MANAGER_DEVICE_ID_NOT_EXIST;
} else {
#ifdef HICOLLIE_ENABLE
int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetRemoteAbilityInfos", REMOTE_TIME_OUT_SECONDS,
nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
#endif
APP_LOGD("GetDistributedBundleMgr get remote d-bms");
DistributedBmsAclInfo info = BuildDistributedBmsAclInfo();
resultCode = iDistBundleMgr->GetAbilityInfos(elementNames, localeInfo, remoteAbilityInfos, &info);
}
#ifdef HISYSEVENT_ENABLE
EventReport::SendSystemEvent(
DBMSEventType::GET_REMOTE_ABILITY_INFOS, GetEventInfo(elementNames, localeInfo, resultCode));
#endif
return resultCode;
}
DistributedBmsAclInfo DistributedBms::BuildDistributedBmsAclInfo()
{
DistributedBmsAclInfo info;
std::string accountId;
#ifdef ACCOUNT_ENABLE
AccountSA::OhosAccountInfo osAccountInfo;
if (!AccountManagerHelper::GetOsAccountData(osAccountInfo)) {
APP_LOGE("GetOsAccountData failed");
return info;
}
accountId = osAccountInfo.uid_;
#endif
DistributedHardware::DmDeviceInfo dmDeviceInfo;
if (!GetLocalDevice(dmDeviceInfo)) {
return info;
}
int32_t userId = AccountManagerHelper::GetCurrentActiveUserId();
auto iBundleMgr = GetBundleMgr();
if (!iBundleMgr) {
APP_LOGE("DistributedBms GetBundleMgr failed");
return info;
}
std::string callingBundleName;
iBundleMgr->GetNameForUid(IPCSkeleton::GetCallingUid(), callingBundleName);
info.networkId = dmDeviceInfo.networkId;
info.userId = userId;
info.accountId = accountId;
info.tokenId = OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, callingBundleName, 0);
info.pkgName = callingBundleName;
return info;
}
int32_t DistributedBms::GetAbilityInfo(
const OHOS::AppExecFwk::ElementName &elementName, RemoteAbilityInfo &remoteAbilityInfo)
{
return GetAbilityInfo(elementName, "", remoteAbilityInfo);
}
int32_t DistributedBms::GetAbilityInfo(const OHOS::AppExecFwk::ElementName &elementName,
const std::string &localeInfo, RemoteAbilityInfo &remoteAbilityInfo,
DistributedBmsAclInfo *info)
{
APP_LOGI("DistributedBms GetAbilityInfo bundleName:%{public}s , abilityName:%{public}s, localeInfo:%{public}s",
elementName.GetBundleName().c_str(), elementName.GetAbilityName().c_str(), localeInfo.c_str());
if (!VerifyCallingPermissionOrAclCheck(info)) {
APP_LOGE("verify permission failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
auto iBundleMgr = GetBundleMgr();
if (!iBundleMgr) {
APP_LOGE("DistributedBms GetBundleMgr failed");
return ERR_APPEXECFWK_FAILED_SERVICE_DIED;
}
int userId = AccountManagerHelper::GetCurrentActiveUserId();
if (userId == Constants::INVALID_USERID) {
APP_LOGE("GetCurrentUserId failed");
return ERR_BUNDLE_MANAGER_INVALID_USER_ID;
}
std::vector<AbilityInfo> abilityInfos;
OHOS::AAFwk::Want want;
want.SetElement(elementName);
ErrCode ret = iBundleMgr->QueryAbilityInfosV9(want, static_cast<int32_t>(
GetAbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION), userId, abilityInfos);
if (ret != ERR_OK) {
APP_LOGE("DistributedBms QueryAbilityInfo failed");
return ret;
}
if (abilityInfos.empty()) {
APP_LOGE("DistributedBms QueryAbilityInfo abilityInfos empty");
return ERR_APPEXECFWK_FAILED_GET_ABILITY_INFO;
}
std::string label = iBundleMgr->GetStringById(
abilityInfos[0].bundleName, abilityInfos[0].moduleName, abilityInfos[0].labelId, userId, localeInfo);
if (label.empty()) {
APP_LOGE("DistributedBms QueryAbilityInfo label empty");
return ERR_APPEXECFWK_FAILED_GET_ABILITY_INFO;
}
remoteAbilityInfo.label = label;
remoteAbilityInfo.elementName = elementName;
return GetAbilityIconByContent(abilityInfos[0], userId, remoteAbilityInfo);
}
int32_t DistributedBms::GetAbilityIconByContent(
const AbilityInfo &abilityInfo, int32_t userId, RemoteAbilityInfo &remoteAbilityInfo)
{
auto iBundleMgr = GetBundleMgr();
if (!iBundleMgr) {
APP_LOGE("DistributedBms GetBundleMgr failed");
return ERR_APPEXECFWK_FAILED_SERVICE_DIED;
}
#ifdef DISTRIBUTED_BUNDLE_IMAGE_ENABLE
std::unique_ptr<uint8_t[]> imageContent;
size_t imageContentSize = 0;
ErrCode ret = iBundleMgr->GetMediaData(abilityInfo.bundleName, abilityInfo.moduleName, abilityInfo.name,
imageContent, imageContentSize, userId);
if (ret != ERR_OK) {
APP_LOGE("DistributedBms GetMediaData failed");
return ret;
}
APP_LOGD("imageContentSize is %{public}d", static_cast<int32_t>(imageContentSize));
std::unique_ptr<ImageCompress> imageCompress = std::make_unique<ImageCompress>();
if (imageCompress->IsImageNeedCompressBySize(imageContentSize)) {
std::unique_ptr<uint8_t[]> compressData;
int64_t compressSize = 0;
std::string imageType;
if (!imageCompress->CompressImageByContent(imageContent, imageContentSize,
compressData, compressSize, imageType)) {
return Base64WithoutCompress(imageContent, imageContentSize, remoteAbilityInfo);
}
if (!GetMediaBase64(compressData, compressSize, imageType, remoteAbilityInfo.icon)) {
APP_LOGE("DistributedBms GetMediaBase64 failed");
return ERR_APPEXECFWK_ENCODE_BASE64_FILE_FAILED;
}
} else {
return Base64WithoutCompress(imageContent, imageContentSize, remoteAbilityInfo);
}
#endif
return OHOS::NO_ERROR;
}
#ifdef DISTRIBUTED_BUNDLE_IMAGE_ENABLE
int32_t DistributedBms::Base64WithoutCompress(std::unique_ptr<uint8_t[]> &imageContent, size_t imageContentSize,
RemoteAbilityInfo &remoteAbilityInfo)
{
std::string imageType;
std::unique_ptr<ImageCompress> imageCompress = std::make_unique<ImageCompress>();
if (!imageCompress->GetImageTypeString(imageContent, imageContentSize, imageType)) {
return ERR_APPEXECFWK_INPUT_WRONG_TYPE_FILE;
}
if (!GetMediaBase64(imageContent, static_cast<int64_t>(imageContentSize), imageType, remoteAbilityInfo.icon)) {
APP_LOGE("DistributedBms GetMediaBase64 failed");
return ERR_APPEXECFWK_ENCODE_BASE64_FILE_FAILED;
}
return OHOS::NO_ERROR;
}
#endif
int32_t DistributedBms::GetAbilityInfos(
const std::vector<ElementName> &elementNames, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
{
APP_LOGD("DistributedBms GetAbilityInfos");
return GetAbilityInfos(elementNames, "", remoteAbilityInfos);
}
int32_t DistributedBms::GetAbilityInfos(const std::vector<ElementName> &elementNames,
const std::string &localeInfo, std::vector<RemoteAbilityInfo> &remoteAbilityInfos,
DistributedBmsAclInfo *info)
{
APP_LOGD("DistributedBms GetAbilityInfos");
if (!VerifyCallingPermissionOrAclCheck(info)) {
APP_LOGE("verify permission failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
for (auto elementName : elementNames) {
RemoteAbilityInfo remoteAbilityInfo;
int32_t result = GetAbilityInfo(elementName, localeInfo, remoteAbilityInfo, info);
if (result) {
APP_LOGE("get AbilityInfo:%{public}s, %{public}s, %{public}s failed", elementName.GetBundleName().c_str(),
elementName.GetModuleName().c_str(), elementName.GetAbilityName().c_str());
return result;
}
remoteAbilityInfos.push_back(remoteAbilityInfo);
}
return OHOS::NO_ERROR;
}
bool DistributedBms::CheckAclData(DistributedBmsAclInfo info)
{
if (dbmsDeviceManager_ == nullptr) {
APP_LOGI("deviceManager_ is nullptr");
InitDeviceManager();
}
return dbmsDeviceManager_->CheckAclData(info);
}
bool DistributedBms::GetMediaBase64(std::unique_ptr<uint8_t[]> &data, int64_t fileLength,
std::string &imageType, std::string &value)
{
if (fileLength <= 0) {
APP_LOGE_NOFUNC("GetMediaBase64 fileLength invalid");
return false;
}
std::unique_ptr<char[]> base64Data = EncodeBase64(data, fileLength);
value = "data:" + imageType + ";base64," + base64Data.get();
return true;
}
bool DistributedBms::GetDistributedBundleInfo(const std::string &networkId, const std::string &bundleName,
DistributedBundleInfo &distributedBundleInfo)
{
if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
if (GetDistributedBundleMgr(networkId) == nullptr) {
APP_LOGW_NOFUNC("remote d-bms not running");
}
#ifdef HICOLLIE_ENABLE
int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetDistributedBundleInfo", LOCAL_TIME_OUT_SECONDS,
nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
#endif
bool ret = DistributedDataStorage::GetInstance()->GetStorageDistributeInfo(
networkId, bundleName, distributedBundleInfo);
#ifdef HICOLLIE_ENABLE
HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
#endif
return ret;
}
int32_t DistributedBms::GetDistributedBundleName(const std::string &networkId, uint32_t accessTokenId,
std::string &bundleName)
{
if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
APP_LOGE("verify calling permission failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
if (GetDistributedBundleMgr(networkId) == nullptr) {
APP_LOGW_NOFUNC("remote d-bms not running");
}
#ifdef HICOLLIE_ENABLE
int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetDistributedBundleName", LOCAL_TIME_OUT_SECONDS,
nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
#endif
int32_t ret = DistributedDataStorage::GetInstance()->GetDistributedBundleName(
networkId, accessTokenId, bundleName);
#ifdef HICOLLIE_ENABLE
HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
#endif
return ret;
}
int32_t DistributedBms::GetRemoteBundleVersionCode(const std::string &deviceId, const std::string &bundleName,
uint32_t &versionCode)
{
if (!VerifySystemApp()) {
APP_LOGE("verify system app failed");
return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
}
if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
if (deviceId.empty()) {
APP_LOGE("deviceId is empty");
return ERR_BUNDLE_MANAGER_DEVICE_ID_NOT_EXIST;
}
if (bundleName.empty()) {
APP_LOGE("bundleName is empty");
return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
}
auto iDistBundleMgr = GetDistributedBundleMgr(deviceId);
int32_t resultCode = 0;
if (!iDistBundleMgr) {
APP_LOGE("GetDistributedBundle object failed");
return ERR_BUNDLE_MANAGER_DEVICE_ID_NOT_EXIST;
}
#ifdef HICOLLIE_ENABLE
int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetRemoteBundleVersionCode", REMOTE_TIME_OUT_SECONDS,
nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
#endif
DistributedBmsAclInfo info = BuildDistributedBmsAclInfo();
resultCode = iDistBundleMgr->GetBundleVersionCode(bundleName, versionCode, info);
#ifdef HICOLLIE_ENABLE
HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
#endif
return resultCode;
}
int32_t DistributedBms::GetBundleVersionCode(const std::string &bundleName, uint32_t &versionCode,
DistributedBmsAclInfo &info)
{
APP_LOGI("DistributedBms GetBundleVersionCode bundleName:%{public}s", bundleName.c_str());
if (!CheckAclData(info)) {
APP_LOGE("verify permission failed");
return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
}
if (bundleName.empty()) {
APP_LOGE("bundleName is empty");
return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
}
auto iBundleMgr = GetBundleMgr();
if (!iBundleMgr) {
APP_LOGE("DistributedBms GetBundleMgr failed");
return ERR_APPEXECFWK_FAILED_SERVICE_DIED;
}
int32_t userId = AccountManagerHelper::GetCurrentActiveUserId();
if (userId == Constants::INVALID_USERID) {
APP_LOGE("GetCurrentUserId failed");
return ERR_BUNDLE_MANAGER_INVALID_USER_ID;
}
ApplicationInfo appInfo;
auto ret = iBundleMgr->GetApplicationInfoV9(bundleName,
static_cast<uint32_t>(ApplicationFlag::GET_BASIC_APPLICATION_INFO), userId, appInfo);
if (ret != ERR_OK) {
APP_LOGE("DistributedBms GetBundleInfo failed, ret:%{public}d", ret);
return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
}
versionCode = appInfo.versionCode;
return ERR_OK;
}
std::unique_ptr<char[]> DistributedBms::EncodeBase64(std::unique_ptr<uint8_t[]> &data, int srcLen)
{
int len = (srcLen / DECODE_VALUE_THREE) * DECODE_VALUE_FOUR;
int outLen = ((srcLen % DECODE_VALUE_THREE) != 0) ? (len + DECODE_VALUE_FOUR) : len;
const uint8_t *srcData = data.get();
std::unique_ptr<char[]> result = std::make_unique<char[]>(outLen + DECODE_VALUE_ONE);
char *dstData = result.get();
int j = 0;
int i = 0;
for (; i < srcLen - DECODE_VALUE_THREE; i += DECODE_VALUE_THREE) {
unsigned char byte1 = srcData[i];
unsigned char byte2 = srcData[i + DECODE_VALUE_ONE];
unsigned char byte3 = srcData[i + DECODE_VALUE_TWO];
dstData[j++] = DECODE_TABLE[byte1 >> DECODE_VALUE_TWO];
dstData[j++] =
DECODE_TABLE[(static_cast<uint8_t>(byte1 & DECODE_VALUE_CHAR_THREE) << DECODE_VALUE_FOUR)
| (byte2 >> DECODE_VALUE_FOUR)];
dstData[j++] =
DECODE_TABLE[(static_cast<uint8_t>(byte2 & DECODE_VALUE_CHAR_FIFTEEN)
<< DECODE_VALUE_TWO) | (byte3 >> DECODE_VALUE_SIX)];
dstData[j++] = DECODE_TABLE[byte3 & DECODE_VALUE_CHAR_SIXTY_THREE];
}
if (srcLen % DECODE_VALUE_THREE == DECODE_VALUE_ONE) {
unsigned char byte1 = srcData[i];
dstData[j++] = DECODE_TABLE[byte1 >> DECODE_VALUE_TWO];
dstData[j++] = DECODE_TABLE[static_cast<uint8_t>(byte1 & DECODE_VALUE_CHAR_THREE) << DECODE_VALUE_FOUR];
dstData[j++] = '=';
dstData[j++] = '=';
} else {
unsigned char byte1 = srcData[i];
unsigned char byte2 = srcData[i + DECODE_VALUE_ONE];
dstData[j++] = DECODE_TABLE[byte1 >> DECODE_VALUE_TWO];
dstData[j++] =
DECODE_TABLE[(static_cast<uint8_t>(byte1 & DECODE_VALUE_CHAR_THREE) << DECODE_VALUE_FOUR)
| (byte2 >> DECODE_VALUE_FOUR)];
dstData[j++] = DECODE_TABLE[static_cast<uint8_t>(byte2 & DECODE_VALUE_CHAR_FIFTEEN)
<< DECODE_VALUE_TWO];
dstData[j++] = '=';
}
dstData[outLen] = '\0';
return result;
}
bool DistributedBms::VerifySystemApp()
{
APP_LOGI("verifying systemApp");
int32_t callingUid = IPCSkeleton::GetCallingUid();
Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
if (VerifyTokenNative(callerToken) || VerifyTokenShell(callerToken)
|| callingUid == Constants::ROOT_UID) {
APP_LOGI("caller tokenType is native or shell, verify success");
return true;
}
uint64_t accessTokenIdEx = IPCSkeleton::GetCallingFullTokenID();
if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenIdEx)) {
APP_LOGE("non-system app calling system api");
return false;
}
return true;
}
bool DistributedBms::VerifyTokenNative(Security::AccessToken::AccessTokenID callerToken)
{
APP_LOGD("verifying system app for native token");
Security::AccessToken::ATokenTypeEnum tokenType =
Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
APP_LOGD("token type is %{public}d", static_cast<int32_t>(tokenType));
if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
APP_LOGI("caller tokenType is native, verify success");
return true;
}
APP_LOGE("caller tokenType not native, verify failed");
return false;
}
bool DistributedBms::VerifyTokenShell(Security::AccessToken::AccessTokenID callerToken)
{
APP_LOGD("verifying system app for shell token");
Security::AccessToken::ATokenTypeEnum tokenType =
Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
APP_LOGD("token type is %{public}d", static_cast<int32_t>(tokenType));
if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
APP_LOGI("caller tokenType is shell, verify success");
return true;
}
APP_LOGE("caller tokenType not shell, verify failed");
return false;
}
bool DistributedBms::VerifyCallingPermission(const std::string &permissionName)
{
APP_LOGD("VerifyCallingPermission permission %{public}s", permissionName.c_str());
Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
auto uid = IPCSkeleton::GetCallingUid();
APP_LOGD("VerifyCallingPermission callingUid %{public}d", uid);
int32_t ret = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permissionName);
if (ret == OHOS::Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
APP_LOGD("verify permission success");
return true;
}
APP_LOGE("permission %{public}s: PERMISSION_DENIED", permissionName.c_str());
return false;
}
bool DistributedBms::VerifyCallingPermissionOrAclCheck(DistributedBmsAclInfo *info)
{
DistributedHardware::DmDeviceInfo dmDeviceInfo;
if (!GetLocalDevice(dmDeviceInfo)) {
APP_LOGE("GetLocalDevice failed");
return false;
}
std::string callingDeviceID = IPCSkeleton::GetCallingDeviceID();
if (callingDeviceID.empty() || std::string(dmDeviceInfo.networkId) == callingDeviceID) {
if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
return false;
}
} else if (info != nullptr && !CheckAclData(*info)) {
APP_LOGE("check ack failed");
return false;
}
return true;
}
}
}