12423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood/* 22423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * Copyright (C) 2010 The Android Open Source Project 32423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * 42423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 52423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * you may not use this file except in compliance with the License. 62423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * You may obtain a copy of the License at 72423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * 82423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 92423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * 102423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * Unless required by applicable law or agreed to in writing, software 112423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 122423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * See the License for the specific language governing permissions an 142423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood * limitations under the License. 152423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood */ 162423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood 1702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodpackage com.android.server.usb; 182423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood 193a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwoodimport android.app.PendingIntent; 20460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.app.admin.DevicePolicyManager; 21fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.BroadcastReceiver; 222423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwoodimport android.content.Context; 23fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.Intent; 24fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.content.IntentFilter; 2502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport android.content.pm.PackageManager; 26c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.IUsbManager; 27c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbAccessory; 28c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodimport android.hardware.usb.UsbDevice; 29460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.hardware.usb.UsbManager; 3076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.hardware.usb.UsbPort; 3176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.hardware.usb.UsbPortStatus; 3276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport android.os.Binder; 33e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.Bundle; 34e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.ParcelFileDescriptor; 35fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.os.UserHandle; 362a67840c3c35a6267663e5d3ae921ee9ac614db9Jeff Brownimport android.os.UserManager; 37460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brownimport android.util.Slog; 38fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.util.SparseArray; 39fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 408b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 41fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 4276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brownimport com.android.internal.util.Preconditions; 432cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinskiimport com.android.server.SystemService; 442423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood 452423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwoodimport java.io.File; 4602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport java.io.FileDescriptor; 4702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodimport java.io.PrintWriter; 482423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood 492423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood/** 5046d0adf8256a42416584765625852b6e48497c90Mike Lockwood * UsbService manages all USB related state, including both host and device support. 5146d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Host related events and calls are delegated to UsbHostManager, and device related 5246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * support is delegated to UsbDeviceManager. 532423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood */ 5402eb8746de2d60563ec2751a34d20923192e4293Mike Lockwoodpublic class UsbService extends IUsbManager.Stub { 552cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski 562cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski public static class Lifecycle extends SystemService { 572cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski private UsbService mUsbService; 582cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski 592cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski public Lifecycle(Context context) { 602cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski super(context); 612cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski } 622cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski 632cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski @Override 642cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski public void onStart() { 652cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski mUsbService = new UsbService(getContext()); 662cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski publishBinderService(Context.USB_SERVICE, mUsbService); 672cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski } 682cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski 692cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski @Override 702cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski public void onBootPhase(int phase) { 712cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 722cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski mUsbService.systemReady(); 73460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 74460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown mUsbService.bootCompleted(); 752cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski } 762cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski } 772cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski } 782cb6c60c0d2de3bc743c043aca963db6fe52662fAdam Lesinski 79fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private static final String TAG = "UsbService"; 80fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 812423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood private final Context mContext; 82fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 8346d0adf8256a42416584765625852b6e48497c90Mike Lockwood private UsbDeviceManager mDeviceManager; 8446d0adf8256a42416584765625852b6e48497c90Mike Lockwood private UsbHostManager mHostManager; 8576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown private UsbPortManager mPortManager; 862e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood private final UsbAlsaManager mAlsaManager; 87ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood 88fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private final Object mLock = new Object(); 89fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 90fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey /** Map from {@link UserHandle} to {@link UsbSettingsManager} */ 918b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey @GuardedBy("mLock") 92fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private final SparseArray<UsbSettingsManager> 93fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey mSettingsByUser = new SparseArray<UsbSettingsManager>(); 94fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 95fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private UsbSettingsManager getSettingsForUser(int userId) { 96fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey synchronized (mLock) { 97fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey UsbSettingsManager settings = mSettingsByUser.get(userId); 98fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey if (settings == null) { 99fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey settings = new UsbSettingsManager(mContext, new UserHandle(userId)); 100fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey mSettingsByUser.put(userId, settings); 101fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 102fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey return settings; 103fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 104fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 1051c0e543638fa940651b675645146fd71c2ebd9b9Mike Lockwood 106770126a678ccc9328a89407ffc82f4d998b25427Mike Lockwood public UsbService(Context context) { 107770126a678ccc9328a89407ffc82f4d998b25427Mike Lockwood mContext = context; 108fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 1092e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood mAlsaManager = new UsbAlsaManager(context); 1102e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood 111fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final PackageManager pm = mContext.getPackageManager(); 11246d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { 1132e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood mHostManager = new UsbHostManager(context, mAlsaManager); 1142423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood } 11502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (new File("/sys/class/android_usb").exists()) { 1162e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood mDeviceManager = new UsbDeviceManager(context, mAlsaManager); 117fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 11876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mHostManager != null || mDeviceManager != null) { 11976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager = new UsbPortManager(context); 12076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 121fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 122fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey setCurrentUser(UserHandle.USER_OWNER); 123fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 124460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown final IntentFilter filter = new IntentFilter(); 125460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 126460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown filter.addAction(Intent.ACTION_USER_SWITCHED); 127460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown filter.addAction(Intent.ACTION_USER_STOPPED); 128460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 129460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown mContext.registerReceiver(mReceiver, filter, null, null); 130fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 131fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 132460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown private BroadcastReceiver mReceiver = new BroadcastReceiver() { 133fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 134fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public void onReceive(Context context, Intent intent) { 135fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 136fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final String action = intent.getAction(); 137fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey if (Intent.ACTION_USER_SWITCHED.equals(action)) { 138fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey setCurrentUser(userId); 139fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 140fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey synchronized (mLock) { 141fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey mSettingsByUser.remove(userId); 142fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 143460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 144460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown .equals(action)) { 145460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown if (mDeviceManager != null) { 146460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown mDeviceManager.updateUserRestrictions(); 147460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } 148fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 149fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 150fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey }; 151fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 152fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private void setCurrentUser(int userId) { 153fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final UsbSettingsManager userSettings = getSettingsForUser(userId); 154fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey if (mHostManager != null) { 155fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey mHostManager.setCurrentSettings(userSettings); 156fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 157fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey if (mDeviceManager != null) { 158460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown mDeviceManager.setCurrentUser(userId, userSettings); 159a8e3a898a2bc004ca1fcd278b68f5da5c344afbbMike Lockwood } 160da39f0e87814c5acb8b6319a1877b93197fb910eMike Lockwood } 161da39f0e87814c5acb8b6319a1877b93197fb910eMike Lockwood 16202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood public void systemReady() { 1632e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood mAlsaManager.systemReady(); 1642e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood 16546d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (mDeviceManager != null) { 16646d0adf8256a42416584765625852b6e48497c90Mike Lockwood mDeviceManager.systemReady(); 16746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 16846d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (mHostManager != null) { 16946d0adf8256a42416584765625852b6e48497c90Mike Lockwood mHostManager.systemReady(); 1702423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood } 17176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 17276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.systemReady(); 17376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 1742423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood } 1752423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood 176460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown public void bootCompleted() { 177460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown if (mDeviceManager != null) { 178460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown mDeviceManager.bootCompleted(); 179460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } 180460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } 181460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown 182ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood /* Returns a list of all currently attached USB devices (host mdoe) */ 183fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 184e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public void getDeviceList(Bundle devices) { 18546d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (mHostManager != null) { 18646d0adf8256a42416584765625852b6e48497c90Mike Lockwood mHostManager.getDeviceList(devices); 187e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 188e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 189e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 190ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood /* Opens the specified USB device (host mode) */ 191fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 192e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public ParcelFileDescriptor openDevice(String deviceName) { 19346d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (mHostManager != null) { 19446d0adf8256a42416584765625852b6e48497c90Mike Lockwood return mHostManager.openDevice(deviceName); 19546d0adf8256a42416584765625852b6e48497c90Mike Lockwood } else { 19646d0adf8256a42416584765625852b6e48497c90Mike Lockwood return null; 1978b682ad08a8e55b3ce2cf58f3aff6d3464ab668bMike Lockwood } 198e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 199e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 200ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood /* returns the currently attached USB accessory (device mode) */ 201fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 2029182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood public UsbAccessory getCurrentAccessory() { 20346d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (mDeviceManager != null) { 20446d0adf8256a42416584765625852b6e48497c90Mike Lockwood return mDeviceManager.getCurrentAccessory(); 20546d0adf8256a42416584765625852b6e48497c90Mike Lockwood } else { 20646d0adf8256a42416584765625852b6e48497c90Mike Lockwood return null; 20746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 2089182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood } 2099182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood 210ddc6cade00bbc08fa668cf937f606538f5c29a80Mike Lockwood /* opens the currently attached USB accessory (device mode) */ 211fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 21202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 21346d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (mDeviceManager != null) { 21402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return mDeviceManager.openAccessory(accessory); 21546d0adf8256a42416584765625852b6e48497c90Mike Lockwood } else { 21646d0adf8256a42416584765625852b6e48497c90Mike Lockwood return null; 21702eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 21802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 21902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood 220fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 221fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public void setDevicePackage(UsbDevice device, String packageName, int userId) { 2227a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 223fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getSettingsForUser(userId).setDevicePackage(device, packageName); 22402eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 22502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood 226fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 227fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) { 2287a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 229fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getSettingsForUser(userId).setAccessoryPackage(accessory, packageName); 23002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 23102eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood 232fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 2333a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood public boolean hasDevicePermission(UsbDevice device) { 234fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final int userId = UserHandle.getCallingUserId(); 235fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey return getSettingsForUser(userId).hasPermission(device); 2363a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood } 2373a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood 238fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 2393a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood public boolean hasAccessoryPermission(UsbAccessory accessory) { 240fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final int userId = UserHandle.getCallingUserId(); 241fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey return getSettingsForUser(userId).hasPermission(accessory); 2423a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood } 2433a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood 244fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 245fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) { 246fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final int userId = UserHandle.getCallingUserId(); 247fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getSettingsForUser(userId).requestPermission(device, packageName, pi); 2483a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood } 2493a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood 250fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 251fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public void requestAccessoryPermission( 252fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey UsbAccessory accessory, String packageName, PendingIntent pi) { 253fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final int userId = UserHandle.getCallingUserId(); 254fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getSettingsForUser(userId).requestPermission(accessory, packageName, pi); 2553a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood } 2563a68b8338b431eb15d28e92f06452efbbda9493eMike Lockwood 257fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 25802eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood public void grantDevicePermission(UsbDevice device, int uid) { 2597a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 260fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final int userId = UserHandle.getUserId(uid); 261fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getSettingsForUser(userId).grantDevicePermission(device, uid); 26202eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 26302eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood 264fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 26502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood public void grantAccessoryPermission(UsbAccessory accessory, int uid) { 2667a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 267fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey final int userId = UserHandle.getUserId(uid); 268fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getSettingsForUser(userId).grantAccessoryPermission(accessory, uid); 26902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 27002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood 271fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 272fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public boolean hasDefaults(String packageName, int userId) { 2737a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 274fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey return getSettingsForUser(userId).hasDefaults(packageName); 27502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 27602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood 277fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 278fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public void clearDefaults(String packageName, int userId) { 2797a976a43700a17a29a0671c8456e41ec0a1086b9Mike Lockwood mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 280fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getSettingsForUser(userId).clearDefaults(packageName); 2819182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood } 2829182d3c4eb1f9065cb33df5a3594969dd0d42accMike Lockwood 283fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 284460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown public boolean isFunctionEnabled(String function) { 285460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 286460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function); 287460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } 288460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown 289460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown @Override 290fcf10f7c12cb3107bdfedce6f76a8c866d154f3cNick Kralevich public void setCurrentFunction(String function) { 29102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 2921848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier 293460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown if (!isSupportedCurrentFunction(function)) { 294460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: " 295460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown + function); 296460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown function = UsbManager.USB_FUNCTION_NONE; 2971848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier } 2981848d31c2cbb5404be383ad44049e58e36b258baEmily Bernier 29902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (mDeviceManager != null) { 300fcf10f7c12cb3107bdfedce6f76a8c866d154f3cNick Kralevich mDeviceManager.setCurrentFunctions(function); 30102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else { 30202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood throw new IllegalStateException("USB device mode not supported"); 30302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 30402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 30502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 306460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown private static boolean isSupportedCurrentFunction(String function) { 307460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown if (function == null) return true; 308460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown 309460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown switch (function) { 310460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown case UsbManager.USB_FUNCTION_NONE: 311460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown case UsbManager.USB_FUNCTION_AUDIO_SOURCE: 312460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown case UsbManager.USB_FUNCTION_MIDI: 313460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown case UsbManager.USB_FUNCTION_MTP: 314460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown case UsbManager.USB_FUNCTION_PTP: 315460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown case UsbManager.USB_FUNCTION_RNDIS: 316460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown return true; 317460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } 318460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown 319460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown return false; 320460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown } 321460a146eb8f827e4e70f2dd93d1ba852d0feb06bJeff Brown 322fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 323674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich public void setUsbDataUnlocked(boolean unlocked) { 324674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 325674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich mDeviceManager.setUsbDataUnlocked(unlocked); 326674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich } 327674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich 328674019065bceb4150190bfb1aa63cda9de0a8560Nick Kralevich @Override 3294e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 3304e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 3314e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); 3324e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby } 3334e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby 334fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey @Override 3354e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby public void denyUsbDebugging() { 3364e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 3374e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby mDeviceManager.denyUsbDebugging(); 3384e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby } 3394e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby 34002eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood @Override 341cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby public void clearUsbDebuggingKeys() { 342cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 343cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby mDeviceManager.clearUsbDebuggingKeys(); 344cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby } 345cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby 346cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby @Override 34776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown public UsbPort[] getPorts() { 34876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 34902eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood 35076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final long ident = Binder.clearCallingIdentity(); 35176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown try { 35276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return mPortManager != null ? mPortManager.getPorts() : null; 35376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } finally { 35476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown Binder.restoreCallingIdentity(ident); 35502eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 35676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 35776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown 35876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown @Override 35976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown public UsbPortStatus getPortStatus(String portId) { 36076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown Preconditions.checkNotNull(portId, "portId must not be null"); 36176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 36276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown 36376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final long ident = Binder.clearCallingIdentity(); 36476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown try { 36576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return mPortManager != null ? mPortManager.getPortStatus(portId) : null; 36676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } finally { 36776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown Binder.restoreCallingIdentity(ident); 36846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 36976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 370fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 37176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown @Override 37276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown public void setPortRoles(String portId, int powerRole, int dataRole) { 37376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown Preconditions.checkNotNull(portId, "portId must not be null"); 37476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown UsbPort.checkRoles(powerRole, dataRole); 37576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); 37676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown 37776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final long ident = Binder.clearCallingIdentity(); 37876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown try { 37976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 38076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.setPortRoles(portId, powerRole, dataRole, null); 38176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 38276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } finally { 38376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown Binder.restoreCallingIdentity(ident); 38476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 38576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 38676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown 38776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown @Override 38876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 38976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 39076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown 39176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 39276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final long ident = Binder.clearCallingIdentity(); 39376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown try { 39476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (args == null || args.length == 0 || "-a".equals(args[0])) { 39576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("USB Manager State:"); 3962dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown pw.increaseIndent(); 39776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mDeviceManager != null) { 39876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mDeviceManager.dump(pw); 39976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 40076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mHostManager != null) { 40176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mHostManager.dump(pw); 40276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 40376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 40476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 40576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 40676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mAlsaManager.dump(pw); 40776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown 40876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown synchronized (mLock) { 40976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown for (int i = 0; i < mSettingsByUser.size(); i++) { 41076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final int userId = mSettingsByUser.keyAt(i); 41176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final UsbSettingsManager settings = mSettingsByUser.valueAt(i); 41276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Settings for user " + userId + ":"); 41376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.increaseIndent(); 41476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown settings.dump(pw); 41576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.decreaseIndent(); 41676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 41776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 41876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else if (args.length == 4 && "set-port-roles".equals(args[0])) { 41976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final String portId = args[1]; 42076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final int powerRole; 42176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown switch (args[2]) { 42276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "source": 42376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown powerRole = UsbPort.POWER_ROLE_SOURCE; 42476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 42576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "sink": 42676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown powerRole = UsbPort.POWER_ROLE_SINK; 42776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 42876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "no-power": 42976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown powerRole = 0; 43076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 43176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown default: 43276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Invalid power role: " + args[2]); 43376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return; 43476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 43576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final int dataRole; 43676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown switch (args[3]) { 43776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "host": 43876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown dataRole = UsbPort.DATA_ROLE_HOST; 43976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 44076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "device": 44176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown dataRole = UsbPort.DATA_ROLE_DEVICE; 44276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 44376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "no-data": 44476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown dataRole = 0; 44576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 44676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown default: 44776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Invalid data role: " + args[3]); 44876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return; 44976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 45076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 45176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.setPortRoles(portId, powerRole, dataRole, pw); 45276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown // Note: It might take some time for the side-effects of this operation 45376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown // to be fully applied by the kernel since the driver may need to 45476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown // renegotiate the USB port mode. If this proves to be an issue 45576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown // during debugging, it might be worth adding a sleep here before 45676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown // dumping the new state. 45776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 45876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 45976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 46076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else if (args.length == 3 && "add-port".equals(args[0])) { 46176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final String portId = args[1]; 46276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final int supportedModes; 46376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown switch (args[2]) { 46476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "ufp": 46576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown supportedModes = UsbPort.MODE_UFP; 46676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 46776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "dfp": 46876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown supportedModes = UsbPort.MODE_DFP; 46976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 47076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "dual": 47176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown supportedModes = UsbPort.MODE_DUAL; 47276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 47376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "none": 47476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown supportedModes = 0; 47576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 47676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown default: 47776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Invalid mode: " + args[2]); 47876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return; 47976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 48076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 48176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.addSimulatedPort(portId, supportedModes, pw); 48276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 48376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 48476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 48576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else if (args.length == 5 && "connect-port".equals(args[0])) { 48676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final String portId = args[1]; 48776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final int mode; 48876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final boolean canChangeMode = args[2].endsWith("?"); 48976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown switch (canChangeMode ? removeLastChar(args[2]) : args[2]) { 49076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "ufp": 49176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mode = UsbPort.MODE_UFP; 49276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 49376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "dfp": 49476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mode = UsbPort.MODE_DFP; 49576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 49676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown default: 49776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Invalid mode: " + args[2]); 49876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return; 49976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 50076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final int powerRole; 50176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final boolean canChangePowerRole = args[3].endsWith("?"); 50276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown switch (canChangePowerRole ? removeLastChar(args[3]) : args[3]) { 50376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "source": 50476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown powerRole = UsbPort.POWER_ROLE_SOURCE; 50576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 50676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "sink": 50776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown powerRole = UsbPort.POWER_ROLE_SINK; 50876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 50976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown default: 51076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Invalid power role: " + args[3]); 51176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return; 51276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 51376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final int dataRole; 51476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final boolean canChangeDataRole = args[4].endsWith("?"); 51576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown switch (canChangeDataRole ? removeLastChar(args[4]) : args[4]) { 51676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "host": 51776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown dataRole = UsbPort.DATA_ROLE_HOST; 51876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 51976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown case "device": 52076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown dataRole = UsbPort.DATA_ROLE_DEVICE; 52176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown break; 52276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown default: 52376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Invalid data role: " + args[4]); 52476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return; 52576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 52676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 52776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.connectSimulatedPort(portId, mode, canChangeMode, 52876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown powerRole, canChangePowerRole, dataRole, canChangeDataRole, pw); 52976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 53076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 53176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 53276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else if (args.length == 2 && "disconnect-port".equals(args[0])) { 53376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final String portId = args[1]; 53476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 53576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.disconnectSimulatedPort(portId, pw); 53676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 53776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 53876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 53976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else if (args.length == 2 && "remove-port".equals(args[0])) { 54076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown final String portId = args[1]; 54176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 54276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.removeSimulatedPort(portId, pw); 54376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 54476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 54576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 54676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else if (args.length == 1 && "reset".equals(args[0])) { 54776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 54876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.resetSimulation(pw); 54976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 55076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 55176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 55276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else if (args.length == 1 && "ports".equals(args[0])) { 55376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown if (mPortManager != null) { 55476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown mPortManager.dump(pw); 55576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 55676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } else { 55776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Dump current USB state or issue command:"); 55876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" ports"); 55976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" set-port-roles <id> <source|sink|no-power> <host|device|no-data>"); 56076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" add-port <id> <ufp|dfp|dual|none>"); 56176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" connect-port <id> <ufp|dfp><?> <source|sink><?> <host|device><?>"); 56276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" (add ? suffix if mode, power role, or data role can be changed)"); 56376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" disconnect-port <id>"); 56476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" remove-port <id>"); 56576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" reset"); 56676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 56776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Example USB type C port role switch:"); 56876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb set-port-roles \"default\" source device"); 56976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 57076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Example USB type C port simulation with full capabilities:"); 57176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb add-port \"matrix\" dual"); 57276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb connect-port \"matrix\" ufp? sink? device?"); 57376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb ports"); 57476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb disconnect-port \"matrix\""); 57576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb remove-port \"matrix\""); 57676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb reset"); 57776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 57876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Example USB type C port where only power role can be changed:"); 57976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb add-port \"matrix\" dual"); 58076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb connect-port \"matrix\" dfp source? host"); 58176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb reset"); 58276c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 58376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Example USB OTG port where id pin determines function:"); 58476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb add-port \"matrix\" dual"); 58576c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb connect-port \"matrix\" dfp source host"); 58676c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb reset"); 58776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(); 58876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println("Example USB device-only port:"); 58976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb add-port \"matrix\" ufp"); 59076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb connect-port \"matrix\" ufp sink device"); 59176c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown pw.println(" dumpsys usb reset"); 592fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 59376c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } finally { 59476c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown Binder.restoreCallingIdentity(ident); 595fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 59602eb8746de2d60563ec2751a34d20923192e4293Mike Lockwood } 59776c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown 59876c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown private static final String removeLastChar(String value) { 59976c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown return value.substring(0, value.length() - 1); 60076c4c6668a1486bc003ab0c585bb1f41d16e27a7Jeff Brown } 6012423607a32d63a0c646b17758ebeb4dc1d0b791fMike Lockwood} 602