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