Android USB permissions: Remember granted USB permissions

USB-permission-header-part1

One Android issue has been causing headaches for quite a few people for a very long time now. We even dare to say it's one of the biggest problems with confirmation dialogs on Android we have witnessed so far.

We are talking about the way permission requests are handled by Android to provide applications with access to connected USB devices – the Android USB permission dialog.

Most questions about the USB permission dialog concern following issues:

  • How to remember the permissions given and stop Android from asking for USB user permissions each time a USB device is reconnected, or the OS is rebooted?
  • How to stop the OS from asking for USB user permissions in the first place?

In this blog article, we take a closer look at the first question. For the second question stay tuned it will be answered in a follow up article.

Are you looking for specific information? Use the table of contents on your right to jump forward.

What is an Android USB permission request?

When a USB peripheral is connected to an Android device, the operating system has full access to it, same as some built-in system applications. However, this is not the case for all apps. If a specific application does not have permission yet, a request dialog is triggered asking for confirmation.

usb-permission

Image: USB permission request dialog

Different USB device types

There is a huge variety of possible USB peripherals to connect. It can be anything like keyboard, thermometer, touchscreen, lighting control etc. The most important difference is the category a specific device belongs to like mass storage devices, such as commonly used USB flash drives or input devices, such as keyboards, touchscreens, or scanners.

Applications that require USB permissions for peripherals access should request them through the official Android API. Once the permission is granted by the OS, the application can access files on the connected storage or use the connection for transferring data and sending commands to input devices.

When does an application ask for USB permission?

Applications should ask for Android USB permission when a device is detected and before an action needs access to it. It is possible for an application to be notified by the OS that a new USB device has been plugged in and immediately ask for permission to interact with it.

Why does Android ask me for granting USB permissions in the first place?

Device security is an important concern, as apps can potentially introduce malware or other security risks to production systems. Once a USB device is attached the app could try to spy on it, read the contained data or upload it to a malicious third party. This is why asking for permissions is essential for maintaining device security, when working with mass storage devices such as hard drives and USB flash drives.

This is the reason why the Android Open Source Project (AOSP) has strict rules and enforces following best practices:

  • User control: The user has control over the data that they share with apps.
  • Transparency: The user understands what data an app uses and why the app accesses this data.
  • Data minimization: An app accesses and uses only the data that's required for a specific task or action that the user invokes.

It's important to be careful when granting USB permissions to applications, as granting permissions to an untrusted or malicious app could potentially expose sensitive data on the device. Always make sure to stay in control by reading the permissions requested before granting them, and only granting permissions to trusted applications.

It is highly important to restrict app permissions to necessary actions only to protect users and prevent misuse.

Why does AOSP show the USB permission confirmation dialog every time?

As we’ve learned and experienced firsthand, Android devices seemingly initiate a new confirmation dialog every time an USB device is plugged in. At the first glance it looks like it does not matter if this device has been plugged in before. In this case, we are forced to give our consent every time we reconnect the USB device or reboot it.

Contrary to what other tutorials or forum discussions claim, this is not a bug in AOSP. A couple of developers reported this behavior, but Google marked this issue as “Won't Fix (Intended Behavior)”.

In most cases, the Android USB permission popup is triggered because steps during app implementation are missing. Therefore, implementation details are very important. This can easily happen and is a common problem that app developers struggle with, mainly because there is a lack of documentation.

That's a problem! And that's probably why lots and lots of people ask about this same exact issue again and again.

You get the gist of it. But why does it bother so many people to grant permission? It is a security mechanism after all.

It’s nonsense.

Not in general, but for YOUR application it could be. You are developing it; you know what it is doing and it's not malicious. Especially if your app will only be running on your own devices.

In this specific case Android is asking you, if you trust your own app, on your own device - and apparently doesn't even remember your answer but keeps bothering you.

It’s not scalable.

Especially when running a large fleet of devices. They are out in the field, and you try to remotely manage them. Confirming lots of confirmation dialogs after every reboot is just not an option.

It’s bad for UX.

In some cases, it is important to not show confirmation dialogs to keep up a high-class user experience. This is especially true for customer- or employee-facing devices that are used in shops or other publicly accessible places.

It’s unfeasible.

Some users may not understand the implications of granting permission to a USB device and do not grant permission. This can result in limited functionality of connected USB devices.

For example, when connecting a keyboard, you will be able to type in text or edit fields - without prior permission granting. But if your app is designed to react to F1-F12 button presses and perform certain actions, e.g. volume up and down, it may not work. The app has no permissions to access the USB device.

You get the point.

Please note: There are several cases where it is not wise to skip asking for USB user permission, especially when distributing apps to consumers via an app store of your choice.

Tutorial: How to remember permissions given and stop Android from asking for USB user permissions each time

Let’s get to how to solve this issue once and for all.

