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

Commit 9182d3c4 authored by Mike Lockwood's avatar Mike Lockwood
Browse files

UsbManager: New APIs for USB accessories



USB accessories are peripherals that connect to android devices as a USB host.

When connected, the accessory will first identify itself to the android device
by sending manufacturer, product, accessory type and version strings
to the device, and then request the device to enter USB accessory mode.
The device will then enable the USB accessory kernel driver and disable
all other USB functionality except possibly adb
(adb can be used while the android device is connected to the PC
and the PC is running software that emulates a USB accessory)

The class android.hardware.UsbAccessory is used to describe the
currently attached USB accessory.
UsbAccessory contains the manufacturer, product, accessory type
and version strings to identify the accessory.
The accessory can be opened as a ParcelFileDescriptor, which can be used
to communicate with the accessory over two bulk endpoints.

The Intents UsbManager.USB_ACCESSORY_ATTACHED and
UsbManager.USB_ACCESSORY_DETACHED are broadcast when accessories are
connected and disconnected to the device.  The USB_ACCESSORY_ATTACHED
contains a UsbAccessory object for the attached accessory as an extra.
The Intent also contains string extras for the manufacturer, product,
accessory type and version strings to allow filtering on these strings.

Change-Id: Ie77cbf51814a4aa44a6b1e62673bfe4c6aa81755
Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent 2fa16084
Loading
Loading
Loading
Loading
+206 −3
Original line number Diff line number Diff line
@@ -94147,6 +94147,97 @@
>
</field>
</class>
<class name="UsbAccessory"
 extends="java.lang.Object"
 abstract="false"
 static="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
<implements name="android.os.Parcelable">
</implements>
<method name="describeContents"
 return="int"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getManufacturer"
 return="java.lang.String"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getModel"
 return="java.lang.String"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getType"
 return="java.lang.String"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getVersion"
 return="java.lang.String"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="writeToParcel"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="parcel" type="android.os.Parcel">
</parameter>
<parameter name="flags" type="int">
</parameter>
</method>
<field name="CREATOR"
 type="android.os.Parcelable.Creator"
 transient="false"
 volatile="false"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
</class>
<class name="UsbConstants"
 extends="java.lang.Object"
 abstract="false"
@@ -95097,6 +95188,17 @@
 deprecated="not deprecated"
 visibility="public"
>
<method name="getAccessoryList"
 return="android.hardware.UsbAccessory[]"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getDeviceList"
 return="java.util.HashMap&lt;java.lang.String, android.hardware.UsbDevice&gt;"
 abstract="false"
@@ -95134,6 +95236,19 @@
<parameter name="function" type="java.lang.String">
</parameter>
</method>
<method name="openAccessory"
 return="android.os.ParcelFileDescriptor"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="accessory" type="android.hardware.UsbAccessory">
</parameter>
</method>
<method name="openDevice"
 return="boolean"
 abstract="false"
@@ -95147,6 +95262,28 @@
<parameter name="device" type="android.hardware.UsbDevice">
</parameter>
</method>
<field name="ACTION_USB_ACCESSORY_ATTACHED"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;android.hardware.action.USB_ACCESSORY_ATTACHED&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="ACTION_USB_ACCESSORY_DETACHED"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;android.hardware.action.USB_ACCESSORY_DETACHED&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="ACTION_USB_DEVICE_ATTACHED"
 type="java.lang.String"
 transient="false"
@@ -95180,6 +95317,61 @@
 visibility="public"
>
</field>
<field name="EXTRA_ACCESSORY"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;accessory&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="EXTRA_ACCESSORY_MANUFACTURER"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;accessory-manufacturer&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="EXTRA_ACCESSORY_PRODUCT"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;accessory-product&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="EXTRA_ACCESSORY_TYPE"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;accessory-type&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="EXTRA_ACCESSORY_VERSION"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;accessory-version&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="EXTRA_DEVICE"
 type="java.lang.String"
 transient="false"
@@ -95279,6 +95471,17 @@
 visibility="public"
>
</field>
<field name="USB_FUNCTION_ACCESSORY"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;accessory&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="USB_FUNCTION_ADB"
 type="java.lang.String"
 transient="false"
@@ -237424,7 +237627,7 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="s" type="java.lang.String">
<parameter name="key" type="java.lang.String">
</parameter>
</method>
<method name="describeContents"
@@ -237459,7 +237662,7 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="s" type="java.lang.String">
<parameter name="key" type="java.lang.String">
</parameter>
</method>
<method name="getIconResId"
@@ -265635,7 +265838,7 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="arg0" type="T">
<parameter name="t" type="T">
</parameter>
</method>
</interface>
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.hardware;

import android.hardware.UsbAccessory;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;

@@ -25,4 +26,6 @@ interface IUsbManager
    /* Returns a list of all currently attached USB devices */
    void getDeviceList(out Bundle devices);
    ParcelFileDescriptor openDevice(String deviceName);
    UsbAccessory getCurrentAccessory();
    ParcelFileDescriptor openAccessory();
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware;

