1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.hardware.cts.helpers;
18 
19 import junit.framework.Assert;
20 
21 import android.content.Context;
22 import android.hardware.Sensor;
23 import android.hardware.SensorEvent;
24 import android.hardware.SensorEventListener;
25 import android.hardware.SensorManager;
26 
27 /**
28  * Helper class that provides a way to identify if movement has been detected in the device.
29  *
30  * Notes:
31  * Alpha is calculated as:
32  *      t / ( t + dT)
33  * Where
34  *       t - low-pass filter's time-constant
35  *      dT - event delivery rate
36  */
37 public abstract class MovementDetectorHelper implements SensorEventListener {
38     private static final float MOVEMENT_DETECTION_ACCELERATION_THRESHOLD = 4.0f;
39     private static final float ALPHA = 0.8f;
40 
41     private final float[] mGravity = {0.0f, 0.0f, 0.0f};
42 
43     private final SensorManager mSensorManager;
44     private final Sensor mAccelerometer;
45 
46     private boolean mInitialized;
47 
MovementDetectorHelper(Context context)48     public MovementDetectorHelper(Context context) {
49         mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
50         Assert.assertNotNull("SensorManager", mSensorManager);
51 
52         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
53         if (mAccelerometer == null) {
54             throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
55         }
56     }
57 
start()58     public synchronized void start() {
59         if (mInitialized) {
60             return;
61         }
62 
63         mInitialized = mSensorManager
64                 .registerListener(this, mAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
65         Assert.assertTrue(mInitialized);
66     }
67 
stop()68     public synchronized void stop() {
69         if (!mInitialized) {
70             return;
71         }
72 
73         mSensorManager.unregisterListener(this);
74         mInitialized = false;
75     }
76 
onMovementDetected()77     protected abstract void onMovementDetected();
78 
79     @Override
onAccuracyChanged(Sensor sensor, int accuracy)80     public void onAccuracyChanged(Sensor sensor, int accuracy) {}
81 
82     @Override
onSensorChanged(SensorEvent event)83     public void onSensorChanged(SensorEvent event) {
84         float[] linearAcceleration = {0.0f, 0.0f, 0.0f};
85 
86         if (mGravity[0] == 0f && mGravity[2] == 0f) {
87             mGravity[0] = event.values[0];
88             mGravity[1] = event.values[1];
89             mGravity[2] = event.values[2];
90         } else {
91             // Isolate the force of gravity with the low-pass filter.
92             mGravity[0] = ALPHA * mGravity[0] + (1 - ALPHA) * event.values[0];
93             mGravity[1] = ALPHA * mGravity[1] + (1 - ALPHA) * event.values[1];
94             mGravity[2] = ALPHA * mGravity[2] + (1 - ALPHA) * event.values[2];
95         }
96 
97         // Remove the gravity contribution with the high-pass filter.
98         linearAcceleration[0] = event.values[0] - mGravity[0];
99         linearAcceleration[1] = event.values[1] - mGravity[1];
100         linearAcceleration[2] = event.values[2] - mGravity[2];
101 
102         float totalAcceleration = Math.abs(linearAcceleration[0])
103                 + Math.abs(linearAcceleration[1])
104                 + Math.abs(linearAcceleration[2]);
105 
106         if (totalAcceleration > MOVEMENT_DETECTION_ACCELERATION_THRESHOLD) {
107             onMovementDetected();
108         }
109     }
110 }
111