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 17 package com.android.server.usb; 18 19 import android.app.Notification; 20 import android.app.NotificationManager; 21 import android.app.PendingIntent; 22 import android.content.ComponentName; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageManager; 27 import android.content.res.Resources; 28 import android.database.ContentObserver; 29 import android.hardware.usb.UsbAccessory; 30 import android.hardware.usb.UsbManager; 31 import android.os.FileUtils; 32 import android.os.Handler; 33 import android.os.Looper; 34 import android.os.Message; 35 import android.os.ParcelFileDescriptor; 36 import android.os.SystemClock; 37 import android.os.SystemProperties; 38 import android.os.UEventObserver; 39 import android.os.UserHandle; 40 import android.os.UserManager; 41 import android.os.storage.StorageManager; 42 import android.os.storage.StorageVolume; 43 import android.provider.Settings; 44 import android.util.Pair; 45 import android.util.Slog; 46 47 import com.android.internal.annotations.GuardedBy; 48 import com.android.internal.util.IndentingPrintWriter; 49 import com.android.server.FgThread; 50 51 import java.io.File; 52 import java.io.FileNotFoundException; 53 import java.io.IOException; 54 import java.util.HashMap; 55 import java.util.LinkedList; 56 import java.util.List; 57 import java.util.Locale; 58 import java.util.Map; 59 import java.util.Scanner; 60 61 /** 62 * UsbDeviceManager manages USB state in device mode. 63 */ 64 public class UsbDeviceManager { 65 66 private static final String TAG = "UsbDeviceManager"; 67 private static final boolean DEBUG = false; 68 69 /** 70 * The persistent property which stores whether adb is enabled or not. 71 * May also contain vendor-specific default functions for testing purposes. 72 */ 73 private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config"; 74 75 /** 76 * The non-persistent property which stores the current USB settings. 77 */ 78 private static final String USB_CONFIG_PROPERTY = "sys.usb.config"; 79 80 /** 81 * The non-persistent property which stores the current USB actual state. 82 */ 83 private static final String USB_STATE_PROPERTY = "sys.usb.state"; 84 85 private static final String USB_STATE_MATCH = 86 "DEVPATH=/devices/virtual/android_usb/android0"; 87 private static final String ACCESSORY_START_MATCH = 88 "DEVPATH=/devices/virtual/misc/usb_accessory"; 89 private static final String FUNCTIONS_PATH = 90 "/sys/class/android_usb/android0/functions"; 91 private static final String STATE_PATH = 92 "/sys/class/android_usb/android0/state"; 93 private static final String RNDIS_ETH_ADDR_PATH = 94 "/sys/class/android_usb/android0/f_rndis/ethaddr"; 95 private static final String AUDIO_SOURCE_PCM_PATH = 96 "/sys/class/android_usb/android0/f_audio_source/pcm"; 97 private static final String MIDI_ALSA_PATH = 98 "/sys/class/android_usb/android0/f_midi/alsa"; 99 100 private static final int MSG_UPDATE_STATE = 0; 101 private static final int MSG_ENABLE_ADB = 1; 102 private static final int MSG_SET_CURRENT_FUNCTIONS = 2; 103 private static final int MSG_SYSTEM_READY = 3; 104 private static final int MSG_BOOT_COMPLETED = 4; 105 private static final int MSG_USER_SWITCHED = 5; 106 private static final int MSG_SET_USB_DATA_UNLOCKED = 6; 107 private static final int MSG_UPDATE_USER_RESTRICTIONS = 7; 108 109 private static final int AUDIO_MODE_SOURCE = 1; 110 111 // Delay for debouncing USB disconnects. 112 // We often get rapid connect/disconnect events when enabling USB functions, 113 // which need debouncing. 114 private static final int UPDATE_DELAY = 1000; 115 116 // Time we received a request to enter USB accessory mode 117 private long mAccessoryModeRequestTime = 0; 118 119 // Timeout for entering USB request mode. 120 // Request is cancelled if host does not configure device within 10 seconds. 121 private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000; 122 123 private static final String BOOT_MODE_PROPERTY = "ro.bootmode"; 124 125 private UsbHandler mHandler; 126 private boolean mBootCompleted; 127 128 private final Object mLock = new Object(); 129 130 private final Context mContext; 131 private final ContentResolver mContentResolver; 132 @GuardedBy("mLock") 133 private UsbSettingsManager mCurrentSettings; 134 private NotificationManager mNotificationManager; 135 private final boolean mHasUsbAccessory; 136 private boolean mUseUsbNotification; 137 private boolean mAdbEnabled; 138 private boolean mAudioSourceEnabled; 139 private boolean mMidiEnabled; 140 private int mMidiCard; 141 private int mMidiDevice; 142 private Map<String, List<Pair<String, String>>> mOemModeMap; 143 private String[] mAccessoryStrings; 144 private UsbDebuggingManager mDebuggingManager; 145 private final UsbAlsaManager mUsbAlsaManager; 146 147 private class AdbSettingsObserver extends ContentObserver { 148 public AdbSettingsObserver() { 149 super(null); 150 } 151 @Override 152 public void onChange(boolean selfChange) { 153 boolean enable = (Settings.Global.getInt(mContentResolver, 154 Settings.Global.ADB_ENABLED, 0) > 0); 155 mHandler.sendMessage(MSG_ENABLE_ADB, enable); 156 } 157 } 158 159 /* 160 * Listens for uevent messages from the kernel to monitor the USB state 161 */ 162 private final UEventObserver mUEventObserver = new UEventObserver() { 163 @Override 164 public void onUEvent(UEventObserver.UEvent event) { 165 if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString()); 166 167 String state = event.get("USB_STATE"); 168 String accessory = event.get("ACCESSORY"); 169 if (state != null) { 170 mHandler.updateState(state); 171 } else if ("START".equals(accessory)) { 172 if (DEBUG) Slog.d(TAG, "got accessory start"); 173 startAccessoryMode(); 174 } 175 } 176 }; 177 178 public UsbDeviceManager(Context context, UsbAlsaManager alsaManager) { 179 mContext = context; 180 mUsbAlsaManager = alsaManager; 181 mContentResolver = context.getContentResolver(); 182 PackageManager pm = mContext.getPackageManager(); 183 mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); 184 initRndisAddress(); 185 186 readOemUsbOverrideConfig(); 187 188 mHandler = new UsbHandler(FgThread.get().getLooper()); 189 190 if (nativeIsStartRequested()) { 191 if (DEBUG) Slog.d(TAG, "accessory attached at boot"); 192 startAccessoryMode(); 193 } 194 195 boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false); 196 boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt")); 197 if (secureAdbEnabled && !dataEncrypted) { 198 mDebuggingManager = new UsbDebuggingManager(context); 199 } 200 } 201 202 private UsbSettingsManager getCurrentSettings() { 203 synchronized (mLock) { 204 return mCurrentSettings; 205 } 206 } 207 208 public void systemReady() { 209 if (DEBUG) Slog.d(TAG, "systemReady"); 210 211 mNotificationManager = (NotificationManager) 212 mContext.getSystemService(Context.NOTIFICATION_SERVICE); 213 214 // We do not show the USB notification if the primary volume supports mass storage. 215 // The legacy mass storage UI will be used instead. 216 boolean massStorageSupported = false; 217 final StorageManager storageManager = StorageManager.from(mContext); 218 final StorageVolume primary = storageManager.getPrimaryVolume(); 219 massStorageSupported = primary != null && primary.allowMassStorage(); 220 mUseUsbNotification = !massStorageSupported; 221 222 // make sure the ADB_ENABLED setting value matches the current state 223 try { 224 Settings.Global.putInt(mContentResolver, 225 Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0); 226 } catch (SecurityException e) { 227 // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed. 228 Slog.d(TAG, "ADB_ENABLED is restricted."); 229 } 230 mHandler.sendEmptyMessage(MSG_SYSTEM_READY); 231 } 232 233 public void bootCompleted() { 234 if (DEBUG) Slog.d(TAG, "boot completed"); 235 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); 236 } 237 238 public void setCurrentUser(int userId, UsbSettingsManager settings) { 239 synchronized (mLock) { 240 mCurrentSettings = settings; 241 mHandler.obtainMessage(MSG_USER_SWITCHED, userId, 0).sendToTarget(); 242 } 243 } 244 245 public void updateUserRestrictions() { 246 mHandler.sendEmptyMessage(MSG_UPDATE_USER_RESTRICTIONS); 247 } 248 249 private void startAccessoryMode() { 250 if (!mHasUsbAccessory) return; 251 252 mAccessoryStrings = nativeGetAccessoryStrings(); 253 boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE); 254 // don't start accessory mode if our mandatory strings have not been set 255 boolean enableAccessory = (mAccessoryStrings != null && 256 mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null && 257 mAccessoryStrings[UsbAccessory.MODEL_STRING] != null); 258 String functions = null; 259 260 if (enableAccessory && enableAudio) { 261 functions = UsbManager.USB_FUNCTION_ACCESSORY + "," 262 + UsbManager.USB_FUNCTION_AUDIO_SOURCE; 263 } else if (enableAccessory) { 264 functions = UsbManager.USB_FUNCTION_ACCESSORY; 265 } else if (enableAudio) { 266 functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE; 267 } 268 269 if (functions != null) { 270 mAccessoryModeRequestTime = SystemClock.elapsedRealtime(); 271 setCurrentFunctions(functions); 272 } 273 } 274 275 private static void initRndisAddress() { 276 // configure RNDIS ethernet address based on our serial number using the same algorithm 277 // we had been previously using in kernel board files 278 final int ETH_ALEN = 6; 279 int address[] = new int[ETH_ALEN]; 280 // first byte is 0x02 to signify a locally administered address 281 address[0] = 0x02; 282 283 String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF"); 284 int serialLength = serial.length(); 285 // XOR the USB serial across the remaining 5 bytes 286 for (int i = 0; i < serialLength; i++) { 287 address[i % (ETH_ALEN - 1) + 1] ^= (int)serial.charAt(i); 288 } 289 String addrString = String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", 290 address[0], address[1], address[2], address[3], address[4], address[5]); 291 try { 292 FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString); 293 } catch (IOException e) { 294 Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH); 295 } 296 } 297 298 private final class UsbHandler extends Handler { 299 300 // current USB state 301 private boolean mConnected; 302 private boolean mConfigured; 303 private boolean mUsbDataUnlocked; 304 private String mCurrentFunctions; 305 private boolean mCurrentFunctionsApplied; 306 private UsbAccessory mCurrentAccessory; 307 private int mUsbNotificationId; 308 private boolean mAdbNotificationShown; 309 private int mCurrentUser = UserHandle.USER_NULL; 310 311 public UsbHandler(Looper looper) { 312 super(looper); 313 try { 314 // Restore default functions. 315 mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY, 316 UsbManager.USB_FUNCTION_NONE); 317 if (UsbManager.USB_FUNCTION_NONE.equals(mCurrentFunctions)) { 318 mCurrentFunctions = UsbManager.USB_FUNCTION_MTP; 319 } 320 mCurrentFunctionsApplied = mCurrentFunctions.equals( 321 SystemProperties.get(USB_STATE_PROPERTY)); 322 mAdbEnabled = UsbManager.containsFunction(getDefaultFunctions(), 323 UsbManager.USB_FUNCTION_ADB); 324 setEnabledFunctions(null, false); 325 326 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim(); 327 updateState(state); 328 329 // register observer to listen for settings changes 330 mContentResolver.registerContentObserver( 331 Settings.Global.getUriFor(Settings.Global.ADB_ENABLED), 332 false, new AdbSettingsObserver()); 333 334 // Watch for USB configuration changes 335 mUEventObserver.startObserving(USB_STATE_MATCH); 336 mUEventObserver.startObserving(ACCESSORY_START_MATCH); 337 } catch (Exception e) { 338 Slog.e(TAG, "Error initializing UsbHandler", e); 339 } 340 } 341 342 public void sendMessage(int what, boolean arg) { 343 removeMessages(what); 344 Message m = Message.obtain(this, what); 345 m.arg1 = (arg ? 1 : 0); 346 sendMessage(m); 347 } 348 349 public void sendMessage(int what, Object arg) { 350 removeMessages(what); 351 Message m = Message.obtain(this, what); 352 m.obj = arg; 353 sendMessage(m); 354 } 355 356 public void updateState(String state) { 357 int connected, configured; 358 359 if ("DISCONNECTED".equals(state)) { 360 connected = 0; 361 configured = 0; 362 } else if ("CONNECTED".equals(state)) { 363 connected = 1; 364 configured = 0; 365 } else if ("CONFIGURED".equals(state)) { 366 connected = 1; 367 configured = 1; 368 } else { 369 Slog.e(TAG, "unknown state " + state); 370 return; 371 } 372 removeMessages(MSG_UPDATE_STATE); 373 Message msg = Message.obtain(this, MSG_UPDATE_STATE); 374 msg.arg1 = connected; 375 msg.arg2 = configured; 376 // debounce disconnects to avoid problems bringing up USB tethering 377 sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0); 378 } 379 380 private boolean waitForState(String state) { 381 // wait for the transition to complete. 382 // give up after 1 second. 383 String value = null; 384 for (int i = 0; i < 20; i++) { 385 // State transition is done when sys.usb.state is set to the new configuration 386 value = SystemProperties.get(USB_STATE_PROPERTY); 387 if (state.equals(value)) return true; 388 SystemClock.sleep(50); 389 } 390 Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value); 391 return false; 392 } 393 394 private boolean setUsbConfig(String config) { 395 if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")"); 396 // set the new configuration 397 String oldConfig = SystemProperties.get(USB_CONFIG_PROPERTY); 398 if (!config.equals(oldConfig)) { 399 SystemProperties.set(USB_CONFIG_PROPERTY, config); 400 } 401 return waitForState(config); 402 } 403 404 private void setUsbDataUnlocked(boolean enable) { 405 if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked: " + enable); 406 mUsbDataUnlocked = enable; 407 updateUsbNotification(); 408 updateUsbStateBroadcast(); 409 setEnabledFunctions(mCurrentFunctions, true); 410 } 411 412 private void setAdbEnabled(boolean enable) { 413 if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable); 414 if (enable != mAdbEnabled) { 415 mAdbEnabled = enable; 416 417 // Due to the persist.sys.usb.config property trigger, changing adb state requires 418 // persisting default function 419 String oldFunctions = getDefaultFunctions(); 420 String newFunctions = applyAdbFunction(oldFunctions); 421 if (!oldFunctions.equals(newFunctions)) { 422 SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunctions); 423 } 424 425 // After persisting them use the lock-down aware function set 426 setEnabledFunctions(mCurrentFunctions, false); 427 updateAdbNotification(); 428 } 429 430 if (mDebuggingManager != null) { 431 mDebuggingManager.setAdbEnabled(mAdbEnabled); 432 } 433 } 434 435 /** 436 * Evaluates USB function policies and applies the change accordingly. 437 */ 438 private void setEnabledFunctions(String functions, boolean forceRestart) { 439 if (DEBUG) Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", " 440 + "forceRestart=" + forceRestart); 441 442 // Try to set the enabled functions. 443 final String oldFunctions = mCurrentFunctions; 444 final boolean oldFunctionsApplied = mCurrentFunctionsApplied; 445 if (trySetEnabledFunctions(functions, forceRestart)) { 446 return; 447 } 448 449 // Didn't work. Try to revert changes. 450 // We always reapply the policy in case certain constraints changed such as 451 // user restrictions independently of any other new functions we were 452 // trying to activate. 453 if (oldFunctionsApplied && !oldFunctions.equals(functions)) { 454 Slog.e(TAG, "Failsafe 1: Restoring previous USB functions."); 455 if (trySetEnabledFunctions(oldFunctions, false)) { 456 return; 457 } 458 } 459 460 // Still didn't work. Try to restore the default functions. 461 Slog.e(TAG, "Failsafe 2: Restoring default USB functions."); 462 if (trySetEnabledFunctions(null, false)) { 463 return; 464 } 465 466 // Now we're desperate. Ignore the default functions. 467 // Try to get ADB working if enabled. 468 Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled)."); 469 if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) { 470 return; 471 } 472 473 // Ouch. 474 Slog.e(TAG, "Unable to set any USB functions!"); 475 } 476 477 private boolean trySetEnabledFunctions(String functions, boolean forceRestart) { 478 if (functions == null) { 479 functions = getDefaultFunctions(); 480 } 481 functions = applyAdbFunction(functions); 482 functions = applyOemOverrideFunction(functions); 483 484 if (!mCurrentFunctions.equals(functions) || !mCurrentFunctionsApplied 485 || forceRestart) { 486 Slog.i(TAG, "Setting USB config to " + functions); 487 mCurrentFunctions = functions; 488 mCurrentFunctionsApplied = false; 489 490 // Kick the USB stack to close existing connections. 491 setUsbConfig(UsbManager.USB_FUNCTION_NONE); 492 493 // Set the new USB configuration. 494 if (!setUsbConfig(functions)) { 495 Slog.e(TAG, "Failed to switch USB config to " + functions); 496 return false; 497 } 498 499 mCurrentFunctionsApplied = true; 500 } 501 return true; 502 } 503 504 private String applyAdbFunction(String functions) { 505 if (mAdbEnabled) { 506 functions = UsbManager.addFunction(functions, UsbManager.USB_FUNCTION_ADB); 507 } else { 508 functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_ADB); 509 } 510 return functions; 511 } 512 513 private boolean isUsbTransferAllowed() { 514 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 515 return !userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER); 516 } 517 518 private void updateCurrentAccessory() { 519 // We are entering accessory mode if we have received a request from the host 520 // and the request has not timed out yet. 521 boolean enteringAccessoryMode = 522 mAccessoryModeRequestTime > 0 && 523 SystemClock.elapsedRealtime() < 524 mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT; 525 526 if (mConfigured && enteringAccessoryMode) { 527 // successfully entered accessory mode 528 529 if (mAccessoryStrings != null) { 530 mCurrentAccessory = new UsbAccessory(mAccessoryStrings); 531 Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory); 532 // defer accessoryAttached if system is not ready 533 if (mBootCompleted) { 534 getCurrentSettings().accessoryAttached(mCurrentAccessory); 535 } // else handle in boot completed 536 } else { 537 Slog.e(TAG, "nativeGetAccessoryStrings failed"); 538 } 539 } else if (!enteringAccessoryMode) { 540 // make sure accessory mode is off 541 // and restore default functions 542 Slog.d(TAG, "exited USB accessory mode"); 543 setEnabledFunctions(null, false); 544 545 if (mCurrentAccessory != null) { 546 if (mBootCompleted) { 547 getCurrentSettings().accessoryDetached(mCurrentAccessory); 548 } 549 mCurrentAccessory = null; 550 mAccessoryStrings = null; 551 } 552 } 553 } 554 555 private void updateUsbStateBroadcast() { 556 // send a sticky broadcast containing current USB state 557 Intent intent = new Intent(UsbManager.ACTION_USB_STATE); 558 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 559 | Intent.FLAG_RECEIVER_FOREGROUND); 560 intent.putExtra(UsbManager.USB_CONNECTED, mConnected); 561 intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured); 562 intent.putExtra(UsbManager.USB_DATA_UNLOCKED, isUsbTransferAllowed() && mUsbDataUnlocked); 563 564 if (mCurrentFunctions != null) { 565 String[] functions = mCurrentFunctions.split(","); 566 for (int i = 0; i < functions.length; i++) { 567 intent.putExtra(functions[i], true); 568 } 569 } 570 571 if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " connected: " + mConnected 572 + " configured: " + mConfigured); 573 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 574 } 575 576 private void updateUsbFunctions() { 577 updateAudioSourceFunction(); 578 updateMidiFunction(); 579 } 580 581 private void updateAudioSourceFunction() { 582 boolean enabled = UsbManager.containsFunction(mCurrentFunctions, 583 UsbManager.USB_FUNCTION_AUDIO_SOURCE); 584 if (enabled != mAudioSourceEnabled) { 585 int card = -1; 586 int device = -1; 587 588 if (enabled) { 589 Scanner scanner = null; 590 try { 591 scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH)); 592 card = scanner.nextInt(); 593 device = scanner.nextInt(); 594 } catch (FileNotFoundException e) { 595 Slog.e(TAG, "could not open audio source PCM file", e); 596 } finally { 597 if (scanner != null) { 598 scanner.close(); 599 } 600 } 601 } 602 mUsbAlsaManager.setAccessoryAudioState(enabled, card, device); 603 mAudioSourceEnabled = enabled; 604 } 605 } 606 607 private void updateMidiFunction() { 608 boolean enabled = UsbManager.containsFunction(mCurrentFunctions, 609 UsbManager.USB_FUNCTION_MIDI); 610 if (enabled != mMidiEnabled) { 611 if (enabled) { 612 Scanner scanner = null; 613 try { 614 scanner = new Scanner(new File(MIDI_ALSA_PATH)); 615 mMidiCard = scanner.nextInt(); 616 mMidiDevice = scanner.nextInt(); 617 } catch (FileNotFoundException e) { 618 Slog.e(TAG, "could not open MIDI PCM file", e); 619 enabled = false; 620 } finally { 621 if (scanner != null) { 622 scanner.close(); 623 } 624 } 625 } 626 mMidiEnabled = enabled; 627 } 628 mUsbAlsaManager.setPeripheralMidiState(mMidiEnabled && mConfigured, mMidiCard, mMidiDevice); 629 } 630 631 @Override 632 public void handleMessage(Message msg) { 633 switch (msg.what) { 634 case MSG_UPDATE_STATE: 635 mConnected = (msg.arg1 == 1); 636 mConfigured = (msg.arg2 == 1); 637 if (!mConnected) { 638 // When a disconnect occurs, relock access to sensitive user data 639 mUsbDataUnlocked = false; 640 } 641 updateUsbNotification(); 642 updateAdbNotification(); 643 if (UsbManager.containsFunction(mCurrentFunctions, 644 UsbManager.USB_FUNCTION_ACCESSORY)) { 645 updateCurrentAccessory(); 646 } else if (!mConnected) { 647 // restore defaults when USB is disconnected 648 setEnabledFunctions(null, false); 649 } 650 if (mBootCompleted) { 651 updateUsbStateBroadcast(); 652 updateUsbFunctions(); 653 } 654 break; 655 case MSG_ENABLE_ADB: 656 setAdbEnabled(msg.arg1 == 1); 657 break; 658 case MSG_SET_CURRENT_FUNCTIONS: 659 String functions = (String)msg.obj; 660 setEnabledFunctions(functions, false); 661 break; 662 case MSG_UPDATE_USER_RESTRICTIONS: 663 setEnabledFunctions(mCurrentFunctions, false); 664 break; 665 case MSG_SET_USB_DATA_UNLOCKED: 666 setUsbDataUnlocked(msg.arg1 == 1); 667 break; 668 case MSG_SYSTEM_READY: 669 updateUsbNotification(); 670 updateAdbNotification(); 671 updateUsbStateBroadcast(); 672 updateUsbFunctions(); 673 break; 674 case MSG_BOOT_COMPLETED: 675 mBootCompleted = true; 676 if (mCurrentAccessory != null) { 677 getCurrentSettings().accessoryAttached(mCurrentAccessory); 678 } 679 if (mDebuggingManager != null) { 680 mDebuggingManager.setAdbEnabled(mAdbEnabled); 681 } 682 break; 683 case MSG_USER_SWITCHED: { 684 if (mCurrentUser != msg.arg1) { 685 // Restart the USB stack and re-apply user restrictions for MTP or PTP. 686 final boolean active = UsbManager.containsFunction(mCurrentFunctions, 687 UsbManager.USB_FUNCTION_MTP) 688 || UsbManager.containsFunction(mCurrentFunctions, 689 UsbManager.USB_FUNCTION_PTP); 690 if (active && mCurrentUser != UserHandle.USER_NULL) { 691 Slog.v(TAG, "Current user switched to " + mCurrentUser 692 + "; resetting USB host stack for MTP or PTP"); 693 setEnabledFunctions(mCurrentFunctions, true); 694 } 695 mCurrentUser = msg.arg1; 696 } 697 break; 698 } 699 } 700 } 701 702 public UsbAccessory getCurrentAccessory() { 703 return mCurrentAccessory; 704 } 705 706 private void updateUsbNotification() { 707 if (mNotificationManager == null || !mUseUsbNotification) return; 708 int id = 0; 709 Resources r = mContext.getResources(); 710 if (mConnected) { 711 if (!mUsbDataUnlocked) { 712 id = com.android.internal.R.string.usb_charging_notification_title; 713 } else if (UsbManager.containsFunction(mCurrentFunctions, 714 UsbManager.USB_FUNCTION_MTP)) { 715 id = com.android.internal.R.string.usb_mtp_notification_title; 716 } else if (UsbManager.containsFunction(mCurrentFunctions, 717 UsbManager.USB_FUNCTION_PTP)) { 718 id = com.android.internal.R.string.usb_ptp_notification_title; 719 } else if (UsbManager.containsFunction(mCurrentFunctions, 720 UsbManager.USB_FUNCTION_MIDI)) { 721 id = com.android.internal.R.string.usb_midi_notification_title; 722 } else if (UsbManager.containsFunction(mCurrentFunctions, 723 UsbManager.USB_FUNCTION_ACCESSORY)) { 724 id = com.android.internal.R.string.usb_accessory_notification_title; 725 } else { 726 id = com.android.internal.R.string.usb_charging_notification_title; 727 } 728 } 729 if (id != mUsbNotificationId) { 730 // clear notification if title needs changing 731 if (mUsbNotificationId != 0) { 732 mNotificationManager.cancelAsUser(null, mUsbNotificationId, 733 UserHandle.ALL); 734 mUsbNotificationId = 0; 735 } 736 if (id != 0) { 737 CharSequence message = r.getText( 738 com.android.internal.R.string.usb_notification_message); 739 CharSequence title = r.getText(id); 740 741 Intent intent = Intent.makeRestartActivityTask( 742 new ComponentName("com.android.settings", 743 "com.android.settings.deviceinfo.UsbModeChooserActivity")); 744 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, 745 intent, 0, null, UserHandle.CURRENT); 746 747 Notification notification = new Notification.Builder(mContext) 748 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) 749 .setWhen(0) 750 .setOngoing(true) 751 .setTicker(title) 752 .setDefaults(0) // please be quiet 753 .setPriority(Notification.PRIORITY_MIN) 754 .setColor(mContext.getColor( 755 com.android.internal.R.color.system_notification_accent_color)) 756 .setContentTitle(title) 757 .setContentText(message) 758 .setContentIntent(pi) 759 .setVisibility(Notification.VISIBILITY_PUBLIC) 760 .build(); 761 mNotificationManager.notifyAsUser(null, id, notification, 762 UserHandle.ALL); 763 mUsbNotificationId = id; 764 } 765 } 766 } 767 768 private void updateAdbNotification() { 769 if (mNotificationManager == null) return; 770 final int id = com.android.internal.R.string.adb_active_notification_title; 771 if (mAdbEnabled && mConnected) { 772 if ("0".equals(SystemProperties.get("persist.adb.notify"))) return; 773 774 if (!mAdbNotificationShown) { 775 Resources r = mContext.getResources(); 776 CharSequence title = r.getText(id); 777 CharSequence message = r.getText( 778 com.android.internal.R.string.adb_active_notification_message); 779 780 Intent intent = Intent.makeRestartActivityTask( 781 new ComponentName("com.android.settings", 782 "com.android.settings.DevelopmentSettings")); 783 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, 784 intent, 0, null, UserHandle.CURRENT); 785 786 Notification notification = new Notification.Builder(mContext) 787 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) 788 .setWhen(0) 789 .setOngoing(true) 790 .setTicker(title) 791 .setDefaults(0) // please be quiet 792 .setPriority(Notification.PRIORITY_LOW) 793 .setColor(mContext.getColor( 794 com.android.internal.R.color.system_notification_accent_color)) 795 .setContentTitle(title) 796 .setContentText(message) 797 .setContentIntent(pi) 798 .setVisibility(Notification.VISIBILITY_PUBLIC) 799 .build(); 800 mAdbNotificationShown = true; 801 mNotificationManager.notifyAsUser(null, id, notification, 802 UserHandle.ALL); 803 } 804 } else if (mAdbNotificationShown) { 805 mAdbNotificationShown = false; 806 mNotificationManager.cancelAsUser(null, id, UserHandle.ALL); 807 } 808 } 809 810 private String getDefaultFunctions() { 811 String func = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, 812 UsbManager.USB_FUNCTION_NONE); 813 if (UsbManager.USB_FUNCTION_NONE.equals(func)) { 814 func = UsbManager.USB_FUNCTION_MTP; 815 } 816 return func; 817 } 818 819 public void dump(IndentingPrintWriter pw) { 820 pw.println("USB Device State:"); 821 pw.println(" mCurrentFunctions: " + mCurrentFunctions); 822 pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied); 823 pw.println(" mConnected: " + mConnected); 824 pw.println(" mConfigured: " + mConfigured); 825 pw.println(" mUsbDataUnlocked: " + mUsbDataUnlocked); 826 pw.println(" mCurrentAccessory: " + mCurrentAccessory); 827 try { 828 pw.println(" Kernel state: " 829 + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim()); 830 pw.println(" Kernel function list: " 831 + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim()); 832 } catch (IOException e) { 833 pw.println("IOException: " + e); 834 } 835 } 836 } 837 838 /* returns the currently attached USB accessory */ 839 public UsbAccessory getCurrentAccessory() { 840 return mHandler.getCurrentAccessory(); 841 } 842 843 /* opens the currently attached USB accessory */ 844 public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 845 UsbAccessory currentAccessory = mHandler.getCurrentAccessory(); 846 if (currentAccessory == null) { 847 throw new IllegalArgumentException("no accessory attached"); 848 } 849 if (!currentAccessory.equals(accessory)) { 850 String error = accessory.toString() 851 + " does not match current accessory " 852 + currentAccessory; 853 throw new IllegalArgumentException(error); 854 } 855 getCurrentSettings().checkPermission(accessory); 856 return nativeOpenAccessory(); 857 } 858 859 public boolean isFunctionEnabled(String function) { 860 return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function); 861 } 862 863 public void setCurrentFunctions(String functions) { 864 if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ")"); 865 mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions); 866 } 867 868 public void setUsbDataUnlocked(boolean unlocked) { 869 if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked(" + unlocked + ")"); 870 mHandler.sendMessage(MSG_SET_USB_DATA_UNLOCKED, unlocked); 871 } 872 873 private void readOemUsbOverrideConfig() { 874 String[] configList = mContext.getResources().getStringArray( 875 com.android.internal.R.array.config_oemUsbModeOverride); 876 877 if (configList != null) { 878 for (String config: configList) { 879 String[] items = config.split(":"); 880 if (items.length == 3) { 881 if (mOemModeMap == null) { 882 mOemModeMap = new HashMap<String, List<Pair<String, String>>>(); 883 } 884 List<Pair<String, String>> overrideList = mOemModeMap.get(items[0]); 885 if (overrideList == null) { 886 overrideList = new LinkedList<Pair<String, String>>(); 887 mOemModeMap.put(items[0], overrideList); 888 } 889 overrideList.add(new Pair<String, String>(items[1], items[2])); 890 } 891 } 892 } 893 } 894 895 private String applyOemOverrideFunction(String usbFunctions) { 896 if ((usbFunctions == null) || (mOemModeMap == null)) return usbFunctions; 897 898 String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown"); 899 900 List<Pair<String, String>> overrides = mOemModeMap.get(bootMode); 901 if (overrides != null) { 902 for (Pair<String, String> pair: overrides) { 903 if (pair.first.equals(usbFunctions)) { 904 Slog.d(TAG, "OEM USB override: " + pair.first + " ==> " + pair.second); 905 return pair.second; 906 } 907 } 908 } 909 // return passed in functions as is. 910 return usbFunctions; 911 } 912 913 public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { 914 if (mDebuggingManager != null) { 915 mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey); 916 } 917 } 918 919 public void denyUsbDebugging() { 920 if (mDebuggingManager != null) { 921 mDebuggingManager.denyUsbDebugging(); 922 } 923 } 924 925 public void clearUsbDebuggingKeys() { 926 if (mDebuggingManager != null) { 927 mDebuggingManager.clearUsbDebuggingKeys(); 928 } else { 929 throw new RuntimeException("Cannot clear Usb Debugging keys, " 930 + "UsbDebuggingManager not enabled"); 931 } 932 } 933 934 public void dump(IndentingPrintWriter pw) { 935 if (mHandler != null) { 936 mHandler.dump(pw); 937 } 938 if (mDebuggingManager != null) { 939 mDebuggingManager.dump(pw); 940 } 941 } 942 943 private native String[] nativeGetAccessoryStrings(); 944 private native ParcelFileDescriptor nativeOpenAccessory(); 945 private native boolean nativeIsStartRequested(); 946 private native int nativeGetAudioMode(); 947 } 948