javaandroidpermissionsandroid-5.1.1-lollipopandroid-4.1-jelly-bean

permission.android.MANAGE_USB works in Jellybean but not in Lollipop OS


I'm developing an application that need this permission: android.permission.MANAGE_USB.


I know that this permission is given only at System Application.

If I install the application as a system application in android 4.1.2 the application works fine.

But if I try to install it in android 5.1 as a system app then the debug log prints out that I don't have the permission:

error:

W/System.err: java.lang.SecurityException: 
Neither user 10074 nor current process has android.permission.MANAGE_USB.

Is anybody know why it keeps giving me this error in android 5.1?

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">

<uses-permission android:name="android.permission.MANAGE_USB"
    android:protectionLevel="signature" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_TASKS"/>
<permission android:name="android.permission.SET_TIME"
android:protectionLevel="signatureOrSystem"
    />
<uses-feature android:name="android.hardware.usb.host"
    android:required="true"/>


<application
    android:name=".services.AppContext"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:hardwareAccelerated="false"
    android:theme="@style/AppTheme">
    <service android:name=".services.KioskService" android:exported="false"/>
    <activity
        android:name=".MainActivity"
        android:launchMode="singleInstance"
        android:stateNotNeeded="true"
        android:screenOrientation="sensorLandscape">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service
        android:name="com.example.app.services.UsbService"
        android:enabled="true">
    </service>

    <receiver android:name=".services.PowerDisconnectReceiver">
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
        </intent-filter>
    </receiver>

    <receiver android:name=".services.UsbPermissionReceiver">
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
        </intent-filter>
    </receiver>

</application>

</manifest>

Solution

  • I would try to change android:protectionLevel to signatureOrSystem:

    A permission that the system grants only to applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission. Please avoid using this option, as the signature protection level should be sufficient for most needs and works regardless of exactly where applications are installed. The "signatureOrSystem" permission is used for certain special situations where multiple vendors have applications built into a system image and need to share specific features explicitly because they are being built together.

    For signature:

    A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user's explicit approval.

    I understand that you have no access to the signing key used by whoever compiled the Android OS image you're using in your devices, so signature protectionLevel will not match and not grant you the permission.

    See https://developer.android.com/guide/topics/manifest/permission-element.html

    Update: For completeness, I'm adding @carlo.S comments to the answer:

    In Lollipop, an app to be considered as a system application needs to be installed under the system/priv-app folder and not system/app folder like in Android 4.2.2! Also, app needs to have 644 permissions.

    Of course, the device needs to be rooted.