FalsingManager.java revision 0e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53
1/*
2 * Copyright (C) 2015 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
17package com.android.systemui.classifier;
18
19import android.content.Context;
20import android.database.ContentObserver;
21import android.hardware.Sensor;
22import android.hardware.SensorEvent;
23import android.hardware.SensorEventListener;
24import android.hardware.SensorManager;
25import android.os.Handler;
26import android.os.UserHandle;
27import android.provider.Settings;
28import android.view.MotionEvent;
29
30import com.android.systemui.analytics.DataCollector;
31import com.android.systemui.statusbar.StatusBarState;
32
33/**
34 * When the phone is locked, listens to touch, sensor and phone events and sends them to
35 * DataCollector and HumanInteractionClassifier.
36 *
37 * It does not collect touch events when the bouncer shows up.
38 */
39public class FalsingManager implements SensorEventListener {
40    private static final String ENFORCE_BOUNCER = "falsing_manager_enforce_bouncer";
41
42    private static final int[] SENSORS = new int[] {
43            Sensor.TYPE_ACCELEROMETER,
44            Sensor.TYPE_GYROSCOPE,
45            Sensor.TYPE_PROXIMITY,
46            Sensor.TYPE_LIGHT,
47            Sensor.TYPE_ROTATION_VECTOR,
48    };
49
50    private final Handler mHandler = new Handler();
51    private final Context mContext;
52
53    private final SensorManager mSensorManager;
54    private final DataCollector mDataCollector;
55    private final HumanInteractionClassifier mHumanInteractionClassifier;
56
57    private static FalsingManager sInstance = null;
58
59    private boolean mEnforceBouncer = false;
60    private boolean mBouncerOn = false;
61    private boolean mSessionActive = false;
62    private int mState = StatusBarState.SHADE;
63
64    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
65        @Override
66        public void onChange(boolean selfChange) {
67            updateConfiguration();
68        }
69    };
70
71    private FalsingManager(Context context) {
72        mContext = context;
73        mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
74        mDataCollector = DataCollector.getInstance(mContext);
75        mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
76
77        mContext.getContentResolver().registerContentObserver(
78                Settings.Secure.getUriFor(ENFORCE_BOUNCER), false,
79                mSettingsObserver,
80                UserHandle.USER_ALL);
81
82        updateConfiguration();
83    }
84
85    public static FalsingManager getInstance(Context context) {
86        if (sInstance == null) {
87            sInstance = new FalsingManager(context);
88        }
89        return sInstance;
90    }
91
92    private void updateConfiguration() {
93        mEnforceBouncer = 0 != Settings.Secure.getInt(mContext.getContentResolver(),
94                ENFORCE_BOUNCER, 0);
95    }
96
97    private boolean sessionEntrypoint() {
98        if (!mSessionActive && isEnabled() &&
99                (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
100            onSessionStart();
101            return true;
102        }
103        return false;
104    }
105
106    private void sessionExitpoint() {
107        if (mSessionActive) {
108            mSessionActive = false;
109            mSensorManager.unregisterListener(this);
110        }
111    }
112
113    private void onSessionStart() {
114        mBouncerOn = false;
115        mSessionActive = true;
116        for (int sensorType : SENSORS) {
117            Sensor s = mSensorManager.getDefaultSensor(sensorType);
118            if (s != null) {
119                mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
120            }
121        }
122    }
123
124    private boolean isEnabled() {
125        return mHumanInteractionClassifier.isEnabled() || mDataCollector.isEnabled();
126    }
127
128    /**
129     * @param type the type of action for which this method is called
130     * @return true if the classifier determined that this is not a human interacting with the phone
131     */
132    public boolean isFalseTouch(int type) {
133        return mHumanInteractionClassifier.getFalseTouchEvaluation(type) > 0.5;
134    }
135
136    @Override
137    public synchronized void onSensorChanged(SensorEvent event) {
138        mDataCollector.onSensorChanged(event);
139        mHumanInteractionClassifier.onSensorChanged(event);
140    }
141
142    @Override
143    public void onAccuracyChanged(Sensor sensor, int accuracy) {
144        mDataCollector.onAccuracyChanged(sensor, accuracy);
145    }
146
147    public boolean shouldEnforceBouncer() {
148        return mEnforceBouncer;
149    }
150
151    public void setStatusBarState(int state) {
152        mState = state;
153    }
154
155    public void onScreenTurningOn() {
156        if (sessionEntrypoint()) {
157            mDataCollector.onScreenTurningOn();
158        }
159    }
160
161    public void onScreenOnFromTouch() {
162        if (sessionEntrypoint()) {
163            mDataCollector.onScreenOnFromTouch();
164        }
165    }
166
167    public void onScreenOff() {
168        mDataCollector.onScreenOff();
169        sessionExitpoint();
170    }
171
172    public void onSucccessfulUnlock() {
173        mDataCollector.onSucccessfulUnlock();
174        sessionExitpoint();
175    }
176
177    public void onBouncerShown() {
178        if (!mBouncerOn) {
179            mBouncerOn = true;
180            mDataCollector.onBouncerShown();
181        }
182    }
183
184    public void onBouncerHidden() {
185        if (mBouncerOn) {
186            mBouncerOn = false;
187            mDataCollector.onBouncerHidden();
188        }
189    }
190
191    public void onQsDown() {
192        mDataCollector.onQsDown();
193    }
194
195    public void setQsExpanded(boolean expanded) {
196        mDataCollector.setQsExpanded(expanded);
197    }
198
199    public void onTrackingStarted() {
200        mDataCollector.onTrackingStarted();
201    }
202
203    public void onTrackingStopped() {
204        mDataCollector.onTrackingStopped();
205    }
206
207    public void onNotificationActive() {
208        mDataCollector.onNotificationActive();
209    }
210
211    public void onNotificationDoubleTap() {
212        mDataCollector.onNotificationDoubleTap();
213    }
214
215    public void setNotificationExpanded() {
216        mDataCollector.setNotificationExpanded();
217    }
218
219    public void onNotificatonStartDraggingDown() {
220        mDataCollector.onNotificatonStartDraggingDown();
221    }
222
223    public void onNotificatonStopDraggingDown() {
224        mDataCollector.onNotificatonStopDraggingDown();
225    }
226
227    public void onNotificationDismissed() {
228        mDataCollector.onNotificationDismissed();
229    }
230
231    public void onNotificatonStartDismissing() {
232        mDataCollector.onNotificatonStartDismissing();
233    }
234
235    public void onNotificatonStopDismissing() {
236        mDataCollector.onNotificatonStopDismissing();
237    }
238
239    public void onCameraOn() {
240        mDataCollector.onCameraOn();
241    }
242
243    public void onLeftAffordanceOn() {
244        mDataCollector.onLeftAffordanceOn();
245    }
246
247    public void onAffordanceSwipingStarted(boolean rightCorner) {
248        mDataCollector.onAffordanceSwipingStarted(rightCorner);
249    }
250
251    public void onAffordanceSwipingAborted() {
252        mDataCollector.onAffordanceSwipingAborted();
253    }
254
255    public void onUnlockHintStarted() {
256        mDataCollector.onUnlockHintStarted();
257    }
258
259    public void onCameraHintStarted() {
260        mDataCollector.onCameraHintStarted();
261    }
262
263    public void onLeftAffordanceHintStarted() {
264        mDataCollector.onLeftAffordanceHintStarted();
265    }
266
267    public void onTouchEvent(MotionEvent event, int width, int height) {
268        if (mSessionActive && !mBouncerOn) {
269            mDataCollector.onTouchEvent(event, width, height);
270            mHumanInteractionClassifier.onTouchEvent(event);
271        }
272    }
273}
274