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