• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #define LOG_TAG "ObserverProxy"
17 #include "data_share_obs_proxy.h"
18 #include "datashare_errno.h"
19 #include "dataproxy_handle_common.h"
20 
21 #include "itypes_util.h"
22 #include "datashare_itypes_utils.h"
23 #include "log_print.h"
24 #include "log_debug.h"
25 
26 namespace OHOS {
27 namespace DataShare {
28 static constexpr int REQUEST_CODE = 0;
29 // length of int32 bytes
30 static constexpr int32_t INT32_BYTE_LEN = static_cast<int32_t>(sizeof(int32_t));
31 // using DATA_SIZEASHMEM_TRANSFER_LIMIT as the maximum length of changeNode.data_[i]
32 static constexpr size_t MAX_STR_LEN = static_cast<size_t>(DATA_SIZE_ASHMEM_TRANSFER_LIMIT);
33 // maximum size of changeNode.data_(all 0-length strings)
34 static constexpr size_t MAX_DATA_SIZE = MAX_STR_LEN >> 2;
CreateAshmem(RdbChangeNode & changeNode)35 int RdbObserverProxy::CreateAshmem(RdbChangeNode &changeNode)
36 {
37     OHOS::sptr<Ashmem> memory = Ashmem::CreateAshmem(ASHMEM_NAME, DATA_SIZE_ASHMEM_TRANSFER_LIMIT);
38     if (memory == nullptr) {
39         ZLOGE("failed to create Ashmem instance.");
40         return E_ERROR;
41     }
42     bool mapRet = memory->MapReadAndWriteAshmem();
43     if (!mapRet) {
44         ZLOGE("failed to map read and write ashmem, ret=%{public}d", mapRet);
45         memory->CloseAshmem();
46         return E_ERROR;
47     }
48     if (changeNode.memory_ != nullptr) {
49         ZLOGE("Unknown error: changeNode.memory_ should be null, but something is there.");
50         return E_ERROR;
51     }
52     changeNode.memory_ = memory;
53     return E_OK;
54 }
55 
WriteAshmem(RdbChangeNode & changeNode,void * data,int32_t len,int32_t & offset)56 int RdbObserverProxy::WriteAshmem(RdbChangeNode &changeNode, void *data, int32_t len, int32_t &offset)
57 {
58     if (changeNode.memory_ == nullptr) {
59         ZLOGE("changeNode memory is nullptr.");
60         return E_ERROR;
61     }
62     bool writeRet = changeNode.memory_->WriteToAshmem(data, len, offset);
63     if (!writeRet) {
64         ZLOGE("failed to write into ashmem, ret=%{public}d", writeRet);
65         changeNode.memory_->UnmapAshmem();
66         changeNode.memory_->CloseAshmem();
67         changeNode.memory_ = nullptr;
68         return E_ERROR;
69     }
70     offset += len;
71     return E_OK;
72 }
73 
SerializeDataIntoAshmem(RdbChangeNode & changeNode)74 int RdbObserverProxy::SerializeDataIntoAshmem(RdbChangeNode &changeNode)
75 {
76     if (changeNode.memory_ == nullptr) {
77         ZLOGE("changeNode.memory_ is nullptr");
78         return E_ERROR;
79     }
80     // move data
81     // simple serialization: [vec_size(int32); str1_len(int32), str1; str2_len(int32), str2; ...],
82     // total byte size is recorded in changeNode.size
83     int32_t offset = 0;
84     size_t dataSize = changeNode.data_.size();
85     // maximum dataSize
86     if (dataSize > MAX_DATA_SIZE) {
87         ZLOGE("changeNode size:%{public}zu, exceeds the maximum limit.", dataSize);
88         return E_ERROR;
89     }
90     if (WriteAshmem(changeNode, (void *)&dataSize, INT32_BYTE_LEN, offset) != E_OK) {
91         ZLOGE("failed to write data with len %{public}d, offset %{public}d.", INT32_BYTE_LEN, offset);
92         return E_ERROR;
93     }
94     for (size_t i = 0; i < dataSize; i++) {
95         const char *str = changeNode.data_[i].c_str();
96         size_t uStrLen = changeNode.data_[i].length();
97         // maximum strLen
98         if (uStrLen > MAX_STR_LEN) {
99             ZLOGE("string length:%{public}zu, exceeds the maximum limit.", uStrLen);
100             return E_ERROR;
101         }
102         int32_t strLen = static_cast<int32_t>(uStrLen);
103         // write length int
104         if (WriteAshmem(changeNode, (void *)&strLen, INT32_BYTE_LEN, offset) != E_OK) {
105             ZLOGE("failed to write data with index %{public}zu, len %{public}d, offset %{public}d.",
106                 i, INT32_BYTE_LEN, offset);
107             return E_ERROR;
108         }
109         // write str
110         if (WriteAshmem(changeNode, (void *)str, strLen, offset) != E_OK) {
111             ZLOGE("failed to write data with index %{public}zu, len %{public}d, offset %{public}d.",
112                 i, strLen, offset);
113             return E_ERROR;
114         }
115     }
116     changeNode.size_ = offset;
117     return E_OK;
118 }
119 
PrepareRdbChangeNodeData(RdbChangeNode & changeNode)120 int RdbObserverProxy::PrepareRdbChangeNodeData(RdbChangeNode &changeNode)
121 {
122     // If data size is bigger than the limit, move it to the shared memory
123     int32_t size = INT32_BYTE_LEN;
124     size_t dataSize = changeNode.data_.size();
125     // maximum dataSize
126     if (dataSize > MAX_DATA_SIZE) {
127         ZLOGE("changeNode size:%{public}zu, exceeds the maximum limit.", dataSize);
128         return E_ERROR;
129     }
130     for (size_t i = 0; i < dataSize; i++) {
131         size += INT32_BYTE_LEN;
132         size_t uStrLen = changeNode.data_[i].length();
133         // maximum strLen
134         if (uStrLen > DATA_SIZE_ASHMEM_TRANSFER_LIMIT) {
135             ZLOGE("string length:%{public}zu, exceeds the maximum limit.", uStrLen);
136             return E_ERROR;
137         }
138         int32_t strLen = static_cast<int32_t>(uStrLen);
139         size += strLen;
140     }
141     if (size > DATA_SIZE_ASHMEM_TRANSFER_LIMIT) {
142         ZLOGE("Data to write into ashmem is %{public}d bytes, over 10M.", size);
143         return E_ERROR;
144     }
145     if (size > DATA_SIZE_IPC_TRANSFER_LIMIT) {
146         ZLOGD_MACRO("Data size is over 200k, transfer it by the shared memory");
147         if (RdbObserverProxy::CreateAshmem(changeNode) != E_OK) {
148             ZLOGE("failed to create ashmem.");
149             return E_ERROR;
150         }
151         if (RdbObserverProxy::SerializeDataIntoAshmem(changeNode) != E_OK) {
152             ZLOGE("failed to serialize data into ashmem.");
153             return E_ERROR;
154         }
155         // clear original data spot
156         changeNode.data_.clear();
157         changeNode.isSharedMemory_ = true;
158         ZLOGD_MACRO("Preparation done. Data size: %{public}d", changeNode.size_);
159     }
160     return E_OK;
161 }
162 
OnChangeFromRdb(RdbChangeNode & changeNode)163 void RdbObserverProxy::OnChangeFromRdb(RdbChangeNode &changeNode)
164 {
165     MessageParcel parcel;
166     if (!parcel.WriteInterfaceToken(RdbObserverProxy::GetDescriptor())) {
167         return;
168     }
169 
170     if (RdbObserverProxy::PrepareRdbChangeNodeData(changeNode) != E_OK) {
171         ZLOGE("failed to prepare RdbChangeNode data.");
172         return;
173     }
174 
175     if (!ITypesUtil::Marshal(parcel, changeNode)) {
176         ZLOGE("failed to WriteParcelable changeNode ");
177         return;
178     }
179 
180     MessageParcel reply;
181     MessageOption option;
182     int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option);
183     if (result != ERR_NONE) {
184         ZLOGE("SendRequest error, result=%{public}d", result);
185         return;
186     }
187     ZLOGI("SendRequest ok, retval is %{public}d", reply.ReadInt32());
188 }
189 
OnChangeFromPublishedData(PublishedDataChangeNode & changeNode)190 void PublishedDataObserverProxy::OnChangeFromPublishedData(PublishedDataChangeNode &changeNode)
191 {
192     MessageParcel parcel;
193     if (!parcel.WriteInterfaceToken(PublishedDataObserverProxy::GetDescriptor())) {
194         return;
195     }
196 
197     if (!ITypesUtil::Marshal(parcel, changeNode)) {
198         ZLOGE("failed to WriteParcelable changeNode ");
199         return;
200     }
201 
202     MessageParcel reply;
203     MessageOption option;
204     int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option);
205     if (result != ERR_NONE) {
206         ZLOGE("SendRequest error, result=%{public}d", result);
207         return;
208     }
209     ZLOGD("SendRequest ok, retval is %{public}d", reply.ReadInt32());
210 }
211 
OnChangeFromProxyData(std::vector<DataProxyChangeInfo> & changeInfo)212 void ProxyDataObserverProxy::OnChangeFromProxyData(std::vector<DataProxyChangeInfo> &changeInfo)
213 {
214     MessageParcel parcel;
215     if (!parcel.WriteInterfaceToken(PublishedDataObserverProxy::GetDescriptor())) {
216         return;
217     }
218 
219     if (!ITypesUtil::Marshal(parcel, changeInfo)) {
220         ZLOGE("failed to WriteParcelable changeNode ");
221         return;
222     }
223 
224     MessageParcel reply;
225     MessageOption option;
226     int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option);
227     if (result != ERR_NONE) {
228         ZLOGE("SendRequest error, result=%{public}d", result);
229         return;
230     }
231     ZLOGI("SendRequest ok, retval is %{public}d", reply.ReadInt32());
232 }
233 } // namespace DataShare
234 } // namespace OHOS