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