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