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 "ash_mem_utils.h"
17 
18 #include <string>
19 
20 #include "hilog/log.h"
21 #include "string_ex.h"
22 
23 #undef LOG_DOMAIN
24 #define LOG_DOMAIN 0xD002D08
25 
26 #undef LOG_TAG
27 #define LOG_TAG "HISYSEVENT_MEMORY_UTILS"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 constexpr char ASH_MEM_NAME[] = "HiSysEventService SharedMemory";
33 constexpr int32_t ASH_MEM_SIZE = 1024 * 769; // 769k
34 
ParseAllStringItemSize(const std::vector<std::u16string> & data,std::vector<std::string> & translatedData,std::vector<uint32_t> & allSize)35 void ParseAllStringItemSize(const std::vector<std::u16string>& data, std::vector<std::string>& translatedData,
36     std::vector<uint32_t>& allSize)
37 {
38     for (auto& item : data) {
39         auto translated = Str16ToStr8(item);
40         translatedData.emplace_back(translated);
41         allSize.emplace_back(strlen(translated.c_str()) + 1);
42     }
43 }
44 }
45 
GetAshmem()46 sptr<Ashmem> AshMemUtils::GetAshmem()
47 {
48     auto ashmem = Ashmem::CreateAshmem(ASH_MEM_NAME, ASH_MEM_SIZE);
49     if (ashmem == nullptr) {
50         HILOG_ERROR(LOG_CORE, "ashmem init failed.");
51         return ashmem;
52     }
53     if (!ashmem->MapReadAndWriteAshmem()) {
54         HILOG_ERROR(LOG_CORE, "ashmem map failed.");
55         return ashmem;
56     }
57     HILOG_DEBUG(LOG_CORE, "ashmem init succeed.");
58     return ashmem;
59 }
60 
CloseAshmem(sptr<Ashmem> ashmem)61 void AshMemUtils::CloseAshmem(sptr<Ashmem> ashmem)
62 {
63     if (ashmem != nullptr) {
64         ashmem->UnmapAshmem();
65         ashmem->CloseAshmem();
66     }
67     HILOG_DEBUG(LOG_CORE, "ashmem closed.");
68 }
69 
WriteBulkData(MessageParcel & parcel,const std::vector<std::u16string> & src)70 sptr<Ashmem> AshMemUtils::WriteBulkData(MessageParcel& parcel, const std::vector<std::u16string>& src)
71 {
72     std::vector<std::string> allData;
73     std::vector<uint32_t> allSize;
74     ParseAllStringItemSize(src, allData, allSize);
75     if (!parcel.WriteUInt32Vector(allSize)) {
76         HILOG_ERROR(LOG_CORE, "writing allSize array failed.");
77         return nullptr;
78     }
79     auto ashmem = GetAshmem();
80     if (ashmem == nullptr) {
81         return nullptr;
82     }
83     uint32_t offset = 0;
84     for (uint32_t i = 0; i < allData.size(); i++) {
85         auto translated = allData[i].c_str();
86         if (!ashmem->WriteToAshmem(translated, strlen(translated), offset)) {
87             HILOG_ERROR(LOG_CORE, "writing ashmem failed.");
88             CloseAshmem(ashmem);
89             return nullptr;
90         }
91         offset += allSize[i];
92     }
93     if (!parcel.WriteAshmem(ashmem)) {
94         HILOG_ERROR(LOG_CORE, "writing ashmem failed.");
95         CloseAshmem(ashmem);
96         return nullptr;
97     }
98     return ashmem;
99 }
100 
ReadBulkData(MessageParcel & parcel,std::vector<std::u16string> & dest)101 bool AshMemUtils::ReadBulkData(MessageParcel& parcel, std::vector<std::u16string>& dest)
102 {
103     std::vector<uint32_t> allSize;
104     if (!parcel.ReadUInt32Vector(&allSize)) {
105         HILOG_ERROR(LOG_CORE, "reading allSize array failed.");
106         return false;
107     }
108     auto ashmem = parcel.ReadAshmem();
109     if (ashmem == nullptr) {
110         HILOG_ERROR(LOG_CORE, "reading ashmem failed.");
111         return false;
112     }
113     bool ret = ashmem->MapReadAndWriteAshmem();
114     if (!ret) {
115         HILOG_ERROR(LOG_CORE, "mapping read only ashmem failed.");
116         CloseAshmem(ashmem);
117         return false;
118     }
119     uint32_t offset = 0;
120     for (uint32_t i = 0; i < allSize.size(); i++) {
121         auto origin = ashmem->ReadFromAshmem(allSize[i], offset);
122         dest.emplace_back(Str8ToStr16(std::string(reinterpret_cast<const char*>(origin))));
123         offset += allSize[i];
124     }
125     CloseAshmem(ashmem);
126     return true;
127 }
128 } // namespace HiviewDFX
129 } // namespace OHOS
130