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