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