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.annotation.NonNull; 20 import android.annotation.UserIdInt; 21 import android.app.PendingIntent; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.BroadcastReceiver; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.pm.PackageManager; 29 import android.hardware.usb.IUsbManager; 30 import android.hardware.usb.UsbAccessory; 31 import android.hardware.usb.UsbDevice; 32 import android.hardware.usb.UsbManager; 33 import android.hardware.usb.UsbPort; 34 import android.hardware.usb.UsbPortStatus; 35 import android.os.Binder; 36 import android.os.Bundle; 37 import android.os.ParcelFileDescriptor; 38 import android.os.UserHandle; 39 import android.os.UserManager; 40 import android.service.usb.UsbServiceDumpProto; 41 import android.util.ArraySet; 42 import android.util.Slog; 43 import android.util.proto.ProtoOutputStream; 44 45 import com.android.internal.annotations.GuardedBy; 46 import com.android.internal.util.DumpUtils; 47 import com.android.internal.util.IndentingPrintWriter; 48 import com.android.internal.util.Preconditions; 49 import com.android.internal.util.dump.DualDumpOutputStream; 50 import com.android.server.SystemService; 51 52 import java.io.File; 53 import java.io.FileDescriptor; 54 import java.io.PrintWriter; 55 import java.util.Collections; 56 57 /** 58 * UsbService manages all USB related state, including both host and device support. 59 * Host related events and calls are delegated to UsbHostManager, and device related 60 * support is delegated to UsbDeviceManager. 61 */ 62 public class UsbService extends IUsbManager.Stub { 63 64 public static class Lifecycle extends SystemService { 65 private UsbService mUsbService; 66 67 public Lifecycle(Context context) { 68 super(context); 69 } 70 71 @Override 72 public void onStart() { 73 mUsbService = new UsbService(getContext()); 74 publishBinderService(Context.USB_SERVICE, mUsbService); 75 } 76 77 @Override 78 public void onBootPhase(int phase) { 79 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 80 mUsbService.systemReady(); 81 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 82 mUsbService.bootCompleted(); 83 } 84 } 85 86 @Override 87 public void onSwitchUser(int newUserId) { 88 mUsbService.onSwitchUser(newUserId); 89 } 90 91 @Override 92 public void onStopUser(int userHandle) { 93 mUsbService.onStopUser(UserHandle.of(userHandle)); 94 } 95 96 @Override 97 public void onUnlockUser(int userHandle) { 98 mUsbService.onUnlockUser(userHandle); 99 } 100 } 101 102 private static final String TAG = "UsbService"; 103 104 private final Context mContext; 105 private final UserManager mUserManager; 106 107 private UsbDeviceManager mDeviceManager; 108 private UsbHostManager mHostManager; 109 private UsbPortManager mPortManager; 110 private final UsbAlsaManager mAlsaManager; 111 112 private final UsbSettingsManager mSettingsManager; 113 114 /** 115 * The user id of the current user. There might be several profiles (with separate user ids) 116 * per user. 117 */ 118 @GuardedBy("mLock") 119 private @UserIdInt int mCurrentUserId; 120 121 private final Object mLock = new Object(); 122 123 private UsbUserSettingsManager getSettingsForUser(@UserIdInt int userIdInt) { 124 return mSettingsManager.getSettingsForUser(userIdInt); 125 } 126 127 public UsbService(Context context) { 128 mContext = context; 129 130 mUserManager = context.getSystemService(UserManager.class); 131 mSettingsManager = new UsbSettingsManager(context); 132 mAlsaManager = new UsbAlsaManager(context); 133 134 final PackageManager pm = mContext.getPackageManager(); 135 if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { 136 mHostManager = new UsbHostManager(context, mAlsaManager, mSettingsManager); 137 } 138 if (new File("/sys/class/android_usb").exists()) { 139 mDeviceManager = new UsbDeviceManager(context, mAlsaManager, mSettingsManager); 140 } 141 if (mHostManager != null || mDeviceManager != null) { 142 mPortManager = new UsbPortManager(context); 143 } 144 145 onSwitchUser(UserHandle.USER_SYSTEM); 146 147 BroadcastReceiver receiver = new BroadcastReceiver() { 148 @Override 149 public void onReceive(Context context, Intent intent) { 150 final String action = intent.getAction(); 151 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 152 .equals(action)) { 153 if (mDeviceManager != null) { 154 mDeviceManager.updateUserRestrictions(); 155 } 156 } 157 } 158 }; 159 160 final IntentFilter filter = new IntentFilter(); 161 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 162 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 163 mContext.registerReceiver(receiver, filter, null, null); 164 } 165 166 /** 167 * Set new {@link #mCurrentUserId} and propagate it to other modules. 168 * 169 * @param newUserId The user id of the new current user. 170 */ 171 private void onSwitchUser(@UserIdInt int newUserId) { 172 synchronized (mLock) { 173 mCurrentUserId = newUserId; 174 175 // The following two modules need to know about the current profile group. If they need 176 // to distinguish by profile of the user, the id has to be passed in the call to the 177 // module. 178 UsbProfileGroupSettingsManager settings = 179 mSettingsManager.getSettingsForProfileGroup(UserHandle.of(newUserId)); 180 if (mHostManager != null) { 181 mHostManager.setCurrentUserSettings(settings); 182 } 183 if (mDeviceManager != null) { 184 mDeviceManager.setCurrentUser(newUserId, settings); 185 } 186 } 187 } 188 189 /** 190 * Execute operations when a user is stopped. 191 * 192 * @param stoppedUser The user that is stopped 193 */ 194 private void onStopUser(@NonNull UserHandle stoppedUser) { 195 mSettingsManager.remove(stoppedUser); 196 } 197 198 public void systemReady() { 199 mAlsaManager.systemReady(); 200 201 if (mDeviceManager != null) { 202 mDeviceManager.systemReady(); 203 } 204 if (mHostManager != null) { 205 mHostManager.systemReady(); 206 } 207 if (mPortManager != null) { 208 mPortManager.systemReady(); 209 } 210 } 211 212 public void bootCompleted() { 213 if (mDeviceManager != null) { 214 mDeviceManager.bootCompleted(); 215 } 216 } 217 218 /** Called when a user is unlocked. */ 219 public void onUnlockUser(int user) { 220 if (mDeviceManager != null) { 221 mDeviceManager.onUnlockUser(user); 222 } 223 } 224 225 /* Returns a list of all currently attached USB devices (host mdoe) */ 226 @Override 227 public void getDeviceList(Bundle devices) { 228 if (mHostManager != null) { 229 mHostManager.getDeviceList(devices); 230 } 231 } 232 233 /** 234 * Check if the calling user is in the same profile group as the {@link #mCurrentUserId 235 * current user}. 236 * 237 * @return Iff the caller is in the current user's profile group 238 */ 239 @GuardedBy("mLock") 240 private boolean isCallerInCurrentUserProfileGroupLocked() { 241 int userIdInt = UserHandle.getCallingUserId(); 242 243 long ident = clearCallingIdentity(); 244 try { 245 return mUserManager.isSameProfileGroup(userIdInt, mCurrentUserId); 246 } finally { 247 restoreCallingIdentity(ident); 248 } 249 } 250 251 /* Opens the specified USB device (host mode) */ 252 @Override 253 public ParcelFileDescriptor openDevice(String deviceName, String packageName) { 254 ParcelFileDescriptor fd = null; 255 256 if (mHostManager != null) { 257 synchronized (mLock) { 258 if (deviceName != null) { 259 int userIdInt = UserHandle.getCallingUserId(); 260 boolean isCurrentUser = isCallerInCurrentUserProfileGroupLocked(); 261 262 if (isCurrentUser) { 263 fd = mHostManager.openDevice(deviceName, getSettingsForUser(userIdInt), 264 packageName, Binder.getCallingUid()); 265 } else { 266 Slog.w(TAG, "Cannot open " + deviceName + " for user " + userIdInt + 267 " as user is not active."); 268 } 269 } 270 } 271 } 272 273 return fd; 274 } 275 276 /* returns the currently attached USB accessory (device mode) */ 277 @Override 278 public UsbAccessory getCurrentAccessory() { 279 if (mDeviceManager != null) { 280 return mDeviceManager.getCurrentAccessory(); 281 } else { 282 return null; 283 } 284 } 285 286 /* opens the currently attached USB accessory (device mode) */ 287 @Override 288 public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 289 if (mDeviceManager != null) { 290 int userIdInt = UserHandle.getCallingUserId(); 291 292 synchronized (mLock) { 293 boolean isCurrentUser = isCallerInCurrentUserProfileGroupLocked(); 294 295 if (isCurrentUser) { 296 return mDeviceManager.openAccessory(accessory, getSettingsForUser(userIdInt)); 297 } else { 298 Slog.w(TAG, "Cannot open " + accessory + " for user " + userIdInt + 299 " as user is not active."); 300 } 301 } 302 } 303 304 return null; 305 } 306 307 /* Returns a dup of the control file descriptor for the given function. */ 308 @Override 309 public ParcelFileDescriptor getControlFd(long function) { 310 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_MTP, null); 311 return mDeviceManager.getControlFd(function); 312 } 313 314 @Override 315 public void setDevicePackage(UsbDevice device, String packageName, int userId) { 316 device = Preconditions.checkNotNull(device); 317 318 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 319 320 UserHandle user = UserHandle.of(userId); 321 mSettingsManager.getSettingsForProfileGroup(user).setDevicePackage(device, packageName, 322 user); 323 } 324 325 @Override 326 public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) { 327 accessory = Preconditions.checkNotNull(accessory); 328 329 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 330 331 UserHandle user = UserHandle.of(userId); 332 mSettingsManager.getSettingsForProfileGroup(user).setAccessoryPackage(accessory, 333 packageName, user); 334 } 335 336 @Override 337 public boolean hasDevicePermission(UsbDevice device, String packageName) { 338 final int userId = UserHandle.getCallingUserId(); 339 return getSettingsForUser(userId).hasPermission(device, packageName, 340 Binder.getCallingUid()); 341 } 342 343 @Override 344 public boolean hasAccessoryPermission(UsbAccessory accessory) { 345 final int userId = UserHandle.getCallingUserId(); 346 return getSettingsForUser(userId).hasPermission(accessory); 347 } 348 349 @Override 350 public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) { 351 final int userId = UserHandle.getCallingUserId(); 352 getSettingsForUser(userId).requestPermission(device, packageName, pi, 353 Binder.getCallingUid()); 354 } 355 356 @Override 357 public void requestAccessoryPermission( 358 UsbAccessory accessory, String packageName, PendingIntent pi) { 359 final int userId = UserHandle.getCallingUserId(); 360 getSettingsForUser(userId).requestPermission(accessory, packageName, pi); 361 } 362 363 @Override 364 public void grantDevicePermission(UsbDevice device, int uid) { 365 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 366 final int userId = UserHandle.getUserId(uid); 367 getSettingsForUser(userId).grantDevicePermission(device, uid); 368 } 369 370 @Override 371 public void grantAccessoryPermission(UsbAccessory accessory, int uid) { 372 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 373 final int userId = UserHandle.getUserId(uid); 374 getSettingsForUser(userId).grantAccessoryPermission(accessory, uid); 375 } 376 377 @Override 378 public boolean hasDefaults(String packageName, int userId) { 379 packageName = Preconditions.checkStringNotEmpty(packageName); 380 381 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 382 383 UserHandle user = UserHandle.of(userId); 384 return mSettingsManager.getSettingsForProfileGroup(user).hasDefaults(packageName, user); 385 } 386 387 @Override 388 public void clearDefaults(String packageName, int userId) { 389 packageName = Preconditions.checkStringNotEmpty(packageName); 390 391 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 392 393 UserHandle user = UserHandle.of(userId); 394 mSettingsManager.getSettingsForProfileGroup(user).clearDefaults(packageName, user); 395 } 396 397 @Override 398 public void setCurrentFunctions(long functions) { 399 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 400 Preconditions.checkArgument(UsbManager.areSettableFunctions(functions)); 401 Preconditions.checkState(mDeviceManager != null); 402 mDeviceManager.setCurrentFunctions(functions); 403 } 404 405 @Override 406 public void setCurrentFunction(String functions, boolean usbDataUnlocked) { 407 setCurrentFunctions(UsbManager.usbFunctionsFromString(functions)); 408 } 409 410 @Override 411 public boolean isFunctionEnabled(String function) { 412 return (getCurrentFunctions() & UsbManager.usbFunctionsFromString(function)) != 0; 413 } 414 415 @Override 416 public long getCurrentFunctions() { 417 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 418 Preconditions.checkState(mDeviceManager != null); 419 return mDeviceManager.getCurrentFunctions(); 420 } 421 422 @Override 423 public void setScreenUnlockedFunctions(long functions) { 424 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 425 Preconditions.checkArgument(UsbManager.areSettableFunctions(functions)); 426 Preconditions.checkState(mDeviceManager != null); 427 428 mDeviceManager.setScreenUnlockedFunctions(functions); 429 } 430 431 @Override 432 public long getScreenUnlockedFunctions() { 433 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 434 Preconditions.checkState(mDeviceManager != null); 435 return mDeviceManager.getScreenUnlockedFunctions(); 436 } 437 438 @Override 439 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 440 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 441 mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); 442 } 443 444 @Override 445 public void denyUsbDebugging() { 446 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 447 mDeviceManager.denyUsbDebugging(); 448 } 449 450 @Override 451 public void clearUsbDebuggingKeys() { 452 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 453 mDeviceManager.clearUsbDebuggingKeys(); 454 } 455 456 @Override 457 public UsbPort[] getPorts() { 458 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 459 460 final long ident = Binder.clearCallingIdentity(); 461 try { 462 return mPortManager != null ? mPortManager.getPorts() : null; 463 } finally { 464 Binder.restoreCallingIdentity(ident); 465 } 466 } 467 468 @Override 469 public UsbPortStatus getPortStatus(String portId) { 470 Preconditions.checkNotNull(portId, "portId must not be null"); 471 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 472 473 final long ident = Binder.clearCallingIdentity(); 474 try { 475 return mPortManager != null ? mPortManager.getPortStatus(portId) : null; 476 } finally { 477 Binder.restoreCallingIdentity(ident); 478 } 479 } 480 481 @Override 482 public void setPortRoles(String portId, int powerRole, int dataRole) { 483 Preconditions.checkNotNull(portId, "portId must not be null"); 484 UsbPort.checkRoles(powerRole, dataRole); 485 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 486 487 final long ident = Binder.clearCallingIdentity(); 488 try { 489 if (mPortManager != null) { 490 mPortManager.setPortRoles(portId, powerRole, dataRole, null); 491 } 492 } finally { 493 Binder.restoreCallingIdentity(ident); 494 } 495 } 496 497 @Override 498 public void setUsbDeviceConnectionHandler(ComponentName usbDeviceConnectionHandler) { 499 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 500 synchronized (mLock) { 501 if (mCurrentUserId == UserHandle.getCallingUserId()) { 502 if (mHostManager != null) { 503 mHostManager.setUsbDeviceConnectionHandler(usbDeviceConnectionHandler); 504 } 505 } else { 506 throw new IllegalArgumentException("Only the current user can register a usb " + 507 "connection handler"); 508 } 509 } 510 } 511 512 @Override 513 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 514 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; 515 516 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 517 final long ident = Binder.clearCallingIdentity(); 518 try { 519 ArraySet<String> argsSet = new ArraySet<>(); 520 Collections.addAll(argsSet, args); 521 522 boolean dumpAsProto = false; 523 if (argsSet.contains("--proto")) { 524 dumpAsProto = true; 525 } 526 527 if (args == null || args.length == 0 || args[0].equals("-a") || dumpAsProto) { 528 DualDumpOutputStream dump; 529 if (dumpAsProto) { 530 dump = new DualDumpOutputStream(new ProtoOutputStream(fd)); 531 } else { 532 pw.println("USB MANAGER STATE (dumpsys usb):"); 533 534 dump = new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")); 535 } 536 537 if (mDeviceManager != null) { 538 mDeviceManager.dump(dump, "device_manager", UsbServiceDumpProto.DEVICE_MANAGER); 539 } 540 if (mHostManager != null) { 541 mHostManager.dump(dump, "host_manager", UsbServiceDumpProto.HOST_MANAGER); 542 } 543 if (mPortManager != null) { 544 mPortManager.dump(dump, "port_manager", UsbServiceDumpProto.PORT_MANAGER); 545 } 546 mAlsaManager.dump(dump, "alsa_manager", UsbServiceDumpProto.ALSA_MANAGER); 547 548 mSettingsManager.dump(dump, "settings_manager", 549 UsbServiceDumpProto.SETTINGS_MANAGER); 550 dump.flush(); 551 } else if ("set-port-roles".equals(args[0]) && args.length == 4) { 552 final String portId = args[1]; 553 final int powerRole; 554 switch (args[2]) { 555 case "source": 556 powerRole = UsbPort.POWER_ROLE_SOURCE; 557 break; 558 case "sink": 559 powerRole = UsbPort.POWER_ROLE_SINK; 560 break; 561 case "no-power": 562 powerRole = 0; 563 break; 564 default: 565 pw.println("Invalid power role: " + args[2]); 566 return; 567 } 568 final int dataRole; 569 switch (args[3]) { 570 case "host": 571 dataRole = UsbPort.DATA_ROLE_HOST; 572 break; 573 case "device": 574 dataRole = UsbPort.DATA_ROLE_DEVICE; 575 break; 576 case "no-data": 577 dataRole = 0; 578 break; 579 default: 580 pw.println("Invalid data role: " + args[3]); 581 return; 582 } 583 if (mPortManager != null) { 584 mPortManager.setPortRoles(portId, powerRole, dataRole, pw); 585 // Note: It might take some time for the side-effects of this operation 586 // to be fully applied by the kernel since the driver may need to 587 // renegotiate the USB port mode. If this proves to be an issue 588 // during debugging, it might be worth adding a sleep here before 589 // dumping the new state. 590 pw.println(); 591 mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), 592 "", 0); 593 } 594 } else if ("add-port".equals(args[0]) && args.length == 3) { 595 final String portId = args[1]; 596 final int supportedModes; 597 switch (args[2]) { 598 case "ufp": 599 supportedModes = UsbPort.MODE_UFP; 600 break; 601 case "dfp": 602 supportedModes = UsbPort.MODE_DFP; 603 break; 604 case "dual": 605 supportedModes = UsbPort.MODE_DUAL; 606 break; 607 case "none": 608 supportedModes = 0; 609 break; 610 default: 611 pw.println("Invalid mode: " + args[2]); 612 return; 613 } 614 if (mPortManager != null) { 615 mPortManager.addSimulatedPort(portId, supportedModes, pw); 616 pw.println(); 617 mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), 618 "", 0); 619 } 620 } else if ("connect-port".equals(args[0]) && args.length == 5) { 621 final String portId = args[1]; 622 final int mode; 623 final boolean canChangeMode = args[2].endsWith("?"); 624 switch (canChangeMode ? removeLastChar(args[2]) : args[2]) { 625 case "ufp": 626 mode = UsbPort.MODE_UFP; 627 break; 628 case "dfp": 629 mode = UsbPort.MODE_DFP; 630 break; 631 default: 632 pw.println("Invalid mode: " + args[2]); 633 return; 634 } 635 final int powerRole; 636 final boolean canChangePowerRole = args[3].endsWith("?"); 637 switch (canChangePowerRole ? removeLastChar(args[3]) : args[3]) { 638 case "source": 639 powerRole = UsbPort.POWER_ROLE_SOURCE; 640 break; 641 case "sink": 642 powerRole = UsbPort.POWER_ROLE_SINK; 643 break; 644 default: 645 pw.println("Invalid power role: " + args[3]); 646 return; 647 } 648 final int dataRole; 649 final boolean canChangeDataRole = args[4].endsWith("?"); 650 switch (canChangeDataRole ? removeLastChar(args[4]) : args[4]) { 651 case "host": 652 dataRole = UsbPort.DATA_ROLE_HOST; 653 break; 654 case "device": 655 dataRole = UsbPort.DATA_ROLE_DEVICE; 656 break; 657 default: 658 pw.println("Invalid data role: " + args[4]); 659 return; 660 } 661 if (mPortManager != null) { 662 mPortManager.connectSimulatedPort(portId, mode, canChangeMode, 663 powerRole, canChangePowerRole, dataRole, canChangeDataRole, pw); 664 pw.println(); 665 mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), 666 "", 0); 667 } 668 } else if ("disconnect-port".equals(args[0]) && args.length == 2) { 669 final String portId = args[1]; 670 if (mPortManager != null) { 671 mPortManager.disconnectSimulatedPort(portId, pw); 672 pw.println(); 673 mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), 674 "", 0); 675 } 676 } else if ("remove-port".equals(args[0]) && args.length == 2) { 677 final String portId = args[1]; 678 if (mPortManager != null) { 679 mPortManager.removeSimulatedPort(portId, pw); 680 pw.println(); 681 mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), 682 "", 0); 683 } 684 } else if ("reset".equals(args[0]) && args.length == 1) { 685 if (mPortManager != null) { 686 mPortManager.resetSimulation(pw); 687 pw.println(); 688 mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), 689 "", 0); 690 } 691 } else if ("ports".equals(args[0]) && args.length == 1) { 692 if (mPortManager != null) { 693 mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), 694 "", 0); 695 } 696 } else if ("dump-descriptors".equals(args[0])) { 697 mHostManager.dumpDescriptors(pw, args); 698 } else { 699 pw.println("Dump current USB state or issue command:"); 700 pw.println(" ports"); 701 pw.println(" set-port-roles <id> <source|sink|no-power> <host|device|no-data>"); 702 pw.println(" add-port <id> <ufp|dfp|dual|none>"); 703 pw.println(" connect-port <id> <ufp|dfp><?> <source|sink><?> <host|device><?>"); 704 pw.println(" (add ? suffix if mode, power role, or data role can be changed)"); 705 pw.println(" disconnect-port <id>"); 706 pw.println(" remove-port <id>"); 707 pw.println(" reset"); 708 pw.println(); 709 pw.println("Example USB type C port role switch:"); 710 pw.println(" dumpsys usb set-port-roles \"default\" source device"); 711 pw.println(); 712 pw.println("Example USB type C port simulation with full capabilities:"); 713 pw.println(" dumpsys usb add-port \"matrix\" dual"); 714 pw.println(" dumpsys usb connect-port \"matrix\" ufp? sink? device?"); 715 pw.println(" dumpsys usb ports"); 716 pw.println(" dumpsys usb disconnect-port \"matrix\""); 717 pw.println(" dumpsys usb remove-port \"matrix\""); 718 pw.println(" dumpsys usb reset"); 719 pw.println(); 720 pw.println("Example USB type C port where only power role can be changed:"); 721 pw.println(" dumpsys usb add-port \"matrix\" dual"); 722 pw.println(" dumpsys usb connect-port \"matrix\" dfp source? host"); 723 pw.println(" dumpsys usb reset"); 724 pw.println(); 725 pw.println("Example USB OTG port where id pin determines function:"); 726 pw.println(" dumpsys usb add-port \"matrix\" dual"); 727 pw.println(" dumpsys usb connect-port \"matrix\" dfp source host"); 728 pw.println(" dumpsys usb reset"); 729 pw.println(); 730 pw.println("Example USB device-only port:"); 731 pw.println(" dumpsys usb add-port \"matrix\" ufp"); 732 pw.println(" dumpsys usb connect-port \"matrix\" ufp sink device"); 733 pw.println(" dumpsys usb reset"); 734 pw.println(); 735 pw.println("Example USB device descriptors:"); 736 pw.println(" dumpsys usb dump-descriptors -dump-short"); 737 pw.println(" dumpsys usb dump-descriptors -dump-tree"); 738 pw.println(" dumpsys usb dump-descriptors -dump-list"); 739 pw.println(" dumpsys usb dump-descriptors -dump-raw"); 740 } 741 } finally { 742 Binder.restoreCallingIdentity(ident); 743 } 744 } 745 746 private static String removeLastChar(String value) { 747 return value.substring(0, value.length() - 1); 748 } 749 } 750