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