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.Handler;
230e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.os.UserHandle;
240e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.provider.Settings;
2591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowskiimport android.util.DisplayMetrics;
26401caaedd871894620accc1d14592c08095b5523Adrian Roosimport android.util.Log;
270e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.view.MotionEvent;
280e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
2991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowskiimport java.util.ArrayDeque;
309f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowskiimport java.util.ArrayList;
319f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
320e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski/**
330e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * An classifier trying to determine whether it is a human interacting with the phone or not.
340e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski */
350e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskipublic class HumanInteractionClassifier extends Classifier {
360e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private static final String HIC_ENABLE = "HIC_enable";
3791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski    private static final float FINGER_DISTANCE = 0.1f;
385c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos
395c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos    /** Default value for the HIC_ENABLE setting: 1 - enabled, 0 - disabled */
405c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos    private static final int HIC_ENABLE_DEFAULT = 1;
415c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos
420e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private static HumanInteractionClassifier sInstance = null;
430e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
440e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private final Handler mHandler = new Handler();
450e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private final Context mContext;
460e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
47401caaedd871894620accc1d14592c08095b5523Adrian Roos    private final StrokeClassifier[] mStrokeClassifiers;
48401caaedd871894620accc1d14592c08095b5523Adrian Roos    private final GestureClassifier[] mGestureClassifiers;
49401caaedd871894620accc1d14592c08095b5523Adrian Roos    private final ArrayDeque<MotionEvent> mBufferedEvents = new ArrayDeque<>();
50401caaedd871894620accc1d14592c08095b5523Adrian Roos    private final HistoryEvaluator mHistoryEvaluator;
5191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski    private final float mDpi;
529f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
5352af6b646bd3abc8223ed01a36f6da785b35085dBlazej Magnowski    private boolean mEnableClassifier = false;
549f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski    private int mCurrentType = Classifier.GENERIC;
550e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
560e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
570e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        @Override
580e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        public void onChange(boolean selfChange) {
590e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski            updateConfiguration();
600e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        }
610e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    };
620e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
630e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private HumanInteractionClassifier(Context context) {
640e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        mContext = context;
6591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
6691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
6791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // If the phone is rotated to landscape, the calculations would be wrong if xdpi and ydpi
6891be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // were to be used separately. Due negligible differences in xdpi and ydpi we can just
6991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // take the average.
7056918509c7f4f8ec021de897a732b4bc4859c0b0Adrian Roos        // Note that xdpi and ydpi are the physical pixels per inch and are not affected by scaling.
7191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        mDpi = (displayMetrics.xdpi + displayMetrics.ydpi) / 2.0f;
7291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        mClassifierData = new ClassifierData(mDpi);
739f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski        mHistoryEvaluator = new HistoryEvaluator();
749f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
75401caaedd871894620accc1d14592c08095b5523Adrian Roos        mStrokeClassifiers = new StrokeClassifier[]{
76401caaedd871894620accc1d14592c08095b5523Adrian Roos                new AnglesClassifier(mClassifierData),
77401caaedd871894620accc1d14592c08095b5523Adrian Roos                new SpeedClassifier(mClassifierData),
78401caaedd871894620accc1d14592c08095b5523Adrian Roos                new DurationCountClassifier(mClassifierData),
79401caaedd871894620accc1d14592c08095b5523Adrian Roos                new EndPointRatioClassifier(mClassifierData),
80401caaedd871894620accc1d14592c08095b5523Adrian Roos                new EndPointLengthClassifier(mClassifierData),
81401caaedd871894620accc1d14592c08095b5523Adrian Roos                new AccelerationClassifier(mClassifierData),
82401caaedd871894620accc1d14592c08095b5523Adrian Roos                new SpeedAnglesClassifier(mClassifierData),
83401caaedd871894620accc1d14592c08095b5523Adrian Roos                new LengthCountClassifier(mClassifierData),
84401caaedd871894620accc1d14592c08095b5523Adrian Roos                new DirectionClassifier(mClassifierData),
85401caaedd871894620accc1d14592c08095b5523Adrian Roos        };
86401caaedd871894620accc1d14592c08095b5523Adrian Roos
87401caaedd871894620accc1d14592c08095b5523Adrian Roos        mGestureClassifiers = new GestureClassifier[] {
88401caaedd871894620accc1d14592c08095b5523Adrian Roos                new PointerCountClassifier(mClassifierData),
89401caaedd871894620accc1d14592c08095b5523Adrian Roos                new ProximityClassifier(mClassifierData)
90401caaedd871894620accc1d14592c08095b5523Adrian Roos        };
910e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
920e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        mContext.getContentResolver().registerContentObserver(
930e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski                Settings.Global.getUriFor(HIC_ENABLE), false,
940e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski                mSettingsObserver,
950e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski                UserHandle.USER_ALL);
960e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
970e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        updateConfiguration();
980e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
990e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
1000e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public static HumanInteractionClassifier getInstance(Context context) {
1010e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        if (sInstance == null) {
1020e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski            sInstance = new HumanInteractionClassifier(context);
1030e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        }
1040e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        return sInstance;
1050e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
1060e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
1070e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private void updateConfiguration() {
1085c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos        mEnableClassifier = 0 != Settings.Global.getInt(
1090e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski                mContext.getContentResolver(),
1105c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos                HIC_ENABLE, HIC_ENABLE_DEFAULT);
1110e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
1120e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
1139f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski    public void setType(int type) {
1149f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski        mCurrentType = type;
1159f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski    }
1169f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
1170e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    @Override
1180e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public void onTouchEvent(MotionEvent event) {
11991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        if (!mEnableClassifier) {
12091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            return;
12191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
1229f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
123c5584ceaad422c96f978132aee4d21ee1f61fc7dAdrian Roos        // If the user is dragging down the notification, they might want to drag it down
12491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // enough to see the content, read it for a while and then lift the finger to open
12591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // the notification. This kind of motion scores very bad in the Classifier so the
12691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // MotionEvents which are close to the current position of the finger are not
12791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // sent to the classifiers until the finger moves far enough. When the finger if lifted
12891be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // up, the last MotionEvent which was far enough from the finger is set as the final
12991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // MotionEvent and sent to the Classifiers.
13091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        if (mCurrentType == Classifier.NOTIFICATION_DRAG_DOWN) {
13191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            mBufferedEvents.add(MotionEvent.obtain(event));
13291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            Point pointEnd = new Point(event.getX() / mDpi, event.getY() / mDpi);
13391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
13491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            while (pointEnd.dist(new Point(mBufferedEvents.getFirst().getX() / mDpi,
13591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                    mBufferedEvents.getFirst().getY() / mDpi)) > FINGER_DISTANCE) {
13691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                addTouchEvent(mBufferedEvents.getFirst());
13791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                mBufferedEvents.remove();
1389f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski            }
1399f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
14091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            int action = event.getActionMasked();
14191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            if (action == MotionEvent.ACTION_UP) {
14291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                mBufferedEvents.getFirst().setAction(MotionEvent.ACTION_UP);
14391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                addTouchEvent(mBufferedEvents.getFirst());
14491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                mBufferedEvents.clear();
1459f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski            }
14691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        } else {
14791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            addTouchEvent(event);
14891be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
14991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski    }
1509f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
15191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski    private void addTouchEvent(MotionEvent event) {
15291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        mClassifierData.update(event);
1539f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
154401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (StrokeClassifier c : mStrokeClassifiers) {
155401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onTouchEvent(event);
15691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
15791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
158401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (GestureClassifier c : mGestureClassifiers) {
159401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onTouchEvent(event);
16091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
16191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
16291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        int size = mClassifierData.getEndingStrokes().size();
16391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        for (int i = 0; i < size; i++) {
16491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            Stroke stroke = mClassifierData.getEndingStrokes().get(i);
16591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            float evaluation = 0.0f;
166401caaedd871894620accc1d14592c08095b5523Adrian Roos            StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("stroke") : null;
167401caaedd871894620accc1d14592c08095b5523Adrian Roos            for (StrokeClassifier c : mStrokeClassifiers) {
168401caaedd871894620accc1d14592c08095b5523Adrian Roos                float e = c.getFalseTouchEvaluation(mCurrentType, stroke);
169401caaedd871894620accc1d14592c08095b5523Adrian Roos                if (FalsingLog.ENABLED) {
170401caaedd871894620accc1d14592c08095b5523Adrian Roos                    String tag = c.getTag();
171401caaedd871894620accc1d14592c08095b5523Adrian Roos                    sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
172401caaedd871894620accc1d14592c08095b5523Adrian Roos                }
173401caaedd871894620accc1d14592c08095b5523Adrian Roos                evaluation += e;
174401caaedd871894620accc1d14592c08095b5523Adrian Roos            }
175401caaedd871894620accc1d14592c08095b5523Adrian Roos
176401caaedd871894620accc1d14592c08095b5523Adrian Roos            if (FalsingLog.ENABLED) {
177401caaedd871894620accc1d14592c08095b5523Adrian Roos                FalsingLog.i(" addTouchEvent", sb.toString());
1789f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski            }
17991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            mHistoryEvaluator.addStroke(evaluation);
18091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
1819f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
18291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        int action = event.getActionMasked();
18391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
18491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            float evaluation = 0.0f;
185401caaedd871894620accc1d14592c08095b5523Adrian Roos            StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("gesture") : null;
186401caaedd871894620accc1d14592c08095b5523Adrian Roos            for (GestureClassifier c : mGestureClassifiers) {
187401caaedd871894620accc1d14592c08095b5523Adrian Roos                float e = c.getFalseTouchEvaluation(mCurrentType);
188401caaedd871894620accc1d14592c08095b5523Adrian Roos                if (FalsingLog.ENABLED) {
189401caaedd871894620accc1d14592c08095b5523Adrian Roos                    String tag = c.getTag();
190401caaedd871894620accc1d14592c08095b5523Adrian Roos                    sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
191401caaedd871894620accc1d14592c08095b5523Adrian Roos                }
192401caaedd871894620accc1d14592c08095b5523Adrian Roos                evaluation += e;
193401caaedd871894620accc1d14592c08095b5523Adrian Roos            }
194401caaedd871894620accc1d14592c08095b5523Adrian Roos            if (FalsingLog.ENABLED) {
195401caaedd871894620accc1d14592c08095b5523Adrian Roos                FalsingLog.i(" addTouchEvent", sb.toString());
19691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            }
19791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            mHistoryEvaluator.addGesture(evaluation);
19891be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            setType(Classifier.GENERIC);
1990e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        }
20091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
20191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        mClassifierData.cleanUp(event);
2020e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
2030e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
2040e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    @Override
2050e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public void onSensorChanged(SensorEvent event) {
206401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (Classifier c : mStrokeClassifiers) {
207401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onSensorChanged(event);
20868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
20968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
210401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (Classifier c : mGestureClassifiers) {
211401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onSensorChanged(event);
21268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
2130e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
2140e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
2159f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski    public boolean isFalseTouch() {
2166dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski        if (mEnableClassifier) {
217401caaedd871894620accc1d14592c08095b5523Adrian Roos            float evaluation = mHistoryEvaluator.getEvaluation();
218401caaedd871894620accc1d14592c08095b5523Adrian Roos            boolean result = evaluation >= 5.0f;
219401caaedd871894620accc1d14592c08095b5523Adrian Roos            if (FalsingLog.ENABLED) {
220401caaedd871894620accc1d14592c08095b5523Adrian Roos                FalsingLog.i("isFalseTouch", new StringBuilder()
221401caaedd871894620accc1d14592c08095b5523Adrian Roos                        .append("eval=").append(evaluation).append(" result=")
222401caaedd871894620accc1d14592c08095b5523Adrian Roos                        .append(result ? 1 : 0).toString());
223401caaedd871894620accc1d14592c08095b5523Adrian Roos            }
224401caaedd871894620accc1d14592c08095b5523Adrian Roos            return result;
2256dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski        }
2266dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski        return false;
2270e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
2280e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
2290e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public boolean isEnabled() {
2300e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        return mEnableClassifier;
2310e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
232401caaedd871894620accc1d14592c08095b5523Adrian Roos
233401caaedd871894620accc1d14592c08095b5523Adrian Roos    @Override
234401caaedd871894620accc1d14592c08095b5523Adrian Roos    public String getTag() {
235401caaedd871894620accc1d14592c08095b5523Adrian Roos        return "HIC";
236401caaedd871894620accc1d14592c08095b5523Adrian Roos    }
2370e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski}
238