• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "message_parcel_warp.h"
17 
18 #include <sys/mman.h>
19 #include <sys/syscall.h>
20 #include <unistd.h>
21 
22 #include "api/visibility.h"
23 #include "ashmem.h"
24 #include "parameters.h"
25 #include "parcel.h"
26 #include "pasteboard_hilog.h"
27 #include "securec.h"
28 
29 namespace OHOS {
30 namespace MiscServices {
31 
32 constexpr int64_t SIZE_K = 1024;
33 constexpr int32_t KERNEL_MAX_SIZE = 2048; // 2G
34 constexpr size_t MIN_RAW_SIZE = 32 * 1024; // 32k
35 constexpr int32_t DEFAULT_LOCAL_CAPACITY = 128;
36 constexpr size_t WRITE_SPLIT_CHUNK_SIZE = 256 * 1024 * 1024;
37 
MessageParcelWarp()38 MessageParcelWarp::MessageParcelWarp()
39 {
40     writeRawDataFd_ = -1;
41     readRawDataFd_ = -1;
42     kernelMappedWrite_ = nullptr;
43     kernelMappedRead_ = nullptr;
44     rawData_ = nullptr;
45     rawDataSize_ = 0;
46     canWrite_ = true;
47     canRead_ = true;
48     static int32_t paramMaxSize =
49         OHOS::system::GetIntParameter("const.pasteboard.local_data_capacity", DEFAULT_LOCAL_CAPACITY);
50     PASTEBOARD_CHECK_AND_RETURN_LOGE(paramMaxSize >= DEFAULT_LOCAL_CAPACITY && paramMaxSize <= KERNEL_MAX_SIZE,
51         PASTEBOARD_MODULE_COMMON, "invalid param, max_raw_size=%{public}d", paramMaxSize);
52     maxRawDataSize_ = paramMaxSize * SIZE_K * SIZE_K;
53 }
54 
~MessageParcelWarp()55 MessageParcelWarp::~MessageParcelWarp()
56 {
57     if (kernelMappedWrite_ != nullptr) {
58         ::munmap(kernelMappedWrite_, rawDataSize_);
59         kernelMappedWrite_ = nullptr;
60     }
61     if (kernelMappedRead_ != nullptr) {
62         ::munmap(kernelMappedRead_, rawDataSize_);
63         kernelMappedRead_ = nullptr;
64     }
65 
66     if (readRawDataFd_ >= 0) {
67         ::close(readRawDataFd_);
68         readRawDataFd_ = -1;
69     }
70     if (writeRawDataFd_ >= 0) {
71         ::close(writeRawDataFd_);
72         writeRawDataFd_ = -1;
73     }
74     rawData_ = nullptr;
75     rawDataSize_ = 0;
76     canWrite_ = false;
77     canRead_ = false;
78 }
79 
MemcpyData(void * ptr,size_t size,const void * data,size_t count)80 bool MessageParcelWarp::MemcpyData(void *ptr, size_t size, const void *data, size_t count)
81 {
82     if (size <= WRITE_SPLIT_CHUNK_SIZE) {
83         if (memcpy_s(ptr, size, data, count) != EOK) {
84             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "memcpy_s failed, size:%{public}zu", size);
85             return false;
86         }
87         return true;
88     }
89     char* ptrDest = static_cast<char*>(ptr);
90     const char* ptrSrc = static_cast<const char*>(data);
91     size_t remaining = size;
92     size_t offset = 0;
93     while (remaining > 0) {
94         size_t currentChunkSize = (remaining > WRITE_SPLIT_CHUNK_SIZE) ? WRITE_SPLIT_CHUNK_SIZE : remaining;
95         size_t destSize = size - offset;
96         size_t destChunkCount = currentChunkSize;
97         size_t copyCount = (destChunkCount <= destSize) ? destChunkCount : destSize;
98         if (memcpy_s(ptrDest + offset, copyCount, ptrSrc + offset, currentChunkSize) != EOK) {
99             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "memcpy_s failed, size:%{public}zu", size);
100             return false;
101         }
102         offset += currentChunkSize;
103         remaining -= currentChunkSize;
104     }
105     return true;
106 }
107 
WriteRawData(MessageParcel & parcelPata,const void * data,size_t size)108 bool MessageParcelWarp::WriteRawData(MessageParcel &parcelPata, const void *data, size_t size)
109 {
110     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(canWrite_, false,
111         PASTEBOARD_MODULE_COMMON, "is already write, size:%{public}zu", size);
112     canWrite_ = false;
113     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(data != nullptr, false, PASTEBOARD_MODULE_COMMON, "data is null");
114     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(0 < size && static_cast<int64_t>(size) <= maxRawDataSize_, false,
115         PASTEBOARD_MODULE_COMMON, "size invalid, size:%{public}zu", size);
116     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(kernelMappedWrite_ == nullptr, false,
117         PASTEBOARD_MODULE_COMMON, "kernelMappedWrite_ not null end.");
118     if (!parcelPata.WriteInt64(size)) {
119         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "data WriteInt64 failed end.");
120         return false;
121     }
122     if (size <= MIN_RAW_SIZE) {
123         rawDataSize_ = size;
124         return parcelPata.WriteUnpadBuffer(data, size);
125     }
126     int fd = AshmemCreate("Pasteboard Ashmem", size);
127     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(fd >= 0, false, PASTEBOARD_MODULE_COMMON, "ashmem create failed");
128 
129     writeRawDataFd_ = fd;
130     int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
131     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(result >= 0, false, PASTEBOARD_MODULE_COMMON, "ashmem set port failed");
132 
133     void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
134     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ptr != MAP_FAILED, false,
135         PASTEBOARD_MODULE_COMMON, "mmap failed, fd:%{public}d size:%{public}zu", fd, size);
136 
137     if (!parcelPata.WriteFileDescriptor(fd)) {
138         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "write file descriptor failed, size:%{public}zu", size);
139         ::munmap(ptr, size);
140         return false;
141     }
142     if (!MemcpyData(ptr, size, data, size)) {
143         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "memcpy_s failed, fd:%{public}d size:%{public}zu", fd, size);
144         ::munmap(ptr, size);
145         return false;
146     }
147     kernelMappedWrite_ = ptr;
148     rawDataSize_ = size;
149     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "write ashmem end. fd:%{public}d size:%{public}zu", fd, size);
150     return true;
151 }
152 
ReadRawData(MessageParcel & parcelPata,size_t size)153 const void *MessageParcelWarp::ReadRawData(MessageParcel &parcelPata, size_t size)
154 {
155     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(canRead_, nullptr,
156         PASTEBOARD_MODULE_COMMON, "is already write, size:%{public}zu", size);
157     canRead_ = false;
158     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(0 < size && static_cast<int64_t>(size) <= maxRawDataSize_, nullptr,
159         PASTEBOARD_MODULE_COMMON, "size invalid, size:%{public}zu", size);
160     size_t bufferSize = static_cast<size_t>(parcelPata.ReadInt64());
161     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(bufferSize == size, nullptr, PASTEBOARD_MODULE_COMMON,
162         "buffer size not equal size, bufferSize:%{public}zu size:%{public}zu", bufferSize, size);
163     if (bufferSize <= MIN_RAW_SIZE) {
164         rawDataSize_ = size;
165         return parcelPata.ReadUnpadBuffer(size);
166     }
167 
168     int fd = parcelPata.ReadFileDescriptor();
169     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(fd >= 0, nullptr,
170         PASTEBOARD_MODULE_COMMON, "read file descriptor failed fd:%{public}d", fd);
171     readRawDataFd_ = fd;
172 
173     void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
174     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ptr != MAP_FAILED, nullptr,
175         PASTEBOARD_MODULE_COMMON, "mmap failed, fd:%{public}d size:%{public}zu", fd, size);
176 
177     kernelMappedRead_ = ptr;
178     rawDataSize_ = size;
179     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "read ashmem end. fd:%{public}d size:%{public}zu", fd, size);
180     return ptr;
181 }
182 
CreateTmpFd()183 int MessageParcelWarp::CreateTmpFd()
184 {
185     int fd = AshmemCreate("PasteboardTmpAshmem", 1);
186     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(fd >= 0, -1, PASTEBOARD_MODULE_COMMON, "ashmem create failed");
187     writeRawDataFd_ = fd;
188     return fd;
189 }
190 
GetWriteDataFd()191 int MessageParcelWarp::GetWriteDataFd()
192 {
193     return writeRawDataFd_;
194 }
195 }
196 }