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