1 /*
2 * Copyright (c) 2021 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 <fstream>
17 #include <iostream>
18 #include <cinttypes>
19
20 #include "app_log_wrapper.h"
21 #include "form_provider_data.h"
22 #include "message_parcel.h"
23 #include "string_ex.h"
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 const int IMAGE_DATA_STATE_REMOVED = -1;
28 const int IMAGE_DATA_STATE_NO_OPERATION = 0;
29 const int IMAGE_DATA_STATE_ADDED = 1;
30 const std::string JSON_EMPTY_STRING = "{}";
31
32 /**
33 * @brief Constructor.
34 */
FormProviderData()35 FormProviderData::FormProviderData()
36 {
37 jsonFormProviderData_.clear();
38 }
39
40 /**
41 * @brief A constructor used to create a {@code FormProviderData} instance with data of
42 * the {@code nlohmann::json} type specified.
43 * @param jsonData Indicates the data to be carried in the new {@code FormProviderData} instance,
44 * in {@code nlohmann::json} format.
45 */
FormProviderData(nlohmann::json & jsonData)46 FormProviderData::FormProviderData(nlohmann::json &jsonData)
47 {
48 jsonFormProviderData_ = jsonData;
49 }
50
51 /**
52 * @brief A constructor used to create a {@code FormProviderData} instance with data of the {@code String} type
53 * specified.
54 * @param jsonDataString Indicates the data to be carried in the new {@code FormProviderData} instance,
55 * in JSON string format.
56 */
FormProviderData(std::string jsonDataString)57 FormProviderData::FormProviderData(std::string jsonDataString)
58 {
59 if(jsonDataString.empty()) {
60 jsonDataString = JSON_EMPTY_STRING;
61 }
62 jsonFormProviderData_ = nlohmann::json::parse(jsonDataString);
63 }
64
65 /**
66 * @brief Updates form data in this {@code FormProviderData} object.
67 * @param jsonData Indicates the new data to use, in {@code ZSONObject} format.
68 */
UpdateData(nlohmann::json & jsonData)69 void FormProviderData::UpdateData(nlohmann::json &jsonData)
70 {
71 jsonFormProviderData_ = jsonData;
72 }
73 /**
74 * @brief Obtains the form data stored in this {@code FormProviderData} object.
75 * @return Returns json data
76 */
GetData() const77 nlohmann::json FormProviderData::GetData() const
78 {
79 return jsonFormProviderData_;
80 }
81 /**
82 * @brief Obtains the form data stored in this {@code FormProviderData} object.
83 * @return Returns json string format
84 */
GetDataString() const85 std::string FormProviderData::GetDataString() const
86 {
87 APP_LOGI("%{public}s called", __func__);
88 std::string dataStr = jsonFormProviderData_.empty() ? "" : jsonFormProviderData_.dump();
89 APP_LOGI("%{public}s, data: %{public}s", __func__, dataStr.c_str());
90 return dataStr;
91 }
92
93 /**
94 * @brief Adds an image to this {@code FormProviderData} instance.
95 * @param picName Indicates the name of the image to add.
96 * @param data Indicates the binary data of the image content.
97 */
AddImageData(std::string picName,char * data)98 void FormProviderData::AddImageData(std::string picName, char *data)
99 {
100 if ((picName.length() == 0) || (sizeof(data) == 0)) {
101 APP_LOGE("input param is NULL!");
102 return;
103 }
104
105 rawImageBytesMap_[picName] = data;
106
107 imageDataState_ = IMAGE_DATA_STATE_ADDED;
108 }
109
110 /**
111 * @brief Removes data of an image with the specified {@code picName} from this {@code FormProviderData} instance.
112 * @param picName Indicates the name of the image to remove.
113 */
RemoveImageData(std::string picName)114 void FormProviderData::RemoveImageData(std::string picName)
115 {
116 rawImageBytesMap_.erase(picName);
117 }
118
119 /**
120 * @brief Set the form data stored from string string.
121 * @param Returns string string.
122 */
SetDataString(std::string & jsonDataString)123 void FormProviderData::SetDataString(std::string &jsonDataString)
124 {
125 APP_LOGI("%{public}s called", __func__);
126 if(jsonDataString.empty()) {
127 jsonDataString = JSON_EMPTY_STRING;
128 }
129 jsonFormProviderData_ = nlohmann::json::parse(jsonDataString);
130 }
131 /**
132 * @brief Merge new data to FormProviderData.
133 * @param addJsonData data to merge to FormProviderData
134 */
MergeData(nlohmann::json & addJsonData)135 void FormProviderData::MergeData(nlohmann::json &addJsonData)
136 {
137 APP_LOGI("%{public}s called", __func__);
138 if (addJsonData.empty()) {
139 return;
140 }
141
142 if (jsonFormProviderData_.empty()) {
143 jsonFormProviderData_ = addJsonData;
144 return;
145 }
146
147 for (auto && [key, value] : addJsonData.items()) {
148 jsonFormProviderData_[key] = value;
149 }
150 }
151
152 /**
153 * @brief Obtains the imageDataMap stored in this {@code FormProviderData} object.
154 * @return Returns the map that contains shared image data.
155 */
GetImageDataMap()156 std::map<std::string, std::pair<sptr<Ashmem>, int32_t>> FormProviderData::GetImageDataMap()
157 {
158 return imageDataMap_;
159 }
160
161 /**
162 * @brief Obtains the add/remove state stored in this {@code FormProviderData} object.
163 * @return Returns the add/remove state of shared image data.
164 */
GetImageDataState()165 int32_t FormProviderData::GetImageDataState()
166 {
167 return imageDataState_;
168 }
169
170 /**
171 * @brief Updates imageDataState in this {@code FormProviderData} object.
172 * @param imageDataState Indicates the imageDataState to update.
173 */
SetImageDataState(int32_t imageDataState)174 void FormProviderData::SetImageDataState(int32_t imageDataState)
175 {
176 imageDataState_ = imageDataState;
177 }
178
179 /**
180 * @brief Updates imageDataMap in this {@code FormProviderData} object.
181 * @param imageDataMap Indicates the imageDataMap to update.
182 */
SetImageDataMap(std::map<std::string,std::pair<sptr<Ashmem>,int32_t>> imageDataMap)183 void FormProviderData::SetImageDataMap(std::map<std::string, std::pair<sptr<Ashmem>, int32_t>> imageDataMap)
184 {
185 imageDataMap_ = imageDataMap;
186 }
187
188 /**
189 * Read this {@code FormProviderData} object from a Parcel.
190 * @param parcel the parcel
191 * eturn Returns {@code true} if the marshalling is successful; returns {@code false} otherwise.
192 */
ReadFromParcel(Parcel & parcel)193 bool FormProviderData::ReadFromParcel(Parcel &parcel)
194 {
195 jsonFormProviderData_ = nlohmann::json::parse(Str16ToStr8(parcel.ReadString16()));
196
197 imageDataState_ = parcel.ReadInt32();
198 switch (imageDataState_) {
199 case IMAGE_DATA_STATE_ADDED: {
200 int32_t imageDataNum = parcel.ReadInt32();
201 for (int32_t i = 0; i < imageDataNum; i++) {
202 MessageParcel* messageParcel = (MessageParcel*)&parcel;
203 sptr<Ashmem> ashmem = messageParcel->ReadAshmem();
204 if (ashmem == nullptr) {
205 APP_LOGE("%{public}s failed, ashmem is nullptr", __func__);
206 return false;
207 }
208
209 int32_t len = parcel.ReadInt32();
210 std::pair<sptr<Ashmem>, int32_t> imageDataRecord = std::make_pair(ashmem, len);
211 imageDataMap_.emplace(Str16ToStr8(parcel.ReadString16()), imageDataRecord);
212 }
213 break;
214 }
215 case IMAGE_DATA_STATE_NO_OPERATION:
216 case IMAGE_DATA_STATE_REMOVED:
217 break;
218 default:
219 APP_LOGW("%{public}s failed, unexpected imageDataState_ %{public}d", __func__, imageDataState_);
220 break;
221 }
222 return true;
223 }
224
225 /**
226 * @brief Marshals this {@code FormProviderData} object into a {@link ohos.utils.Parcel} object.
227 * @param parcel Indicates the {@code Parcel} object for marshalling.
228 * @return Returns {@code true} if the marshalling is successful; returns {@code false} otherwise.
229 */
Marshalling(Parcel & parcel) const230 bool FormProviderData::Marshalling(Parcel &parcel) const
231 {
232 APP_LOGI("%{public}s called, jsonFormProviderData_: %{public}s", __func__, jsonFormProviderData_.dump().c_str());
233 if (!parcel.WriteString16(Str8ToStr16(jsonFormProviderData_.empty() ? JSON_EMPTY_STRING : jsonFormProviderData_.dump()))) {
234 return false;
235 }
236
237 parcel.WriteInt32(imageDataState_);
238 switch (imageDataState_) {
239 case IMAGE_DATA_STATE_ADDED: {
240 if (rawImageBytesMap_.size() == 0) {
241 APP_LOGE("%{public}s failed, rawImageBytesMap_ is empty", __func__);
242 return false;
243 }
244 parcel.WriteInt32(rawImageBytesMap_.size()); // firstly write the number of shared image to add
245 for (auto &entry : rawImageBytesMap_) {
246 if (!WriteImageDataToParcel(parcel, entry.first, entry.second)) {
247 APP_LOGE("%{public}s failed, the picture name is %{public}s", __func__, entry.first.c_str());
248 return false;
249 }
250 parcel.WriteInt32(sizeof(entry.second));
251 parcel.WriteString16(Str8ToStr16(entry.first));
252 }
253 break;
254 }
255 case IMAGE_DATA_STATE_NO_OPERATION:
256 case IMAGE_DATA_STATE_REMOVED:
257 break;
258 default:
259 APP_LOGW("%{public}s failed, unexpected imageDataState_ %{public}d", __func__, imageDataState_);
260 break;
261 }
262 return true;
263 }
264
265 /**
266 * @brief Unmarshals this {@code FormProviderData} object from a {@link ohos.utils.Parcel} object.
267 * @param parcel Indicates the {@code Parcel} object for unmarshalling.
268 * @return FormProviderData.
269 */
Unmarshalling(Parcel & parcel)270 FormProviderData* FormProviderData::Unmarshalling(Parcel &parcel)
271 {
272 FormProviderData *formProviderData = new (std::nothrow) FormProviderData();
273 if (formProviderData && !formProviderData->ReadFromParcel(parcel)) {
274 delete formProviderData;
275 formProviderData = nullptr;
276 }
277 std::string str = formProviderData->GetDataString();
278 APP_LOGI("%{public}s, , provider data length: %{public}zu, provider data: %{public}s", __func__, str.length(), str.c_str());
279 return formProviderData;
280 }
281
282 /**
283 * @brief Clear imageDataMap, rawImageBytesMap_, imageDataState_ and jsonFormProviderData_.
284 */
ClearData()285 void FormProviderData::ClearData()
286 {
287 jsonFormProviderData_.clear();
288 }
289
WriteImageDataToParcel(Parcel & parcel,std::string picName,char * data) const290 bool FormProviderData::WriteImageDataToParcel(Parcel &parcel, std::string picName, char *data) const
291 {
292 sptr<Ashmem> ashmem = Ashmem::CreateAshmem(picName.c_str(), sizeof(data));
293 if (ashmem == nullptr) {
294 APP_LOGE("create shared memory fail");
295 return false;
296 }
297
298 bool ret = ashmem->MapReadAndWriteAshmem();
299 if (!ret) {
300 APP_LOGE("map shared memory fail");
301 return false;
302 }
303
304 ret = ashmem->WriteToAshmem(data, sizeof(data), 0);
305 if (!ret) {
306 APP_LOGE("write image data to shared memory fail");
307 return false;
308 }
309
310 ashmem->UnmapAshmem();
311
312 MessageParcel* messageParcel = (MessageParcel*)&parcel;
313 ret = messageParcel->WriteAshmem(ashmem);
314
315 ashmem->CloseAshmem(); // close ashmem after writeAshmem because writeAshmem will dup fd
316 if (!ret) {
317 APP_LOGE("writeAshmem fail, the picture name is %{public}s", picName.c_str());
318 return false;
319 }
320
321 return true;
322 }
323 } // namespace AppExecFwk
324 } // namespace OHOS
325