• 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 
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