1 /*
2  * Copyright (c) 2022 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_manager_adapter_proxy.h"
17 #include "ability_info.h"
18 #include "account_error_no.h"
19 #include "account_log_wrapper.h"
20 #include "nlohmann/json.hpp"
21 #include "securec.h"
22 #include "string_ex.h"
23 
24 namespace OHOS {
25 namespace AccountSA {
26 namespace {
27 const int32_t ASHMEM_LEN = 16;
28 const int32_t MAX_INFO_SIZE = 1048576; // 1024 x 1024
29 const std::string BUNDLE_INFO_NAME = "name";
30 const std::string BUNDLE_INFO_LABEL = "label";
31 const std::string BUNDLE_INFO_DESCRIPTION = "description";
32 const std::string BUNDLE_INFO_SINGLETON = "singleton";
33 const std::string BUNDLE_INFO_IS_NATIVE_APP = "isNativeApp";
34 const std::string BUNDLE_INFO_APPID = "appId";
35 const std::string BUNDLE_INFO_APP_INDEX = "appIndex";
36 const std::string BUNDLE_INFO_EXTENSION_ABILITY_INFOS = "extensionAbilityInfo";
37 
ClearAshmem(sptr<Ashmem> & optMem)38 inline void ClearAshmem(sptr<Ashmem> &optMem)
39 {
40     if (optMem != nullptr) {
41         optMem->UnmapAshmem();
42         optMem->CloseAshmem();
43     }
44 }
45 
46 const std::string EXTENSION_NAME = "name";
47 const std::string EXTENSION_LABEL = "label";
48 const std::string EXTENSION_DESCRIPTION = "description";
49 const std::string EXTENSION_TYPE = "type";
50 const std::string EXTENSION_VISIBLE = "visible";
51 const std::string EXTENSION_UID = "uid";
52 }
53 
ParseExtensionInfo(std::string infoStr,ExtensionAbilityInfo & extensionInfo)54 bool BundleManagerAdapterProxy::ParseExtensionInfo(std::string infoStr, ExtensionAbilityInfo &extensionInfo)
55 {
56     nlohmann::json jsonObject = nlohmann::json::parse(infoStr.c_str(), nullptr, false);
57     if (jsonObject.is_discarded()) {
58         ACCOUNT_LOGE("failed due to data is discarded");
59         return false;
60     }
61     if ((jsonObject.find(EXTENSION_NAME) != jsonObject.end()) && jsonObject.at(EXTENSION_NAME).is_string()) {
62         extensionInfo.name = jsonObject.at(EXTENSION_NAME).get<std::string>();
63     }
64     if ((jsonObject.find(EXTENSION_LABEL) != jsonObject.end()) && jsonObject.at(EXTENSION_LABEL).is_string()) {
65         extensionInfo.label = jsonObject.at(EXTENSION_LABEL).get<std::string>();
66     }
67     if ((jsonObject.find(EXTENSION_DESCRIPTION) != jsonObject.end()) &&
68         jsonObject.at(EXTENSION_DESCRIPTION).is_string()) {
69         extensionInfo.description = jsonObject.at(EXTENSION_DESCRIPTION).get<std::string>();
70     }
71     if ((jsonObject.find(EXTENSION_TYPE) != jsonObject.end()) &&
72         jsonObject.at(EXTENSION_TYPE).is_number()) {
73         extensionInfo.type = static_cast<ExtensionAbilityType>(jsonObject.at(EXTENSION_TYPE).get<int32_t>());
74     }
75     if ((jsonObject.find(EXTENSION_VISIBLE) != jsonObject.end()) &&
76         jsonObject.at(EXTENSION_VISIBLE).is_boolean()) {
77         extensionInfo.visible = jsonObject.at(EXTENSION_VISIBLE).get<bool>();
78     }
79     if ((jsonObject.find(EXTENSION_UID) != jsonObject.end()) &&
80         jsonObject.at(EXTENSION_UID).is_number()) {
81         extensionInfo.uid = jsonObject.at(EXTENSION_UID).get<int32_t>();
82     }
83     return true;
84 }
85 
BundleManagerAdapterProxy(const sptr<IRemoteObject> & impl)86 BundleManagerAdapterProxy::BundleManagerAdapterProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<IBundleMgr>(impl)
87 {}
88 
~BundleManagerAdapterProxy()89 BundleManagerAdapterProxy::~BundleManagerAdapterProxy()
90 {}
91 
ParseStr(const char * buf,const int itemLen,int index,std::string & result)92 bool BundleManagerAdapterProxy::ParseStr(const char *buf, const int itemLen, int index, std::string &result)
93 {
94     ACCOUNT_LOGD("ParseStr itemLen:%{public}d index:%{public}d.", itemLen, index);
95     if (buf == nullptr || itemLen <= 0 || index < 0) {
96         ACCOUNT_LOGE("param invalid.");
97         return false;
98     }
99 
100     char item[itemLen + 1];
101     if (strncpy_s(item, sizeof(item), buf + index, itemLen) != 0) {
102         ACCOUNT_LOGE("ParseStr failed due to strncpy_s error.");
103         return false;
104     }
105 
106     std::string str(item, 0, itemLen);
107     result = str;
108     return true;
109 }
110 
ParseExtensionAbilityInfos(nlohmann::json jsonObject,std::vector<ExtensionAbilityInfo> & extensionInfos)111 bool BundleManagerAdapterProxy::ParseExtensionAbilityInfos(
112     nlohmann::json jsonObject, std::vector<ExtensionAbilityInfo> &extensionInfos)
113 {
114     if ((jsonObject.find(BUNDLE_INFO_EXTENSION_ABILITY_INFOS) == jsonObject.end()) ||
115         (!jsonObject.at(BUNDLE_INFO_EXTENSION_ABILITY_INFOS).is_array())) {
116         return true;
117     }
118     auto arrays = jsonObject.at(BUNDLE_INFO_EXTENSION_ABILITY_INFOS);
119     if (arrays.empty()) {
120         return true;
121     }
122     if (arrays.size() > Constants::MAX_JSON_ARRAY_LENGTH) {
123         ACCOUNT_LOGE("array is oversize");
124         return false;
125     }
126     for (const auto &iter : arrays) {
127         if (!iter.is_object()) {
128             ACCOUNT_LOGE("array %{public}s exist error type info", BUNDLE_INFO_EXTENSION_ABILITY_INFOS.c_str());
129             continue;
130         }
131         ExtensionAbilityInfo abilityInfo;
132         if (!ParseExtensionInfo(iter.dump(), abilityInfo)) {
133             continue;
134         }
135         extensionInfos.emplace_back(abilityInfo);
136     }
137     return true;
138 }
139 
140 template<typename T>
ParseInfo(std::string & infoStr,T & info)141 bool BundleManagerAdapterProxy::ParseInfo(std::string &infoStr, T &info)
142 {
143     nlohmann::json jsonObject = nlohmann::json::parse(infoStr.c_str(), nullptr, false);
144     if (jsonObject.is_discarded()) {
145         ACCOUNT_LOGE("failed due to data is discarded");
146         return false;
147     }
148 
149     if ((jsonObject.find(BUNDLE_INFO_NAME) != jsonObject.end()) && jsonObject.at(BUNDLE_INFO_NAME).is_string()) {
150         info.name = jsonObject.at(BUNDLE_INFO_NAME).get<std::string>();
151     }
152     if ((jsonObject.find(BUNDLE_INFO_LABEL) != jsonObject.end()) && jsonObject.at(BUNDLE_INFO_LABEL).is_string()) {
153         info.label = jsonObject.at(BUNDLE_INFO_LABEL).get<std::string>();
154     }
155     if ((jsonObject.find(BUNDLE_INFO_DESCRIPTION) != jsonObject.end()) &&
156         jsonObject.at(BUNDLE_INFO_DESCRIPTION).is_string()) {
157         info.description = jsonObject.at(BUNDLE_INFO_DESCRIPTION).get<std::string>();
158     }
159     if ((jsonObject.find(BUNDLE_INFO_SINGLETON) != jsonObject.end()) &&
160         jsonObject.at(BUNDLE_INFO_SINGLETON).is_boolean()) {
161         info.singleton = jsonObject.at(BUNDLE_INFO_SINGLETON).get<bool>();
162     }
163     if ((jsonObject.find(BUNDLE_INFO_IS_NATIVE_APP) != jsonObject.end()) &&
164         jsonObject.at(BUNDLE_INFO_IS_NATIVE_APP).is_boolean()) {
165         info.isNativeApp = jsonObject.at(BUNDLE_INFO_IS_NATIVE_APP).get<bool>();
166     }
167     if ((jsonObject.find(BUNDLE_INFO_APPID) != jsonObject.end()) && jsonObject.at(BUNDLE_INFO_APPID).is_string()) {
168         info.appId = jsonObject.at(BUNDLE_INFO_APPID).get<std::string>();
169     }
170     if ((jsonObject.find(BUNDLE_INFO_APP_INDEX) != jsonObject.end()) &&
171         jsonObject.at(BUNDLE_INFO_APP_INDEX).is_number()) {
172         info.appIndex = jsonObject.at(BUNDLE_INFO_APP_INDEX).get<int32_t>();
173     }
174     if (!ParseExtensionAbilityInfos(jsonObject, info.extensionInfos)) {
175         return false;
176     }
177     return true;
178 }
179 
GetBundleInfo(const std::string & bundleName,const BundleFlag flag,BundleInfo & bundleInfo,int32_t userId)180 bool BundleManagerAdapterProxy::GetBundleInfo(
181     const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo, int32_t userId)
182 {
183     if (bundleName.empty()) {
184         ACCOUNT_LOGE("fail to GetBundleInfo due to params empty");
185         return false;
186     }
187 
188     MessageParcel data;
189     if (!data.WriteInterfaceToken(GetDescriptor())) {
190         ACCOUNT_LOGE("fail to GetBundleInfo due to write InterfaceToken fail");
191         return false;
192     }
193     if (!data.WriteString(bundleName)) {
194         ACCOUNT_LOGE("fail to GetBundleInfo due to write bundleName fail");
195         return false;
196     }
197     if (!data.WriteInt32(static_cast<int>(flag))) {
198         ACCOUNT_LOGE("fail to GetBundleInfo due to write flag fail");
199         return false;
200     }
201     if (!data.WriteInt32(userId)) {
202         ACCOUNT_LOGE("fail to GetBundleInfo due to write userId fail");
203         return false;
204     }
205     return GetParcelInfo<BundleInfo>(BundleMgrInterfaceCode::GET_BUNDLE_INFO, data, bundleInfo);
206 }
207 
GetUidByBundleName(const std::string & bundleName,const int userId)208 int BundleManagerAdapterProxy::GetUidByBundleName(const std::string &bundleName, const int userId)
209 {
210     if (bundleName.empty()) {
211         ACCOUNT_LOGE("failed to GetUidByBundleName due to bundleName empty");
212         return AppExecFwk::Constants::INVALID_UID;
213     }
214 
215     MessageParcel data;
216     if (!data.WriteInterfaceToken(GetDescriptor())) {
217         ACCOUNT_LOGE("failed to GetUidByBundleName due to write InterfaceToken fail");
218         return AppExecFwk::Constants::INVALID_UID;
219     }
220     if (!data.WriteString(bundleName)) {
221         ACCOUNT_LOGE("failed to GetUidByBundleName due to write bundleName fail");
222         return AppExecFwk::Constants::INVALID_UID;
223     }
224     if (!data.WriteInt32(userId)) {
225         ACCOUNT_LOGE("failed to GetUidByBundleName due to write uid fail");
226         return AppExecFwk::Constants::INVALID_UID;
227     }
228 
229     MessageParcel reply;
230     if (!SendTransactCmd(BundleMgrInterfaceCode::GET_UID_BY_BUNDLE_NAME, data, reply)) {
231         ACCOUNT_LOGE("failed to GetUidByBundleName from server");
232         return AppExecFwk::Constants::INVALID_UID;
233     }
234     int32_t uid = reply.ReadInt32();
235     return uid;
236 }
237 
GetNameForUid(const int uid,std::string & bundleName)238 ErrCode BundleManagerAdapterProxy::GetNameForUid(const int uid, std::string &bundleName)
239 {
240     MessageParcel data;
241     if (!data.WriteInterfaceToken(GetDescriptor())) {
242         ACCOUNT_LOGE("fail to GetNameForUid due to write InterfaceToken fail");
243         return ERR_ACCOUNT_COMMON_WRITE_PARCEL_ERROR;
244     }
245     if (!data.WriteInt32(uid)) {
246         ACCOUNT_LOGE("fail to GetNameForUid due to write uid fail");
247         return ERR_ACCOUNT_COMMON_WRITE_PARCEL_ERROR;
248     }
249 
250     MessageParcel reply;
251     if (!SendTransactCmd(BundleMgrInterfaceCode::GET_NAME_FOR_UID, data, reply)) {
252         ACCOUNT_LOGE("fail to GetNameForUid from server");
253         return ERR_ACCOUNT_COMMON_WRITE_PARCEL_ERROR;
254     }
255     ErrCode result;
256     if (!reply.ReadInt32(result)) {
257         ACCOUNT_LOGE("reply result false");
258         return ERR_ACCOUNT_COMMON_READ_PARCEL_ERROR;
259     }
260     bundleName = reply.ReadString();
261     return result;
262 }
263 
QueryAbilityInfos(const Want & want,int32_t flags,int32_t userId,std::vector<AbilityInfo> & abilityInfos)264 bool BundleManagerAdapterProxy::QueryAbilityInfos(
265     const Want &want, int32_t flags, int32_t userId, std::vector<AbilityInfo> &abilityInfos)
266 {
267     MessageParcel data;
268     if (!data.WriteInterfaceToken(GetDescriptor())) {
269         ACCOUNT_LOGE("fail to QueryAbilityInfos due to write MessageParcel fail");
270         return false;
271     }
272     if (!data.WriteParcelable(&want)) {
273         ACCOUNT_LOGE("fail to QueryAbilityInfos due to write want fail");
274         return false;
275     }
276     if (!data.WriteInt32(flags)) {
277         ACCOUNT_LOGE("fail to QueryAbilityInfos due to write flags fail");
278         return false;
279     }
280     if (!data.WriteInt32(userId)) {
281         ACCOUNT_LOGE("fail to QueryAbilityInfos due to write userId error");
282         return false;
283     }
284 
285     if (!GetVectorFromParcelIntelligent<AbilityInfo>(BundleMgrInterfaceCode::QUERY_ABILITY_INFOS_MUTI_PARAM,
286         data, abilityInfos)) {
287         ACCOUNT_LOGE("fail to QueryAbilityInfos from server");
288         return false;
289     }
290     return true;
291 }
292 
GetBundleUserMgr()293 sptr<IBundleUserMgr> BundleManagerAdapterProxy::GetBundleUserMgr()
294 {
295     MessageParcel data;
296     MessageParcel reply;
297     if (!data.WriteInterfaceToken(GetDescriptor())) {
298         ACCOUNT_LOGE("fail to get bundle user mgr due to write InterfaceToken fail");
299         return nullptr;
300     }
301     if (!SendTransactCmd(BundleMgrInterfaceCode::GET_BUNDLE_USER_MGR, data, reply)) {
302         return nullptr;
303     }
304 
305     sptr<IRemoteObject> object = reply.ReadObject<IRemoteObject>();
306     if (object == nullptr) {
307         ACCOUNT_LOGE("read failed");
308         return nullptr;
309     }
310     sptr<IBundleUserMgr> bundleUserMgr = iface_cast<IBundleUserMgr>(object);
311     if (bundleUserMgr == nullptr) {
312         ACCOUNT_LOGE("bundleUserMgr is nullptr");
313     }
314 
315     return bundleUserMgr;
316 }
317 
QueryExtensionAbilityInfos(const Want & want,const int32_t & flag,const int32_t & userId,std::vector<ExtensionAbilityInfo> & extensionInfos)318 bool BundleManagerAdapterProxy::QueryExtensionAbilityInfos(const Want &want, const int32_t &flag,
319     const int32_t &userId, std::vector<ExtensionAbilityInfo> &extensionInfos)
320 {
321     MessageParcel data;
322     if (!data.WriteInterfaceToken(GetDescriptor())) {
323         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write InterfaceToken fail");
324         return false;
325     }
326     if (!data.WriteParcelable(&want)) {
327         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write want fail");
328         return false;
329     }
330     if (!data.WriteInt32(flag)) {
331         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write flag fail");
332         return false;
333     }
334     if (!data.WriteInt32(userId)) {
335         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write userId fail");
336         return false;
337     }
338 
339     if (!GetParcelableInfos(BundleMgrInterfaceCode::QUERY_EXTENSION_INFO_WITHOUT_TYPE, data, extensionInfos)) {
340         ACCOUNT_LOGE("fail to obtain extensionInfos");
341         return false;
342     }
343     return true;
344 }
345 
QueryExtensionAbilityInfos(const Want & want,const ExtensionAbilityType & extensionType,const int32_t & flag,const int32_t & userId,std::vector<ExtensionAbilityInfo> & extensionInfos)346 bool BundleManagerAdapterProxy::QueryExtensionAbilityInfos(const Want &want, const ExtensionAbilityType &extensionType,
347     const int32_t &flag, const int32_t &userId, std::vector<ExtensionAbilityInfo> &extensionInfos)
348 {
349     MessageParcel data;
350     if (!data.WriteInterfaceToken(GetDescriptor())) {
351         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write InterfaceToken fail");
352         return false;
353     }
354     if (!data.WriteParcelable(&want)) {
355         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write want fail");
356         return false;
357     }
358     if (!data.WriteInt32(static_cast<int32_t>(extensionType))) {
359         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write type fail");
360         return false;
361     }
362     if (!data.WriteInt32(flag)) {
363         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write flag fail");
364         return false;
365     }
366     if (!data.WriteInt32(userId)) {
367         ACCOUNT_LOGE("fail to QueryExtensionAbilityInfos due to write userId fail");
368         return false;
369     }
370 
371     if (!GetParcelableInfos(BundleMgrInterfaceCode::QUERY_EXTENSION_INFO, data, extensionInfos)) {
372         ACCOUNT_LOGE("fail to obtain extensionInfos");
373         return false;
374     }
375     return true;
376 }
377 
GetData(void * & buffer,size_t size,const void * data)378 bool BundleManagerAdapterProxy::GetData(void *&buffer, size_t size, const void *data)
379 {
380     if (data == nullptr) {
381         ACCOUNT_LOGE("GetData failed duo to null data");
382         return false;
383     }
384     if (size == 0) {
385         ACCOUNT_LOGE("GetData failed duo to zero size");
386         return false;
387     }
388     buffer = malloc(size);
389     if (buffer == nullptr) {
390         ACCOUNT_LOGE("GetData failed duo to malloc buffer failed");
391         return false;
392     }
393     if (memcpy_s(buffer, size, data, size) != EOK) {
394         free(buffer);
395         ACCOUNT_LOGE("GetData failed duo to memcpy_s failed");
396         return false;
397     }
398     return true;
399 }
400 
401 template<typename T>
GetParcelInfo(BundleMgrInterfaceCode code,MessageParcel & data,T & parcelInfo)402 bool BundleManagerAdapterProxy::GetParcelInfo(BundleMgrInterfaceCode code, MessageParcel &data, T &parcelInfo)
403 {
404     MessageParcel reply;
405     if (!SendTransactCmd(code, data, reply)) {
406         ACCOUNT_LOGE("SendTransactCmd failed");
407         return false;
408     }
409 
410     ErrCode ret = reply.ReadInt32();
411     if (ret != ERR_OK) {
412         ACCOUNT_LOGE("reply result failed , ret = %{public}d", ret);
413         return false;
414     }
415 
416     return InnerGetParcelInfo<T>(reply, parcelInfo);
417 }
418 
419 template<typename T>
InnerGetParcelInfo(MessageParcel & reply,T & parcelInfo)420 bool BundleManagerAdapterProxy::InnerGetParcelInfo(MessageParcel &reply, T &parcelInfo)
421 {
422     size_t dataSize = static_cast<size_t>(reply.ReadInt32());
423     void *buffer = nullptr;
424     if (!GetData(buffer, dataSize, reply.ReadRawData(dataSize))) {
425         ACCOUNT_LOGE("GetData failed");
426         return false;
427     }
428 
429     MessageParcel tmpParcel;
430     if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), dataSize)) {
431         ACCOUNT_LOGE("ParseFrom failed");
432         return false;
433     }
434 
435     std::unique_ptr<T> info(tmpParcel.ReadParcelable<T>());
436     if (info == nullptr) {
437         ACCOUNT_LOGE("ReadParcelableInfo failed");
438         return false;
439     }
440     parcelInfo = *info;
441     return true;
442 }
443 
444 template<typename T>
GetParcelableInfo(BundleMgrInterfaceCode code,MessageParcel & data,T & parcelableInfo)445 bool BundleManagerAdapterProxy::GetParcelableInfo(BundleMgrInterfaceCode code, MessageParcel &data, T &parcelableInfo)
446 {
447     MessageParcel reply;
448     if (!SendTransactCmd(code, data, reply)) {
449         return false;
450     }
451 
452     if (!reply.ReadBool()) {
453         ACCOUNT_LOGE("reply result false");
454         return false;
455     }
456 
457     std::unique_ptr<T> info(reply.ReadParcelable<T>());
458     if (info == nullptr) {
459         ACCOUNT_LOGE("readParcelableInfo failed");
460         return false;
461     }
462     parcelableInfo = *info;
463 
464     return true;
465 }
466 
467 template <typename T>
GetBigParcelableInfo(BundleMgrInterfaceCode code,MessageParcel & data,T & parcelableInfo)468 bool BundleManagerAdapterProxy::GetBigParcelableInfo(
469     BundleMgrInterfaceCode code, MessageParcel &data, T &parcelableInfo)
470 {
471     MessageParcel reply;
472     if (!SendTransactCmd(code, data, reply)) {
473         return false;
474     }
475 
476     if (!reply.ReadBool()) {
477         ACCOUNT_LOGE("reply result false");
478         return false;
479     }
480 
481     if (reply.ReadBool()) {
482         ACCOUNT_LOGI("big reply, reading data from ashmem");
483         return GetParcelableFromAshmem<T>(reply, parcelableInfo);
484     }
485 
486     std::unique_ptr<T> info(reply.ReadParcelable<T>());
487     if (info == nullptr) {
488         ACCOUNT_LOGE("readParcelableInfo failed");
489         return false;
490     }
491     parcelableInfo = *info;
492     ACCOUNT_LOGD("get parcelable info success");
493     return true;
494 }
495 
496 template <typename T>
GetParcelableFromAshmem(MessageParcel & reply,T & parcelableInfo)497 bool BundleManagerAdapterProxy::GetParcelableFromAshmem(MessageParcel &reply, T &parcelableInfo)
498 {
499     sptr<Ashmem> ashmem = reply.ReadAshmem();
500     if (ashmem == nullptr) {
501         ACCOUNT_LOGE("Ashmem is nullptr");
502         return false;
503     }
504 
505     bool ret = ashmem->MapReadOnlyAshmem();
506     if (!ret) {
507         ACCOUNT_LOGE("Map read only ashmem fail");
508         ClearAshmem(ashmem);
509         return false;
510     }
511 
512     int32_t offset = 0;
513     const char* dataStr = static_cast<const char*>(
514         ashmem->ReadFromAshmem(ashmem->GetAshmemSize(), offset));
515     if (dataStr == nullptr) {
516         ACCOUNT_LOGE("Data is nullptr when read from ashmem");
517         ClearAshmem(ashmem);
518         return false;
519     }
520 
521     std::string lenStr;
522     if (!ParseStr(dataStr, ASHMEM_LEN, offset, lenStr)) {
523         ACCOUNT_LOGE("Parse lenStr fail");
524         ClearAshmem(ashmem);
525         return false;
526     }
527 
528     int32_t strLen = 0;
529     if (!StrToInt(lenStr, strLen)) {
530         ACCOUNT_LOGE("Convert lenStr failed");
531         ClearAshmem(ashmem);
532         return false;
533     }
534     offset += ASHMEM_LEN;
535     std::string infoStr;
536     if (!ParseStr(dataStr, strLen, offset, infoStr)) {
537         ACCOUNT_LOGE("Parse infoStr fail");
538         ClearAshmem(ashmem);
539         return false;
540     }
541 
542     if (!ParseInfo(infoStr, parcelableInfo)) {
543         ACCOUNT_LOGE("Parse info from json fail");
544         ClearAshmem(ashmem);
545         return false;
546     }
547 
548     ClearAshmem(ashmem);
549     ACCOUNT_LOGD("Get parcelable vector from ashmem success");
550     return true;
551 }
552 
553 template <typename T>
GetParcelableInfoWithErrCode(BundleMgrInterfaceCode code,MessageParcel & data,T & parcelableInfo)554 ErrCode BundleManagerAdapterProxy::GetParcelableInfoWithErrCode(BundleMgrInterfaceCode code, MessageParcel &data,
555     T &parcelableInfo)
556 {
557     ACCOUNT_LOGE("not support interface!");
558     return ERR_ACCOUNT_COMMON_INTERFACE_NOT_SUPPORT_ERROR;
559 }
560 
561 template<typename T>
GetParcelableInfos(BundleMgrInterfaceCode code,MessageParcel & data,std::vector<T> & parcelableInfos)562 bool BundleManagerAdapterProxy::GetParcelableInfos(BundleMgrInterfaceCode code, MessageParcel &data,
563     std::vector<T> &parcelableInfos)
564 {
565     MessageParcel reply;
566     if (!SendTransactCmd(code, data, reply)) {
567         return false;
568     }
569 
570     if (!reply.ReadBool()) {
571         ACCOUNT_LOGE("readParcelableInfo failed");
572         return false;
573     }
574 
575     int32_t infoSize = reply.ReadInt32();
576     for (int32_t i = 0; i < infoSize; i++) {
577         std::unique_ptr<T> info(reply.ReadParcelable<T>());
578         if (info == nullptr) {
579             ACCOUNT_LOGE("Read Parcelable infos failed");
580             return false;
581         }
582         parcelableInfos.emplace_back(*info);
583     }
584     ACCOUNT_LOGI("get parcelable infos success");
585     return true;
586 }
587 
588 template<typename T>
GetVectorFromParcelIntelligent(BundleMgrInterfaceCode code,MessageParcel & data,std::vector<T> & parcelableInfos)589 bool BundleManagerAdapterProxy::GetVectorFromParcelIntelligent(
590     BundleMgrInterfaceCode code, MessageParcel &data, std::vector<T> &parcelableInfos)
591 {
592     MessageParcel reply;
593     if (!SendTransactCmd(code, data, reply)) {
594         return false;
595     }
596 
597     if (!reply.ReadBool()) {
598         ACCOUNT_LOGE("readParcelableInfo failed");
599         return false;
600     }
601 
602     if (InnerGetVectorFromParcelIntelligent<T>(reply, parcelableInfos) != ERR_OK) {
603         ACCOUNT_LOGE("InnerGetVectorFromParcelIntelligent failed");
604         return false;
605     }
606 
607     return true;
608 }
609 
610 template<typename T>
InnerGetVectorFromParcelIntelligent(MessageParcel & reply,std::vector<T> & parcelableInfos)611 ErrCode BundleManagerAdapterProxy::InnerGetVectorFromParcelIntelligent(
612     MessageParcel &reply, std::vector<T> &parcelableInfos)
613 {
614     size_t dataSize = static_cast<size_t>(reply.ReadInt32());
615     if (dataSize == 0) {
616         ACCOUNT_LOGW("Parcel no data");
617         return ERR_OK;
618     }
619 
620     void *buffer = nullptr;
621     if (!SendData(buffer, dataSize, reply.ReadRawData(dataSize))) {
622         ACCOUNT_LOGE("Fail to read raw data, length = %{public}zu", dataSize);
623         return ERR_APPEXECFWK_PARCEL_ERROR;
624     }
625 
626     MessageParcel tempParcel;
627     if (!tempParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), dataSize)) {
628         ACCOUNT_LOGE("Fail to ParseFrom");
629         return ERR_APPEXECFWK_PARCEL_ERROR;
630     }
631 
632     int32_t infoSize = tempParcel.ReadInt32();
633     for (int32_t i = 0; i < infoSize; i++) {
634         std::unique_ptr<T> info(tempParcel.ReadParcelable<T>());
635         if (info == nullptr) {
636             ACCOUNT_LOGE("Read Parcelable infos failed");
637             return false;
638         }
639         parcelableInfos.emplace_back(*info);
640     }
641 
642     return ERR_OK;
643 }
644 
645 template <typename T>
ParseAshmem(int32_t infoSize,const char * dataStr,int32_t offset,std::vector<T> & parcelableInfos)646 bool BundleManagerAdapterProxy::ParseAshmem(
647     int32_t infoSize, const char* dataStr, int32_t offset, std::vector<T> &parcelableInfos)
648 {
649     if (dataStr == nullptr) {
650         return false;
651     }
652     while (infoSize > 0) {
653         std::string lenStr;
654         if (!ParseStr(dataStr, ASHMEM_LEN, offset, lenStr)) {
655             return false;
656         }
657         int32_t strLen = 0;
658         if (!StrToInt(lenStr, strLen)) {
659             ACCOUNT_LOGE("Convert lenStr failed");
660             return false;
661         }
662         offset += ASHMEM_LEN;
663         std::string infoStr;
664         if (!ParseStr(dataStr, strLen, offset, infoStr)) {
665             return false;
666         }
667         T info;
668         if (!ParseInfo(infoStr, info)) {
669             return false;
670         }
671         parcelableInfos.emplace_back(info);
672         infoSize--;
673         offset += strLen;
674     }
675     return true;
676 }
677 
678 template <typename T>
GetParcelableInfosFromAshmem(BundleMgrInterfaceCode code,MessageParcel & data,std::vector<T> & parcelableInfos)679 bool BundleManagerAdapterProxy::GetParcelableInfosFromAshmem(
680     BundleMgrInterfaceCode code, MessageParcel &data, std::vector<T> &parcelableInfos)
681 {
682     MessageParcel reply;
683     if (!SendTransactCmd(code, data, reply)) {
684         return false;
685     }
686     if (!reply.ReadBool()) {
687         return false;
688     }
689     int32_t infoSize = reply.ReadInt32();
690     if (infoSize > MAX_INFO_SIZE) {
691         ACCOUNT_LOGE("info size is too large");
692         return false;
693     }
694     sptr<Ashmem> ashmem = reply.ReadAshmem();
695     if (ashmem == nullptr) {
696         ACCOUNT_LOGE("Ashmem is nullptr");
697         return false;
698     }
699     if (!ashmem->MapReadOnlyAshmem()) {
700         ACCOUNT_LOGE("Map read only ashmem fail");
701         ClearAshmem(ashmem);
702         return false;
703     }
704     int32_t offset = 0;
705     const char* dataStr = static_cast<const char*>(
706         ashmem->ReadFromAshmem(ashmem->GetAshmemSize(), offset));
707     bool result = ParseAshmem(infoSize, dataStr, offset, parcelableInfos);
708     ClearAshmem(ashmem);
709     return result;
710 }
711 
SendData(void * & buffer,size_t size,const void * data)712 bool BundleManagerAdapterProxy::SendData(void *&buffer, size_t size, const void *data)
713 {
714     if (data == nullptr) {
715         ACCOUNT_LOGE("data is nullptr");
716         return false;
717     }
718 
719     if (size <= 0) {
720         ACCOUNT_LOGE("size is invalid");
721         return false;
722     }
723 
724     buffer = malloc(size);
725     if (buffer == nullptr) {
726         ACCOUNT_LOGE("buffer malloc failed");
727         return false;
728     }
729 
730     if (memcpy_s(buffer, size, data, size) != EOK) {
731         free(buffer);
732         ACCOUNT_LOGE("memcpy_s failed");
733         return false;
734     }
735 
736     return true;
737 }
738 
SendTransactCmd(BundleMgrInterfaceCode code,MessageParcel & data,MessageParcel & reply)739 bool BundleManagerAdapterProxy::SendTransactCmd(
740     BundleMgrInterfaceCode code, MessageParcel &data, MessageParcel &reply)
741 {
742     MessageOption option(MessageOption::TF_SYNC);
743 
744     sptr<IRemoteObject> remote = Remote();
745     if (remote == nullptr) {
746         ACCOUNT_LOGE("fail to send transact cmd %{public}d due to remote object", code);
747         return false;
748     }
749     int32_t result = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option);
750     if (result != NO_ERROR) {
751         ACCOUNT_LOGE("receive error transact code %{public}d in transact cmd %{public}d", result, code);
752         return false;
753     }
754     return true;
755 }
756 }  // namespace AccountSA
757 }  // namespace OHOS
758