1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.classifier; 18 19 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE; 20 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE; 21 import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE; 22 import static com.android.systemui.classifier.Classifier.RIGHT_AFFORDANCE; 23 24 import android.provider.DeviceConfig; 25 26 import com.android.systemui.util.DeviceConfigProxy; 27 28 import java.util.Locale; 29 30 import javax.inject.Inject; 31 32 /** 33 * False on swipes that are too close to 45 degrees. 34 * 35 * Horizontal swipes may have a different threshold than vertical. 36 * 37 * This falser should not run on "affordance" swipes, as they will always be close to 45. 38 */ 39 class DiagonalClassifier extends FalsingClassifier { 40 41 private static final float HORIZONTAL_ANGLE_RANGE = (float) (5f / 360f * Math.PI * 2f); 42 private static final float VERTICAL_ANGLE_RANGE = (float) (5f / 360f * Math.PI * 2f); 43 private static final float DIAGONAL = (float) (Math.PI / 4); // 45 deg 44 private static final float NINETY_DEG = (float) (Math.PI / 2); 45 private static final float ONE_HUNDRED_EIGHTY_DEG = (float) (Math.PI); 46 private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI); 47 48 private final float mHorizontalAngleRange; 49 private final float mVerticalAngleRange; 50 51 @Inject DiagonalClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy)52 DiagonalClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) { 53 super(dataProvider); 54 55 mHorizontalAngleRange = deviceConfigProxy.getFloat( 56 DeviceConfig.NAMESPACE_SYSTEMUI, 57 BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE, 58 HORIZONTAL_ANGLE_RANGE); 59 mVerticalAngleRange = deviceConfigProxy.getFloat( 60 DeviceConfig.NAMESPACE_SYSTEMUI, 61 BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE, 62 VERTICAL_ANGLE_RANGE); 63 } 64 calculateFalsingResult( @lassifier.InteractionType int interactionType, double historyBelief, double historyConfidence)65 Result calculateFalsingResult( 66 @Classifier.InteractionType int interactionType, 67 double historyBelief, double historyConfidence) { 68 float angle = getAngle(); 69 70 if (angle == Float.MAX_VALUE) { // Unknown angle 71 return Result.passed(0); 72 } 73 74 if (interactionType == LEFT_AFFORDANCE 75 || interactionType == RIGHT_AFFORDANCE) { 76 return Result.passed(0); 77 } 78 79 float minAngle = DIAGONAL - mHorizontalAngleRange; 80 float maxAngle = DIAGONAL + mHorizontalAngleRange; 81 if (isVertical()) { 82 minAngle = DIAGONAL - mVerticalAngleRange; 83 maxAngle = DIAGONAL + mVerticalAngleRange; 84 } 85 86 boolean falsed = angleBetween(angle, minAngle, maxAngle) 87 || angleBetween(angle, minAngle + NINETY_DEG, maxAngle + NINETY_DEG) 88 || angleBetween(angle, minAngle - NINETY_DEG, maxAngle - NINETY_DEG) 89 || angleBetween(angle, minAngle + ONE_HUNDRED_EIGHTY_DEG, 90 maxAngle + ONE_HUNDRED_EIGHTY_DEG); 91 return falsed ? falsed(0.5f, getReason()) : Result.passed(0.5); 92 } 93 getReason()94 private String getReason() { 95 return String.format( 96 (Locale) null, 97 "{angle=%f, vertical=%s}", 98 getAngle(), 99 isVertical()); 100 } 101 angleBetween(float angle, float min, float max)102 private boolean angleBetween(float angle, float min, float max) { 103 // No need to normalize angle as it is guaranteed to be between 0 and 2*PI. 104 min = normalizeAngle(min); 105 max = normalizeAngle(max); 106 107 if (min > max) { // Can happen when angle is close to 0. 108 return angle >= min || angle <= max; 109 } 110 111 return angle >= min && angle <= max; 112 } 113 normalizeAngle(float angle)114 private float normalizeAngle(float angle) { 115 if (angle < 0) { 116 return THREE_HUNDRED_SIXTY_DEG + (angle % THREE_HUNDRED_SIXTY_DEG); 117 } else if (angle > THREE_HUNDRED_SIXTY_DEG) { 118 return angle % THREE_HUNDRED_SIXTY_DEG; 119 } 120 return angle; 121 } 122 } 123