HumanInteractionClassifier.java revision 9f01c5bfa5c1c63e350808c154adfc2953949b15
10e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski/* 20e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * Copyright (C) 2015 The Android Open Source Project 30e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * 40e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * Licensed under the Apache License, Version 2.0 (the "License"); 50e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * you may not use this file except in compliance with the License. 60e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * You may obtain a copy of the License at 70e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * 80e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * http://www.apache.org/licenses/LICENSE-2.0 90e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * 100e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * Unless required by applicable law or agreed to in writing, software 110e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * distributed under the License is distributed on an "AS IS" BASIS, 120e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * See the License for the specific language governing permissions and 140e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * limitations under the License 150e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski */ 160e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 170e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskipackage com.android.systemui.classifier; 180e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 190e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.content.Context; 200e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.database.ContentObserver; 210e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.hardware.SensorEvent; 220e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.os.Build; 230e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.os.Handler; 240e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.os.UserHandle; 250e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.provider.Settings; 260e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.view.MotionEvent; 270e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 289f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowskiimport java.util.ArrayList; 299f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 300e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski/** 310e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * An classifier trying to determine whether it is a human interacting with the phone or not. 320e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski */ 330e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskipublic class HumanInteractionClassifier extends Classifier { 340e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private static final String HIC_ENABLE = "HIC_enable"; 350e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private static HumanInteractionClassifier sInstance = null; 360e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 370e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private final Handler mHandler = new Handler(); 380e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private final Context mContext; 390e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 409f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski private ArrayList<StrokeClassifier> mStrokeClassifiers = new ArrayList<>(); 419f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski private ArrayList<GestureClassifier> mGestureClassifiers = new ArrayList<>(); 429f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski private final int mStrokeClassifiersSize; 439f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski private final int mGestureClassifiersSize; 449f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 459f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski private HistoryEvaluator mHistoryEvaluator; 460e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private boolean mEnableClassifier = false; 479f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski private int mCurrentType = Classifier.GENERIC; 480e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 490e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { 500e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski @Override 510e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski public void onChange(boolean selfChange) { 520e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski updateConfiguration(); 530e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 540e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski }; 550e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 560e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private HumanInteractionClassifier(Context context) { 570e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mContext = context; 580e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mClassifierData = new ClassifierData(); 599f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mHistoryEvaluator = new HistoryEvaluator(); 609f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 619f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mStrokeClassifiers.add(new AnglesVarianceClassifier(mClassifierData)); 629f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 639f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mStrokeClassifiersSize = mStrokeClassifiers.size(); 649f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mGestureClassifiersSize = mGestureClassifiers.size(); 650e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 660e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mContext.getContentResolver().registerContentObserver( 670e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski Settings.Global.getUriFor(HIC_ENABLE), false, 680e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mSettingsObserver, 690e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski UserHandle.USER_ALL); 700e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 710e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski updateConfiguration(); 720e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 730e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 740e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski public static HumanInteractionClassifier getInstance(Context context) { 750e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski if (sInstance == null) { 760e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski sInstance = new HumanInteractionClassifier(context); 770e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 780e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski return sInstance; 790e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 800e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 810e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private void updateConfiguration() { 820e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mEnableClassifier = Build.IS_DEBUGGABLE && 0 != Settings.Global.getInt( 830e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mContext.getContentResolver(), 840e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski HIC_ENABLE, 0); 850e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 860e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 879f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski public void setType(int type) { 889f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mCurrentType = type; 899f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski } 909f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 910e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski @Override 920e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski public void onTouchEvent(MotionEvent event) { 930e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski if (mEnableClassifier) { 940e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mClassifierData.update(event); 959f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 969f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski for (int i = 0; i < mStrokeClassifiersSize; i++) { 979f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mStrokeClassifiers.get(i).onTouchEvent(event); 989f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski } 999f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 1009f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski for (int i = 0; i < mGestureClassifiersSize; i++) { 1019f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mGestureClassifiers.get(i).onTouchEvent(event); 1029f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski } 1039f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 1049f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski int size = mClassifierData.getEndingStrokes().size(); 1059f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski for (int i = 0; i < size; i++) { 1069f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski Stroke stroke = mClassifierData.getEndingStrokes().get(i); 1079f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski float evaluation = 0.0f; 1089f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski for (int j = 0; j < mStrokeClassifiersSize; j++) { 1099f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski evaluation += mStrokeClassifiers.get(j).getFalseTouchEvaluation( 1109f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mCurrentType, stroke); 1119f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski } 1129f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mHistoryEvaluator.addStroke(evaluation); 1139f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski } 1149f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 1159f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski int action = event.getActionMasked(); 1169f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 1179f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski float evaluation = 0.0f; 1189f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski for (int i = 0; i < mGestureClassifiersSize; i++) { 1199f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski evaluation += mGestureClassifiers.get(i).getFalseTouchEvaluation(mCurrentType); 1209f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski } 1219f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski mHistoryEvaluator.addGesture(evaluation); 1229f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski setType(Classifier.GENERIC); 1239f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski } 1249f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski 1250e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mClassifierData.cleanUp(event); 1260e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 1270e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 1280e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 1290e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski @Override 1300e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski public void onSensorChanged(SensorEvent event) { 1310e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 1320e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 1339f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski public boolean isFalseTouch() { 1349f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski return mHistoryEvaluator.getEvaluation() >= 5.0f; 1350e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 1360e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski 1370e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski public boolean isEnabled() { 1380e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski return mEnableClassifier; 1390e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 1400e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski} 141