Sometimes Android does not remember that you have granted USB permissions. It doesn't automatically repopulate the permission settings after a reboot, or it doesn't seem to send the connection notification. This means that Android does not recall that you wanted to use this setting by default for your USB device.

In this tutorial we’ll look into a way to fix your implementation to remember the confirmed USB device permission for Android devices.

Please note: There will be a second blog article explaining how to skip USB permission confirmation dialogs when building a custom Android ROM. Check out part 2.

Fix your implementation to let the OS remember the USB permission

After extending your application according to this implementation, you will still get one initial USB permission dialog with the option to check a field to:

  • Use confirmed permission by default for this specific USB peripheral
  • Open your app immediately when this specific USB peripheral is connected again

usb-permission-remember

Image: Extended USB permission dialog

However, this approach makes sure that once you have confirmed the dialog with enabled checkbox to remember your decision, the USB permission dialog will be properly stored in Android OS and will no longer be displayed in future. Your app will receive permissions to access this USB device whenever it is connected, or when your device is rebooted.

Here’s what you need to do.

Step 1: Extend manifest file

You need to extend the AndroidManifest.xml file of your app to make the Activity direct-boot aware and add an intent filter to be notified when a USB device is connected.

It is important to make sure android:directBootAware="true" is added to the activity tag responsible for handling permissions when USB devices get attached: USB_DEVICE_ATTACHED.

Here is how the extended AndroidManifest.xml file should look like:

<manifest ...>

<uses-feature android:name="android.hardware.usb.host" />

...

<application>

<activity android:name=".MainActivity" android:directBootAware="true" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

<intent-filter>

<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />

</intent-filter>

<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />

</activity>

</application>

</manifest>

Step 2: Create new XML resource file

Create a resource file res/xml/device_filter.xml. Enter vendor-id and product-id of your USB peripherals to specify which devices should be filtered. Your resource file can have multiple entries.

Please note that IDs in the device_filter.xml file are numbers in decimal format. Sometimes manufacturers specify them in hex format, make sure to convert them correctly. Please test thoroughly, ID changes are not always well documented by manufacturers, making it sometimes difficult to find the right ID.

These are the contents of your res/xml/device_filter.xml file:

<?xml version="1.0" encoding="utf-8"?>

<resources>

   <!-- in hex: vendor id = 0b05 and product id = 17cb -->

   <usb-device vendor-id="2821" product-id="6091" />

</resources>

Step 3: Change MainActivity to remember permissions

Make sure your application can enumerate all connected devices. This is possible through the UsbManager by listing all devices on the bus with getDeviceList(). This method gets you a hash map of all connected USB devices.

Iterate through the list of USB devices. Use the UsbDevice class to check for the vendor-id and product-id you entered in your device_filter.xml file. Once you have found the right device, request access permissions from Android OS.

When the app calls for requestPermission(), Android OS displays a USB permission with a possibility to remember giving the permission on the device. After the permission is given the device can be accessed and used.

The app remembers the confirmation and the USB permission dialog is no longer displayed when the device is reconnected or rebooted.

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);

HashMap<String, UsbDevice> deviceList = manager.getDeviceList();

for (UsbDevice usbDevice : deviceList.values())

{

if (usbDevice.getVendorId() == … && usbDevice.getProductId() == …)

{

manager.requestPermission(usbDevice, permissionIntent);

}

}

Here’s proof it works!

We have created a sample app that can be used to see how the implementation looks like once it is implemented.

Sample app

Wrap up and final thoughts on how to get Android to remember granted USB permissions

Congrats you fixed your implementation! Android is now able to remember that you have granted USB permissions for your USB device in the first place.

But this approach has some downsides: The dialog must be confirmed once for all USB peripherals in your device_filter.xml. It can be tedious to provision every device in that way.

Additionally, you are bound to vendor-id and product-id combinations. If you purchase a new revision of a device where the manufacturer changed the product-id or want to use a different model of your USB peripheral, you need to enter the new ID and again confirm the dialog. This can be an issue when replacing broken peripherals in the field.

Stop showing USB permission dialogs
This is the first article in a series. The next one tackles the short comings of this approach and focus on a way to implement changes directly in the OS, rather than your application. This way Android will stop showing USB permission dialogs for all connected USB devices.

Learn more in Android USB permissions - Part 2

Please keep in mind to only use apps and USB devices from trusted sources. In case you stumble across issues, or you are looking for a fast and professional solution to this problem contact us.

Emteria offers custom Android ROMs without USB permission confirmation dialogs. We also provide a wide set of other customization and feature options depending on your requirements.

If you want to suppress this behavior for certain USB peripherals because your project or client requires it, we can help you to stop Android applications from asking for USB permissions.


Sources

Build unique Android products, boost device performance

See why emteria is the chosen Android™ customization & management platform for product builders — build Android products based on your requirements.

Book live demo
Group 3113

Table of contents

emteria Demo
See emteria in action