blob: a6a617dc51ded3d527d53382b78728c71d301e6f [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.classifier.brightline;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN;
import android.provider.DeviceConfig;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import java.util.List;
/**
* Ensure that the swipe + momentum covers a minimum distance.
*/
class DistanceClassifier extends FalsingClassifier {
private static final float HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN = 1;
private static final float VERTICAL_FLING_THRESHOLD_DISTANCE_IN = 1;
private static final float HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
private static final float VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
private static final float VELOCITY_TO_DISTANCE = 80f;
private static final float SCREEN_FRACTION_MAX_DISTANCE = 0.8f;
private final float mVerticalFlingThresholdPx;
private final float mHorizontalFlingThresholdPx;
private final float mVerticalSwipeThresholdPx;
private final float mHorizontalSwipeThresholdPx;
private final float mVelocityToDistanceMultiplier;
private boolean mDistanceDirty;
private DistanceVectors mCachedDistance;
DistanceClassifier(FalsingDataProvider dataProvider) {
super(dataProvider);
mVelocityToDistanceMultiplier = DeviceConfig.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE,
VELOCITY_TO_DISTANCE);
float horizontalFlingThresholdIn = DeviceConfig.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN,
HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN);
float verticalFlingThresholdIn = DeviceConfig.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN,
VERTICAL_FLING_THRESHOLD_DISTANCE_IN);
float horizontalSwipeThresholdIn = DeviceConfig.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN,
HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN);
float verticalSwipeThresholdIn = DeviceConfig.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN,
VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN);
float screenFractionMaxDistance = DeviceConfig.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE,
SCREEN_FRACTION_MAX_DISTANCE);
mHorizontalFlingThresholdPx = Math
.min(getWidthPixels() * screenFractionMaxDistance,
horizontalFlingThresholdIn * getXdpi());
mVerticalFlingThresholdPx = Math
.min(getHeightPixels() * screenFractionMaxDistance,
verticalFlingThresholdIn * getYdpi());
mHorizontalSwipeThresholdPx = Math
.min(getWidthPixels() * screenFractionMaxDistance,
horizontalSwipeThresholdIn * getXdpi());
mVerticalSwipeThresholdPx = Math
.min(getHeightPixels() * screenFractionMaxDistance,
verticalSwipeThresholdIn * getYdpi());
mDistanceDirty = true;
}
private DistanceVectors getDistances() {
if (mDistanceDirty) {
mCachedDistance = calculateDistances();
mDistanceDirty = false;
}
return mCachedDistance;
}
private DistanceVectors calculateDistances() {
// This code assumes that there will be no missed DOWN or UP events.
VelocityTracker velocityTracker = VelocityTracker.obtain();
List<MotionEvent> motionEvents = getRecentMotionEvents();
if (motionEvents.size() < 3) {
logDebug("Only " + motionEvents.size() + " motion events recorded.");
return new DistanceVectors(0, 0, 0, 0);
}
for (MotionEvent motionEvent : motionEvents) {
velocityTracker.addMovement(motionEvent);
}
velocityTracker.computeCurrentVelocity(1);
float vX = velocityTracker.getXVelocity();
float vY = velocityTracker.getYVelocity();
velocityTracker.recycle();
float dX = getLastMotionEvent().getX() - getFirstMotionEvent().getX();
float dY = getLastMotionEvent().getY() - getFirstMotionEvent().getY();
logInfo("dX: " + dX + " dY: " + dY + " xV: " + vX + " yV: " + vY);
return new DistanceVectors(dX, dY, vX, vY);
}
@Override
public void onTouchEvent(MotionEvent motionEvent) {
mDistanceDirty = true;
}
@Override
public boolean isFalseTouch() {
return !getDistances().getPassedFlingThreshold();
}
boolean isLongSwipe() {
boolean longSwipe = getDistances().getPassedDistanceThreshold();
logDebug("Is longSwipe? " + longSwipe);
return longSwipe;
}
private class DistanceVectors {
final float mDx;
final float mDy;
private final float mVx;
private final float mVy;
DistanceVectors(float dX, float dY, float vX, float vY) {
this.mDx = dX;
this.mDy = dY;
this.mVx = vX;
this.mVy = vY;
}
boolean getPassedDistanceThreshold() {
if (isHorizontal()) {
logDebug("Horizontal swipe distance: " + Math.abs(mDx));
logDebug("Threshold: " + mHorizontalSwipeThresholdPx);
return Math.abs(mDx) >= mHorizontalSwipeThresholdPx;
}
logDebug("Vertical swipe distance: " + Math.abs(mDy));
logDebug("Threshold: " + mVerticalSwipeThresholdPx);
return Math.abs(mDy) >= mVerticalSwipeThresholdPx;
}
boolean getPassedFlingThreshold() {
float dX = this.mDx + this.mVx * mVelocityToDistanceMultiplier;
float dY = this.mDy + this.mVy * mVelocityToDistanceMultiplier;
if (isHorizontal()) {
logDebug("Horizontal swipe and fling distance: " + this.mDx + ", "
+ this.mVx * mVelocityToDistanceMultiplier);
logDebug("Threshold: " + mHorizontalFlingThresholdPx);
return Math.abs(dX) >= mHorizontalFlingThresholdPx;
}
logDebug("Vertical swipe and fling distance: " + this.mDy + ", "
+ this.mVy * mVelocityToDistanceMultiplier);
logDebug("Threshold: " + mVerticalFlingThresholdPx);
return Math.abs(dY) >= mVerticalFlingThresholdPx;
}
}
}