UsbService.java revision 2a67840c3c35a6267663e5d3ae921ee9ac614db9
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.app.admin.DevicePolicyManager; 21import android.content.BroadcastReceiver; 22import android.content.Context; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.content.pm.PackageManager; 26import android.hardware.usb.IUsbManager; 27import android.hardware.usb.UsbAccessory; 28import android.hardware.usb.UsbDevice; 29import android.hardware.usb.UsbManager; 30import android.os.Bundle; 31import android.os.ParcelFileDescriptor; 32import android.os.UserHandle; 33import android.os.UserManager; 34import android.util.Slog; 35import android.util.SparseArray; 36 37import com.android.internal.annotations.GuardedBy; 38import com.android.internal.util.IndentingPrintWriter; 39import com.android.server.SystemService; 40 41import java.io.File; 42import java.io.FileDescriptor; 43import java.io.PrintWriter; 44 45/** 46 * UsbService manages all USB related state, including both host and device support. 47 * Host related events and calls are delegated to UsbHostManager, and device related 48 * support is delegated to UsbDeviceManager. 49 */ 50public class UsbService extends IUsbManager.Stub { 51 52 public static class Lifecycle extends SystemService { 53 private UsbService mUsbService; 54 55 public Lifecycle(Context context) { 56 super(context); 57 } 58 59 @Override 60 public void onStart() { 61 mUsbService = new UsbService(getContext()); 62 publishBinderService(Context.USB_SERVICE, mUsbService); 63 } 64 65 @Override 66 public void onBootPhase(int phase) { 67 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 68 mUsbService.systemReady(); 69 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 70 mUsbService.bootCompleted(); 71 } 72 } 73 } 74 75 private static final String TAG = "UsbService"; 76 77 private final Context mContext; 78 79 private UsbDeviceManager mDeviceManager; 80 private UsbHostManager mHostManager; 81 private final UsbAlsaManager mAlsaManager; 82 83 private final Object mLock = new Object(); 84 85 /** Map from {@link UserHandle} to {@link UsbSettingsManager} */ 86 @GuardedBy("mLock") 87 private final SparseArray<UsbSettingsManager> 88 mSettingsByUser = new SparseArray<UsbSettingsManager>(); 89 90 private UsbSettingsManager getSettingsForUser(int userId) { 91 synchronized (mLock) { 92 UsbSettingsManager settings = mSettingsByUser.get(userId); 93 if (settings == null) { 94 settings = new UsbSettingsManager(mContext, new UserHandle(userId)); 95 mSettingsByUser.put(userId, settings); 96 } 97 return settings; 98 } 99 } 100 101 public UsbService(Context context) { 102 mContext = context; 103 104 mAlsaManager = new UsbAlsaManager(context); 105 106 final PackageManager pm = mContext.getPackageManager(); 107 if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { 108 mHostManager = new UsbHostManager(context, mAlsaManager); 109 } 110 if (new File("/sys/class/android_usb").exists()) { 111 mDeviceManager = new UsbDeviceManager(context, mAlsaManager); 112 } 113 114 setCurrentUser(UserHandle.USER_OWNER); 115 116 final IntentFilter filter = new IntentFilter(); 117 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 118 filter.addAction(Intent.ACTION_USER_SWITCHED); 119 filter.addAction(Intent.ACTION_USER_STOPPED); 120 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 121 mContext.registerReceiver(mReceiver, filter, null, null); 122 } 123 124 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 125 @Override 126 public void onReceive(Context context, Intent intent) { 127 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 128 final String action = intent.getAction(); 129 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 130 setCurrentUser(userId); 131 } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 132 synchronized (mLock) { 133 mSettingsByUser.remove(userId); 134 } 135 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 136 .equals(action)) { 137 if (mDeviceManager != null) { 138 mDeviceManager.updateUserRestrictions(); 139 } 140 } 141 } 142 }; 143 144 private void setCurrentUser(int userId) { 145 final UsbSettingsManager userSettings = getSettingsForUser(userId); 146 if (mHostManager != null) { 147 mHostManager.setCurrentSettings(userSettings); 148 } 149 if (mDeviceManager != null) { 150 mDeviceManager.setCurrentUser(userId, userSettings); 151 } 152 } 153 154 public void systemReady() { 155 mAlsaManager.systemReady(); 156 157 if (mDeviceManager != null) { 158 mDeviceManager.systemReady(); 159 } 160 if (mHostManager != null) { 161 mHostManager.systemReady(); 162 } 163 } 164 165 public void bootCompleted() { 166 if (mDeviceManager != null) { 167 mDeviceManager.bootCompleted(); 168 } 169 } 170 171 /* Returns a list of all currently attached USB devices (host mdoe) */ 172 @Override 173 public void getDeviceList(Bundle devices) { 174 if (mHostManager != null) { 175 mHostManager.getDeviceList(devices); 176 } 177 } 178 179 /* Opens the specified USB device (host mode) */ 180 @Override 181 public ParcelFileDescriptor openDevice(String deviceName) { 182 if (mHostManager != null) { 183 return mHostManager.openDevice(deviceName); 184 } else { 185 return null; 186 } 187 } 188 189 /* returns the currently attached USB accessory (device mode) */ 190 @Override 191 public UsbAccessory getCurrentAccessory() { 192 if (mDeviceManager != null) { 193 return mDeviceManager.getCurrentAccessory(); 194 } else { 195 return null; 196 } 197 } 198 199 /* opens the currently attached USB accessory (device mode) */ 200 @Override 201 public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 202 if (mDeviceManager != null) { 203 return mDeviceManager.openAccessory(accessory); 204 } else { 205 return null; 206 } 207 } 208 209 @Override 210 public void setDevicePackage(UsbDevice device, String packageName, int userId) { 211 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 212 getSettingsForUser(userId).setDevicePackage(device, packageName); 213 } 214 215 @Override 216 public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) { 217 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 218 getSettingsForUser(userId).setAccessoryPackage(accessory, packageName); 219 } 220 221 @Override 222 public boolean hasDevicePermission(UsbDevice device) { 223 final int userId = UserHandle.getCallingUserId(); 224 return getSettingsForUser(userId).hasPermission(device); 225 } 226 227 @Override 228 public boolean hasAccessoryPermission(UsbAccessory accessory) { 229 final int userId = UserHandle.getCallingUserId(); 230 return getSettingsForUser(userId).hasPermission(accessory); 231 } 232 233 @Override 234 public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) { 235 final int userId = UserHandle.getCallingUserId(); 236 getSettingsForUser(userId).requestPermission(device, packageName, pi); 237 } 238 239 @Override 240 public void requestAccessoryPermission( 241 UsbAccessory accessory, String packageName, PendingIntent pi) { 242 final int userId = UserHandle.getCallingUserId(); 243 getSettingsForUser(userId).requestPermission(accessory, packageName, pi); 244 } 245 246 @Override 247 public void grantDevicePermission(UsbDevice device, int uid) { 248 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 249 final int userId = UserHandle.getUserId(uid); 250 getSettingsForUser(userId).grantDevicePermission(device, uid); 251 } 252 253 @Override 254 public void grantAccessoryPermission(UsbAccessory accessory, int uid) { 255 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 256 final int userId = UserHandle.getUserId(uid); 257 getSettingsForUser(userId).grantAccessoryPermission(accessory, uid); 258 } 259 260 @Override 261 public boolean hasDefaults(String packageName, int userId) { 262 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 263 return getSettingsForUser(userId).hasDefaults(packageName); 264 } 265 266 @Override 267 public void clearDefaults(String packageName, int userId) { 268 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 269 getSettingsForUser(userId).clearDefaults(packageName); 270 } 271 272 @Override 273 public boolean isFunctionEnabled(String function) { 274 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 275 return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function); 276 } 277 278 @Override 279 public void setCurrentFunction(String function) { 280 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 281 282 if (!isSupportedCurrentFunction(function)) { 283 Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: " 284 + function); 285 function = UsbManager.USB_FUNCTION_NONE; 286 } 287 288 if (mDeviceManager != null) { 289 mDeviceManager.setCurrentFunctions(function); 290 } else { 291 throw new IllegalStateException("USB device mode not supported"); 292 } 293 } 294 295 private static boolean isSupportedCurrentFunction(String function) { 296 if (function == null) return true; 297 298 switch (function) { 299 case UsbManager.USB_FUNCTION_NONE: 300 case UsbManager.USB_FUNCTION_AUDIO_SOURCE: 301 case UsbManager.USB_FUNCTION_MIDI: 302 case UsbManager.USB_FUNCTION_MTP: 303 case UsbManager.USB_FUNCTION_PTP: 304 case UsbManager.USB_FUNCTION_RNDIS: 305 return true; 306 } 307 308 return false; 309 } 310 311 @Override 312 public void setUsbDataUnlocked(boolean unlocked) { 313 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 314 // If attempt to change USB function while file transfer is restricted, ensure that 315 // usb data is always locked, and return. 316 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 317 if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) { 318 if (mDeviceManager != null) mDeviceManager.setUsbDataUnlocked(false); 319 return; 320 } 321 mDeviceManager.setUsbDataUnlocked(unlocked); 322 } 323 324 @Override 325 public boolean isUsbDataUnlocked() { 326 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 327 return mDeviceManager.isUsbDataUnlocked(); 328 } 329 330 @Override 331 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 332 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 333 mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); 334 } 335 336 @Override 337 public void denyUsbDebugging() { 338 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 339 mDeviceManager.denyUsbDebugging(); 340 } 341 342 @Override 343 public void clearUsbDebuggingKeys() { 344 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 345 mDeviceManager.clearUsbDebuggingKeys(); 346 } 347 348 @Override 349 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 350 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 351 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 352 353 pw.println("USB Manager State:"); 354 if (mDeviceManager != null) { 355 mDeviceManager.dump(fd, pw); 356 } 357 if (mHostManager != null) { 358 mHostManager.dump(fd, pw); 359 } 360 mAlsaManager.dump(fd, pw); 361 362 synchronized (mLock) { 363 for (int i = 0; i < mSettingsByUser.size(); i++) { 364 final int userId = mSettingsByUser.keyAt(i); 365 final UsbSettingsManager settings = mSettingsByUser.valueAt(i); 366 pw.increaseIndent(); 367 pw.println("Settings for user " + userId + ":"); 368 settings.dump(fd, pw); 369 pw.decreaseIndent(); 370 } 371 } 372 pw.decreaseIndent(); 373 } 374} 375