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
18 #include <chrono>
19 #include <cmath>
20 #include <condition_variable>
21 #include <tokenid_kit.h>
22
23 #include "hisysevent.h"
24 #include "hitrace_meter.h"
25
26 #include "devicestatus_define.h"
27 #include "devicestatus_dumper.h"
28 #include "devicestatus_hisysevent.h"
29 #include "stationary_data.h"
30 #include "stationary_params.h"
31 #include "sensor_agent.h"
32 #include "sensor_agent_type.h"
33 #include "sensor_manager.h"
34
35 #undef LOG_TAG
36 #define LOG_TAG "StationaryServer"
37
38 namespace OHOS {
39 namespace Msdp {
40 namespace DeviceStatus {
41 namespace {
42 #ifdef MOTION_ENABLE
43 constexpr int32_t MOTION_TYPE_STAND = 3602;
44 constexpr int32_t STATUS_ENTER = 1;
45 constexpr int32_t STATUS_EXIT = 0;
46 std::map<Type, int32_t> MOTION_TYPE_MAP {
47 { Type::TYPE_STAND, MOTION_TYPE_STAND },
48 };
49 std::map<int32_t, Type> DEVICE_STATUS_TYPE_MAP {
50 { MOTION_TYPE_STAND, Type::TYPE_STAND },
51 };
52 #endif
53 constexpr int32_t RET_NO_SUPPORT = 801;
54 constexpr int32_t RET_NO_SYSTEM_API = 202;
55 constexpr int32_t SENSOR_SAMPLING_INTERVAL = 10000000;
56 constexpr int32_t WAIT_SENSOR_DATA_TIMEOUT_MS = 200;
57 constexpr int32_t ROTATION_MAT_LEN = 3;
58 constexpr int32_t MAT_IDX_0 = 0;
59 constexpr int32_t MAT_IDX_1 = 1;
60 constexpr int32_t MAT_IDX_2 = 2;
61 constexpr float DOUBLE_FACTOR = 2.0F;
62 constexpr float PI = 3.141592653589846;
63 constexpr float EPSILON_FLOAT = 1e-6;
64 std::optional<RotationVectorData> cacheRotVecData_;
65 std::mutex g_mtx;
66 std::condition_variable g_cv;
67 } // namespace
68
OnReceivedData(SensorEvent * event)69 static void OnReceivedData(SensorEvent *event)
70 {
71 if (event == nullptr) {
72 return;
73 }
74 if (event->sensorTypeId == SENSOR_TYPE_ID_ROTATION_VECTOR) {
75 std::unique_lock lockGrd(g_mtx);
76 RotationVectorData *data = reinterpret_cast<RotationVectorData *>(event->data);
77 cacheRotVecData_ = std::make_optional(*data);
78 g_cv.notify_all();
79 }
80 }
81
82 #ifdef MOTION_ENABLE
OnMotionChanged(const MotionEvent & motionEvent)83 void MotionCallback::OnMotionChanged(const MotionEvent &motionEvent)
84 {
85 Data data;
86 data.type = DEVICE_STATUS_TYPE_MAP[motionEvent.type];
87 switch (motionEvent.status) {
88 case STATUS_ENTER:
89 data.value = VALUE_ENTER;
90 break;
91 case STATUS_EXIT:
92 data.value = VALUE_EXIT;
93 break;
94 default:
95 data.value = VALUE_INVALID;
96 break;
97 }
98 event_(data);
99 }
100
OnRemoteDied(const wptr<IRemoteObject> & remote)101 void RemoteDevStaCallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
102 {
103 event_(remote);
104 }
105 #endif
106
StationaryServer()107 StationaryServer::StationaryServer()
108 {
109 manager_.Init();
110 #ifdef MOTION_ENABLE
111 auto deathRecipientCB = [this](const wptr<IRemoteObject> &remote) {
112 this->StationaryServerDeathRecipient(remote);
113 };
114 devStaCBDeathRecipient_ = new (std::nothrow) RemoteDevStaCallbackDeathRecipient(deathRecipientCB);
115 #endif
116 }
117
SubscribeStationaryCallback(CallingContext & context,int32_t type,int32_t event,int32_t latency,const sptr<IRemoteDevStaCallback> & subCallback)118 int32_t StationaryServer::SubscribeStationaryCallback(CallingContext &context, int32_t type, int32_t event,
119 int32_t latency, const sptr<IRemoteDevStaCallback> &subCallback)
120 {
121 Type stationaryType = static_cast<Type>(type);
122 ActivityEvent stationaryEvent = static_cast<ActivityEvent>(event);
123 ReportLatencyNs stationaryLatency = static_cast<ReportLatencyNs>(latency);
124 if (stationaryType == Type::TYPE_STAND) {
125 #ifdef MOTION_ENABLE
126 return SubscribeMotion(stationaryType, subCallback);
127 #else
128 return RET_NO_SUPPORT;
129 #endif
130 } else {
131 Subscribe(context, stationaryType, stationaryEvent, stationaryLatency, subCallback);
132 }
133 return RET_OK;
134 }
135
UnsubscribeStationaryCallback(CallingContext & context,int32_t type,int32_t event,const sptr<IRemoteDevStaCallback> & unsubCallback)136 int32_t StationaryServer::UnsubscribeStationaryCallback(CallingContext &context, int32_t type, int32_t event,
137 const sptr<IRemoteDevStaCallback> &unsubCallback)
138 {
139 Type stationaryType = static_cast<Type>(type);
140 ActivityEvent stationaryEvent = static_cast<ActivityEvent>(event);
141 if (stationaryType == Type::TYPE_STAND) {
142 #ifdef MOTION_ENABLE
143 return UnsubscribeMotion(stationaryType, unsubCallback);
144 #else
145 return RET_NO_SUPPORT;
146 #endif
147 } else {
148 Unsubscribe(context, stationaryType, stationaryEvent, unsubCallback);
149 }
150 return RET_OK;
151 }
152
GetDeviceStatusData(CallingContext & context,int32_t type,int32_t & replyType,int32_t & replyValue)153 int32_t StationaryServer::GetDeviceStatusData(CallingContext &context, int32_t type,
154 int32_t &replyType, int32_t &replyValue)
155 {
156 Type stationaryType = static_cast<Type>(type);
157 Data data = GetCache(context, stationaryType);
158 replyType = static_cast<int32_t>(data.type);
159 replyValue = static_cast<int32_t>(data.value);
160 return RET_OK;
161 }
162
GetDevicePostureDataSync(CallingContext & context,DevicePostureData & data)163 int32_t StationaryServer::GetDevicePostureDataSync(CallingContext &context, DevicePostureData &data)
164 {
165 if (!IsSystemCalling(context)) {
166 return RET_NO_SYSTEM_API;
167 }
168 #ifndef DEVICE_STATUS_SENSOR_ENABLE
169 return RET_NO_SUPPORT;
170 #else
171 if (!SensorManager::IsSupportedSensor(SENSOR_TYPE_ID_ROTATION_VECTOR)) {
172 FI_HILOGE("rotation vector sensor is not supported");
173 return RET_NO_SUPPORT;
174 }
175 // 订阅sensor获取四元数
176 SensorManager sensorManager(SENSOR_TYPE_ID_ROTATION_VECTOR, SENSOR_SAMPLING_INTERVAL);
177 sensorManager.SetCallback(&OnReceivedData);
178 sensorManager.StartSensor();
179 std::unique_lock lockGrd(g_mtx);
180 g_cv.wait_for(lockGrd, std::chrono::milliseconds(WAIT_SENSOR_DATA_TIMEOUT_MS));
181 sensorManager.StopSensor();
182 // 数据转换
183 if (cacheRotVecData_ == std::nullopt) {
184 return RET_ERR;
185 }
186 TransQuaternionsToZXYRot(cacheRotVecData_.value(), data);
187 return RET_OK;
188 #endif
189 }
190
191 #ifdef DEVICE_STATUS_SENSOR_ENABLE
TransQuaternionsToZXYRot(RotationVectorData quaternions,DevicePostureData & data)192 void StationaryServer::TransQuaternionsToZXYRot(RotationVectorData quaternions, DevicePostureData &data)
193 {
194 // 四元数表示法: w+xi+yj+zk
195 float x = quaternions.x;
196 float y = quaternions.y;
197 float z = quaternions.z;
198 float w = quaternions.w;
199 FI_HILOGI("x:%{public}f, y:%{public}f, z:%{public}f, w:%{public}f", x, y, z, w);
200 // 计算旋转矩阵
201 std::vector<std::vector<float>> rotationMat(ROTATION_MAT_LEN, std::vector<float>(ROTATION_MAT_LEN, 0.0F));
202 rotationMat[MAT_IDX_0][MAT_IDX_0] = 1 - DOUBLE_FACTOR * y * y - DOUBLE_FACTOR * z * z;
203 rotationMat[MAT_IDX_0][MAT_IDX_1] = DOUBLE_FACTOR * x * y - DOUBLE_FACTOR * w * z;
204 rotationMat[MAT_IDX_0][MAT_IDX_2] = DOUBLE_FACTOR * x * z + DOUBLE_FACTOR * w * y;
205 rotationMat[MAT_IDX_1][MAT_IDX_0] = DOUBLE_FACTOR * x * y + DOUBLE_FACTOR * w * z;
206 rotationMat[MAT_IDX_1][MAT_IDX_1] = 1 - DOUBLE_FACTOR * x * x - DOUBLE_FACTOR * z * z;
207 rotationMat[MAT_IDX_1][MAT_IDX_2] = DOUBLE_FACTOR * y * z - DOUBLE_FACTOR * w * x;
208 rotationMat[MAT_IDX_2][MAT_IDX_0] = DOUBLE_FACTOR * x * z - DOUBLE_FACTOR * w * y;
209 rotationMat[MAT_IDX_2][MAT_IDX_1] = DOUBLE_FACTOR * y * z + DOUBLE_FACTOR * w * x;
210 rotationMat[MAT_IDX_2][MAT_IDX_2] = 1 - DOUBLE_FACTOR * x * x - DOUBLE_FACTOR * y * y;
211 auto transFunc = [](const float angle) -> float {
212 float ret = angle;
213 if (angle < 0) {
214 ret = angle + 2 * PI;
215 }
216 return ret;
217 };
218 auto pitch = transFunc(std::atan2(-rotationMat[MAT_IDX_2][MAT_IDX_0], rotationMat[MAT_IDX_2][MAT_IDX_2]));
219 auto yaw = transFunc(std::atan2(-rotationMat[MAT_IDX_0][MAT_IDX_1], rotationMat[MAT_IDX_1][MAT_IDX_1]));
220 float roll = 0.0F;
221 if (std::cos(pitch) >= EPSILON_FLOAT) {
222 roll = transFunc(std::atan2(rotationMat[MAT_IDX_2][MAT_IDX_1],
223 rotationMat[MAT_IDX_2][MAT_IDX_2] / std::cos(pitch)));
224 } else {
225 roll = transFunc(std::atan2(rotationMat[MAT_IDX_2][MAT_IDX_1],
226 -rotationMat[MAT_IDX_2][MAT_IDX_0] / std::sin(pitch)));
227 }
228 data.rollRad = roll;
229 data.yawRad = yaw;
230 data.pitchRad = pitch;
231 }
232 #endif
233
IsSystemCalling(CallingContext & context)234 bool StationaryServer::IsSystemCalling(CallingContext &context)
235 {
236 if (IsSystemServiceCalling(context)) {
237 return true;
238 }
239 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(context.fullTokenId);
240 }
241
IsSystemServiceCalling(CallingContext & context)242 bool StationaryServer::IsSystemServiceCalling(CallingContext &context)
243 {
244 auto flag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(context.tokenId);
245 if ((flag == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) ||
246 (flag == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL)) {
247 FI_HILOGI("system service calling, flag:%{public}u", flag);
248 return true;
249 }
250 return false;
251 }
252
DumpDeviceStatusSubscriber(int32_t fd) const253 void StationaryServer::DumpDeviceStatusSubscriber(int32_t fd) const
254 {
255 DS_DUMPER->DumpDeviceStatusSubscriber(fd);
256 }
257
DumpDeviceStatusChanges(int32_t fd) const258 void StationaryServer::DumpDeviceStatusChanges(int32_t fd) const
259 {
260 DS_DUMPER->DumpDeviceStatusChanges(fd);
261 }
262
DumpCurrentDeviceStatus(int32_t fd)263 void StationaryServer::DumpCurrentDeviceStatus(int32_t fd)
264 {
265 std::vector<Data> datas;
266
267 for (auto type = TYPE_ABSOLUTE_STILL; type <= TYPE_LID_OPEN; type = static_cast<Type>(type + 1)) {
268 Data data = manager_.GetLatestDeviceStatusData(type);
269 if (data.value != OnChangedValue::VALUE_INVALID) {
270 datas.emplace_back(data);
271 }
272 }
273 DS_DUMPER->DumpDeviceStatusCurrentStatus(fd, datas);
274 }
275
Subscribe(CallingContext & context,Type type,ActivityEvent event,ReportLatencyNs latency,sptr<IRemoteDevStaCallback> callback)276 void StationaryServer::Subscribe(CallingContext &context, Type type, ActivityEvent event,
277 ReportLatencyNs latency, sptr<IRemoteDevStaCallback> callback)
278 {
279 FI_HILOGI("SubscribeStationary(type:%{public}d,event:%{public}d,latency:%{public}d)", type, event, latency);
280 auto appInfo = std::make_shared<AppInfo>();
281 appInfo->uid = context.uid;
282 appInfo->pid = context.pid;
283 appInfo->tokenId = context.tokenId;
284 manager_.GetPackageName(appInfo->tokenId, appInfo->packageName);
285 appInfo->type = type;
286 appInfo->callback = callback;
287 DS_DUMPER->SaveAppInfo(appInfo);
288 StartTrace(HITRACE_TAG_MSDP, "serviceSubscribeStart");
289 manager_.Subscribe(type, event, latency, callback);
290 FinishTrace(HITRACE_TAG_MSDP);
291 ReportSensorSysEvent(context, type, true);
292 WriteSubscribeHiSysEvent(appInfo->uid, appInfo->packageName, type);
293 }
294
Unsubscribe(CallingContext & context,Type type,ActivityEvent event,sptr<IRemoteDevStaCallback> callback)295 void StationaryServer::Unsubscribe(CallingContext &context, Type type,
296 ActivityEvent event, sptr<IRemoteDevStaCallback> callback)
297 {
298 FI_HILOGI("UnsubscribeStationary(type:%{public}d,event:%{public}d)", type, event);
299 auto appInfo = std::make_shared<AppInfo>();
300 appInfo->uid = context.uid;
301 appInfo->pid = context.pid;
302 appInfo->tokenId = context.tokenId;
303 appInfo->packageName = DS_DUMPER->GetPackageName(appInfo->tokenId);
304 appInfo->type = type;
305 appInfo->callback = callback;
306 DS_DUMPER->RemoveAppInfo(appInfo);
307 StartTrace(HITRACE_TAG_MSDP, "serviceUnSubscribeStart");
308 manager_.Unsubscribe(type, event, callback);
309 FinishTrace(HITRACE_TAG_MSDP);
310 ReportSensorSysEvent(context, type, false);
311 WriteUnSubscribeHiSysEvent(appInfo->uid, appInfo->packageName, type);
312 }
313
GetCache(CallingContext & context,const Type & type)314 Data StationaryServer::GetCache(CallingContext &context, const Type &type)
315 {
316 return manager_.GetLatestDeviceStatusData(type);
317 }
318
ReportSensorSysEvent(CallingContext & context,int32_t type,bool enable)319 void StationaryServer::ReportSensorSysEvent(CallingContext &context, int32_t type, bool enable)
320 {
321 std::string packageName;
322 manager_.GetPackageName(context.tokenId, packageName);
323 int32_t ret = HiSysEventWrite(
324 OHOS::HiviewDFX::HiSysEvent::Domain::MSDP,
325 std::string(enable ? "Subscribe" : "Unsubscribe"),
326 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
327 "UID", context.uid,
328 "PKGNAME", packageName,
329 "TYPE", type);
330 if (ret != 0) {
331 FI_HILOGE("HiviewDFX write failed, error:%{public}d", ret);
332 }
333 }
334
335 #ifdef MOTION_ENABLE
SubscribeMotion(Type type,sptr<IRemoteDevStaCallback> callback)336 int32_t StationaryServer::SubscribeMotion(Type type, sptr<IRemoteDevStaCallback> callback)
337 {
338 FI_HILOGD("Enter");
339 std::lock_guard lockGrd(mtx_);
340 int32_t ret = 0;
341 if (motionCallback_ == nullptr) {
342 FI_HILOGI("create motion callback and subscribe");
343 auto event = [this, type](const Data &data) {
344 this->NotifyMotionCallback(type, data);
345 };
346 motionCallback_ = new (std::nothrow) MotionCallback(event);
347 ret = SubscribeCallback(MOTION_TYPE_MAP[type], motionCallback_);
348 if (ret != RET_OK) {
349 FI_HILOGE("subscribe motion failed, ret = %{public}d", ret);
350 motionCallback_ = nullptr;
351 return ret;
352 }
353 }
354 FI_HILOGI("motionCallback is not null, subscribe ok");
355 auto iter = deviceStatusMotionCallbacks_.find(type);
356 if (iter == deviceStatusMotionCallbacks_.end()) {
357 deviceStatusMotionCallbacks_[type] = std::set<sptr<IRemoteDevStaCallback>, DevStaCallbackCmp>();
358 }
359 deviceStatusMotionCallbacks_[type].insert(callback);
360 auto object = callback->AsObject();
361 object->AddDeathRecipient(devStaCBDeathRecipient_);
362 if (motionCallback_ != nullptr && cacheData_.find(type) != cacheData_.end()) {
363 callback->OnDeviceStatusChanged(cacheData_[type]);
364 }
365 return ret;
366 }
367
UnsubscribeMotion(Type type,sptr<IRemoteDevStaCallback> callback)368 int32_t StationaryServer::UnsubscribeMotion(Type type, sptr<IRemoteDevStaCallback> callback)
369 {
370 FI_HILOGI("Enter");
371 std::lock_guard lockGrd(mtx_);
372 int32_t ret = 0;
373 auto iter = deviceStatusMotionCallbacks_.find(type);
374 if (iter == deviceStatusMotionCallbacks_.end()) {
375 FI_HILOGE("dont find callback set in callbacks, failed");
376 return RET_ERR;
377 }
378 auto callbackIter = deviceStatusMotionCallbacks_[type].find(callback);
379 if (callbackIter == deviceStatusMotionCallbacks_[type].end()) {
380 FI_HILOGE("dont find callback in callback set, failed");
381 return RET_ERR;
382 }
383 deviceStatusMotionCallbacks_[type].erase(callbackIter);
384 auto object = callback->AsObject();
385 object->RemoveDeathRecipient(devStaCBDeathRecipient_);
386 if (deviceStatusMotionCallbacks_[type].size() == 0) {
387 ret = UnsubscribeCallback(MOTION_TYPE_MAP[type], motionCallback_);
388 motionCallback_ = nullptr;
389 if (ret != RET_OK) {
390 FI_HILOGE("unsubscribe motion failed, ret = %{public}d", ret);
391 return ret;
392 }
393 FI_HILOGI("unsubscribe motion succ");
394 auto cacheIter = cacheData_.find(type);
395 if (cacheIter != cacheData_.end()) {
396 cacheData_.erase(cacheIter);
397 FI_HILOGI("cache data clear");
398 }
399 }
400 return ret;
401 }
402
StationaryServerDeathRecipient(const wptr<IRemoteObject> & remote)403 void StationaryServer::StationaryServerDeathRecipient(const wptr<IRemoteObject> &remote)
404 {
405 FI_HILOGW("Enter recv death notice");
406 sptr<IRemoteObject> client = remote.promote();
407 if (client == nullptr) {
408 FI_HILOGE("OnRemoteDied failed, client is nullptr");
409 return;
410 }
411 sptr<IRemoteDevStaCallback> callback = iface_cast<IRemoteDevStaCallback>(client);
412 if (callback == nullptr) {
413 FI_HILOGE("OnRemoteDied failed, callback is nullptr");
414 return;
415 }
416 std::vector<std::pair<Type, sptr<IRemoteDevStaCallback>>> delCallbacks;
417 {
418 std::lock_guard lockGrd(mtx_);
419 for (auto &[type, set] : deviceStatusMotionCallbacks_) {
420 for (auto &callbackInSet : set) {
421 if (callbackInSet->AsObject() == callback->AsObject()) {
422 delCallbacks.push_back(std::make_pair(type, callbackInSet));
423 }
424 }
425 }
426 }
427 for (auto &[delType, delCallback] : delCallbacks) {
428 UnsubscribeMotion(delType, delCallback);
429 FI_HILOGW("remote died, unsubscribe motion");
430 }
431 }
432
NotifyMotionCallback(Type type,const Data & data)433 void StationaryServer::NotifyMotionCallback(Type type, const Data &data)
434 {
435 FI_HILOGI("Enter, type %{public}d, data.value %{public}d", type, data.value);
436 std::lock_guard lockGrd(mtx_);
437 cacheData_[type] = data;
438 auto iter = deviceStatusMotionCallbacks_.find(type);
439 if (iter == deviceStatusMotionCallbacks_.end()) {
440 FI_HILOGW("callbacks is empty");
441 return;
442 }
443 for (auto callback : iter->second) {
444 callback->OnDeviceStatusChanged(data);
445 }
446 }
447 #endif
448 } // namespace DeviceStatus
449 } // namespace Msdp
450 } // namespace OHOS