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