1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 package com.android.future.usb;
19 
20 import android.app.PendingIntent;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.hardware.usb.IUsbManager;
24 import android.os.IBinder;
25 import android.os.ParcelFileDescriptor;
26 import android.os.RemoteException;
27 import android.os.ServiceManager;
28 import android.util.Log;
29 
30 /**
31  * This is a wrapper class for the USB Manager to support USB accessories.
32  *
33  * <p>You can obtain an instance of this class by calling {@link #getInstance}
34  *
35  */
36 public class UsbManager {
37     private static final String TAG = "UsbManager";
38 
39    /**
40      * Broadcast Action:  A broadcast for USB accessory attached event.
41      *
42      * This intent is sent when a USB accessory is attached.
43      * Call {@link #getAccessory(android.content.Intent)} to retrieve the
44      * {@link com.google.android.usb.UsbAccessory} for the attached accessory.
45      */
46     public static final String ACTION_USB_ACCESSORY_ATTACHED =
47             "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
48 
49    /**
50      * Broadcast Action:  A broadcast for USB accessory detached event.
51      *
52      * This intent is sent when a USB accessory is detached.
53      * Call {@link #getAccessory(android.content.Intent)} to retrieve the
54      * {@link com.google.android.usb.UsbAccessory} for the attached accessory that was detached.
55      */
56     public static final String ACTION_USB_ACCESSORY_DETACHED =
57             "android.hardware.usb.action.USB_ACCESSORY_DETACHED";
58 
59     /**
60      * Name of extra added to the {@link android.app.PendingIntent}
61      * passed into {#requestPermission} or {#requestPermission}
62      * containing a boolean value indicating whether the user granted permission or not.
63      */
64     public static final String EXTRA_PERMISSION_GRANTED = "permission";
65 
66     private final Context mContext;
67     private final IUsbManager mService;
68 
UsbManager(Context context, IUsbManager service)69     private UsbManager(Context context, IUsbManager service) {
70         mContext = context;
71         mService = service;
72     }
73 
74     /**
75      * Returns a new instance of this class.
76      *
77      * @param context the caller's {@link android.content.Context}
78      * @return UsbManager instance.
79      */
getInstance(Context context)80     public static UsbManager getInstance(Context context) {
81         IBinder b = ServiceManager.getService(Context.USB_SERVICE);
82         return new UsbManager(context, IUsbManager.Stub.asInterface(b));
83     }
84 
85     /**
86      * Returns the {@link com.google.android.usb.UsbAccessory} for
87      * a {@link #ACTION_USB_ACCESSORY_ATTACHED} or {@link #ACTION_USB_ACCESSORY_ATTACHED}
88      * broadcast Intent. This can also be used to retrieve the accessory from the result
89      * of a call to {#requestPermission}.
90      *
91      * @return UsbAccessory for the intent.
92      */
getAccessory(Intent intent)93     public static UsbAccessory getAccessory(Intent intent) {
94         android.hardware.usb.UsbAccessory accessory =
95             intent.getParcelableExtra(android.hardware.usb.UsbManager.EXTRA_ACCESSORY);
96         if (accessory == null) {
97             return null;
98         } else {
99             return new UsbAccessory(accessory);
100         }
101     }
102 
103     /**
104      * Returns a list of currently attached USB accessories.
105      * (in the current implementation there can be at most one)
106      *
107      * @return list of USB accessories, or null if none are attached.
108      */
getAccessoryList()109     public UsbAccessory[] getAccessoryList() {
110         try {
111             android.hardware.usb.UsbAccessory accessory = mService.getCurrentAccessory();
112             if (accessory == null) {
113                 return null;
114             } else {
115                 return new UsbAccessory[] { new UsbAccessory(accessory) };
116             }
117         } catch (RemoteException e) {
118             Log.e(TAG, "RemoteException in getAccessoryList" , e);
119             return null;
120         }
121     }
122 
123     /**
124      * Opens a file descriptor for reading and writing data to the USB accessory.
125      *
126      * @param accessory the USB accessory to open
127      * @return file descriptor, or null if the accessor could not be opened.
128      */
openAccessory(UsbAccessory accessory)129     public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
130         try {
131             return mService.openAccessory(new android.hardware.usb.UsbAccessory(
132                     accessory.getManufacturer(),accessory.getModel(),
133                     accessory.getDescription(), accessory.getVersion(),
134                     accessory.getUri(), accessory.getSerial()));
135         } catch (RemoteException e) {
136             Log.e(TAG, "RemoteException in openAccessory" , e);
137             return null;
138         }
139     }
140 
141     /**
142      * Returns true if the caller has permission to access the accessory.
143      * Permission might have been granted temporarily via
144      * {@link #requestPermission} or
145      * by the user choosing the caller as the default application for the accessory.
146      *
147      * @param accessory to check permissions for
148      * @return true if caller has permission
149      */
hasPermission(UsbAccessory accessory)150     public boolean hasPermission(UsbAccessory accessory) {
151         try {
152             return mService.hasAccessoryPermission(new android.hardware.usb.UsbAccessory(
153                     accessory.getManufacturer(),accessory.getModel(),
154                     accessory.getDescription(), accessory.getVersion(),
155                     accessory.getUri(), accessory.getSerial()));
156         } catch (RemoteException e) {
157             Log.e(TAG, "RemoteException in hasPermission", e);
158             return false;
159         }
160     }
161 
162     /**
163      * Requests temporary permission for the given package to access the accessory.
164      * This may result in a system dialog being displayed to the user
165      * if permission had not already been granted.
166      * Success or failure is returned via the {@link android.app.PendingIntent} pi.
167      * The boolean extra {@link #EXTRA_PERMISSION_GRANTED} will be attached to the
168      * PendingIntent to indicate success or failure.
169      * If successful, this grants the caller permission to access the device only
170      * until the device is disconnected.
171      *
172      * @param accessory to request permissions for
173      * @param pi PendingIntent for returning result
174      */
requestPermission(UsbAccessory accessory, PendingIntent pi)175     public void requestPermission(UsbAccessory accessory, PendingIntent pi) {
176         try {
177             mService.requestAccessoryPermission(new android.hardware.usb.UsbAccessory(
178                     accessory.getManufacturer(),accessory.getModel(),
179                     accessory.getDescription(), accessory.getVersion(),
180                     accessory.getUri(), accessory.getSerial()),
181                     mContext.getPackageName(), pi);
182         } catch (RemoteException e) {
183             Log.e(TAG, "RemoteException in requestPermission", e);
184         }
185     }
186 }
187