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