1 /*
2 * Copyright (c) 2023 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 "motion_sensor_monitor.h"
17
18 #include <vector>
19 #include <string>
20
21 #include "istate_manager_adapter.h"
22 #include "standby_config_manager.h"
23 #include "standby_service_impl.h"
24 #include "standby_service_log.h"
25
26 namespace OHOS {
27 namespace DevStandbyMgr {
28 namespace {
29 const int32_t COUNT_TIMES = 15;
30 }
31
32 double MotionSensorMonitor::energy_ = 0;
33 // use the difference between two acceleration data to judge the motion state
34 // hasPrevAccelData_ is true if we has previous acceleration data to calculate the difference
35 bool MotionSensorMonitor::hasPrevAccelData_ = false;
36 AccelData MotionSensorMonitor::previousAccelData_ {0, 0, 0};
37 AccelData MotionSensorMonitor::currentAccelData_ {0, 0, 0};
38
MotionSensorMonitor(int32_t detectionTimeOut,int32_t restTimeOut,int32_t totalTimeOut,const ConstraintEvalParam & params)39 MotionSensorMonitor::MotionSensorMonitor(int32_t detectionTimeOut, int32_t restTimeOut, int32_t totalTimeOut,
40 const ConstraintEvalParam& params): detectionTimeOut_(detectionTimeOut), restTimeOut_(restTimeOut),
41 totalTimeOut_(totalTimeOut), params_(params)
42 {
43 handler_ = StandbyServiceImpl::GetInstance()->GetHandler();
44 }
45
CheckSersorUsable(SensorInfo * sensorInfo,int32_t count,int32_t sensorTypeId)46 bool MotionSensorMonitor::CheckSersorUsable(SensorInfo *sensorInfo, int32_t count, int32_t sensorTypeId)
47 {
48 SensorInfo *pt = sensorInfo + count;
49 for (SensorInfo *ps = sensorInfo; ps < pt; ++ps) {
50 if (sensorInfo->sensorTypeId == sensorTypeId) {
51 return true;
52 }
53 }
54 return false;
55 }
56
AcceleromterCallback(SensorEvent * event)57 void MotionSensorMonitor::AcceleromterCallback(SensorEvent *event)
58 {
59 if (event == NULL) {
60 return;
61 }
62 AccelData* sensorData = reinterpret_cast<AccelData*>(event->data);
63 MotionSensorMonitor::AddEnergy(sensorData);
64 STANDBYSERVICE_LOGD("sensor motion: %{public}lf, threshold: %{public}d", MotionSensorMonitor::GetEnergy(),
65 StandbyConfigManager::GetInstance()->GetStandbyParam(MOTION_THREADSHOLD));
66 if (MotionSensorMonitor::GetEnergy() > StandbyConfigManager::GetInstance()->
67 GetStandbyParam(MOTION_THREADSHOLD)) {
68 StandbyServiceImpl::GetInstance()->GetHandler()->PostTask([]() {
69 StandbyServiceImpl::GetInstance()->GetStateManager()->EndEvalCurrentState(false);
70 }, MOTION_DECTION_TASK);
71 }
72 }
73
RepeatAcceleromterCallback(SensorEvent * event)74 void MotionSensorMonitor::RepeatAcceleromterCallback(SensorEvent *event)
75 {
76 if (event == NULL) {
77 return;
78 }
79 STANDBYSERVICE_LOGD("periodly receive Acceleromter motion sensor callback");
80 AccelData* sensorData = reinterpret_cast<AccelData*>(event->data);
81 MotionSensorMonitor::AddEnergy(sensorData);
82 STANDBYSERVICE_LOGD("sensor motion: %{public}lf, threshold: %{public}lf", MotionSensorMonitor::GetEnergy(),
83 StandbyConfigManager::GetInstance()->GetStandbyParam(MOTION_THREADSHOLD) * 1.0 / COUNT_TIMES);
84 if (MotionSensorMonitor::GetEnergy() > StandbyConfigManager::GetInstance()->
85 GetStandbyParam(MOTION_THREADSHOLD) * 1.0 / COUNT_TIMES) {
86 StandbyServiceImpl::GetInstance()->GetHandler()->PostTask([]() {
87 StandbyServiceImpl::GetInstance()->GetStateManager()->EndEvalCurrentState(false);
88 }, MOTION_DECTION_TASK);
89 }
90 }
91
MotionSensorCallback(SensorEvent * event)92 void MotionSensorMonitor::MotionSensorCallback(SensorEvent *event)
93 {
94 StandbyServiceImpl::GetInstance()->GetHandler()->PostTask([]() {
95 StandbyServiceImpl::GetInstance()->GetStateManager()->EndEvalCurrentState(false);
96 }, MOTION_DECTION_TASK);
97 }
98
GetEnergy()99 double MotionSensorMonitor::GetEnergy()
100 {
101 return energy_;
102 }
103
SetEnergy(double energy)104 void MotionSensorMonitor::SetEnergy(double energy)
105 {
106 energy_ = energy;
107 }
108
AddEnergy(AccelData * accelData)109 void MotionSensorMonitor::AddEnergy(AccelData *accelData)
110 {
111 currentAccelData_ = *accelData;
112 if (!hasPrevAccelData_) {
113 hasPrevAccelData_ = true;
114 previousAccelData_ = currentAccelData_;
115 }
116 AccelData diff {currentAccelData_.x - previousAccelData_.x, currentAccelData_.y - previousAccelData_.y,
117 currentAccelData_.z - previousAccelData_.z};
118 energy_ += (diff.x * diff.x) + (diff.y * diff.y) + (diff.z * diff.z);
119 }
120
Init()121 bool MotionSensorMonitor::Init()
122 {
123 int32_t count = -1;
124 SensorInfo* sensorInfo = nullptr;
125 int32_t ret = GetAllSensors(&sensorInfo, &count);
126 if (ret != 0) {
127 STANDBYSERVICE_LOGE("get all sensors failed, sensors are not available");
128 return false;
129 }
130
131 if (!InitSensorUserMap(sensorInfo, count)) {
132 STANDBYSERVICE_LOGE("do not find any usable sensor to detect motion");
133 return false;
134 }
135
136 // assign callback to accleromtere sensor user and motion sensor user
137 AssignAcclerometerSensorCallBack();
138 AssignMotionSensorCallBack();
139
140 auto &constraintManager = StandbyServiceImpl::GetInstance()->GetConstraintManager();
141 constraintManager->RegisterConstraintCallback(params_, shared_from_this());
142 return true;
143 }
144
InitSensorUserMap(SensorInfo * sensorInfo,int32_t count)145 bool MotionSensorMonitor::InitSensorUserMap(SensorInfo* sensorInfo, int32_t count)
146 {
147 // use acceleromter sensor and significant motion sensor to check motion
148 const std::vector<int32_t> SENSOR_TYPE_CONFIG = {SENSOR_TYPE_ID_ACCELEROMETER, SENSOR_TYPE_ID_SIGNIFICANT_MOTION};
149
150 for (const auto sensorType : SENSOR_TYPE_CONFIG) {
151 if (CheckSersorUsable(sensorInfo, count, sensorType)) {
152 sensorUserMap_.emplace(sensorType, SensorUser {});
153 }
154 }
155 return sensorUserMap_.size() > 0;
156 }
157
AssignAcclerometerSensorCallBack()158 void MotionSensorMonitor::AssignAcclerometerSensorCallBack()
159 {
160 auto iter = sensorUserMap_.find(SENSOR_TYPE_ID_ACCELEROMETER);
161 if (iter == sensorUserMap_.end()) {
162 return;
163 }
164
165 if (params_.isRepeatedDetection_) {
166 iter->second.callback = &RepeatAcceleromterCallback;
167 } else {
168 iter->second.callback = &AcceleromterCallback;
169 }
170 }
171
AssignMotionSensorCallBack()172 void MotionSensorMonitor::AssignMotionSensorCallBack()
173 {
174 auto iter = sensorUserMap_.find(SENSOR_TYPE_ID_SIGNIFICANT_MOTION);
175 if (iter == sensorUserMap_.end()) {
176 return;
177 }
178
179 iter->second.callback = &MotionSensorCallback;
180 }
181
StartMonitoring()182 void MotionSensorMonitor::StartMonitoring()
183 {
184 STANDBYSERVICE_LOGD("start motion sensor monitoring");
185 handler_->PostTask([]() {
186 STANDBYSERVICE_LOGI("stop motion sensor monitoring");
187 StandbyServiceImpl::GetInstance()->GetStateManager()->EndEvalCurrentState(true);
188 }, MOTION_DECTION_TASK, totalTimeOut_);
189 PeriodlyStartMotionDetection();
190 }
191
StopMotionDetection()192 void MotionSensorMonitor::StopMotionDetection()
193 {
194 handler_->PostTask([monitor = shared_from_this()]() {
195 monitor->StopMonitoringInner();
196 }, MOTION_DECTION_TASK, detectionTimeOut_);
197 }
198
PeriodlyStartMotionDetection()199 void MotionSensorMonitor::PeriodlyStartMotionDetection()
200 {
201 if (StartMonitoringInner() != ERR_OK) {
202 // once constraint blocked, nap state start open maintenance state
203 StandbyServiceImpl::GetInstance()->GetStateManager()->BlockCurrentState();
204 return;
205 }
206 StopMotionDetection();
207 handler_->PostTask([monitor = shared_from_this()]() {
208 monitor->PeriodlyStartMotionDetection();
209 }, MOTION_DECTION_TASK, detectionTimeOut_ + restTimeOut_);
210 }
211
StartMonitoringInner()212 ErrCode MotionSensorMonitor::StartMonitoringInner()
213 {
214 energy_ = 0;
215 isMonitoring_ = true;
216 if (StartSensor() == ERR_OK) {
217 return ERR_OK;
218 }
219
220 // if failed to start sensor, must stop sensor, in case of sensor keep callback
221 StopSensor();
222 return ERR_STANDBY_START_SENSOR_FAILED;
223 }
224
StopMonitoring()225 void MotionSensorMonitor::StopMonitoring()
226 {
227 handler_->RemoveTask(MOTION_DECTION_TASK);
228 StopMonitoringInner();
229 }
230
StopMonitoringInner()231 void MotionSensorMonitor::StopMonitoringInner()
232 {
233 StopSensor();
234 isMonitoring_ = false;
235 }
236
StartSensor()237 ErrCode MotionSensorMonitor::StartSensor()
238 {
239 for (const auto &[sensorTypeId, sensorUser] : sensorUserMap_) {
240 if (SubscribeSensor(sensorTypeId, &sensorUser) != 0) {
241 STANDBYSERVICE_LOGE("subscribe sensor failed for sensor ID %{public}d", sensorTypeId);
242 return ERR_STANDBY_START_SENSOR_FAILED;
243 }
244 STANDBYSERVICE_LOGD("subscribe sensor succeed for sensor ID %{public}d", sensorTypeId);
245
246 SetBatch(sensorTypeId, &sensorUser, SENSOR_SAMPLING_RATE, SENSOR_REPORTING_RATE);
247 if (ActivateSensor(sensorTypeId, &sensorUser) != 0) {
248 STANDBYSERVICE_LOGE("activate sensor failed for sensor ID %{public}d", sensorTypeId);
249 return ERR_STANDBY_START_SENSOR_FAILED;
250 }
251 }
252 return ERR_OK;
253 }
254
StopSensor()255 void MotionSensorMonitor::StopSensor()
256 {
257 hasPrevAccelData_ = false;
258 previousAccelData_ = {0, 0, 0};
259 if (!isMonitoring_) {
260 return;
261 }
262
263 for (const auto &[sensorTypeId, sensorUser] : sensorUserMap_) {
264 if (DeactivateSensor(sensorTypeId, &sensorUser) != 0) {
265 STANDBYSERVICE_LOGE("deactivate sensor failed for sensor ID %{public}d", sensorTypeId);
266 }
267 if (UnsubscribeSensor(sensorTypeId, &sensorUser) != 0) {
268 STANDBYSERVICE_LOGE("unsubscribe sensor failed for sensor ID %{public}d", sensorTypeId);
269 }
270 }
271 }
272 } // DevStandbyMgr
273 } // OHOS