140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood/*
240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * Copyright (C) 2011 The Android Open Source Project
340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood *
440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * you may not use this file except in compliance with the License.
640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * You may obtain a copy of the License at
740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood *
840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood *
1040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * Unless required by applicable law or agreed to in writing, software
1140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
1240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * See the License for the specific language governing permissions and
1440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * limitations under the License.
1540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood */
1640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
1740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
181110748b2df664f9c5066819c1f0616eae3394a7Mike Lockwoodpackage com.android.future.usb;
1940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
202cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwoodimport android.app.PendingIntent;
2140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.content.Context;
2240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.content.Intent;
2340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.hardware.usb.IUsbManager;
2440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.os.IBinder;
2540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.os.ParcelFileDescriptor;
2640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.os.RemoteException;
2740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.os.ServiceManager;
2840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodimport android.util.Log;
2940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
3040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood/**
3143707a83ec12957fb84a406276a38fbaf4e23fd3Mike Lockwood * This is a wrapper class for the USB Manager to support USB accessories.
3240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood *
3340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood * <p>You can obtain an instance of this class by calling {@link #getInstance}
3440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood *
3540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood */
3640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwoodpublic class UsbManager {
3740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    private static final String TAG = "UsbManager";
3840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
3940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood   /**
4040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Broadcast Action:  A broadcast for USB accessory attached event.
4140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     *
4240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * This intent is sent when a USB accessory is attached.
4340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Call {@link #getAccessory(android.content.Intent)} to retrieve the
4440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * {@link com.google.android.usb.UsbAccessory} for the attached accessory.
4540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     */
4640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    public static final String ACTION_USB_ACCESSORY_ATTACHED =
4740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
4840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
4940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood   /**
5040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Broadcast Action:  A broadcast for USB accessory detached event.
5140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     *
5240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * This intent is sent when a USB accessory is detached.
5340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Call {@link #getAccessory(android.content.Intent)} to retrieve the
5440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * {@link com.google.android.usb.UsbAccessory} for the attached accessory that was detached.
5540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     */
5640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    public static final String ACTION_USB_ACCESSORY_DETACHED =
5740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            "android.hardware.usb.action.USB_ACCESSORY_DETACHED";
5840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
592cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    /**
602cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * Name of extra added to the {@link android.app.PendingIntent}
612cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * passed into {#requestPermission} or {#requestPermission}
622cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * containing a boolean value indicating whether the user granted permission or not.
632cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     */
642cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    public static final String EXTRA_PERMISSION_GRANTED = "permission";
652cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood
662cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    private final Context mContext;
6740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    private final IUsbManager mService;
6840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
692cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    private UsbManager(Context context, IUsbManager service) {
702cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        mContext = context;
7140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        mService = service;
7240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    }
7340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
7440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    /**
7540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Returns a new instance of this class.
7640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     *
772cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * @param context the caller's {@link android.content.Context}
7840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * @return UsbManager instance.
7940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     */
802cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    public static UsbManager getInstance(Context context) {
8140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        IBinder b = ServiceManager.getService(Context.USB_SERVICE);
822cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        return new UsbManager(context, IUsbManager.Stub.asInterface(b));
8340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    }
8440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
8540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    /**
8640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Returns the {@link com.google.android.usb.UsbAccessory} for
8740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * a {@link #ACTION_USB_ACCESSORY_ATTACHED} or {@link #ACTION_USB_ACCESSORY_ATTACHED}
882cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * broadcast Intent. This can also be used to retrieve the accessory from the result
892cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * of a call to {#requestPermission}.
9040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     *
912cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * @return UsbAccessory for the intent.
9240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     */
9340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    public static UsbAccessory getAccessory(Intent intent) {
9440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        android.hardware.usb.UsbAccessory accessory =
9540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            intent.getParcelableExtra(android.hardware.usb.UsbManager.EXTRA_ACCESSORY);
9640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        if (accessory == null) {
9740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            return null;
9840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        } else {
9940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            return new UsbAccessory(accessory);
10040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        }
10140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    }
10240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
10340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    /**
10440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Returns a list of currently attached USB accessories.
10540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * (in the current implementation there can be at most one)
10640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     *
10740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * @return list of USB accessories, or null if none are attached.
10840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     */
10940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    public UsbAccessory[] getAccessoryList() {
11040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        try {
11140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            android.hardware.usb.UsbAccessory accessory = mService.getCurrentAccessory();
11240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            if (accessory == null) {
11340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood                return null;
11440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            } else {
11540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood                return new UsbAccessory[] { new UsbAccessory(accessory) };
11640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            }
11740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        } catch (RemoteException e) {
11840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            Log.e(TAG, "RemoteException in getAccessoryList" , e);
11940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            return null;
12040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        }
12140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    }
12240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood
12340bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    /**
12440bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * Opens a file descriptor for reading and writing data to the USB accessory.
12540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     *
12640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * @param accessory the USB accessory to open
12740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     * @return file descriptor, or null if the accessor could not be opened.
12840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood     */
12940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
13040bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        try {
13140bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            return mService.openAccessory(new android.hardware.usb.UsbAccessory(
13240bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood                    accessory.getManufacturer(),accessory.getModel(),
133638d7cb3ee0bb3596b01dc19eca9456fa72a36e0Mike Lockwood                    accessory.getDescription(), accessory.getVersion(),
134638d7cb3ee0bb3596b01dc19eca9456fa72a36e0Mike Lockwood                    accessory.getUri(), accessory.getSerial()));
13540bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        } catch (RemoteException e) {
13640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            Log.e(TAG, "RemoteException in openAccessory" , e);
13740bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood            return null;
13840bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood        }
13940bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood    }
1402cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood
1412cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    /**
1422cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * Returns true if the caller has permission to access the accessory.
1432cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * Permission might have been granted temporarily via
14443707a83ec12957fb84a406276a38fbaf4e23fd3Mike Lockwood     * {@link #requestPermission} or
1452cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * by the user choosing the caller as the default application for the accessory.
1462cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     *
1472cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * @param accessory to check permissions for
1482cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * @return true if caller has permission
1492cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     */
1502cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    public boolean hasPermission(UsbAccessory accessory) {
1512cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        try {
1522cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood            return mService.hasAccessoryPermission(new android.hardware.usb.UsbAccessory(
1532cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood                    accessory.getManufacturer(),accessory.getModel(),
154638d7cb3ee0bb3596b01dc19eca9456fa72a36e0Mike Lockwood                    accessory.getDescription(), accessory.getVersion(),
155638d7cb3ee0bb3596b01dc19eca9456fa72a36e0Mike Lockwood                    accessory.getUri(), accessory.getSerial()));
1562cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        } catch (RemoteException e) {
1572cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood            Log.e(TAG, "RemoteException in hasPermission", e);
1582cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood            return false;
1592cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        }
1602cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    }
1612cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood
1622cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    /**
1632cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * Requests temporary permission for the given package to access the accessory.
1642cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * This may result in a system dialog being displayed to the user
1652cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * if permission had not already been granted.
1662cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * Success or failure is returned via the {@link android.app.PendingIntent} pi.
1672cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * The boolean extra {@link #EXTRA_PERMISSION_GRANTED} will be attached to the
1682cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * PendingIntent to indicate success or failure.
1692cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * If successful, this grants the caller permission to access the device only
1702cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * until the device is disconnected.
1712cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     *
1722cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * @param accessory to request permissions for
1732cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     * @param pi PendingIntent for returning result
1742cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood     */
1752cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    public void requestPermission(UsbAccessory accessory, PendingIntent pi) {
1762cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        try {
1772cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood            mService.requestAccessoryPermission(new android.hardware.usb.UsbAccessory(
1782cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood                    accessory.getManufacturer(),accessory.getModel(),
179638d7cb3ee0bb3596b01dc19eca9456fa72a36e0Mike Lockwood                    accessory.getDescription(), accessory.getVersion(),
180638d7cb3ee0bb3596b01dc19eca9456fa72a36e0Mike Lockwood                    accessory.getUri(), accessory.getSerial()),
1812cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood                    mContext.getPackageName(), pi);
1822cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        } catch (RemoteException e) {
1832cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood            Log.e(TAG, "RemoteException in requestPermission", e);
1842cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood        }
1852cc0377200b94b2f68f34e34554f2aa39e09cbceMike Lockwood    }
18640bbf9295d5245d3917629ce15f7b37670aef1acMike Lockwood}
187