• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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