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 "stationary_server.h"
17 #ifdef MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
18 #include "hisysevent.h"
19 #endif // MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
20 #ifdef MSDP_HIVIEWDFX_HITRACE_ENABLE
21 #include "hitrace_meter.h"
22 #endif // MSDP_HIVIEWDFX_HITRACE_ENABLE
23
24 #include "default_params.h"
25 #include "devicestatus_define.h"
26 #include "devicestatus_dumper.h"
27 #include "devicestatus_hisysevent.h"
28 #include "stationary_data.h"
29 #include "stationary_params.h"
30
31 #undef LOG_TAG
32 #define LOG_TAG "StationaryServer"
33
34 namespace OHOS {
35 namespace Msdp {
36 namespace DeviceStatus {
37 namespace {
38 #ifdef MOTION_ENABLE
39 constexpr int32_t MOTION_TYPE_STAND = 3602;
40 constexpr int32_t STATUS_ENTER = 1;
41 constexpr int32_t STATUS_EXIT = 0;
42 std::map<Type, int32_t> MOTION_TYPE_MAP {
43 { Type::TYPE_STAND, MOTION_TYPE_STAND },
44 };
45 std::map<int32_t, Type> DEVICE_STATUS_TYPE_MAP {
46 { MOTION_TYPE_STAND, Type::TYPE_STAND },
47 };
48 #else
49 constexpr int32_t RET_NO_SUPPORT = 801;
50 #endif
51 } // namespace
52
53 #ifdef MOTION_ENABLE
OnMotionChanged(const MotionEvent & motionEvent)54 void MotionCallback::OnMotionChanged(const MotionEvent &motionEvent)
55 {
56 Data data;
57 data.type = DEVICE_STATUS_TYPE_MAP[motionEvent.type];
58 switch (motionEvent.status) {
59 case STATUS_ENTER:
60 data.value = VALUE_ENTER;
61 break;
62 case STATUS_EXIT:
63 data.value = VALUE_EXIT;
64 break;
65 default:
66 data.value = VALUE_INVALID;
67 break;
68 }
69 event_(data);
70 }
71
OnRemoteDied(const wptr<IRemoteObject> & remote)72 void RemoteDevStaCallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
73 {
74 event_(remote);
75 }
76 #endif
77
StationaryServer()78 StationaryServer::StationaryServer()
79 {
80 manager_.Init();
81 #ifdef MOTION_ENABLE
82 auto deathRecipientCB = [this](const wptr<IRemoteObject> &remote) {
83 this->StationaryServerDeathRecipient(remote);
84 };
85 devStaCBDeathRecipient_ = new (std::nothrow) RemoteDevStaCallbackDeathRecipient(deathRecipientCB);
86 #endif
87 }
88
Enable(CallingContext & context,MessageParcel & data,MessageParcel & reply)89 int32_t StationaryServer::Enable(CallingContext &context, MessageParcel &data, MessageParcel &reply)
90 {
91 CALL_DEBUG_ENTER;
92 return RET_ERR;
93 }
94
Disable(CallingContext & context,MessageParcel & data,MessageParcel & reply)95 int32_t StationaryServer::Disable(CallingContext &context, MessageParcel &data, MessageParcel &reply)
96 {
97 CALL_DEBUG_ENTER;
98 return RET_ERR;
99 }
100
Start(CallingContext & context,MessageParcel & data,MessageParcel & reply)101 int32_t StationaryServer::Start(CallingContext &context, MessageParcel &data, MessageParcel &reply)
102 {
103 CALL_DEBUG_ENTER;
104 return RET_ERR;
105 }
106
Stop(CallingContext & context,MessageParcel & data,MessageParcel & reply)107 int32_t StationaryServer::Stop(CallingContext &context, MessageParcel &data, MessageParcel &reply)
108 {
109 CALL_DEBUG_ENTER;
110 return RET_ERR;
111 }
112
AddWatch(CallingContext & context,uint32_t id,MessageParcel & data,MessageParcel & reply)113 int32_t StationaryServer::AddWatch(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
114 {
115 if (id != StationaryRequestID::SUBSCRIBE_STATIONARY) {
116 FI_HILOGE("Unexpected request ID (%{public}u)", id);
117 return RET_ERR;
118 }
119 SubscribeStationaryParam param {};
120
121 if (!param.Unmarshalling(data)) {
122 FI_HILOGE("SubscribeStationaryParam::Unmarshalling fail");
123 return RET_ERR;
124 }
125 if (param.type_ == Type::TYPE_STAND) {
126 #ifdef MOTION_ENABLE
127 return SubscribeMotion(param.type_, param.callback_);
128 #else
129 return RET_NO_SUPPORT;
130 #endif
131 } else {
132 Subscribe(context, param.type_, param.event_, param.latency_, param.callback_);
133 }
134 return RET_OK;
135 }
136
RemoveWatch(CallingContext & context,uint32_t id,MessageParcel & data,MessageParcel & reply)137 int32_t StationaryServer::RemoveWatch(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
138 {
139 if (id != StationaryRequestID::UNSUBSCRIBE_STATIONARY) {
140 FI_HILOGE("Unexpected request ID (%{public}u)", id);
141 return RET_ERR;
142 }
143 UnsubscribeStationaryParam param {};
144
145 if (!param.Unmarshalling(data)) {
146 FI_HILOGE("UnsubscribeStationaryParam::Unmarshalling fail");
147 return RET_ERR;
148 }
149 if (param.type_ == Type::TYPE_STAND) {
150 #ifdef MOTION_ENABLE
151 return UnsubscribeMotion(param.type_, param.callback_);
152 #else
153 return RET_NO_SUPPORT;
154 #endif
155 } else {
156 Unsubscribe(context, param.type_, param.event_, param.callback_);
157 }
158 return RET_OK;
159 }
160
SetParam(CallingContext & context,uint32_t id,MessageParcel & data,MessageParcel & reply)161 int32_t StationaryServer::SetParam(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
162 {
163 CALL_DEBUG_ENTER;
164 return RET_ERR;
165 }
166
GetParam(CallingContext & context,uint32_t id,MessageParcel & data,MessageParcel & reply)167 int32_t StationaryServer::GetParam(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
168 {
169 if (id != StationaryRequestID::GET_STATIONARY_DATA) {
170 FI_HILOGE("Unexpected request ID (%{public}u)", id);
171 return RET_ERR;
172 }
173 GetStaionaryDataParam param {};
174
175 if (!param.Unmarshalling(data)) {
176 FI_HILOGE("GetStaionaryDataParam::Unmarshalling fail");
177 return RET_ERR;
178 }
179 GetStaionaryDataReply dataReply { GetCache(context, param.type_) };
180 if (!dataReply.Marshalling(reply)) {
181 FI_HILOGE("GetStaionaryDataReply::Marshalling fail");
182 return RET_ERR;
183 }
184 return RET_OK;
185 }
186
Control(CallingContext & context,uint32_t id,MessageParcel & data,MessageParcel & reply)187 int32_t StationaryServer::Control(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
188 {
189 CALL_DEBUG_ENTER;
190 return RET_ERR;
191 }
192
DumpDeviceStatusSubscriber(int32_t fd) const193 void StationaryServer::DumpDeviceStatusSubscriber(int32_t fd) const
194 {
195 DS_DUMPER->DumpDeviceStatusSubscriber(fd);
196 }
197
DumpDeviceStatusChanges(int32_t fd) const198 void StationaryServer::DumpDeviceStatusChanges(int32_t fd) const
199 {
200 DS_DUMPER->DumpDeviceStatusChanges(fd);
201 }
202
DumpCurrentDeviceStatus(int32_t fd)203 void StationaryServer::DumpCurrentDeviceStatus(int32_t fd)
204 {
205 std::vector<Data> datas;
206
207 for (auto type = TYPE_ABSOLUTE_STILL; type <= TYPE_LID_OPEN; type = static_cast<Type>(type + 1)) {
208 Data data = manager_.GetLatestDeviceStatusData(type);
209 if (data.value != OnChangedValue::VALUE_INVALID) {
210 datas.emplace_back(data);
211 }
212 }
213 DS_DUMPER->DumpDeviceStatusCurrentStatus(fd, datas);
214 }
215
Subscribe(CallingContext & context,Type type,ActivityEvent event,ReportLatencyNs latency,sptr<IRemoteDevStaCallback> callback)216 void StationaryServer::Subscribe(CallingContext &context, Type type, ActivityEvent event,
217 ReportLatencyNs latency, sptr<IRemoteDevStaCallback> callback)
218 {
219 FI_HILOGI("SubscribeStationary(type:%{public}d,event:%{public}d,latency:%{public}d)", type, event, latency);
220 auto appInfo = std::make_shared<AppInfo>();
221 appInfo->uid = context.uid;
222 appInfo->pid = context.pid;
223 appInfo->tokenId = context.tokenId;
224 manager_.GetPackageName(appInfo->tokenId, appInfo->packageName);
225 appInfo->type = type;
226 appInfo->callback = callback;
227 DS_DUMPER->SaveAppInfo(appInfo);
228 #ifdef MSDP_HIVIEWDFX_HITRACE_ENABLE
229 StartTrace(HITRACE_TAG_MSDP, "serviceSubscribeStart");
230 #endif // MSDP_HIVIEWDFX_HITRACE_ENABLE
231 manager_.Subscribe(type, event, latency, callback);
232 #ifdef MSDP_HIVIEWDFX_HITRACE_ENABLE
233 FinishTrace(HITRACE_TAG_MSDP);
234 #endif // MSDP_HIVIEWDFX_HITRACE_ENABLE
235 ReportSensorSysEvent(context, type, true);
236 WriteSubscribeHiSysEvent(appInfo->uid, appInfo->packageName, type);
237 }
238
Unsubscribe(CallingContext & context,Type type,ActivityEvent event,sptr<IRemoteDevStaCallback> callback)239 void StationaryServer::Unsubscribe(CallingContext &context, Type type,
240 ActivityEvent event, sptr<IRemoteDevStaCallback> callback)
241 {
242 FI_HILOGI("UnsubscribeStationary(type:%{public}d,event:%{public}d)", type, event);
243 auto appInfo = std::make_shared<AppInfo>();
244 appInfo->uid = context.uid;
245 appInfo->pid = context.pid;
246 appInfo->tokenId = context.tokenId;
247 appInfo->packageName = DS_DUMPER->GetPackageName(appInfo->tokenId);
248 appInfo->type = type;
249 appInfo->callback = callback;
250 DS_DUMPER->RemoveAppInfo(appInfo);
251 #ifdef MSDP_HIVIEWDFX_HITRACE_ENABLE
252 StartTrace(HITRACE_TAG_MSDP, "serviceUnSubscribeStart");
253 #endif // MSDP_HIVIEWDFX_HITRACE_ENABLE
254 manager_.Unsubscribe(type, event, callback);
255 #ifdef MSDP_HIVIEWDFX_HITRACE_ENABLE
256 FinishTrace(HITRACE_TAG_MSDP);
257 #endif // MSDP_HIVIEWDFX_HITRACE_ENABLE
258 ReportSensorSysEvent(context, type, false);
259 WriteUnSubscribeHiSysEvent(appInfo->uid, appInfo->packageName, type);
260 }
261
GetCache(CallingContext & context,const Type & type)262 Data StationaryServer::GetCache(CallingContext &context, const Type &type)
263 {
264 return manager_.GetLatestDeviceStatusData(type);
265 }
266
ReportSensorSysEvent(CallingContext & context,int32_t type,bool enable)267 void StationaryServer::ReportSensorSysEvent(CallingContext &context, int32_t type, bool enable)
268 {
269 #ifdef MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
270 std::string packageName;
271 manager_.GetPackageName(context.tokenId, packageName);
272 int32_t ret = HiSysEventWrite(
273 OHOS::HiviewDFX::HiSysEvent::Domain::MSDP,
274 std::string(enable ? "Subscribe" : "Unsubscribe"),
275 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
276 "UID", context.uid,
277 "PKGNAME", packageName,
278 "TYPE", type);
279 if (ret != 0) {
280 FI_HILOGE("HiviewDFX write failed, error:%{public}d", ret);
281 }
282 #endif // MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
283 }
284
285 #ifdef MOTION_ENABLE
SubscribeMotion(Type type,sptr<IRemoteDevStaCallback> callback)286 int32_t StationaryServer::SubscribeMotion(Type type, sptr<IRemoteDevStaCallback> callback)
287 {
288 FI_HILOGD("Enter");
289 std::lock_guard lockGrd(mtx_);
290 int32_t ret = 0;
291 if (motionCallback_ == nullptr) {
292 FI_HILOGI("create motion callback and subscribe");
293 auto event = [this, type](const Data &data) {
294 this->NotifyMotionCallback(type, data);
295 };
296 motionCallback_ = new (std::nothrow) MotionCallback(event);
297 ret = SubscribeCallback(MOTION_TYPE_MAP[type], motionCallback_);
298 if (ret != RET_OK) {
299 FI_HILOGE("subscribe motion failed, ret = %{public}d", ret);
300 motionCallback_ = nullptr;
301 return ret;
302 }
303 }
304 FI_HILOGI("motionCallback is not null, subscribe ok");
305 auto iter = deviceStatusMotionCallbacks_.find(type);
306 if (iter == deviceStatusMotionCallbacks_.end()) {
307 deviceStatusMotionCallbacks_[type] = std::set<sptr<IRemoteDevStaCallback>, DevStaCallbackCmp>();
308 }
309 deviceStatusMotionCallbacks_[type].insert(callback);
310 auto object = callback->AsObject();
311 object->AddDeathRecipient(devStaCBDeathRecipient_);
312 if (motionCallback_ != nullptr && cacheData_.find(type) != cacheData_.end()) {
313 callback->OnDeviceStatusChanged(cacheData_[type]);
314 }
315 return ret;
316 }
317
UnsubscribeMotion(Type type,sptr<IRemoteDevStaCallback> callback)318 int32_t StationaryServer::UnsubscribeMotion(Type type, sptr<IRemoteDevStaCallback> callback)
319 {
320 FI_HILOGI("Enter");
321 std::lock_guard lockGrd(mtx_);
322 int32_t ret = 0;
323 auto iter = deviceStatusMotionCallbacks_.find(type);
324 if (iter == deviceStatusMotionCallbacks_.end()) {
325 FI_HILOGE("dont find callback set in callbacks, failed");
326 return RET_ERR;
327 }
328 auto callbackIter = deviceStatusMotionCallbacks_[type].find(callback);
329 if (callbackIter == deviceStatusMotionCallbacks_[type].end()) {
330 FI_HILOGE("dont find callback in callback set, failed");
331 return RET_ERR;
332 }
333 deviceStatusMotionCallbacks_[type].erase(callbackIter);
334 auto object = callback->AsObject();
335 object->RemoveDeathRecipient(devStaCBDeathRecipient_);
336 if (deviceStatusMotionCallbacks_[type].size() == 0) {
337 ret = UnsubscribeCallback(MOTION_TYPE_MAP[type], motionCallback_);
338 motionCallback_ = nullptr;
339 if (ret != RET_OK) {
340 FI_HILOGE("unsubscribe motion failed, ret = %{public}d", ret);
341 return ret;
342 }
343 FI_HILOGI("unsubscribe motion succ");
344 auto cacheIter = cacheData_.find(type);
345 if (cacheIter != cacheData_.end()) {
346 cacheData_.erase(cacheIter);
347 FI_HILOGI("cache data clear");
348 }
349 }
350 return ret;
351 }
352
StationaryServerDeathRecipient(const wptr<IRemoteObject> & remote)353 void StationaryServer::StationaryServerDeathRecipient(const wptr<IRemoteObject> &remote)
354 {
355 FI_HILOGW("Enter recv death notice");
356 sptr<IRemoteObject> client = remote.promote();
357 if (client == nullptr) {
358 FI_HILOGE("OnRemoteDied failed, client is nullptr");
359 return;
360 }
361 sptr<IRemoteDevStaCallback> callback = iface_cast<IRemoteDevStaCallback>(client);
362 if (callback == nullptr) {
363 FI_HILOGE("OnRemoteDied failed, callback is nullptr");
364 return;
365 }
366 std::vector<std::pair<Type, sptr<IRemoteDevStaCallback>>> delCallbacks;
367 {
368 std::lock_guard lockGrd(mtx_);
369 for (auto &[type, set] : deviceStatusMotionCallbacks_) {
370 for (auto &callbackInSet : set) {
371 if (callbackInSet->AsObject() == callback->AsObject()) {
372 delCallbacks.push_back(std::make_pair(type, callbackInSet));
373 }
374 }
375 }
376 }
377 for (auto &[delType, delCallback] : delCallbacks) {
378 UnsubscribeMotion(delType, delCallback);
379 FI_HILOGW("remote died, unsubscribe motion");
380 }
381 }
382
NotifyMotionCallback(Type type,const Data & data)383 void StationaryServer::NotifyMotionCallback(Type type, const Data &data)
384 {
385 FI_HILOGI("Enter, type %{public}d, data.value %{public}d", type, data.value);
386 std::lock_guard lockGrd(mtx_);
387 cacheData_[type] = data;
388 auto iter = deviceStatusMotionCallbacks_.find(type);
389 if (iter == deviceStatusMotionCallbacks_.end()) {
390 FI_HILOGW("callbacks is empty");
391 return;
392 }
393 for (auto callback : iter->second) {
394 callback->OnDeviceStatusChanged(data);
395 }
396 }
397 #endif
398 } // namespace DeviceStatus
399 } // namespace Msdp
400 } // namespace OHOS