Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit badbbae6 authored by Keun-young Park's avatar Keun-young Park Committed by Vitalii Tomkiv
Browse files

allow external USB host management

- Setting config_UsbDeviceConnectionHandling_component leads into
  launching specified Activity whenever USB device is connected.
- This allows external Activity to manage USB device based on
  its own setup and settings.
- Device access can be passed to other app with permission update
  by UsbManager.grantPermission.
- added UsbDeviceConnection.resetDevice() to reset USB device connected.
  This is necessary to get device out from AOAP.
- Test requires installing UsbHostExternalManagmentTestApp and
  AoapTestHost to USB host, and AoapTestDevice to USB Device.

bug: 26404209
Change-Id: I8e77ddc646c15454d9b2ecf1356924cf6351fc28
parent d3ca5980
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -15944,6 +15944,7 @@ package android.hardware.usb {
    method public java.lang.String getSerial();
    method public boolean releaseInterface(android.hardware.usb.UsbInterface);
    method public android.hardware.usb.UsbRequest requestWait();
    method public boolean resetDevice();
    method public boolean setConfiguration(android.hardware.usb.UsbConfiguration);
    method public boolean setInterface(android.hardware.usb.UsbInterface);
  }
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.hardware.usb;

import android.app.PendingIntent;
import android.content.ComponentName;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbPort;
@@ -116,4 +117,7 @@ interface IUsbManager

    /* Sets the port's current role. */
    void setPortRoles(in String portId, int powerRole, int dataRole);

   /* Sets USB device connection handler. */
   void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
}
+15 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.hardware.usb;

import android.annotation.SystemApi;
import android.os.ParcelFileDescriptor;

import java.io.FileDescriptor;
@@ -214,6 +215,18 @@ public class UsbDeviceConnection {
        return native_bulk_request(endpoint.getAddress(), buffer, offset, length, timeout);
    }

    /**
     * Reset USB port for the connected device.
     *
     * @return true if reset succeeds.
     *
     * @hide
     */
    @SystemApi
    public boolean resetDevice() {
        return native_reset_device();
    }

    /**
     * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
     * Note that this may return requests queued on multiple
@@ -263,4 +276,5 @@ public class UsbDeviceConnection {
            int offset, int length, int timeout);
    private native UsbRequest native_request_wait();
    private native String native_get_serial();
    private native boolean native_reset_device();
}
+36 −4
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@ package android.hardware.usb;

import com.android.internal.util.Preconditions;

import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
@@ -469,8 +471,20 @@ public class UsbManager {
     * {@hide}
     */
    public void grantPermission(UsbDevice device) {
        grantPermission(device, Process.myUid());
    }

    /**
     * Grants permission for USB device to given uid without showing system dialog.
     * Only system components can call this function.
     * @param device to request permissions for
     * @uid uid to give permission
     *
     * {@hide}
     */
    public void grantPermission(UsbDevice device, int uid) {
        try {
            mService.grantDevicePermission(device, Process.myUid());
            mService.grantDevicePermission(device, uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -488,11 +502,9 @@ public class UsbManager {
        try {
            int uid = mContext.getPackageManager()
                .getPackageUidAsUser(packageName, mContext.getUserId());
            mService.grantDevicePermission(device, uid);
            grantPermission(device, uid);
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Package " + packageName + " not found.", e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

@@ -631,6 +643,26 @@ public class UsbManager {
        }
    }

    /**
     * Sets the component that will handle USB device connection.
     * <p>
     * Setting component allows to specify external USB host manager to handle use cases, where
     * selection dialog for an activity that will handle USB device is undesirable.
     * Only system components can call this function, as it requires the MANAGE_USB permission.
     *
     * @param usbDeviceConnectionHandler The component to handle usb connections,
     * {@code null} to unset.
     *
     * {@hide}
     */
    public void setUsbDeviceConnectionHandler(@Nullable ComponentName usbDeviceConnectionHandler) {
        try {
            mService.setUsbDeviceConnectionHandler(usbDeviceConnectionHandler);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    public static String addFunction(String functions, String function) {
        if (USB_FUNCTION_NONE.equals(functions)) {
+13 −0
Original line number Diff line number Diff line
@@ -246,6 +246,18 @@ android_hardware_UsbDeviceConnection_get_serial(JNIEnv *env, jobject thiz)
    return result;
}

static jboolean
android_hardware_UsbDeviceConnection_reset_device(JNIEnv *env, jobject thiz)
{
    struct usb_device* device = get_device_from_object(env, thiz);
    if (!device) {
        ALOGE("device is closed in native_reset_device");
        return JNI_FALSE;
    }
    int ret = usb_device_reset(device);
    return (ret == 0) ? JNI_TRUE : JNI_FALSE;
}

static const JNINativeMethod method_table[] = {
    {"native_open",             "(Ljava/lang/String;Ljava/io/FileDescriptor;)Z",
                                        (void *)android_hardware_UsbDeviceConnection_open},
@@ -264,6 +276,7 @@ static const JNINativeMethod method_table[] = {
                                        (void *)android_hardware_UsbDeviceConnection_request_wait},
    { "native_get_serial",      "()Ljava/lang/String;",
                                        (void*)android_hardware_UsbDeviceConnection_get_serial },
    {"native_reset_device","()Z", (void *)android_hardware_UsbDeviceConnection_reset_device},
};

int register_android_hardware_UsbDeviceConnection(JNIEnv *env)
Loading