UsbService.java revision 233d94c0df13a7e54f738f442457cebc62294384
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.hardware.usb.UsbPort; 31import android.hardware.usb.UsbPortStatus; 32import android.os.Binder; 33import android.os.Bundle; 34import android.os.ParcelFileDescriptor; 35import android.os.UserHandle; 36import android.os.UserManager; 37import android.util.Slog; 38import android.util.SparseArray; 39 40import com.android.internal.annotations.GuardedBy; 41import com.android.internal.util.IndentingPrintWriter; 42import com.android.internal.util.Preconditions; 43import com.android.server.SystemService; 44 45import java.io.File; 46import java.io.FileDescriptor; 47import java.io.PrintWriter; 48 49/** 50 * UsbService manages all USB related state, including both host and device support. 51 * Host related events and calls are delegated to UsbHostManager, and device related 52 * support is delegated to UsbDeviceManager. 53 */ 54public class UsbService extends IUsbManager.Stub { 55 56 public static class Lifecycle extends SystemService { 57 private UsbService mUsbService; 58 59 public Lifecycle(Context context) { 60 super(context); 61 } 62 63 @Override 64 public void onStart() { 65 mUsbService = new UsbService(getContext()); 66 publishBinderService(Context.USB_SERVICE, mUsbService); 67 } 68 69 @Override 70 public void onBootPhase(int phase) { 71 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 72 mUsbService.systemReady(); 73 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 74 mUsbService.bootCompleted(); 75 } 76 } 77 } 78 79 private static final String TAG = "UsbService"; 80 81 private final Context mContext; 82 83 private UsbDeviceManager mDeviceManager; 84 private UsbHostManager mHostManager; 85 private UsbPortManager mPortManager; 86 private final UsbAlsaManager mAlsaManager; 87 88 private final Object mLock = new Object(); 89 90 /** Map from {@link UserHandle} to {@link UsbSettingsManager} */ 91 @GuardedBy("mLock") 92 private final SparseArray<UsbSettingsManager> 93 mSettingsByUser = new SparseArray<UsbSettingsManager>(); 94 95 private UsbSettingsManager getSettingsForUser(int userId) { 96 synchronized (mLock) { 97 UsbSettingsManager settings = mSettingsByUser.get(userId); 98 if (settings == null) { 99 settings = new UsbSettingsManager(mContext, new UserHandle(userId)); 100 mSettingsByUser.put(userId, settings); 101 } 102 return settings; 103 } 104 } 105 106 public UsbService(Context context) { 107 mContext = context; 108 109 mAlsaManager = new UsbAlsaManager(context); 110 111 final PackageManager pm = mContext.getPackageManager(); 112 if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { 113 mHostManager = new UsbHostManager(context, mAlsaManager); 114 } 115 if (new File("/sys/class/android_usb").exists()) { 116 mDeviceManager = new UsbDeviceManager(context, mAlsaManager); 117 } 118 if (mHostManager != null || mDeviceManager != null) { 119 mPortManager = new UsbPortManager(context); 120 } 121 122 setCurrentUser(UserHandle.USER_SYSTEM); 123 124 final IntentFilter filter = new IntentFilter(); 125 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 126 filter.addAction(Intent.ACTION_USER_SWITCHED); 127 filter.addAction(Intent.ACTION_USER_STOPPED); 128 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 129 mContext.registerReceiver(mReceiver, filter, null, null); 130 } 131 132 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 133 @Override 134 public void onReceive(Context context, Intent intent) { 135 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 136 final String action = intent.getAction(); 137 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 138 setCurrentUser(userId); 139 } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 140 synchronized (mLock) { 141 mSettingsByUser.remove(userId); 142 } 143 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 144 .equals(action)) { 145 if (mDeviceManager != null) { 146 mDeviceManager.updateUserRestrictions(); 147 } 148 } 149 } 150 }; 151 152 private void setCurrentUser(int userId) { 153 final UsbSettingsManager userSettings = getSettingsForUser(userId); 154 if (mHostManager != null) { 155 mHostManager.setCurrentSettings(userSettings); 156 } 157 if (mDeviceManager != null) { 158 mDeviceManager.setCurrentUser(userId, userSettings); 159 } 160 } 161 162 public void systemReady() { 163 mAlsaManager.systemReady(); 164 165 if (mDeviceManager != null) { 166 mDeviceManager.systemReady(); 167 } 168 if (mHostManager != null) { 169 mHostManager.systemReady(); 170 } 171 if (mPortManager != null) { 172 mPortManager.systemReady(); 173 } 174 } 175 176 public void bootCompleted() { 177 if (mDeviceManager != null) { 178 mDeviceManager.bootCompleted(); 179 } 180 } 181 182 /* Returns a list of all currently attached USB devices (host mdoe) */ 183 @Override 184 public void getDeviceList(Bundle devices) { 185 if (mHostManager != null) { 186 mHostManager.getDeviceList(devices); 187 } 188 } 189 190 /* Opens the specified USB device (host mode) */ 191 @Override 192 public ParcelFileDescriptor openDevice(String deviceName) { 193 if (mHostManager != null) { 194 return mHostManager.openDevice(deviceName); 195 } else { 196 return null; 197 } 198 } 199 200 /* returns the currently attached USB accessory (device mode) */ 201 @Override 202 public UsbAccessory getCurrentAccessory() { 203 if (mDeviceManager != null) { 204 return mDeviceManager.getCurrentAccessory(); 205 } else { 206 return null; 207 } 208 } 209 210 /* opens the currently attached USB accessory (device mode) */ 211 @Override 212 public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 213 if (mDeviceManager != null) { 214 return mDeviceManager.openAccessory(accessory); 215 } else { 216 return null; 217 } 218 } 219 220 @Override 221 public void setDevicePackage(UsbDevice device, String packageName, int userId) { 222 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 223 getSettingsForUser(userId).setDevicePackage(device, packageName); 224 } 225 226 @Override 227 public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) { 228 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 229 getSettingsForUser(userId).setAccessoryPackage(accessory, packageName); 230 } 231 232 @Override 233 public boolean hasDevicePermission(UsbDevice device) { 234 final int userId = UserHandle.getCallingUserId(); 235 return getSettingsForUser(userId).hasPermission(device); 236 } 237 238 @Override 239 public boolean hasAccessoryPermission(UsbAccessory accessory) { 240 final int userId = UserHandle.getCallingUserId(); 241 return getSettingsForUser(userId).hasPermission(accessory); 242 } 243 244 @Override 245 public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) { 246 final int userId = UserHandle.getCallingUserId(); 247 getSettingsForUser(userId).requestPermission(device, packageName, pi); 248 } 249 250 @Override 251 public void requestAccessoryPermission( 252 UsbAccessory accessory, String packageName, PendingIntent pi) { 253 final int userId = UserHandle.getCallingUserId(); 254 getSettingsForUser(userId).requestPermission(accessory, packageName, pi); 255 } 256 257 @Override 258 public void grantDevicePermission(UsbDevice device, int uid) { 259 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 260 final int userId = UserHandle.getUserId(uid); 261 getSettingsForUser(userId).grantDevicePermission(device, uid); 262 } 263 264 @Override 265 public void grantAccessoryPermission(UsbAccessory accessory, int uid) { 266 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 267 final int userId = UserHandle.getUserId(uid); 268 getSettingsForUser(userId).grantAccessoryPermission(accessory, uid); 269 } 270 271 @Override 272 public boolean hasDefaults(String packageName, int userId) { 273 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 274 return getSettingsForUser(userId).hasDefaults(packageName); 275 } 276 277 @Override 278 public void clearDefaults(String packageName, int userId) { 279 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 280 getSettingsForUser(userId).clearDefaults(packageName); 281 } 282 283 @Override 284 public boolean isFunctionEnabled(String function) { 285 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 286 return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function); 287 } 288 289 @Override 290 public void setCurrentFunction(String function) { 291 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 292 293 if (!isSupportedCurrentFunction(function)) { 294 Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: " 295 + function); 296 function = UsbManager.USB_FUNCTION_NONE; 297 } 298 299 if (mDeviceManager != null) { 300 mDeviceManager.setCurrentFunctions(function); 301 } else { 302 throw new IllegalStateException("USB device mode not supported"); 303 } 304 } 305 306 private static boolean isSupportedCurrentFunction(String function) { 307 if (function == null) return true; 308 309 switch (function) { 310 case UsbManager.USB_FUNCTION_NONE: 311 case UsbManager.USB_FUNCTION_AUDIO_SOURCE: 312 case UsbManager.USB_FUNCTION_MIDI: 313 case UsbManager.USB_FUNCTION_MTP: 314 case UsbManager.USB_FUNCTION_PTP: 315 case UsbManager.USB_FUNCTION_RNDIS: 316 return true; 317 } 318 319 return false; 320 } 321 322 @Override 323 public void setUsbDataUnlocked(boolean unlocked) { 324 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 325 // If attempt to change USB function while file transfer is restricted, ensure that 326 // usb data is always locked, and return. 327 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 328 if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) { 329 if (mDeviceManager != null) mDeviceManager.setUsbDataUnlocked(false); 330 return; 331 } 332 mDeviceManager.setUsbDataUnlocked(unlocked); 333 } 334 335 @Override 336 public boolean isUsbDataUnlocked() { 337 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 338 return mDeviceManager.isUsbDataUnlocked(); 339 } 340 341 @Override 342 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 343 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 344 mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); 345 } 346 347 @Override 348 public void denyUsbDebugging() { 349 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 350 mDeviceManager.denyUsbDebugging(); 351 } 352 353 @Override 354 public void clearUsbDebuggingKeys() { 355 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 356 mDeviceManager.clearUsbDebuggingKeys(); 357 } 358 359 @Override 360 public UsbPort[] getPorts() { 361 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 362 363 final long ident = Binder.clearCallingIdentity(); 364 try { 365 return mPortManager != null ? mPortManager.getPorts() : null; 366 } finally { 367 Binder.restoreCallingIdentity(ident); 368 } 369 } 370 371 @Override 372 public UsbPortStatus getPortStatus(String portId) { 373 Preconditions.checkNotNull(portId, "portId must not be null"); 374 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 375 376 final long ident = Binder.clearCallingIdentity(); 377 try { 378 return mPortManager != null ? mPortManager.getPortStatus(portId) : null; 379 } finally { 380 Binder.restoreCallingIdentity(ident); 381 } 382 } 383 384 @Override 385 public void setPortRoles(String portId, int powerRole, int dataRole) { 386 Preconditions.checkNotNull(portId, "portId must not be null"); 387 UsbPort.checkRoles(powerRole, dataRole); 388 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 389 390 final long ident = Binder.clearCallingIdentity(); 391 try { 392 if (mPortManager != null) { 393 mPortManager.setPortRoles(portId, powerRole, dataRole, null); 394 } 395 } finally { 396 Binder.restoreCallingIdentity(ident); 397 } 398 } 399 400 @Override 401 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 402 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 403 404 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 405 final long ident = Binder.clearCallingIdentity(); 406 try { 407 if (args == null || args.length == 0 || "-a".equals(args[0])) { 408 pw.println("USB Manager State:"); 409 pw.increaseIndent(); 410 if (mDeviceManager != null) { 411 mDeviceManager.dump(pw); 412 } 413 if (mHostManager != null) { 414 mHostManager.dump(pw); 415 } 416 if (mPortManager != null) { 417 mPortManager.dump(pw); 418 } 419 mAlsaManager.dump(pw); 420 421 synchronized (mLock) { 422 for (int i = 0; i < mSettingsByUser.size(); i++) { 423 final int userId = mSettingsByUser.keyAt(i); 424 final UsbSettingsManager settings = mSettingsByUser.valueAt(i); 425 pw.println("Settings for user " + userId + ":"); 426 pw.increaseIndent(); 427 settings.dump(pw); 428 pw.decreaseIndent(); 429 } 430 } 431 } else if (args.length == 4 && "set-port-roles".equals(args[0])) { 432 final String portId = args[1]; 433 final int powerRole; 434 switch (args[2]) { 435 case "source": 436 powerRole = UsbPort.POWER_ROLE_SOURCE; 437 break; 438 case "sink": 439 powerRole = UsbPort.POWER_ROLE_SINK; 440 break; 441 case "no-power": 442 powerRole = 0; 443 break; 444 default: 445 pw.println("Invalid power role: " + args[2]); 446 return; 447 } 448 final int dataRole; 449 switch (args[3]) { 450 case "host": 451 dataRole = UsbPort.DATA_ROLE_HOST; 452 break; 453 case "device": 454 dataRole = UsbPort.DATA_ROLE_DEVICE; 455 break; 456 case "no-data": 457 dataRole = 0; 458 break; 459 default: 460 pw.println("Invalid data role: " + args[3]); 461 return; 462 } 463 if (mPortManager != null) { 464 mPortManager.setPortRoles(portId, powerRole, dataRole, pw); 465 // Note: It might take some time for the side-effects of this operation 466 // to be fully applied by the kernel since the driver may need to 467 // renegotiate the USB port mode. If this proves to be an issue 468 // during debugging, it might be worth adding a sleep here before 469 // dumping the new state. 470 pw.println(); 471 mPortManager.dump(pw); 472 } 473 } else if (args.length == 3 && "add-port".equals(args[0])) { 474 final String portId = args[1]; 475 final int supportedModes; 476 switch (args[2]) { 477 case "ufp": 478 supportedModes = UsbPort.MODE_UFP; 479 break; 480 case "dfp": 481 supportedModes = UsbPort.MODE_DFP; 482 break; 483 case "dual": 484 supportedModes = UsbPort.MODE_DUAL; 485 break; 486 case "none": 487 supportedModes = 0; 488 break; 489 default: 490 pw.println("Invalid mode: " + args[2]); 491 return; 492 } 493 if (mPortManager != null) { 494 mPortManager.addSimulatedPort(portId, supportedModes, pw); 495 pw.println(); 496 mPortManager.dump(pw); 497 } 498 } else if (args.length == 5 && "connect-port".equals(args[0])) { 499 final String portId = args[1]; 500 final int mode; 501 final boolean canChangeMode = args[2].endsWith("?"); 502 switch (canChangeMode ? removeLastChar(args[2]) : args[2]) { 503 case "ufp": 504 mode = UsbPort.MODE_UFP; 505 break; 506 case "dfp": 507 mode = UsbPort.MODE_DFP; 508 break; 509 default: 510 pw.println("Invalid mode: " + args[2]); 511 return; 512 } 513 final int powerRole; 514 final boolean canChangePowerRole = args[3].endsWith("?"); 515 switch (canChangePowerRole ? removeLastChar(args[3]) : args[3]) { 516 case "source": 517 powerRole = UsbPort.POWER_ROLE_SOURCE; 518 break; 519 case "sink": 520 powerRole = UsbPort.POWER_ROLE_SINK; 521 break; 522 default: 523 pw.println("Invalid power role: " + args[3]); 524 return; 525 } 526 final int dataRole; 527 final boolean canChangeDataRole = args[4].endsWith("?"); 528 switch (canChangeDataRole ? removeLastChar(args[4]) : args[4]) { 529 case "host": 530 dataRole = UsbPort.DATA_ROLE_HOST; 531 break; 532 case "device": 533 dataRole = UsbPort.DATA_ROLE_DEVICE; 534 break; 535 default: 536 pw.println("Invalid data role: " + args[4]); 537 return; 538 } 539 if (mPortManager != null) { 540 mPortManager.connectSimulatedPort(portId, mode, canChangeMode, 541 powerRole, canChangePowerRole, dataRole, canChangeDataRole, pw); 542 pw.println(); 543 mPortManager.dump(pw); 544 } 545 } else if (args.length == 2 && "disconnect-port".equals(args[0])) { 546 final String portId = args[1]; 547 if (mPortManager != null) { 548 mPortManager.disconnectSimulatedPort(portId, pw); 549 pw.println(); 550 mPortManager.dump(pw); 551 } 552 } else if (args.length == 2 && "remove-port".equals(args[0])) { 553 final String portId = args[1]; 554 if (mPortManager != null) { 555 mPortManager.removeSimulatedPort(portId, pw); 556 pw.println(); 557 mPortManager.dump(pw); 558 } 559 } else if (args.length == 1 && "reset".equals(args[0])) { 560 if (mPortManager != null) { 561 mPortManager.resetSimulation(pw); 562 pw.println(); 563 mPortManager.dump(pw); 564 } 565 } else if (args.length == 1 && "ports".equals(args[0])) { 566 if (mPortManager != null) { 567 mPortManager.dump(pw); 568 } 569 } else { 570 pw.println("Dump current USB state or issue command:"); 571 pw.println(" ports"); 572 pw.println(" set-port-roles <id> <source|sink|no-power> <host|device|no-data>"); 573 pw.println(" add-port <id> <ufp|dfp|dual|none>"); 574 pw.println(" connect-port <id> <ufp|dfp><?> <source|sink><?> <host|device><?>"); 575 pw.println(" (add ? suffix if mode, power role, or data role can be changed)"); 576 pw.println(" disconnect-port <id>"); 577 pw.println(" remove-port <id>"); 578 pw.println(" reset"); 579 pw.println(); 580 pw.println("Example USB type C port role switch:"); 581 pw.println(" dumpsys usb set-port-roles \"default\" source device"); 582 pw.println(); 583 pw.println("Example USB type C port simulation with full capabilities:"); 584 pw.println(" dumpsys usb add-port \"matrix\" dual"); 585 pw.println(" dumpsys usb connect-port \"matrix\" ufp? sink? device?"); 586 pw.println(" dumpsys usb ports"); 587 pw.println(" dumpsys usb disconnect-port \"matrix\""); 588 pw.println(" dumpsys usb remove-port \"matrix\""); 589 pw.println(" dumpsys usb reset"); 590 pw.println(); 591 pw.println("Example USB type C port where only power role can be changed:"); 592 pw.println(" dumpsys usb add-port \"matrix\" dual"); 593 pw.println(" dumpsys usb connect-port \"matrix\" dfp source? host"); 594 pw.println(" dumpsys usb reset"); 595 pw.println(); 596 pw.println("Example USB OTG port where id pin determines function:"); 597 pw.println(" dumpsys usb add-port \"matrix\" dual"); 598 pw.println(" dumpsys usb connect-port \"matrix\" dfp source host"); 599 pw.println(" dumpsys usb reset"); 600 pw.println(); 601 pw.println("Example USB device-only port:"); 602 pw.println(" dumpsys usb add-port \"matrix\" ufp"); 603 pw.println(" dumpsys usb connect-port \"matrix\" ufp sink device"); 604 pw.println(" dumpsys usb reset"); 605 } 606 } finally { 607 Binder.restoreCallingIdentity(ident); 608 } 609 } 610 611 private static final String removeLastChar(String value) { 612 return value.substring(0, value.length() - 1); 613 } 614} 615