• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 an
14  * limitations under the License.
15  */
16 
17 package com.android.server.usb;
18 
19 import android.app.PendingIntent;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.PackageManager;
25 import android.hardware.usb.IUsbManager;
26 import android.hardware.usb.UsbAccessory;
27 import android.hardware.usb.UsbDevice;
28 import android.os.Bundle;
29 import android.os.ParcelFileDescriptor;
30 import android.os.UserHandle;
31 import android.util.SparseArray;
32 
33 import com.android.internal.annotations.GuardedBy;
34 import com.android.internal.util.IndentingPrintWriter;
35 
36 import java.io.File;
37 import java.io.FileDescriptor;
38 import java.io.PrintWriter;
39 
40 /**
41  * UsbService manages all USB related state, including both host and device support.
42  * Host related events and calls are delegated to UsbHostManager, and device related
43  * support is delegated to UsbDeviceManager.
44  */
45 public class UsbService extends IUsbManager.Stub {
46     private static final String TAG = "UsbService";
47 
48     private final Context mContext;
49 
50     private UsbDeviceManager mDeviceManager;
51     private UsbHostManager mHostManager;
52 
53     private final Object mLock = new Object();
54 
55     /** Map from {@link UserHandle} to {@link UsbSettingsManager} */
56     @GuardedBy("mLock")
57     private final SparseArray<UsbSettingsManager>
58             mSettingsByUser = new SparseArray<UsbSettingsManager>();
59 
getSettingsForUser(int userId)60     private UsbSettingsManager getSettingsForUser(int userId) {
61         synchronized (mLock) {
62             UsbSettingsManager settings = mSettingsByUser.get(userId);
63             if (settings == null) {
64                 settings = new UsbSettingsManager(mContext, new UserHandle(userId));
65                 mSettingsByUser.put(userId, settings);
66             }
67             return settings;
68         }
69     }
70 
UsbService(Context context)71     public UsbService(Context context) {
72         mContext = context;
73 
74         final PackageManager pm = mContext.getPackageManager();
75         if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
76             mHostManager = new UsbHostManager(context);
77         }
78         if (new File("/sys/class/android_usb").exists()) {
79             mDeviceManager = new UsbDeviceManager(context);
80         }
81 
82         setCurrentUser(UserHandle.USER_OWNER);
83 
84         final IntentFilter userFilter = new IntentFilter();
85         userFilter.addAction(Intent.ACTION_USER_SWITCHED);
86         userFilter.addAction(Intent.ACTION_USER_STOPPED);
87         mContext.registerReceiver(mUserReceiver, userFilter, null, null);
88     }
89 
90     private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
91         @Override
92         public void onReceive(Context context, Intent intent) {
93             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
94             final String action = intent.getAction();
95             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
96                 setCurrentUser(userId);
97             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
98                 synchronized (mLock) {
99                     mSettingsByUser.remove(userId);
100                 }
101             }
102         }
103     };
104 
setCurrentUser(int userId)105     private void setCurrentUser(int userId) {
106         final UsbSettingsManager userSettings = getSettingsForUser(userId);
107         if (mHostManager != null) {
108             mHostManager.setCurrentSettings(userSettings);
109         }
110         if (mDeviceManager != null) {
111             mDeviceManager.setCurrentSettings(userSettings);
112         }
113     }
114 
systemReady()115     public void systemReady() {
116         if (mDeviceManager != null) {
117             mDeviceManager.systemReady();
118         }
119         if (mHostManager != null) {
120             mHostManager.systemReady();
121         }
122     }
123 
124     /* Returns a list of all currently attached USB devices (host mdoe) */
125     @Override
getDeviceList(Bundle devices)126     public void getDeviceList(Bundle devices) {
127         if (mHostManager != null) {
128             mHostManager.getDeviceList(devices);
129         }
130     }
131 
132     /* Opens the specified USB device (host mode) */
133     @Override
openDevice(String deviceName)134     public ParcelFileDescriptor openDevice(String deviceName) {
135         if (mHostManager != null) {
136             return mHostManager.openDevice(deviceName);
137         } else {
138             return null;
139         }
140     }
141 
142     /* returns the currently attached USB accessory (device mode) */
143     @Override
getCurrentAccessory()144     public UsbAccessory getCurrentAccessory() {
145         if (mDeviceManager != null) {
146             return mDeviceManager.getCurrentAccessory();
147         } else {
148             return null;
149         }
150     }
151 
152     /* opens the currently attached USB accessory (device mode) */
153     @Override
openAccessory(UsbAccessory accessory)154     public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
155         if (mDeviceManager != null) {
156             return mDeviceManager.openAccessory(accessory);
157         } else {
158             return null;
159         }
160     }
161 
162     @Override
setDevicePackage(UsbDevice device, String packageName, int userId)163     public void setDevicePackage(UsbDevice device, String packageName, int userId) {
164         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
165         getSettingsForUser(userId).setDevicePackage(device, packageName);
166     }
167 
168     @Override
setAccessoryPackage(UsbAccessory accessory, String packageName, int userId)169     public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) {
170         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
171         getSettingsForUser(userId).setAccessoryPackage(accessory, packageName);
172     }
173 
174     @Override
hasDevicePermission(UsbDevice device)175     public boolean hasDevicePermission(UsbDevice device) {
176         final int userId = UserHandle.getCallingUserId();
177         return getSettingsForUser(userId).hasPermission(device);
178     }
179 
180     @Override
hasAccessoryPermission(UsbAccessory accessory)181     public boolean hasAccessoryPermission(UsbAccessory accessory) {
182         final int userId = UserHandle.getCallingUserId();
183         return getSettingsForUser(userId).hasPermission(accessory);
184     }
185 
186     @Override
requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi)187     public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
188         final int userId = UserHandle.getCallingUserId();
189         getSettingsForUser(userId).requestPermission(device, packageName, pi);
190     }
191 
192     @Override
requestAccessoryPermission( UsbAccessory accessory, String packageName, PendingIntent pi)193     public void requestAccessoryPermission(
194             UsbAccessory accessory, String packageName, PendingIntent pi) {
195         final int userId = UserHandle.getCallingUserId();
196         getSettingsForUser(userId).requestPermission(accessory, packageName, pi);
197     }
198 
199     @Override
grantDevicePermission(UsbDevice device, int uid)200     public void grantDevicePermission(UsbDevice device, int uid) {
201         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
202         final int userId = UserHandle.getUserId(uid);
203         getSettingsForUser(userId).grantDevicePermission(device, uid);
204     }
205 
206     @Override
grantAccessoryPermission(UsbAccessory accessory, int uid)207     public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
208         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
209         final int userId = UserHandle.getUserId(uid);
210         getSettingsForUser(userId).grantAccessoryPermission(accessory, uid);
211     }
212 
213     @Override
hasDefaults(String packageName, int userId)214     public boolean hasDefaults(String packageName, int userId) {
215         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
216         return getSettingsForUser(userId).hasDefaults(packageName);
217     }
218 
219     @Override
clearDefaults(String packageName, int userId)220     public void clearDefaults(String packageName, int userId) {
221         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
222         getSettingsForUser(userId).clearDefaults(packageName);
223     }
224 
225     @Override
setCurrentFunction(String function, boolean makeDefault)226     public void setCurrentFunction(String function, boolean makeDefault) {
227         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
228         if (mDeviceManager != null) {
229             mDeviceManager.setCurrentFunctions(function, makeDefault);
230         } else {
231             throw new IllegalStateException("USB device mode not supported");
232         }
233     }
234 
235     @Override
setMassStorageBackingFile(String path)236     public void setMassStorageBackingFile(String path) {
237         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
238         if (mDeviceManager != null) {
239             mDeviceManager.setMassStorageBackingFile(path);
240         } else {
241             throw new IllegalStateException("USB device mode not supported");
242         }
243     }
244 
245     @Override
allowUsbDebugging(boolean alwaysAllow, String publicKey)246     public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
247         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
248         mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
249     }
250 
251     @Override
denyUsbDebugging()252     public void denyUsbDebugging() {
253         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
254         mDeviceManager.denyUsbDebugging();
255     }
256 
257     @Override
clearUsbDebuggingKeys()258     public void clearUsbDebuggingKeys() {
259         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
260         mDeviceManager.clearUsbDebuggingKeys();
261     }
262 
263     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)264     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
265         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
266         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
267 
268         pw.println("USB Manager State:");
269         if (mDeviceManager != null) {
270             mDeviceManager.dump(fd, pw);
271         }
272         if (mHostManager != null) {
273             mHostManager.dump(fd, pw);
274         }
275 
276         synchronized (mLock) {
277             for (int i = 0; i < mSettingsByUser.size(); i++) {
278                 final int userId = mSettingsByUser.keyAt(i);
279                 final UsbSettingsManager settings = mSettingsByUser.valueAt(i);
280                 pw.increaseIndent();
281                 pw.println("Settings for user " + userId + ":");
282                 settings.dump(fd, pw);
283                 pw.decreaseIndent();
284             }
285         }
286         pw.decreaseIndent();
287     }
288 }
289