1 /*
2 * Copyright (c) 2024 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 "common/include/extension_data_handler.h"
17
18 #include <sstream>
19
20 #include <hitrace_meter.h>
21 #include <iremote_proxy.h>
22 #include <message_parcel.h>
23 #include <securec.h>
24 #include <want.h>
25
26 #include "window_manager_hilog.h"
27
28 namespace OHOS::Rosen::Extension {
29
Marshalling(Parcel & parcel) const30 bool DataTransferConfig::Marshalling(Parcel& parcel) const
31 {
32 return parcel.WriteUint8(static_cast<uint8_t>(subSystemId)) && parcel.WriteUint32(customId) &&
33 parcel.WriteBool(needReply) && parcel.WriteBool(needSyncSend);
34 }
35
Unmarshalling(Parcel & parcel)36 DataTransferConfig* DataTransferConfig::Unmarshalling(Parcel& parcel)
37 {
38 auto config = new DataTransferConfig();
39 uint8_t subSystemIdValue = static_cast<uint8_t>(SubSystemId::INVALID);
40 if (!parcel.ReadUint8(subSystemIdValue) || subSystemIdValue >= static_cast<uint8_t>(SubSystemId::INVALID)) {
41 delete config;
42 return nullptr;
43 }
44 if (!parcel.ReadUint32(config->customId) || !parcel.ReadBool(config->needReply) ||
45 !parcel.ReadBool(config->needSyncSend)) {
46 delete config;
47 return nullptr;
48 }
49 config->subSystemId = static_cast<SubSystemId>(subSystemIdValue);
50 return config;
51 }
52
ToString() const53 std::string DataTransferConfig::ToString() const
54 {
55 std::string str;
56 constexpr int BUFFER_SIZE = 128;
57 char buffer[BUFFER_SIZE] = { 0 };
58 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1,
59 "subSystemId: %hhu, customId: %u, needReply: %d, needSyncSend: %d", subSystemId, customId, needReply,
60 needSyncSend) > 0) {
61 str.append(buffer);
62 }
63 return str;
64 }
65
RegisterDataConsumer(SubSystemId subSystemId,DataConsumeCallback && callback)66 DataHandlerErr DataHandler::RegisterDataConsumer(SubSystemId subSystemId, DataConsumeCallback&& callback)
67 {
68 std::lock_guard lock(mutex_);
69 if (consumers_.find(subSystemId) != consumers_.end()) {
70 // A consumer already exists for this subSystemId
71 TLOGE(WmsLogTag::WMS_UIEXT, "Consumer already exists for subSystemId: %{public}hhu", subSystemId);
72 return DataHandlerErr::DUPLICATE_REGISTRATION;
73 }
74 consumers_.emplace(subSystemId, std::move(callback));
75 return DataHandlerErr::OK;
76 }
77
UnregisterDataConsumer(SubSystemId subSystemId)78 void DataHandler::UnregisterDataConsumer(SubSystemId subSystemId)
79 {
80 std::lock_guard lock(mutex_);
81 consumers_.erase(subSystemId);
82 TLOGD(WmsLogTag::WMS_UIEXT, "Unregister consumer for subSystemId: %{public}hhu", subSystemId);
83 }
84
IsProxyObject() const85 bool DataHandler::IsProxyObject() const
86 {
87 std::lock_guard lock(mutex_);
88 return remoteProxy_ && remoteProxy_->IsProxyObject();
89 }
90
PrepareSendData(MessageParcel & data,const DataTransferConfig & config,const AAFwk::Want & toSend)91 DataHandlerErr DataHandler::PrepareSendData(MessageParcel& data, const DataTransferConfig& config,
92 const AAFwk::Want& toSend)
93 {
94 if (IsProxyObject() && !WriteInterfaceToken(data)) {
95 TLOGE(WmsLogTag::WMS_UIEXT, "write interface token failed, %{public}s", config.ToString().c_str());
96 return DataHandlerErr::WRITE_PARCEL_ERROR;
97 }
98
99 if (!data.WriteParcelable(&config)) {
100 TLOGE(WmsLogTag::WMS_UIEXT, "write config failed, %{public}s", config.ToString().c_str());
101 return DataHandlerErr::WRITE_PARCEL_ERROR;
102 }
103
104 if (!data.WriteParcelable(&toSend)) {
105 TLOGE(WmsLogTag::WMS_UIEXT, "write toSend failed, %{public}s", config.ToString().c_str());
106 return DataHandlerErr::WRITE_PARCEL_ERROR;
107 }
108 return DataHandlerErr::OK;
109 }
110
ParseReply(MessageParcel & replyParcel,AAFwk::Want & reply,const DataTransferConfig & config)111 DataHandlerErr DataHandler::ParseReply(MessageParcel& replyParcel, AAFwk::Want& reply, const DataTransferConfig& config)
112 {
113 if (!config.needReply) {
114 return DataHandlerErr::OK;
115 }
116
117 uint32_t replyCode = 0;
118 if (!replyParcel.ReadUint32(replyCode)) {
119 TLOGE(WmsLogTag::WMS_UIEXT, "read replyCode failed, %{public}s", config.ToString().c_str());
120 return DataHandlerErr::READ_PARCEL_ERROR;
121 }
122
123 if (config.needReply) {
124 sptr<AAFwk::Want> response = replyParcel.ReadParcelable<AAFwk::Want>();
125 if (!response) {
126 TLOGE(WmsLogTag::WMS_UIEXT, "read response failed, %{public}s", config.ToString().c_str());
127 return DataHandlerErr::READ_PARCEL_ERROR;
128 }
129 reply = std::move(*response);
130 }
131
132 return static_cast<DataHandlerErr>(replyCode);
133 }
134
135 // process data from peer
NotifyDataConsumer(MessageParcel & recieved,MessageParcel & reply)136 void DataHandler::NotifyDataConsumer(MessageParcel& recieved, MessageParcel& reply)
137 {
138 sptr<DataTransferConfig> config = recieved.ReadParcelable<DataTransferConfig>();
139 if (config == nullptr) {
140 TLOGE(WmsLogTag::WMS_UIEXT, "read config failed");
141 reply.WriteUint32(static_cast<uint32_t>(DataHandlerErr::READ_PARCEL_ERROR));
142 return;
143 }
144
145 sptr<AAFwk::Want> sendWant = recieved.ReadParcelable<AAFwk::Want>();
146 if (sendWant == nullptr) {
147 TLOGE(WmsLogTag::WMS_UIEXT, "read want failed");
148 reply.WriteUint32(static_cast<uint32_t>(DataHandlerErr::READ_PARCEL_ERROR));
149 return;
150 }
151
152 std::optional<AAFwk::Want> replyWant;
153 bool needReply = (config->needSyncSend && config->needReply);
154 if (needReply) {
155 replyWant = std::make_optional<AAFwk::Want>();
156 }
157
158 auto ret = NotifyDataConsumer(std::move(*sendWant), replyWant, *config);
159 reply.WriteUint32(static_cast<uint32_t>(ret));
160 if (needReply && replyWant) {
161 reply.WriteParcelable(&(replyWant.value()));
162 }
163 }
164
SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> & eventHandler)165 void DataHandler::SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler>& eventHandler)
166 {
167 eventHandler_ = eventHandler;
168 }
169
SetRemoteProxyObject(const sptr<IRemoteObject> & remoteObject)170 void DataHandler::SetRemoteProxyObject(const sptr<IRemoteObject>& remoteObject)
171 {
172 std::lock_guard lock(mutex_);
173 remoteProxy_ = remoteObject;
174 }
175
SendDataSync(SubSystemId subSystemId,uint32_t customId,const AAFwk::Want & toSend,AAFwk::Want & reply)176 DataHandlerErr DataHandler::SendDataSync(SubSystemId subSystemId, uint32_t customId, const AAFwk::Want& toSend,
177 AAFwk::Want& reply)
178 {
179 DataTransferConfig config;
180 config.needSyncSend = true;
181 config.needReply = true;
182 config.subSystemId = subSystemId;
183 config.customId = customId;
184 return SendData(toSend, reply, config);
185 }
186
SendDataSync(SubSystemId subSystemId,uint32_t customId,const AAFwk::Want & toSend)187 DataHandlerErr DataHandler::SendDataSync(SubSystemId subSystemId, uint32_t customId, const AAFwk::Want& toSend)
188 {
189 DataTransferConfig config;
190 config.needSyncSend = true;
191 config.subSystemId = subSystemId;
192 config.customId = customId;
193 AAFwk::Want reply;
194 return SendData(toSend, reply, config);
195 }
196
SendDataAsync(SubSystemId subSystemId,uint32_t customId,const AAFwk::Want & toSend)197 DataHandlerErr DataHandler::SendDataAsync(SubSystemId subSystemId, uint32_t customId, const AAFwk::Want& toSend)
198 {
199 DataTransferConfig config;
200 config.subSystemId = subSystemId;
201 config.customId = customId;
202 AAFwk::Want reply;
203 return SendData(toSend, reply, config);
204 }
205
NotifyDataConsumer(AAFwk::Want && data,std::optional<AAFwk::Want> & reply,const DataTransferConfig & config)206 DataHandlerErr DataHandler::NotifyDataConsumer(AAFwk::Want&& data, std::optional<AAFwk::Want>& reply,
207 const DataTransferConfig& config)
208 {
209 DataConsumeCallback callback;
210 {
211 std::lock_guard lock(mutex_);
212 auto it = consumers_.find(config.subSystemId);
213 if (it == consumers_.end()) {
214 TLOGE(WmsLogTag::WMS_UIEXT, "not found, %{public}s", config.ToString().c_str());
215 return DataHandlerErr::NO_CONSUME_CALLBACK;
216 }
217 callback = it->second;
218 }
219
220 if (!callback) {
221 TLOGE(WmsLogTag::WMS_UIEXT, "not callable, %{public}s", config.ToString().c_str());
222 return DataHandlerErr::INVALID_CALLBACK;
223 }
224
225 // sync mode
226 if (config.needSyncSend) {
227 auto ret = callback(config.subSystemId, config.customId, std::move(data), reply);
228 TLOGD(WmsLogTag::WMS_UIEXT, "subSystemId: %{public}hhu, customId: %{public}u, ret: %{public}d",
229 config.subSystemId, config.customId, ret);
230 return DataHandlerErr::OK;
231 }
232
233 // async mode
234 auto task = [input = std::move(data), subSystemId = config.subSystemId, customId = config.customId,
235 func = std::move(callback)]() mutable {
236 std::optional<AAFwk::Want> reply;
237 auto ret = func(subSystemId, customId, std::move(input), reply);
238 TLOGND(WmsLogTag::WMS_UIEXT, "subSystemId: %{public}hhu, customId: %{public}u, ret: %{public}d", subSystemId,
239 customId, ret);
240 };
241
242 std::ostringstream oss;
243 oss << "NotifyDataConsumer_" << static_cast<uint32_t>(config.subSystemId) << "_" << config.customId;
244 PostAsyncTask(std::move(task), oss.str(), 0);
245 return DataHandlerErr::OK;
246 }
247
PostAsyncTask(Task && task,const std::string & name,int64_t delayTime)248 void DataHandler::PostAsyncTask(Task&& task, const std::string& name, int64_t delayTime)
249 {
250 if (!eventHandler_) {
251 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "uiext:%s", name.c_str());
252 task();
253 return;
254 }
255
256 if (auto runner = eventHandler_->GetEventRunner(); !runner || runner->IsCurrentRunnerThread()) {
257 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "uiext:%s", name.c_str());
258 task();
259 return;
260 }
261
262 auto localTask = [task = std::move(task), name] {
263 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "uiext:%s", name.c_str());
264 task();
265 };
266
267 auto ret = eventHandler_->PostTask(std::move(localTask), "uiext:" + name, delayTime,
268 AppExecFwk::EventQueue::Priority::IMMEDIATE);
269 if (!ret) {
270 TLOGE(WmsLogTag::WMS_UIEXT, "Post task failed, name: %{public}s", name.c_str());
271 }
272 }
273 } // namespace OHOS::Rosen::Extension