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