1# Falsing in SystemUI 2 3Phones are easily and often accidentally-activated in owners' pockets ("falsing" or "pocket 4dialing"). Because a phone's screen can be turned on with a single tap, and because we have further 5actions that be activated with basic tapping and swiping, it is critical that we 6analyze touch events on the screen for intentional vs accidental behavior. With analysis, 7features within SystemUI have an opportunity to ignore or even undo accidental interactions as they 8are occurring. 9 10## Technical Details 11 12The `FalsingManager` tracks all touch interactions happening on a phone's lock screen. 13 14If you support any sort of touch gestures on the lock screen, you **must**, at a 15minimum, inform the `FalsingManager` of what touches are on touch targets vs not (things that may be 16 intentional). If you do not tell the `FalsingManager`, it will assume touches on your feature are 17always accidental and penalize the session accordingly. 18 19Individual touch targets do not _have_ to be separated out; it's acceptable to 20wrap your whole feature in one virtual block that reports touches to the 21`FalsingManager`, however more granular tracking will result in better results 22across the whole lock screen. 23 24You can _act_ on the results of the `FalsingManager`. Instead of only telling 25the `FalsingManager` that touch events were on touch targets, you can further use the 26returned results to decide if you want to respond to an owner's touch, if you 27want to prompt them to confirm their action, or if you simply want to ignore the 28touch. 29 30The flow through the system looks like such: 31 321. Gesture on the screen. 332. The `FalsingManager` makes a note of all of the `MotionEvents`. 34 * If no feature/touch target receives the `MotionEvents`, skip to 4. 353. Your touch target receives the `MotionEvents`. 36 * Once your feature is ready to respond to the gesture in a substantive manner, it queries 37 the `FalsingManager`. 38 - Dragging animations, touch ripples, and other purely visual effects should not query. 39 - Query once you are ready to launch a new feature or dialogue, or are otherwise going to 40 change the state of the UI. 41 - Generally, wait until `MotionEvent.ACTION_UP` to query or `View.OnClickListener#onClick`. 42 - Only query once per gesture, at the end. 43 * If the `FalsingManager` says it looks good, respond to the touch. 444. The `FalsingManager` checks to see if anyone queried about the gesture. If not, mark it as 45 accidental. 46 47There is also an event fired by the `FalsingManager` that can be listened to by anyone, that 48indicates that the the `FalsingManager` believes the phone is actively being pocket-dialed. When 49fired, modal features, such as quick settings, keyguard bouncer, and others should retract 50themselves to prevent further pocket-dialing. 51 52## Falsing "Belief" and History 53 54The `FalsingManager` maintains a recent history of false analyses. Using 55Bayesian statistics, it updates a "belief" in whether recent 56gestures are intentional or not. Any gesture that it is not explicitly queried about is treated as 57accidental, increasing the overall belief in 58false-iness. Gestures that are explicitly queried and that pass the relevant heuristics 59reduce belief that falsing is occurring. This information is tracked within the `HistoryTracker`. 60 61Changes in belief may influence internal heurstics within the `FalsingManager`, 62making it easier or harder for an owner to interact with their device. (An owner 63will always be able to interact with their device, but we may require double 64taps, or more deliberate swipes.) 65 66## Responding to Touch Events 67 68The methods below inform the `FalsingManager` that a tap is occurring within an expected touch 69target. Match the methods with the gesture you expect the device owner to use. 70 71### Single Tap 72 73`FalsingManager#isSimpleTape()`. This method 74performs a only very basic checking, checking that observed `MotionEvent`s are 75all within some small x & y region ("touch slop"). Useful for only the most simple of scenarios, 76you probably want `FalsingManager#isFalseTap` method for most cases. 77 78`FalsingManager#isFalseTap(@Penalty int penalty)`. This 79method tells the `FalsingManager` that you want to thoroughly validate a single tap. It 80returns true if it thinks the tap should be rejected (i.e. the tap looks more 81like a swipe) and false otherwise. 82 83It runs through the following heuristics to validate a tap: 84 851. If the device recognizes a face (i.e. face-auth) the tap is **accepted**. 862. If the tap is the _second_ tap in recent history and looks like a valid Double Tap 87 the tap is **accepted**. This works exactly like `FalsingManager#isFalseDoubleTap`. 883. If the `HistoryTracker` reports strong belief in recent falsing, the tap is 89 **rejected**. 904. Otherwise the tap is **accepted**. 91 92All the above rules are applied only after first confirming the gesture does 93in fact look like a simple tap. 94 95`penalty` is a measure of how much the `HistoryTracker`'s belief should be 96penalized in the event that the tap is rejected. This value is only used if 97the gesture fails to validate as a simple tap. 98 99The `@FalsingManager.Penalty` values are fairly straightforward, but note that you 100should generally be choosing `LOW_PENALTY`. It is inherently difficult to know if a 101tap is truly false or not, so a single mis-tap should apply only a small penalty. 102If the owner is further along in a UX flow, and is still mis-tapping, it may make more 103sense to increase the penalty as mis-taps should be less likely to occur after 104several successful gestures. 105 106### Double Tap 107 108`FalsingManager#isFalseDoubleTap()`. This method tells the `FalsingManager` that 109your UI wants to validate a double tap. There are no parameters to pass to this method. 110Call this when you explicitly receive and want to verify a double tap, _not_ a single tap. 111 112Note that `FalsingManager#isFalseTap(boolean robustCheck, double falsePenalty)` 113will also check for double taps when `robustCheck` is set to true. If you are 114willing to use single taps, use that instead. 115 116### Swipes and Other Gestures 117 118`FalsingManager#isFalseTouch(@Classifier.InteractionType int interactionType)`. 119Use this for any non-tap interactions. This includes expanding notifications, 120expanding quick settings, pulling up the bouncer, and more. You must pass 121the type of interaction you are evaluating when calling it. A large set of 122heuristics will be applied to analyze the gesture, and the exact rules vary depending upon 123the `InteractionType`. 124 125### Ignoring A Gesture 126 127`FalsingCollector#avoidGesture()`. Tell the `FalsingManager` to pretend like the 128observed gesture never happened. **This method must be called when the observed 129`MotionEvent` is `MotionEvent.ACTION_DOWN`.** Attempting to call this method 130later in a gesture will not work. 131 132Notice that this method is actually a method on `FalsingCollector`. It is 133forcefully telling the `FalsingManager` to wholly pretend the gesture never 134happened. This is intended for security and PII sensitive gestures, such as 135password inputs. Please don't use this as a shortcut for avoiding the 136FalsingManager. Falsing works better the more behavior it is told about. 137 138### Other Considerations 139 140Please try to call the `FalsingManager` only once per gesture. Wait until you 141are ready to act on the owner's action, and then query the `FalsingManager`. The `FalsingManager` 142will update its belief in pocket dialing based only on the last call made, so multiple calls per 143gesture are not well defined. 144 145The `FalsingManager` does not update its belief in pocket-dialing until after a gesture completes. 146That is to say, if the owner makes a bad tap on your feature, the "belief" in pocket dialing will 147not incorporate this new data after processing on the final `ACTION_UP` or `ACTION_CANCEL` event 148occurs. 149 150If you expect a mix of taps, double taps, and swipes on your feature, segment them 151accordingly. Figure out which `FalsingManager` method you need to call first, rather than relying 152on multiple calls to the `FalsingManager` to act as a sieve. 153 154Don't: 155``` 156if (!mFalsingManager.isFalseTap(false, 0)) { 157 // its a tap 158} else if (!mFalsingManager.isFalseTouch(GESTURE_A) { 159 // do thing a 160} else if (!mFalsingManager.isFalseTouch(GESTURE_B) { 161 // do thing b 162} else { 163 // must be a false. 164} 165``` 166 167Do: 168``` 169void onTap() { 170 if (!mFalsingManager.isFalseTap(false, 0)) { 171 // its a tap 172} 173 174void onGestureA() { 175 if (!mFalsingManager.isFalseTouch(GESTURE_A) { 176 // do thing a 177 } 178} 179 180void onGestureB() { 181 if (!mFalsingManager.isFalseTouch(GESTURE_B) { 182 // do thing b 183 } 184} 185``` 186 187 188## Influencing Belief 189 190`FalsingCollector#updateFalseConfidence(FalsingClassifier.Result result)`. This 191method allows you to directly change the `FalsingManager`'s belief in the state 192of pocket dialing. If the owner does something unusual with their phone that you 193think indicates pocket dialing, you can call: 194 195``` 196 mFalsingCollector.updateFalseConfidence( 197 FalsingClassifier.Result.falsed(0.6, "Owner is doing something fishy")); 198``` 199 200A belief value of `1` indicates a 100% confidence of false behavior. A belief 201value of `0` would make no change in the `FalsingManager` and should be avoided 202as it simply creates noise in the logs. Generally, a middle value between the 203two extremes makes sense. 204 205A good example of where this is used is in the "Pattern" password input. We 206avoid recording those gestures in the `FalsingManager`, but we have the pattern input update 207the `FalsingManager` directly in some cases. If the owner simply taps on the pattern input, we 208record it as a false, (patterns are always 4 "cells" long, so single "cell" inputs are penalized). 209 210Conversely, if you think the owner does something that deserves a nice reward: 211 212``` 213 mFalsingCollector.updateFalseConfidence( 214 FalsingClassifier.Result.passed(0.6)); 215``` 216 217Again, useful on password inputs where the FalsingManager is avoiding recording 218the gesture. This is used on the "pin" password input, to recognize successful 219taps on the input buttons. 220 221## Global Falsing Event 222 223If the `FalsingManager`'s belief in falsing crosses some internally defined 224threshold, it will fire an event that other parts of the system can listen for. 225This even indicates that the owner is likely actively pocket-dialing, and any 226currently open activities on the phone should retract themselves. 227 228To subscribe to this event, call 229`FalsingManager#addFalsingBeliefListener(FalsingBeliefListener listener)`. 230`FalsingBeliefListener` is a simple one method interface that will be called 231after when activities should retract themselves. 232 233**Do Listen For This**. Your code will work without it, but it is a handy, 234universal signal that will save the phone owner a lot of accidents. A simple 235implementation looks like: 236 237``` 238 mFalsingManager.addFalsingBeliefListener(MyFeatureClass::hide); 239``` 240