/*
|
* 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.3f;
|
|
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;
|
}
|
}
|
}
|