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