UsbDeviceManager.java revision 31f5b6875c1b6b84caec2ef27861a703f4a79a6d
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions an 14 * limitations under the License. 15 */ 16 17package com.android.server.usb; 18 19import android.app.Notification; 20import android.app.NotificationChannel; 21import android.app.NotificationManager; 22import android.app.PendingIntent; 23import android.content.BroadcastReceiver; 24import android.content.ComponentName; 25import android.content.ContentResolver; 26import android.content.Context; 27import android.content.Intent; 28import android.content.IntentFilter; 29import android.content.pm.PackageManager; 30import android.content.res.Resources; 31import android.database.ContentObserver; 32import android.hardware.usb.UsbAccessory; 33import android.hardware.usb.UsbConfiguration; 34import android.hardware.usb.UsbConstants; 35import android.hardware.usb.UsbDevice; 36import android.hardware.usb.UsbInterface; 37import android.hardware.usb.UsbManager; 38import android.hardware.usb.UsbPort; 39import android.hardware.usb.UsbPortStatus; 40import android.os.BatteryManager; 41import android.os.FileUtils; 42import android.os.Handler; 43import android.os.Looper; 44import android.os.Message; 45import android.os.ParcelFileDescriptor; 46import android.os.SystemClock; 47import android.os.SystemProperties; 48import android.os.UEventObserver; 49import android.os.UserHandle; 50import android.os.UserManager; 51import android.os.storage.StorageManager; 52import android.os.storage.StorageVolume; 53import android.provider.Settings; 54import android.util.Pair; 55import android.util.Slog; 56 57import com.android.internal.annotations.GuardedBy; 58import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 59import com.android.internal.notification.SystemNotificationChannels; 60import com.android.internal.os.SomeArgs; 61import com.android.internal.util.IndentingPrintWriter; 62import com.android.server.FgThread; 63 64import java.io.File; 65import java.io.FileNotFoundException; 66import java.io.IOException; 67import java.util.HashMap; 68import java.util.HashSet; 69import java.util.Iterator; 70import java.util.Locale; 71import java.util.Map; 72import java.util.Scanner; 73import java.util.Set; 74 75/** 76 * UsbDeviceManager manages USB state in device mode. 77 */ 78public class UsbDeviceManager { 79 80 private static final String TAG = "UsbDeviceManager"; 81 private static final boolean DEBUG = false; 82 83 /** 84 * The persistent property which stores whether adb is enabled or not. 85 * May also contain vendor-specific default functions for testing purposes. 86 */ 87 private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config"; 88 89 /** 90 * The non-persistent property which stores the current USB settings. 91 */ 92 private static final String USB_CONFIG_PROPERTY = "sys.usb.config"; 93 94 /** 95 * The property which stores the current build type (user/userdebug/eng). 96 */ 97 private static final String BUILD_TYPE_PROPERTY = "ro.build.type"; 98 99 private static final String BUILD_TYPE_USERDEBUG = "userdebug"; 100 private static final String BUILD_TYPE_ENG = "eng"; 101 102 /** 103 * The non-persistent property which stores the current USB actual state. 104 */ 105 private static final String USB_STATE_PROPERTY = "sys.usb.state"; 106 107 /** 108 * ro.bootmode value when phone boots into usual Android. 109 */ 110 private static final String NORMAL_BOOT = "normal"; 111 112 private static final String USB_STATE_MATCH = 113 "DEVPATH=/devices/virtual/android_usb/android0"; 114 private static final String ACCESSORY_START_MATCH = 115 "DEVPATH=/devices/virtual/misc/usb_accessory"; 116 private static final String FUNCTIONS_PATH = 117 "/sys/class/android_usb/android0/functions"; 118 private static final String STATE_PATH = 119 "/sys/class/android_usb/android0/state"; 120 private static final String RNDIS_ETH_ADDR_PATH = 121 "/sys/class/android_usb/android0/f_rndis/ethaddr"; 122 private static final String AUDIO_SOURCE_PCM_PATH = 123 "/sys/class/android_usb/android0/f_audio_source/pcm"; 124 private static final String MIDI_ALSA_PATH = 125 "/sys/class/android_usb/android0/f_midi/alsa"; 126 127 private static final int MSG_UPDATE_STATE = 0; 128 private static final int MSG_ENABLE_ADB = 1; 129 private static final int MSG_SET_CURRENT_FUNCTIONS = 2; 130 private static final int MSG_SYSTEM_READY = 3; 131 private static final int MSG_BOOT_COMPLETED = 4; 132 private static final int MSG_USER_SWITCHED = 5; 133 private static final int MSG_UPDATE_USER_RESTRICTIONS = 6; 134 private static final int MSG_UPDATE_PORT_STATE = 7; 135 private static final int MSG_ACCESSORY_MODE_ENTER_TIMEOUT = 8; 136 private static final int MSG_UPDATE_CHARGING_STATE = 9; 137 private static final int MSG_UPDATE_HOST_STATE = 10; 138 private static final int MSG_LOCALE_CHANGED = 11; 139 140 private static final int AUDIO_MODE_SOURCE = 1; 141 142 // Delay for debouncing USB disconnects. 143 // We often get rapid connect/disconnect events when enabling USB functions, 144 // which need debouncing. 145 private static final int UPDATE_DELAY = 1000; 146 147 // Timeout for entering USB request mode. 148 // Request is cancelled if host does not configure device within 10 seconds. 149 private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000; 150 151 private static final String BOOT_MODE_PROPERTY = "ro.bootmode"; 152 153 private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv"; 154 155 private UsbHandler mHandler; 156 private boolean mBootCompleted; 157 158 private final Object mLock = new Object(); 159 160 private final Context mContext; 161 private final ContentResolver mContentResolver; 162 @GuardedBy("mLock") 163 private UsbProfileGroupSettingsManager mCurrentSettings; 164 private NotificationManager mNotificationManager; 165 private final boolean mHasUsbAccessory; 166 private boolean mUseUsbNotification; 167 private boolean mAdbEnabled; 168 private boolean mAudioSourceEnabled; 169 private boolean mMidiEnabled; 170 private int mMidiCard; 171 private int mMidiDevice; 172 private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap; 173 private String[] mAccessoryStrings; 174 private UsbDebuggingManager mDebuggingManager; 175 private final UsbAlsaManager mUsbAlsaManager; 176 private final UsbSettingsManager mSettingsManager; 177 private Intent mBroadcastedIntent; 178 private boolean mPendingBootBroadcast; 179 private static Set<Integer> sBlackListedInterfaces; 180 181 static { 182 sBlackListedInterfaces = new HashSet<Integer>(); 183 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_AUDIO); 184 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_COMM); 185 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HID); 186 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_PRINTER); 187 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_MASS_STORAGE); 188 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HUB); 189 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CDC_DATA); 190 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CSCID); 191 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CONTENT_SEC); 192 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_VIDEO); 193 sBlackListedInterfaces.add(UsbConstants.USB_CLASS_WIRELESS_CONTROLLER); 194 }; 195 196 private class AdbSettingsObserver extends ContentObserver { 197 public AdbSettingsObserver() { 198 super(null); 199 } 200 201 @Override 202 public void onChange(boolean selfChange) { 203 boolean enable = (Settings.Global.getInt(mContentResolver, 204 Settings.Global.ADB_ENABLED, 0) > 0); 205 mHandler.sendMessage(MSG_ENABLE_ADB, enable); 206 } 207 } 208 209 /* 210 * Listens for uevent messages from the kernel to monitor the USB state 211 */ 212 private final UEventObserver mUEventObserver = new UEventObserver() { 213 @Override 214 public void onUEvent(UEventObserver.UEvent event) { 215 if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString()); 216 217 String state = event.get("USB_STATE"); 218 String accessory = event.get("ACCESSORY"); 219 if (state != null) { 220 mHandler.updateState(state); 221 } else if ("START".equals(accessory)) { 222 if (DEBUG) Slog.d(TAG, "got accessory start"); 223 startAccessoryMode(); 224 } 225 } 226 }; 227 228 private final BroadcastReceiver mPortReceiver = new BroadcastReceiver() { 229 @Override 230 public void onReceive(Context context, Intent intent) { 231 UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT); 232 UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS); 233 mHandler.updateHostState(port, status); 234 } 235 }; 236 237 private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() { 238 @Override 239 public void onReceive(Context context, Intent intent) { 240 int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); 241 boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB; 242 mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging); 243 } 244 }; 245 246 private final BroadcastReceiver mHostReceiver = new BroadcastReceiver() { 247 @Override 248 public void onReceive(Context context, Intent intent) { 249 Iterator devices = ((UsbManager) context.getSystemService(Context.USB_SERVICE)) 250 .getDeviceList().entrySet().iterator(); 251 if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { 252 mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, true); 253 } else { 254 mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, false); 255 } 256 } 257 }; 258 259 private final BroadcastReceiver mLanguageChangedReceiver = new BroadcastReceiver() { 260 @Override 261 public void onReceive(Context context, Intent intent) { 262 mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED); 263 } 264 }; 265 266 public UsbDeviceManager(Context context, UsbAlsaManager alsaManager, 267 UsbSettingsManager settingsManager) { 268 mContext = context; 269 mUsbAlsaManager = alsaManager; 270 mSettingsManager = settingsManager; 271 mContentResolver = context.getContentResolver(); 272 PackageManager pm = mContext.getPackageManager(); 273 mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); 274 initRndisAddress(); 275 276 readOemUsbOverrideConfig(); 277 278 mHandler = new UsbHandler(FgThread.get().getLooper()); 279 280 if (nativeIsStartRequested()) { 281 if (DEBUG) Slog.d(TAG, "accessory attached at boot"); 282 startAccessoryMode(); 283 } 284 285 boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false); 286 boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt")); 287 if (secureAdbEnabled && !dataEncrypted) { 288 mDebuggingManager = new UsbDebuggingManager(context); 289 } 290 mContext.registerReceiver(mPortReceiver, 291 new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED)); 292 mContext.registerReceiver(mChargingReceiver, 293 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 294 295 IntentFilter filter = 296 new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED); 297 filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 298 mContext.registerReceiver(mHostReceiver, filter); 299 300 mContext.registerReceiver(mLanguageChangedReceiver, 301 new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); 302 } 303 304 private UsbProfileGroupSettingsManager getCurrentSettings() { 305 synchronized (mLock) { 306 return mCurrentSettings; 307 } 308 } 309 310 public void systemReady() { 311 if (DEBUG) Slog.d(TAG, "systemReady"); 312 313 mNotificationManager = (NotificationManager) 314 mContext.getSystemService(Context.NOTIFICATION_SERVICE); 315 316 // Ensure that the notification channels are set up 317 if (isTv()) { 318 // TV-specific notification channel 319 mNotificationManager.createNotificationChannel( 320 new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV, 321 mContext.getString( 322 com.android.internal.R.string 323 .adb_debugging_notification_channel_tv), 324 NotificationManager.IMPORTANCE_HIGH)); 325 } 326 327 // We do not show the USB notification if the primary volume supports mass storage. 328 // The legacy mass storage UI will be used instead. 329 boolean massStorageSupported = false; 330 final StorageManager storageManager = StorageManager.from(mContext); 331 final StorageVolume primary = storageManager.getPrimaryVolume(); 332 massStorageSupported = primary != null && primary.allowMassStorage(); 333 mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean( 334 com.android.internal.R.bool.config_usbChargingMessage); 335 336 // make sure the ADB_ENABLED setting value matches the current state 337 try { 338 Settings.Global.putInt(mContentResolver, 339 Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0); 340 } catch (SecurityException e) { 341 // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed. 342 Slog.d(TAG, "ADB_ENABLED is restricted."); 343 } 344 mHandler.sendEmptyMessage(MSG_SYSTEM_READY); 345 } 346 347 public void bootCompleted() { 348 if (DEBUG) Slog.d(TAG, "boot completed"); 349 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); 350 } 351 352 public void setCurrentUser(int newCurrentUserId, UsbProfileGroupSettingsManager settings) { 353 synchronized (mLock) { 354 mCurrentSettings = settings; 355 mHandler.obtainMessage(MSG_USER_SWITCHED, newCurrentUserId, 0).sendToTarget(); 356 } 357 } 358 359 public void updateUserRestrictions() { 360 mHandler.sendEmptyMessage(MSG_UPDATE_USER_RESTRICTIONS); 361 } 362 363 private void startAccessoryMode() { 364 if (!mHasUsbAccessory) return; 365 366 mAccessoryStrings = nativeGetAccessoryStrings(); 367 boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE); 368 // don't start accessory mode if our mandatory strings have not been set 369 boolean enableAccessory = (mAccessoryStrings != null && 370 mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null && 371 mAccessoryStrings[UsbAccessory.MODEL_STRING] != null); 372 String functions = null; 373 374 if (enableAccessory && enableAudio) { 375 functions = UsbManager.USB_FUNCTION_ACCESSORY + "," 376 + UsbManager.USB_FUNCTION_AUDIO_SOURCE; 377 } else if (enableAccessory) { 378 functions = UsbManager.USB_FUNCTION_ACCESSORY; 379 } else if (enableAudio) { 380 functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE; 381 } 382 383 if (functions != null) { 384 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_MODE_ENTER_TIMEOUT), 385 ACCESSORY_REQUEST_TIMEOUT); 386 setCurrentFunctions(functions, false); 387 } 388 } 389 390 private static void initRndisAddress() { 391 // configure RNDIS ethernet address based on our serial number using the same algorithm 392 // we had been previously using in kernel board files 393 final int ETH_ALEN = 6; 394 int address[] = new int[ETH_ALEN]; 395 // first byte is 0x02 to signify a locally administered address 396 address[0] = 0x02; 397 398 String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF"); 399 int serialLength = serial.length(); 400 // XOR the USB serial across the remaining 5 bytes 401 for (int i = 0; i < serialLength; i++) { 402 address[i % (ETH_ALEN - 1) + 1] ^= (int) serial.charAt(i); 403 } 404 String addrString = String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", 405 address[0], address[1], address[2], address[3], address[4], address[5]); 406 try { 407 FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString); 408 } catch (IOException e) { 409 Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH); 410 } 411 } 412 413 private boolean isTv() { 414 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); 415 } 416 417 private final class UsbHandler extends Handler { 418 419 // current USB state 420 private boolean mConnected; 421 private boolean mHostConnected; 422 private boolean mSourcePower; 423 private boolean mSinkPower; 424 private boolean mConfigured; 425 private boolean mUsbDataUnlocked; 426 private boolean mAudioAccessoryConnected; 427 private boolean mAudioAccessorySupported; 428 private String mCurrentFunctions; 429 private boolean mCurrentFunctionsApplied; 430 private UsbAccessory mCurrentAccessory; 431 private int mUsbNotificationId; 432 private boolean mAdbNotificationShown; 433 private int mCurrentUser = UserHandle.USER_NULL; 434 private boolean mUsbCharging; 435 private String mCurrentOemFunctions; 436 private boolean mHideUsbNotification; 437 private boolean mSupportsAllCombinations; 438 439 public UsbHandler(Looper looper) { 440 super(looper); 441 try { 442 // Restore default functions. 443 444 if (isNormalBoot()) { 445 mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY, 446 UsbManager.USB_FUNCTION_NONE); 447 mCurrentFunctionsApplied = mCurrentFunctions.equals( 448 SystemProperties.get(USB_STATE_PROPERTY)); 449 } else { 450 mCurrentFunctions = SystemProperties.get(getPersistProp(true), 451 UsbManager.USB_FUNCTION_NONE); 452 mCurrentFunctionsApplied = SystemProperties.get(USB_CONFIG_PROPERTY, 453 UsbManager.USB_FUNCTION_NONE).equals( 454 SystemProperties.get(USB_STATE_PROPERTY)); 455 } 456 457 /** 458 * Use the normal bootmode persistent prop to maintain state of adb across 459 * all boot modes. 460 */ 461 mAdbEnabled = UsbManager.containsFunction( 462 SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY), 463 UsbManager.USB_FUNCTION_ADB); 464 465 /** 466 * Previous versions can set persist config to mtp/ptp but it does not 467 * get reset on OTA. Reset the property here instead. 468 */ 469 String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY); 470 if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP) 471 || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) { 472 SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, 473 UsbManager.removeFunction(UsbManager.removeFunction(persisted, 474 UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP)); 475 } 476 477 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim(); 478 updateState(state); 479 480 // register observer to listen for settings changes 481 mContentResolver.registerContentObserver( 482 Settings.Global.getUriFor(Settings.Global.ADB_ENABLED), 483 false, new AdbSettingsObserver()); 484 485 // Watch for USB configuration changes 486 mUEventObserver.startObserving(USB_STATE_MATCH); 487 mUEventObserver.startObserving(ACCESSORY_START_MATCH); 488 } catch (Exception e) { 489 Slog.e(TAG, "Error initializing UsbHandler", e); 490 } 491 } 492 493 public void sendMessage(int what, boolean arg) { 494 removeMessages(what); 495 Message m = Message.obtain(this, what); 496 m.arg1 = (arg ? 1 : 0); 497 sendMessage(m); 498 } 499 500 public void sendMessage(int what, Object arg) { 501 removeMessages(what); 502 Message m = Message.obtain(this, what); 503 m.obj = arg; 504 sendMessage(m); 505 } 506 507 public void sendMessage(int what, Object arg, boolean arg1) { 508 removeMessages(what); 509 Message m = Message.obtain(this, what); 510 m.obj = arg; 511 m.arg1 = (arg1 ? 1 : 0); 512 sendMessage(m); 513 } 514 515 public void updateState(String state) { 516 int connected, configured; 517 518 if ("DISCONNECTED".equals(state)) { 519 connected = 0; 520 configured = 0; 521 } else if ("CONNECTED".equals(state)) { 522 connected = 1; 523 configured = 0; 524 } else if ("CONFIGURED".equals(state)) { 525 connected = 1; 526 configured = 1; 527 } else { 528 Slog.e(TAG, "unknown state " + state); 529 return; 530 } 531 removeMessages(MSG_UPDATE_STATE); 532 Message msg = Message.obtain(this, MSG_UPDATE_STATE); 533 msg.arg1 = connected; 534 msg.arg2 = configured; 535 // debounce disconnects to avoid problems bringing up USB tethering 536 sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0); 537 } 538 539 public void updateHostState(UsbPort port, UsbPortStatus status) { 540 if (DEBUG) { 541 Slog.i(TAG, "updateHostState " + port + " status=" + status); 542 } 543 544 SomeArgs args = SomeArgs.obtain(); 545 args.arg1 = port; 546 args.arg2 = status; 547 548 removeMessages(MSG_UPDATE_PORT_STATE); 549 Message msg = obtainMessage(MSG_UPDATE_PORT_STATE, args); 550 // debounce rapid transitions of connect/disconnect on type-c ports 551 sendMessageDelayed(msg, UPDATE_DELAY); 552 } 553 554 private boolean waitForState(String state) { 555 // wait for the transition to complete. 556 // give up after 1 second. 557 String value = null; 558 for (int i = 0; i < 20; i++) { 559 // State transition is done when sys.usb.state is set to the new configuration 560 value = SystemProperties.get(USB_STATE_PROPERTY); 561 if (state.equals(value)) return true; 562 SystemClock.sleep(50); 563 } 564 Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value); 565 return false; 566 } 567 568 private void setUsbConfig(String config) { 569 if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")"); 570 // set the new configuration 571 // we always set it due to b/23631400, where adbd was getting killed 572 // and not restarted due to property timeouts on some devices 573 SystemProperties.set(USB_CONFIG_PROPERTY, config); 574 } 575 576 private void setAdbEnabled(boolean enable) { 577 if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable); 578 if (enable != mAdbEnabled) { 579 mAdbEnabled = enable; 580 String oldFunctions = mCurrentFunctions; 581 582 // Persist the adb setting 583 String newFunction = applyAdbFunction(SystemProperties.get( 584 USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE)); 585 SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunction); 586 587 // Remove mtp from the config if file transfer is not enabled 588 if (oldFunctions.equals(UsbManager.USB_FUNCTION_MTP) && 589 !mUsbDataUnlocked && enable) { 590 oldFunctions = UsbManager.USB_FUNCTION_NONE; 591 } 592 593 setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked); 594 updateAdbNotification(false); 595 } 596 597 if (mDebuggingManager != null) { 598 mDebuggingManager.setAdbEnabled(mAdbEnabled); 599 } 600 } 601 602 /** 603 * Evaluates USB function policies and applies the change accordingly. 604 */ 605 private void setEnabledFunctions(String functions, boolean forceRestart, 606 boolean usbDataUnlocked) { 607 if (DEBUG) { 608 Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", " 609 + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked); 610 } 611 612 if (usbDataUnlocked != mUsbDataUnlocked) { 613 mUsbDataUnlocked = usbDataUnlocked; 614 updateUsbNotification(false); 615 forceRestart = true; 616 } 617 618 // Try to set the enabled functions. 619 final String oldFunctions = mCurrentFunctions; 620 final boolean oldFunctionsApplied = mCurrentFunctionsApplied; 621 if (trySetEnabledFunctions(functions, forceRestart)) { 622 return; 623 } 624 625 // Didn't work. Try to revert changes. 626 // We always reapply the policy in case certain constraints changed such as 627 // user restrictions independently of any other new functions we were 628 // trying to activate. 629 if (oldFunctionsApplied && !oldFunctions.equals(functions)) { 630 Slog.e(TAG, "Failsafe 1: Restoring previous USB functions."); 631 if (trySetEnabledFunctions(oldFunctions, false)) { 632 return; 633 } 634 } 635 636 // Still didn't work. Try to restore the default functions. 637 Slog.e(TAG, "Failsafe 2: Restoring default USB functions."); 638 if (trySetEnabledFunctions(null, false)) { 639 return; 640 } 641 642 // Now we're desperate. Ignore the default functions. 643 // Try to get ADB working if enabled. 644 Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled)."); 645 if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) { 646 return; 647 } 648 649 // Ouch. 650 Slog.e(TAG, "Unable to set any USB functions!"); 651 } 652 653 private boolean isNormalBoot() { 654 String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown"); 655 if (bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown")) { 656 return true; 657 } 658 return false; 659 } 660 661 private boolean trySetEnabledFunctions(String functions, boolean forceRestart) { 662 if (functions == null || applyAdbFunction(functions) 663 .equals(UsbManager.USB_FUNCTION_NONE)) { 664 functions = getDefaultFunctions(); 665 } 666 functions = applyAdbFunction(functions); 667 668 String oemFunctions = applyOemOverrideFunction(functions); 669 670 if (!isNormalBoot() && !mCurrentFunctions.equals(functions)) { 671 SystemProperties.set(getPersistProp(true), functions); 672 } 673 674 if ((!functions.equals(oemFunctions) && 675 (mCurrentOemFunctions == null || 676 !mCurrentOemFunctions.equals(oemFunctions))) 677 || !mCurrentFunctions.equals(functions) 678 || !mCurrentFunctionsApplied 679 || forceRestart) { 680 Slog.i(TAG, "Setting USB config to " + functions); 681 mCurrentFunctions = functions; 682 mCurrentOemFunctions = oemFunctions; 683 mCurrentFunctionsApplied = false; 684 685 // Kick the USB stack to close existing connections. 686 setUsbConfig(UsbManager.USB_FUNCTION_NONE); 687 688 if (!waitForState(UsbManager.USB_FUNCTION_NONE)) { 689 Slog.e(TAG, "Failed to kick USB config"); 690 return false; 691 } 692 693 // Set the new USB configuration. 694 setUsbConfig(oemFunctions); 695 696 if (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP) 697 || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP)) { 698 // Start up dependent services. 699 updateUsbStateBroadcastIfNeeded(true); 700 } 701 702 if (!waitForState(oemFunctions)) { 703 Slog.e(TAG, "Failed to switch USB config to " + functions); 704 return false; 705 } 706 707 mCurrentFunctionsApplied = true; 708 } 709 return true; 710 } 711 712 private String applyAdbFunction(String functions) { 713 // Do not pass null pointer to the UsbManager. 714 // There isnt a check there. 715 if (functions == null) { 716 functions = ""; 717 } 718 if (mAdbEnabled) { 719 functions = UsbManager.addFunction(functions, UsbManager.USB_FUNCTION_ADB); 720 } else { 721 functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_ADB); 722 } 723 return functions; 724 } 725 726 private boolean isUsbTransferAllowed() { 727 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 728 return !userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER); 729 } 730 731 private void updateCurrentAccessory() { 732 // We are entering accessory mode if we have received a request from the host 733 // and the request has not timed out yet. 734 boolean enteringAccessoryMode = hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT); 735 736 if (mConfigured && enteringAccessoryMode) { 737 // successfully entered accessory mode 738 if (mAccessoryStrings != null) { 739 mCurrentAccessory = new UsbAccessory(mAccessoryStrings); 740 Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory); 741 // defer accessoryAttached if system is not ready 742 if (mBootCompleted) { 743 getCurrentSettings().accessoryAttached(mCurrentAccessory); 744 } // else handle in boot completed 745 } else { 746 Slog.e(TAG, "nativeGetAccessoryStrings failed"); 747 } 748 } else { 749 if (!enteringAccessoryMode) { 750 notifyAccessoryModeExit(); 751 } else if (DEBUG) { 752 Slog.v(TAG, "Debouncing accessory mode exit"); 753 } 754 } 755 } 756 757 private void notifyAccessoryModeExit() { 758 // make sure accessory mode is off 759 // and restore default functions 760 Slog.d(TAG, "exited USB accessory mode"); 761 setEnabledFunctions(null, false, false); 762 763 if (mCurrentAccessory != null) { 764 if (mBootCompleted) { 765 mSettingsManager.usbAccessoryRemoved(mCurrentAccessory); 766 } 767 mCurrentAccessory = null; 768 mAccessoryStrings = null; 769 } 770 } 771 772 private boolean isUsbStateChanged(Intent intent) { 773 final Set<String> keySet = intent.getExtras().keySet(); 774 if (mBroadcastedIntent == null) { 775 for (String key : keySet) { 776 if (intent.getBooleanExtra(key, false)) { 777 return true; 778 } 779 } 780 } else { 781 if (!keySet.equals(mBroadcastedIntent.getExtras().keySet())) { 782 return true; 783 } 784 for (String key : keySet) { 785 if (intent.getBooleanExtra(key, false) != 786 mBroadcastedIntent.getBooleanExtra(key, false)) { 787 return true; 788 } 789 } 790 } 791 return false; 792 } 793 794 private void updateUsbStateBroadcastIfNeeded(boolean configChanged) { 795 // send a sticky broadcast containing current USB state 796 Intent intent = new Intent(UsbManager.ACTION_USB_STATE); 797 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 798 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND 799 | Intent.FLAG_RECEIVER_FOREGROUND); 800 intent.putExtra(UsbManager.USB_CONNECTED, mConnected); 801 intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected); 802 intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured); 803 intent.putExtra(UsbManager.USB_DATA_UNLOCKED, 804 isUsbTransferAllowed() && mUsbDataUnlocked); 805 intent.putExtra(UsbManager.USB_CONFIG_CHANGED, configChanged); 806 807 if (mCurrentFunctions != null) { 808 String[] functions = mCurrentFunctions.split(","); 809 for (int i = 0; i < functions.length; i++) { 810 final String function = functions[i]; 811 if (UsbManager.USB_FUNCTION_NONE.equals(function)) { 812 continue; 813 } 814 intent.putExtra(function, true); 815 } 816 } 817 818 // send broadcast intent only if the USB state has changed 819 if (!isUsbStateChanged(intent) && !configChanged) { 820 if (DEBUG) { 821 Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras()); 822 } 823 return; 824 } 825 826 if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras()); 827 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 828 mBroadcastedIntent = intent; 829 } 830 831 private void updateUsbFunctions() { 832 updateAudioSourceFunction(); 833 updateMidiFunction(); 834 } 835 836 private void updateAudioSourceFunction() { 837 boolean enabled = UsbManager.containsFunction(mCurrentFunctions, 838 UsbManager.USB_FUNCTION_AUDIO_SOURCE); 839 if (enabled != mAudioSourceEnabled) { 840 int card = -1; 841 int device = -1; 842 843 if (enabled) { 844 Scanner scanner = null; 845 try { 846 scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH)); 847 card = scanner.nextInt(); 848 device = scanner.nextInt(); 849 } catch (FileNotFoundException e) { 850 Slog.e(TAG, "could not open audio source PCM file", e); 851 } finally { 852 if (scanner != null) { 853 scanner.close(); 854 } 855 } 856 } 857 mUsbAlsaManager.setAccessoryAudioState(enabled, card, device); 858 mAudioSourceEnabled = enabled; 859 } 860 } 861 862 private void updateMidiFunction() { 863 boolean enabled = UsbManager.containsFunction(mCurrentFunctions, 864 UsbManager.USB_FUNCTION_MIDI); 865 if (enabled != mMidiEnabled) { 866 if (enabled) { 867 Scanner scanner = null; 868 try { 869 scanner = new Scanner(new File(MIDI_ALSA_PATH)); 870 mMidiCard = scanner.nextInt(); 871 mMidiDevice = scanner.nextInt(); 872 } catch (FileNotFoundException e) { 873 Slog.e(TAG, "could not open MIDI file", e); 874 enabled = false; 875 } finally { 876 if (scanner != null) { 877 scanner.close(); 878 } 879 } 880 } 881 mMidiEnabled = enabled; 882 } 883 mUsbAlsaManager.setPeripheralMidiState( 884 mMidiEnabled && mConfigured, mMidiCard, mMidiDevice); 885 } 886 887 @Override 888 public void handleMessage(Message msg) { 889 switch (msg.what) { 890 case MSG_UPDATE_STATE: 891 mConnected = (msg.arg1 == 1); 892 mConfigured = (msg.arg2 == 1); 893 894 updateUsbNotification(false); 895 updateAdbNotification(false); 896 if (mBootCompleted) { 897 updateUsbStateBroadcastIfNeeded(false); 898 } 899 if (UsbManager.containsFunction(mCurrentFunctions, 900 UsbManager.USB_FUNCTION_ACCESSORY)) { 901 updateCurrentAccessory(); 902 } 903 if (mBootCompleted) { 904 if (!mConnected) { 905 // restore defaults when USB is disconnected 906 setEnabledFunctions(null, !mAdbEnabled, false); 907 } 908 updateUsbFunctions(); 909 } else { 910 mPendingBootBroadcast = true; 911 } 912 break; 913 case MSG_UPDATE_PORT_STATE: 914 SomeArgs args = (SomeArgs) msg.obj; 915 boolean prevHostConnected = mHostConnected; 916 UsbPort port = (UsbPort) args.arg1; 917 UsbPortStatus status = (UsbPortStatus) args.arg2; 918 mHostConnected = status.getCurrentDataRole() == UsbPort.DATA_ROLE_HOST; 919 mSourcePower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE; 920 mSinkPower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SINK; 921 mAudioAccessoryConnected = 922 (status.getCurrentMode() == UsbPort.MODE_AUDIO_ACCESSORY); 923 mAudioAccessorySupported = port.isModeSupported(UsbPort.MODE_AUDIO_ACCESSORY); 924 // Ideally we want to see if PR_SWAP and DR_SWAP is supported. 925 // But, this should be suffice, since, all four combinations are only supported 926 // when PR_SWAP and DR_SWAP are supported. 927 mSupportsAllCombinations = status.isRoleCombinationSupported( 928 UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST) 929 && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, 930 UsbPort.DATA_ROLE_HOST) 931 && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, 932 UsbPort.DATA_ROLE_DEVICE) 933 && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, 934 UsbPort.DATA_ROLE_HOST); 935 936 args.recycle(); 937 updateUsbNotification(false); 938 if (mBootCompleted) { 939 if (mHostConnected || prevHostConnected) { 940 updateUsbStateBroadcastIfNeeded(false); 941 } 942 } else { 943 mPendingBootBroadcast = true; 944 } 945 break; 946 case MSG_UPDATE_CHARGING_STATE: 947 mUsbCharging = (msg.arg1 == 1); 948 updateUsbNotification(false); 949 break; 950 case MSG_UPDATE_HOST_STATE: 951 Iterator devices = (Iterator) msg.obj; 952 boolean connected = (msg.arg1 == 1); 953 954 if (DEBUG) { 955 Slog.i(TAG, "HOST_STATE connected:" + connected); 956 } 957 958 if ((mHideUsbNotification && connected) 959 || (!mHideUsbNotification && !connected)) { 960 break; 961 } 962 963 mHideUsbNotification = false; 964 while (devices.hasNext()) { 965 Map.Entry pair = (Map.Entry) devices.next(); 966 if (DEBUG) { 967 Slog.i(TAG, pair.getKey() + " = " + pair.getValue()); 968 } 969 UsbDevice device = (UsbDevice) pair.getValue(); 970 int configurationCount = device.getConfigurationCount() - 1; 971 while (configurationCount >= 0) { 972 UsbConfiguration config = device.getConfiguration(configurationCount); 973 configurationCount--; 974 int interfaceCount = config.getInterfaceCount() - 1; 975 while (interfaceCount >= 0) { 976 UsbInterface intrface = config.getInterface(interfaceCount); 977 interfaceCount--; 978 if (sBlackListedInterfaces.contains(intrface.getInterfaceClass())) { 979 mHideUsbNotification = true; 980 break; 981 } 982 } 983 } 984 } 985 updateUsbNotification(false); 986 break; 987 case MSG_ENABLE_ADB: 988 setAdbEnabled(msg.arg1 == 1); 989 break; 990 case MSG_SET_CURRENT_FUNCTIONS: 991 String functions = (String) msg.obj; 992 setEnabledFunctions(functions, false, msg.arg1 == 1); 993 break; 994 case MSG_UPDATE_USER_RESTRICTIONS: 995 // Restart the USB stack if USB transfer is enabled but no longer allowed. 996 final boolean forceRestart = mUsbDataUnlocked 997 && isUsbDataTransferActive() 998 && !isUsbTransferAllowed(); 999 setEnabledFunctions( 1000 mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart); 1001 break; 1002 case MSG_SYSTEM_READY: 1003 updateUsbNotification(false); 1004 updateAdbNotification(false); 1005 updateUsbFunctions(); 1006 break; 1007 case MSG_LOCALE_CHANGED: 1008 updateAdbNotification(true); 1009 updateUsbNotification(true); 1010 break; 1011 case MSG_BOOT_COMPLETED: 1012 mBootCompleted = true; 1013 if (mPendingBootBroadcast) { 1014 updateUsbStateBroadcastIfNeeded(false); 1015 mPendingBootBroadcast = false; 1016 } 1017 setEnabledFunctions(null, false, false); 1018 if (mCurrentAccessory != null) { 1019 getCurrentSettings().accessoryAttached(mCurrentAccessory); 1020 } 1021 if (mDebuggingManager != null) { 1022 mDebuggingManager.setAdbEnabled(mAdbEnabled); 1023 } 1024 break; 1025 case MSG_USER_SWITCHED: { 1026 if (mCurrentUser != msg.arg1) { 1027 // Restart the USB stack and re-apply user restrictions for MTP or PTP. 1028 if (mUsbDataUnlocked 1029 && isUsbDataTransferActive() 1030 && mCurrentUser != UserHandle.USER_NULL) { 1031 Slog.v(TAG, "Current user switched to " + msg.arg1 1032 + "; resetting USB host stack for MTP or PTP"); 1033 // avoid leaking sensitive data from previous user 1034 setEnabledFunctions(mCurrentFunctions, true, false); 1035 } 1036 mCurrentUser = msg.arg1; 1037 } 1038 break; 1039 } 1040 case MSG_ACCESSORY_MODE_ENTER_TIMEOUT: { 1041 if (DEBUG) { 1042 Slog.v(TAG, "Accessory mode enter timeout: " + mConnected); 1043 } 1044 if (!mConnected) { 1045 notifyAccessoryModeExit(); 1046 } 1047 break; 1048 } 1049 } 1050 } 1051 1052 private boolean isUsbDataTransferActive() { 1053 return UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP) 1054 || UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP); 1055 } 1056 1057 public UsbAccessory getCurrentAccessory() { 1058 return mCurrentAccessory; 1059 } 1060 1061 private void updateUsbNotification(boolean force) { 1062 if (mNotificationManager == null || !mUseUsbNotification 1063 || ("0".equals(SystemProperties.get("persist.charging.notify"))) 1064 // Dont show the notification when connected to a USB peripheral 1065 // and the link does not support PR_SWAP and DR_SWAP 1066 || (mHideUsbNotification && !mSupportsAllCombinations)) { 1067 return; 1068 } 1069 int id = 0; 1070 int titleRes = 0; 1071 Resources r = mContext.getResources(); 1072 if (mAudioAccessoryConnected && !mAudioAccessorySupported) { 1073 titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title; 1074 id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED; 1075 } else if (mConnected) { 1076 if (!mUsbDataUnlocked) { 1077 if (mSourcePower) { 1078 titleRes = com.android.internal.R.string.usb_supplying_notification_title; 1079 id = SystemMessage.NOTE_USB_SUPPLYING; 1080 } else { 1081 titleRes = com.android.internal.R.string.usb_charging_notification_title; 1082 id = SystemMessage.NOTE_USB_CHARGING; 1083 } 1084 } else if (UsbManager.containsFunction(mCurrentFunctions, 1085 UsbManager.USB_FUNCTION_MTP)) { 1086 titleRes = com.android.internal.R.string.usb_mtp_notification_title; 1087 id = SystemMessage.NOTE_USB_MTP; 1088 } else if (UsbManager.containsFunction(mCurrentFunctions, 1089 UsbManager.USB_FUNCTION_PTP)) { 1090 titleRes = com.android.internal.R.string.usb_ptp_notification_title; 1091 id = SystemMessage.NOTE_USB_PTP; 1092 } else if (UsbManager.containsFunction(mCurrentFunctions, 1093 UsbManager.USB_FUNCTION_MIDI)) { 1094 titleRes = com.android.internal.R.string.usb_midi_notification_title; 1095 id = SystemMessage.NOTE_USB_MIDI; 1096 } else if (UsbManager.containsFunction(mCurrentFunctions, 1097 UsbManager.USB_FUNCTION_ACCESSORY)) { 1098 titleRes = com.android.internal.R.string.usb_accessory_notification_title; 1099 id = SystemMessage.NOTE_USB_ACCESSORY; 1100 } else if (mSourcePower) { 1101 titleRes = com.android.internal.R.string.usb_supplying_notification_title; 1102 id = SystemMessage.NOTE_USB_SUPPLYING; 1103 } else { 1104 titleRes = com.android.internal.R.string.usb_charging_notification_title; 1105 id = SystemMessage.NOTE_USB_CHARGING; 1106 } 1107 } else if (mSourcePower) { 1108 titleRes = com.android.internal.R.string.usb_supplying_notification_title; 1109 id = SystemMessage.NOTE_USB_SUPPLYING; 1110 } else if (mHostConnected && mSinkPower && mUsbCharging) { 1111 titleRes = com.android.internal.R.string.usb_charging_notification_title; 1112 id = SystemMessage.NOTE_USB_CHARGING; 1113 } 1114 if (id != mUsbNotificationId || force) { 1115 // clear notification if title needs changing 1116 if (mUsbNotificationId != 0) { 1117 mNotificationManager.cancelAsUser(null, mUsbNotificationId, 1118 UserHandle.ALL); 1119 mUsbNotificationId = 0; 1120 } 1121 if (id != 0) { 1122 CharSequence message; 1123 CharSequence title = r.getText(titleRes); 1124 PendingIntent pi; 1125 String channel; 1126 1127 if (titleRes 1128 != com.android.internal.R.string 1129 .usb_unsupported_audio_accessory_title) { 1130 Intent intent = Intent.makeRestartActivityTask( 1131 new ComponentName("com.android.settings", 1132 "com.android.settings.deviceinfo.UsbModeChooserActivity")); 1133 pi = PendingIntent.getActivityAsUser(mContext, 0, 1134 intent, 0, null, UserHandle.CURRENT); 1135 channel = SystemNotificationChannels.USB; 1136 message = r.getText( 1137 com.android.internal.R.string.usb_notification_message); 1138 } else { 1139 final Intent intent = new Intent(); 1140 intent.setClassName("com.android.settings", 1141 "com.android.settings.HelpTrampoline"); 1142 intent.putExtra(Intent.EXTRA_TEXT, 1143 "help_url_audio_accessory_not_supported"); 1144 1145 if (mContext.getPackageManager().resolveActivity(intent, 0) != null) { 1146 pi = PendingIntent.getActivity(mContext, 0, intent, 0); 1147 } else { 1148 pi = null; 1149 } 1150 1151 channel = SystemNotificationChannels.ALERTS; 1152 message = r.getText( 1153 com.android.internal.R.string 1154 .usb_unsupported_audio_accessory_message); 1155 } 1156 1157 Notification notification = 1158 new Notification.Builder(mContext, channel) 1159 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) 1160 .setWhen(0) 1161 .setOngoing(true) 1162 .setTicker(title) 1163 .setDefaults(0) // please be quiet 1164 .setColor(mContext.getColor( 1165 com.android.internal.R.color 1166 .system_notification_accent_color)) 1167 .setContentTitle(title) 1168 .setContentText(message) 1169 .setContentIntent(pi) 1170 .setVisibility(Notification.VISIBILITY_PUBLIC) 1171 .build(); 1172 1173 mNotificationManager.notifyAsUser(null, id, notification, 1174 UserHandle.ALL); 1175 mUsbNotificationId = id; 1176 } 1177 } 1178 } 1179 1180 private void updateAdbNotification(boolean force) { 1181 if (mNotificationManager == null) return; 1182 final int id = SystemMessage.NOTE_ADB_ACTIVE; 1183 final int titleRes = com.android.internal.R.string.adb_active_notification_title; 1184 1185 if (mAdbEnabled && mConnected) { 1186 if ("0".equals(SystemProperties.get("persist.adb.notify"))) return; 1187 1188 if (force && mAdbNotificationShown) { 1189 mAdbNotificationShown = false; 1190 mNotificationManager.cancelAsUser(null, id, UserHandle.ALL); 1191 } 1192 1193 if (!mAdbNotificationShown) { 1194 Resources r = mContext.getResources(); 1195 CharSequence title = r.getText(titleRes); 1196 CharSequence message = r.getText( 1197 com.android.internal.R.string.adb_active_notification_message); 1198 1199 Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); 1200 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1201 | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1202 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, 1203 intent, 0, null, UserHandle.CURRENT); 1204 1205 Notification notification = 1206 new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER) 1207 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) 1208 .setWhen(0) 1209 .setOngoing(true) 1210 .setTicker(title) 1211 .setDefaults(0) // please be quiet 1212 .setColor(mContext.getColor( 1213 com.android.internal.R.color 1214 .system_notification_accent_color)) 1215 .setContentTitle(title) 1216 .setContentText(message) 1217 .setContentIntent(pi) 1218 .setVisibility(Notification.VISIBILITY_PUBLIC) 1219 .extend(new Notification.TvExtender() 1220 .setChannelId(ADB_NOTIFICATION_CHANNEL_ID_TV)) 1221 .build(); 1222 mAdbNotificationShown = true; 1223 mNotificationManager.notifyAsUser(null, id, notification, 1224 UserHandle.ALL); 1225 } 1226 } else if (mAdbNotificationShown) { 1227 mAdbNotificationShown = false; 1228 mNotificationManager.cancelAsUser(null, id, UserHandle.ALL); 1229 } 1230 } 1231 1232 private String getDefaultFunctions() { 1233 String func = SystemProperties.get(getPersistProp(true), 1234 UsbManager.USB_FUNCTION_NONE); 1235 // if ADB is enabled, reset functions to ADB 1236 // else enable MTP as usual. 1237 if (UsbManager.containsFunction(func, UsbManager.USB_FUNCTION_ADB)) { 1238 return UsbManager.USB_FUNCTION_ADB; 1239 } else { 1240 return UsbManager.USB_FUNCTION_MTP; 1241 } 1242 } 1243 1244 public void dump(IndentingPrintWriter pw) { 1245 pw.println("USB Device State:"); 1246 pw.println(" mCurrentFunctions: " + mCurrentFunctions); 1247 pw.println(" mCurrentOemFunctions: " + mCurrentOemFunctions); 1248 pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied); 1249 pw.println(" mConnected: " + mConnected); 1250 pw.println(" mConfigured: " + mConfigured); 1251 pw.println(" mUsbDataUnlocked: " + mUsbDataUnlocked); 1252 pw.println(" mCurrentAccessory: " + mCurrentAccessory); 1253 pw.println(" mHostConnected: " + mHostConnected); 1254 pw.println(" mSourcePower: " + mSourcePower); 1255 pw.println(" mSinkPower: " + mSinkPower); 1256 pw.println(" mUsbCharging: " + mUsbCharging); 1257 pw.println(" mHideUsbNotification: " + mHideUsbNotification); 1258 pw.println(" mAudioAccessoryConnected: " + mAudioAccessoryConnected); 1259 1260 try { 1261 pw.println(" Kernel state: " 1262 + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim()); 1263 pw.println(" Kernel function list: " 1264 + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim()); 1265 } catch (IOException e) { 1266 pw.println("IOException: " + e); 1267 } 1268 } 1269 } 1270 1271 /* returns the currently attached USB accessory */ 1272 public UsbAccessory getCurrentAccessory() { 1273 return mHandler.getCurrentAccessory(); 1274 } 1275 1276 /* opens the currently attached USB accessory */ 1277 public ParcelFileDescriptor openAccessory(UsbAccessory accessory, 1278 UsbUserSettingsManager settings) { 1279 UsbAccessory currentAccessory = mHandler.getCurrentAccessory(); 1280 if (currentAccessory == null) { 1281 throw new IllegalArgumentException("no accessory attached"); 1282 } 1283 if (!currentAccessory.equals(accessory)) { 1284 String error = accessory.toString() 1285 + " does not match current accessory " 1286 + currentAccessory; 1287 throw new IllegalArgumentException(error); 1288 } 1289 settings.checkPermission(accessory); 1290 return nativeOpenAccessory(); 1291 } 1292 1293 public boolean isFunctionEnabled(String function) { 1294 return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function); 1295 } 1296 1297 public void setCurrentFunctions(String functions, boolean usbDataUnlocked) { 1298 if (DEBUG) { 1299 Slog.d(TAG, "setCurrentFunctions(" + functions + ", " + 1300 usbDataUnlocked + ")"); 1301 } 1302 mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked); 1303 } 1304 1305 private void readOemUsbOverrideConfig() { 1306 String[] configList = mContext.getResources().getStringArray( 1307 com.android.internal.R.array.config_oemUsbModeOverride); 1308 1309 if (configList != null) { 1310 for (String config : configList) { 1311 String[] items = config.split(":"); 1312 if (items.length == 3 || items.length == 4) { 1313 if (mOemModeMap == null) { 1314 mOemModeMap = new HashMap<String, HashMap<String, 1315 Pair<String, String>>>(); 1316 } 1317 HashMap<String, Pair<String, String>> overrideMap 1318 = mOemModeMap.get(items[0]); 1319 if (overrideMap == null) { 1320 overrideMap = new HashMap<String, 1321 Pair<String, String>>(); 1322 mOemModeMap.put(items[0], overrideMap); 1323 } 1324 1325 // Favoring the first combination if duplicate exists 1326 if (!overrideMap.containsKey(items[1])) { 1327 if (items.length == 3) { 1328 overrideMap.put(items[1], 1329 new Pair<String, String>(items[2], "")); 1330 } else { 1331 overrideMap.put(items[1], 1332 new Pair<String, String>(items[2], items[3])); 1333 } 1334 } 1335 } 1336 } 1337 } 1338 } 1339 1340 private String applyOemOverrideFunction(String usbFunctions) { 1341 if ((usbFunctions == null) || (mOemModeMap == null)) { 1342 return usbFunctions; 1343 } 1344 1345 String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown"); 1346 Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode); 1347 1348 Map<String, Pair<String, String>> overridesMap = 1349 mOemModeMap.get(bootMode); 1350 // Check to ensure that the oem is not overriding in the normal 1351 // boot mode 1352 if (overridesMap != null && !(bootMode.equals(NORMAL_BOOT) || 1353 bootMode.equals("unknown"))) { 1354 Pair<String, String> overrideFunctions = 1355 overridesMap.get(usbFunctions); 1356 if (overrideFunctions != null) { 1357 Slog.d(TAG, "OEM USB override: " + usbFunctions 1358 + " ==> " + overrideFunctions.first 1359 + " persist across reboot " 1360 + overrideFunctions.second); 1361 if (!overrideFunctions.second.equals("")) { 1362 String newFunction; 1363 if (mAdbEnabled) { 1364 newFunction = UsbManager.addFunction(overrideFunctions.second, 1365 UsbManager.USB_FUNCTION_ADB); 1366 } else { 1367 newFunction = overrideFunctions.second; 1368 } 1369 Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: " 1370 + UsbDeviceManager.getPersistProp(false)); 1371 SystemProperties.set(UsbDeviceManager.getPersistProp(false), 1372 newFunction); 1373 } 1374 return overrideFunctions.first; 1375 } else if (mAdbEnabled) { 1376 String newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE, 1377 UsbManager.USB_FUNCTION_ADB); 1378 SystemProperties.set(UsbDeviceManager.getPersistProp(false), 1379 newFunction); 1380 } else { 1381 SystemProperties.set(UsbDeviceManager.getPersistProp(false), 1382 UsbManager.USB_FUNCTION_NONE); 1383 } 1384 } 1385 // return passed in functions as is. 1386 return usbFunctions; 1387 } 1388 1389 public static String getPersistProp(boolean functions) { 1390 String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown"); 1391 String persistProp = USB_PERSISTENT_CONFIG_PROPERTY; 1392 if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) { 1393 if (functions == true) { 1394 persistProp = "persist.sys.usb." + bootMode + ".func"; 1395 } else { 1396 persistProp = "persist.sys.usb." + bootMode + ".config"; 1397 } 1398 } 1399 1400 return persistProp; 1401 } 1402 1403 1404 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 1405 if (mDebuggingManager != null) { 1406 mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey); 1407 } 1408 } 1409 1410 public void denyUsbDebugging() { 1411 if (mDebuggingManager != null) { 1412 mDebuggingManager.denyUsbDebugging(); 1413 } 1414 } 1415 1416 public void clearUsbDebuggingKeys() { 1417 if (mDebuggingManager != null) { 1418 mDebuggingManager.clearUsbDebuggingKeys(); 1419 } else { 1420 throw new RuntimeException("Cannot clear Usb Debugging keys, " 1421 + "UsbDebuggingManager not enabled"); 1422 } 1423 } 1424 1425 public void dump(IndentingPrintWriter pw) { 1426 if (mHandler != null) { 1427 mHandler.dump(pw); 1428 } 1429 if (mDebuggingManager != null) { 1430 mDebuggingManager.dump(pw); 1431 } 1432 } 1433 1434 private native String[] nativeGetAccessoryStrings(); 1435 1436 private native ParcelFileDescriptor nativeOpenAccessory(); 1437 1438 private native boolean nativeIsStartRequested(); 1439 1440 private native int nativeGetAudioMode(); 1441} 1442