Untrusted Touch Events in Android

Meghan Mehta
Android Developers
Published in
6 min readMay 26, 2021

--

In Android 12, we are making changes to enhance app and platform security to provide our users with a safer experience. After this article, check out our other blog posts that cover security and privacy.

Touch input is the primary means of interaction with an app in Android. Android 12 includes additional measures to ensure that touch events are properly passed to the intended apps to ensure an intuitive and safe UX. Specifically, Android 12 prevents touch events from being delivered to apps if these touches pass through a window from a different app. This behavior change applies to all apps running on Android 12, regardless of `targetSdkVersion`. This helps ensure that users can see what they are interacting with. Read on to learn about alternatives, to see if your app will be affected and how you can test for it.

Use special-purpose APIs if possible

Before checking if your use-case is affected, it’s good to evaluate if your app can utilize one of the following APIs in Android. These easy to use APIs prevent you from having to worry about these restrictions altogether since they are partly controlled by the system, and as such can be trusted. Consider the following:

  • Bubbles: Bubbles float on top of other app content, follow the user wherever they go, and can be expanded to reveal app functionality and information.
  • Picture-in-Picture (PIP): PIP allows the app to display content in a small window, pinned to a corner of the screen, while the user is navigating between apps or browsing content on the main screen. The user can drag the PIP window around and can click on it to expand or close.
  • Notifications: Notifications are the standard way to provide the user with reminders, messages from other people, or other timely information from your app while minimally disrupting use of the device. Users can tap the notification to open your app, or take an action directly from the notification.
  • Snackbars and Toasts: If you need to display a message for a brief period of time inside your app, take a look at Snackbars. If you need to display that message while your app is in the background, see if Toasts fit your use-case.

If your use-case fits one of these APIs, it’s strongly recommended to use them. Not only are they easier to use, they are safer, and the user is already familiar with most of them.

Does this affect me?

If your app can’t utilize one of the APIs above and lets touch events pass through its windows, it’s possible that, on Android 12, they will not go through to whatever is underneath as intended.

Examples include, but aren’t limited to, the following:

If you’re using FLAG_NOT_TOUCHABLE you’re likely affected, unless your use-case falls into one of the exemptions below:

If your use-case doesn’t fall into the list above, touches will be blocked. If this works for your use case, consider removing FLAG_NOT_TOUCHABLE to remove the intention of letting touches pass-through. If you need to let touches pass-through, you’ll have to adjust your code to fit one of the exemptions above. The next section covers, examples of common patterns that will have to be changed:

Windows with transparent background and no UI

Apps that display some UI in a window with a transparent background can hide their UI at the view level at certain times while adding FLAG_NOT_TOUCHABLE so the user can interact with what’s behind.

If, like in the diagram above, the app merely hid the UI, either by removing child views or changing their visibility, and added FLAG_NOT_TOUCHABLE so the user could interact with what’s behind, this won’t work on Android 12 anymore (note the difference from exemptions mentioned before — here we are changing internal views, not the window), since touches to other apps behind will be blocked. Fixing that is easy in this case; you can either:

Whenever you need to display that UI again, you just need to reverse the action above.

Unnecessarily large windows

Apps might want to display some small UI while still allowing the user to interact with what is behind the window. Previously, an app could achieve that by simply using a fullscreen window and marking it with FLAG_NOT_TOUCHABLE, such as in figure 1:

Note that touches that go through the actual UI element would in this case pass-through to the windows behind in previous OS versions. The first suggestion in this case is to take a look at the Toast API to see if that fits your purpose. If not, the solution here is also straightforward and illustrated on the image on the right: you just need to reduce the window boundaries to the actual UI and use FLAG_NOT_TOUCH_MODAL, at which point you probably want to remove FLAG_NOT_TOUCHABLE too.

Now touches outside your UI will go directly to the window behind and won’t be blocked.

Translucent windows

If you are using a TYPE_APPLICATION_OVERLAY window and absolutely need to let touches pass-through it while displaying content, you’ll have to reduce the opacity such that the user is able to reasonably see what they are touching behind the window.

You’ll have to reduce your opacity at the window level, merely changing the opacity of views doesn’t work. You can use LayoutParams.alpha to reduce the opacity to a value below or equal to InputManager.getMaximumObscuringOpacityForTouch() like shown on the right. This value is currently 0.8 but might change before the Android 12 final release.

Now, provided you don’t have multiple windows from your app that overlap each other, touches will go through to the window behind. For more details about overlapping windows, take a look at the documentation of FLAG_NOT_TOUCHABLE.

Accessibility services

As a connected accessibility service, it’s possible to create windows of type TYPE_ACCESSIBILITY_OVERLAY, which are trusted and thus are exempt from the restrictions described earlier. In order to create such windows, just use the context of your AccessibilityService to obtain a WindowManager via getSystemService() to create said windows.

How to test if your app is affected

If a touch action is blocked by the system, you will see the following message in Logcat: Untrusted touch due to occlusion by PACKAGE_NAME.

Next steps

Check out the documentation if you want to learn more about untrusted touch events and their exceptions.

Happy coding!

--

--