parcelable UsbAccessory;
+131 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
import android.util.Log;

/**
 * A class representing a USB accessory.
 */
public final class UsbAccessory implements Parcelable {

    private static final String TAG = "UsbAccessory";

    private String mManufacturer;
    private String mModel;
    private String mType;
    private String mVersion;

    private UsbAccessory() {
    }

    /**
     * UsbAccessory should only be instantiated by UsbService implementation
     * @hide
     */
    public UsbAccessory(String manufacturer, String model, String type, String version) {
        mManufacturer = manufacturer;
        mModel = model;
        mType = type;
        mVersion = version;
    }

    /**
     * UsbAccessory should only be instantiated by UsbService implementation
     * @hide
     */
    public UsbAccessory(String[] strings) {
        mManufacturer = strings[0];
        mModel = strings[1];
        mType = strings[2];
        mVersion = strings[3];
    }

    /**
     * Returns the manufacturer of the accessory.
     *
     * @return the accessory manufacturer
     */
    public String getManufacturer() {
        return mManufacturer;
    }

    /**
     * Returns the model name of the accessory.
     *
     * @return the accessory model
     */
    public String getModel() {
        return mModel;
    }

    /**
     * Returns the type of the accessory.
     *
     * @return the accessory type
     */
    public String getType() {
        return mType;
    }

    /**
     * Returns the version of the accessory.
     *
     * @return the accessory version
     */
    public String getVersion() {
        return mVersion;
    }

    @Override
    public String toString() {
        return "UsbAccessory[mManufacturer=" + mManufacturer +
                            ", mModel=" + mModel +
                            ", mType=" + mType +
                            ", mVersion=" + mVersion + "]";
    }

    public static final Parcelable.Creator<UsbAccessory> CREATOR =
        new Parcelable.Creator<UsbAccessory>() {
        public UsbAccessory createFromParcel(Parcel in) {
            String manufacturer = in.readString();
            String model = in.readString();
            String type = in.readString();
            String version = in.readString();
            return new UsbAccessory(manufacturer, model, type, version);
        }

        public UsbAccessory[] newArray(int size) {
            return new UsbAccessory[size];
        }
    };

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeString(mManufacturer);
        parcel.writeString(mModel);
        parcel.writeString(mType);
        parcel.writeString(mVersion);
   }
}
+142 −7
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;

