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;
23f8c4add85188a90940d9d7045ab4c945375fcff2Selim Cinekimport android.os.Looper;
240e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.os.UserHandle;
250e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.provider.Settings;
2691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowskiimport android.util.DisplayMetrics;
27401caaedd871894620accc1d14592c08095b5523Adrian Roosimport android.util.Log;
280e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport android.view.MotionEvent;
290e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
30633b6ba7e301a01947ee5e37dd804b42e7189f4fAdrian Roosimport com.android.systemui.R;
31633b6ba7e301a01947ee5e37dd804b42e7189f4fAdrian Roos
3291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowskiimport java.util.ArrayDeque;
339f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowskiimport java.util.ArrayList;
349f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
350e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski/**
360e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * An classifier trying to determine whether it is a human interacting with the phone or not.
370e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski */
380e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskipublic class HumanInteractionClassifier extends Classifier {
390e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private static final String HIC_ENABLE = "HIC_enable";
4091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski    private static final float FINGER_DISTANCE = 0.1f;
415c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos
420e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private static HumanInteractionClassifier sInstance = null;
430e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
44f8c4add85188a90940d9d7045ab4c945375fcff2Selim Cinek    private final Handler mHandler = new Handler(Looper.getMainLooper());
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() {
108633b6ba7e301a01947ee5e37dd804b42e7189f4fAdrian Roos        boolean defaultValue = mContext.getResources().getBoolean(
109633b6ba7e301a01947ee5e37dd804b42e7189f4fAdrian Roos                R.bool.config_lockscreenAntiFalsingClassifierEnabled);
110633b6ba7e301a01947ee5e37dd804b42e7189f4fAdrian Roos
1115c42df13a457abc99926e4b1a6aa4d45af3719c7Adrian Roos        mEnableClassifier = 0 != Settings.Global.getInt(
1120e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski                mContext.getContentResolver(),
113633b6ba7e301a01947ee5e37dd804b42e7189f4fAdrian Roos                HIC_ENABLE, defaultValue ? 1 : 0);
1140e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
1150e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
1169f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski    public void setType(int type) {
1179f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski        mCurrentType = type;
1189f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski    }
1199f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
1200e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    @Override
1210e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public void onTouchEvent(MotionEvent event) {
12291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        if (!mEnableClassifier) {
12391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            return;
12491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
1259f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
126c5584ceaad422c96f978132aee4d21ee1f61fc7dAdrian Roos        // If the user is dragging down the notification, they might want to drag it down
12791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // enough to see the content, read it for a while and then lift the finger to open
12891be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // the notification. This kind of motion scores very bad in the Classifier so the
12991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // MotionEvents which are close to the current position of the finger are not
13091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // sent to the classifiers until the finger moves far enough. When the finger if lifted
13191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // up, the last MotionEvent which was far enough from the finger is set as the final
13291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        // MotionEvent and sent to the Classifiers.
13391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        if (mCurrentType == Classifier.NOTIFICATION_DRAG_DOWN) {
13491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            mBufferedEvents.add(MotionEvent.obtain(event));
13591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            Point pointEnd = new Point(event.getX() / mDpi, event.getY() / mDpi);
13691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
13791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            while (pointEnd.dist(new Point(mBufferedEvents.getFirst().getX() / mDpi,
13891be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                    mBufferedEvents.getFirst().getY() / mDpi)) > FINGER_DISTANCE) {
13991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                addTouchEvent(mBufferedEvents.getFirst());
14091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                mBufferedEvents.remove();
1419f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski            }
1429f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
14391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            int action = event.getActionMasked();
14491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            if (action == MotionEvent.ACTION_UP) {
14591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                mBufferedEvents.getFirst().setAction(MotionEvent.ACTION_UP);
14691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                addTouchEvent(mBufferedEvents.getFirst());
14791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski                mBufferedEvents.clear();
1489f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski            }
14991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        } else {
15091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            addTouchEvent(event);
15191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
15291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski    }
1539f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
15491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski    private void addTouchEvent(MotionEvent event) {
15591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        mClassifierData.update(event);
1569f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
157401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (StrokeClassifier c : mStrokeClassifiers) {
158401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onTouchEvent(event);
15991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
16091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
161401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (GestureClassifier c : mGestureClassifiers) {
162401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onTouchEvent(event);
16391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
16491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
16591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        int size = mClassifierData.getEndingStrokes().size();
16691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        for (int i = 0; i < size; i++) {
16791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            Stroke stroke = mClassifierData.getEndingStrokes().get(i);
16891be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            float evaluation = 0.0f;
169401caaedd871894620accc1d14592c08095b5523Adrian Roos            StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("stroke") : null;
170401caaedd871894620accc1d14592c08095b5523Adrian Roos            for (StrokeClassifier c : mStrokeClassifiers) {
171401caaedd871894620accc1d14592c08095b5523Adrian Roos                float e = c.getFalseTouchEvaluation(mCurrentType, stroke);
172401caaedd871894620accc1d14592c08095b5523Adrian Roos                if (FalsingLog.ENABLED) {
173401caaedd871894620accc1d14592c08095b5523Adrian Roos                    String tag = c.getTag();
174401caaedd871894620accc1d14592c08095b5523Adrian Roos                    sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
175401caaedd871894620accc1d14592c08095b5523Adrian Roos                }
176401caaedd871894620accc1d14592c08095b5523Adrian Roos                evaluation += e;
177401caaedd871894620accc1d14592c08095b5523Adrian Roos            }
178401caaedd871894620accc1d14592c08095b5523Adrian Roos
179401caaedd871894620accc1d14592c08095b5523Adrian Roos            if (FalsingLog.ENABLED) {
180401caaedd871894620accc1d14592c08095b5523Adrian Roos                FalsingLog.i(" addTouchEvent", sb.toString());
1819f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski            }
18291be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            mHistoryEvaluator.addStroke(evaluation);
18391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        }
1849f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski
18591be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        int action = event.getActionMasked();
18691be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
18791be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            float evaluation = 0.0f;
188401caaedd871894620accc1d14592c08095b5523Adrian Roos            StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("gesture") : null;
189401caaedd871894620accc1d14592c08095b5523Adrian Roos            for (GestureClassifier c : mGestureClassifiers) {
190401caaedd871894620accc1d14592c08095b5523Adrian Roos                float e = c.getFalseTouchEvaluation(mCurrentType);
191401caaedd871894620accc1d14592c08095b5523Adrian Roos                if (FalsingLog.ENABLED) {
192401caaedd871894620accc1d14592c08095b5523Adrian Roos                    String tag = c.getTag();
193401caaedd871894620accc1d14592c08095b5523Adrian Roos                    sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
194401caaedd871894620accc1d14592c08095b5523Adrian Roos                }
195401caaedd871894620accc1d14592c08095b5523Adrian Roos                evaluation += e;
196401caaedd871894620accc1d14592c08095b5523Adrian Roos            }
197401caaedd871894620accc1d14592c08095b5523Adrian Roos            if (FalsingLog.ENABLED) {
198401caaedd871894620accc1d14592c08095b5523Adrian Roos                FalsingLog.i(" addTouchEvent", sb.toString());
19991be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            }
20091be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            mHistoryEvaluator.addGesture(evaluation);
20191be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski            setType(Classifier.GENERIC);
2020e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        }
20391be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski
20491be2f88a5434f73514f7ce58f35f47a6033265dBlazej Magnowski        mClassifierData.cleanUp(event);
2050e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
2060e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
2070e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    @Override
2080e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public void onSensorChanged(SensorEvent event) {
209401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (Classifier c : mStrokeClassifiers) {
210401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onSensorChanged(event);
21168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
21268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
213401caaedd871894620accc1d14592c08095b5523Adrian Roos        for (Classifier c : mGestureClassifiers) {
214401caaedd871894620accc1d14592c08095b5523Adrian Roos            c.onSensorChanged(event);
21568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
2160e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
2170e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
2189f01c5bfa5c1c63e350808c154adfc2953949b15Blazej Magnowski    public boolean isFalseTouch() {
2196dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski        if (mEnableClassifier) {
220401caaedd871894620accc1d14592c08095b5523Adrian Roos            float evaluation = mHistoryEvaluator.getEvaluation();
221401caaedd871894620accc1d14592c08095b5523Adrian Roos            boolean result = evaluation >= 5.0f;
222401caaedd871894620accc1d14592c08095b5523Adrian Roos            if (FalsingLog.ENABLED) {
223401caaedd871894620accc1d14592c08095b5523Adrian Roos                FalsingLog.i("isFalseTouch", new StringBuilder()
224401caaedd871894620accc1d14592c08095b5523Adrian Roos                        .append("eval=").append(evaluation).append(" result=")
225401caaedd871894620accc1d14592c08095b5523Adrian Roos                        .append(result ? 1 : 0).toString());
226401caaedd871894620accc1d14592c08095b5523Adrian Roos            }
227401caaedd871894620accc1d14592c08095b5523Adrian Roos            return result;
2286dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski        }
2296dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski        return false;
2300e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
2310e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
2320e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public boolean isEnabled() {
2330e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        return mEnableClassifier;
2340e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
235401caaedd871894620accc1d14592c08095b5523Adrian Roos
236401caaedd871894620accc1d14592c08095b5523Adrian Roos    @Override
237401caaedd871894620accc1d14592c08095b5523Adrian Roos    public String getTag() {
238401caaedd871894620accc1d14592c08095b5523Adrian Roos        return "HIC";
239401caaedd871894620accc1d14592c08095b5523Adrian Roos    }
2400e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski}
241