@@ -44,11 +45,14 @@ public class UsbManager {
     * Broadcast Action:  A sticky broadcast for USB state change events when in device mode.
     *
     * This is a sticky broadcast for clients that includes USB connected/disconnected state,
     * the USB configuration that is currently set and a bundle containing name/value pairs
     * with the names of the functions and a value of either {@link #USB_FUNCTION_ENABLED}
     * or {@link #USB_FUNCTION_DISABLED}.
     * Possible USB function names include {@link #USB_FUNCTION_MASS_STORAGE},
     * {@link #USB_FUNCTION_ADB}, {@link #USB_FUNCTION_RNDIS} and {@link #USB_FUNCTION_MTP}.
     * <ul>
     * <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected.
     * <li> {@link #USB_CONFIGURATION} a Bundle containing name/value pairs where the name
     * is the name of a USB function and the value is either {@link #USB_FUNCTION_ENABLED}
     * or {@link #USB_FUNCTION_DISABLED}.  The possible function names include
     * {@link #USB_FUNCTION_MASS_STORAGE}, {@link #USB_FUNCTION_ADB}, {@link #USB_FUNCTION_RNDIS},
     * {@link #USB_FUNCTION_MTP} and {@link #USB_FUNCTION_ACCESSORY}.
     * </ul>
     */
    public static final String ACTION_USB_STATE =
            "android.hardware.action.USB_STATE";
@@ -57,6 +61,16 @@ public class UsbManager {
     * Broadcast Action:  A broadcast for USB device attached event.
     *
     * This intent is sent when a USB device is attached to the USB bus when in host mode.
     * <ul>
     * <li> {@link #EXTRA_DEVICE_NAME} containing the device's name (String)
     * <li> {@link #EXTRA_VENDOR_ID} containing the device's vendor ID (Integer)
     * <li> {@link #EXTRA_PRODUCT_ID} containing the device's product ID (Integer)
     * <li> {@link #EXTRA_DEVICE_CLASS} } containing the device class (Integer)
     * <li> {@link #EXTRA_DEVICE_SUBCLASS} containing the device subclass (Integer)
     * <li> {@link #EXTRA_DEVICE_PROTOCOL} containing the device protocol (Integer)
     * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.UsbDevice}
     * for the attached device
     * </ul>
     */
    public static final String ACTION_USB_DEVICE_ATTACHED =
            "android.hardware.action.USB_DEVICE_ATTACHED";
@@ -65,10 +79,41 @@ public class UsbManager {
     * Broadcast Action:  A broadcast for USB device detached event.
     *
     * This intent is sent when a USB device is detached from the USB bus when in host mode.
     * <ul>
     * <li> {@link #EXTRA_DEVICE_NAME} containing the device's name (String)
     * </ul>
     */
    public static final String ACTION_USB_DEVICE_DETACHED =
            "android.hardware.action.USB_DEVICE_DETACHED";

   /**
     * Broadcast Action:  A broadcast for USB accessory attached event.
     *
     * This intent is sent when a USB accessory is attached.
     * <ul>
     * <li> {@link #EXTRA_ACCESSORY_MANUFACTURER} containing the accessory's manufacturer (String)
     * <li> {@link #EXTRA_ACCESSORY_PRODUCT} containing the accessory's product name (String)
     * <li> {@link #EXTRA_ACCESSORY_TYPE} containing the accessory's type (String)
     * <li> {@link #EXTRA_ACCESSORY_VERSION} containing the accessory's version (String)
     * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory}
     * for the attached accessory
     * </ul>
     */
    public static final String ACTION_USB_ACCESSORY_ATTACHED =
            "android.hardware.action.USB_ACCESSORY_ATTACHED";

   /**
     * Broadcast Action:  A broadcast for USB accessory detached event.
     *
     * This intent is sent when a USB accessory is detached.
     * <ul>
      * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory}
     * for the attached accessory that was detached
     * </ul>
     */
    public static final String ACTION_USB_ACCESSORY_DETACHED =
            "android.hardware.action.USB_ACCESSORY_DETACHED";

    /**
     * Boolean extra indicating whether USB is connected or disconnected.
     * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
@@ -106,14 +151,22 @@ public class UsbManager {
    public static final String USB_FUNCTION_MTP = "mtp";

    /**
     * Value indicating that a USB function is enabled.
     * Name of the Accessory USB function.
     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
     */
    public static final String USB_FUNCTION_ACCESSORY = "accessory";

    /**
     * Value indicating that a USB function is enabled.
     * Used in {@link #USB_CONFIGURATION} extras bundle for the
     * {@link #ACTION_USB_STATE} broadcast
     */
    public static final String USB_FUNCTION_ENABLED = "enabled";

    /**
     * Value indicating that a USB function is disabled.
     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
     * Used in {@link #USB_CONFIGURATION} extras bundle for the
     * {@link #ACTION_USB_STATE} broadcast
     */
    public static final String USB_FUNCTION_DISABLED = "disabled";

@@ -158,8 +211,39 @@ public class UsbManager {
     * Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
     * containing the UsbDevice object for the device.
     */

    public static final String EXTRA_DEVICE = "device";

    /**
     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
     * containing the UsbAccessory object for the accessory.
     */
    public static final String EXTRA_ACCESSORY = "accessory";

    /**
     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
     * containing the accessory's manufacturer name.
     */
    public static final String EXTRA_ACCESSORY_MANUFACTURER = "accessory-manufacturer";

    /**
     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
     * containing the accessory's product name.
     */
    public static final String EXTRA_ACCESSORY_PRODUCT = "accessory-product";

    /**
     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
     * containing the accessory's type.
     */
    public static final String EXTRA_ACCESSORY_TYPE = "accessory-type";

    /**
     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
     * containing the accessory's version.
     */
    public static final String EXTRA_ACCESSORY_VERSION = "accessory-version";

    private IUsbManager mService;

    /**
@@ -214,6 +298,41 @@ public class UsbManager {
        }
    }

    /**
     * Returns a list of currently attached USB accessories.
     * (in the current implementation there can be at most one)
     *
     * @return list of USB accessories, or null if none are attached.
     */
    public UsbAccessory[] getAccessoryList() {
        try {
            UsbAccessory accessory = mService.getCurrentAccessory();
            if (accessory == null) {
                return null;
            } else {
                return new UsbAccessory[] { accessory };
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in openAccessory" , e);
            return null;
        }
    }

    /**
     * Opens a file descriptor for reading and writing data to the USB accessory.
     *
     * @param accessory the USB accessory to open
     * @return file descriptor, or null if the accessor could not be opened.
     */
    public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
        try {
            return mService.openAccessory();
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in openAccessory" , e);
            return null;
        }
    }

    private static File getFunctionEnableFile(String function) {
        return new File("/sys/class/usb_composite/" + function + "/enable");
    }
@@ -245,4 +364,20 @@ public class UsbManager {
            return false;
        }
    }

    /**
     * Enables or disables a USB function.
     *
     * @hide
     */
    public static boolean setFunctionEnabled(String function, boolean enable) {
        try {
            FileOutputStream stream = new FileOutputStream(getFunctionEnableFile(function));
            stream.write(enable ? '1' : '0');
            stream.close();
            return true;
        } catch (IOException e) {
            return false;
        }
    }
}
Loading