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 static com.android.internal.usb.DumpUtils.writeAccessory;
     20 import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
     21 
     22 import android.app.ActivityManager;
     23 import android.app.ActivityManagerInternal;
     24 import android.app.KeyguardManager;
     25 import android.app.Notification;
     26 import android.app.NotificationChannel;
     27 import android.app.NotificationManager;
     28 import android.app.PendingIntent;
     29 import android.content.BroadcastReceiver;
     30 import android.content.ComponentName;
     31 import android.content.ContentResolver;
     32 import android.content.Context;
     33 import android.content.Intent;
     34 import android.content.IntentFilter;
     35 import android.content.SharedPreferences;
     36 import android.content.pm.PackageManager;
     37 import android.content.res.Resources;
     38 import android.database.ContentObserver;
     39 import android.hardware.usb.UsbAccessory;
     40 import android.hardware.usb.UsbConfiguration;
     41 import android.hardware.usb.UsbConstants;
     42 import android.hardware.usb.UsbDevice;
     43 import android.hardware.usb.UsbInterface;
     44 import android.hardware.usb.UsbManager;
     45 import android.hardware.usb.UsbPort;
     46 import android.hardware.usb.UsbPortStatus;
     47 import android.hardware.usb.gadget.V1_0.GadgetFunction;
     48 import android.hardware.usb.gadget.V1_0.IUsbGadget;
     49 import android.hardware.usb.gadget.V1_0.IUsbGadgetCallback;
     50 import android.hardware.usb.gadget.V1_0.Status;
     51 import android.hidl.manager.V1_0.IServiceManager;
     52 import android.hidl.manager.V1_0.IServiceNotification;
     53 import android.os.BatteryManager;
     54 import android.os.Environment;
     55 import android.os.FileUtils;
     56 import android.os.Handler;
     57 import android.os.HwBinder;
     58 import android.os.Looper;
     59 import android.os.Message;
     60 import android.os.ParcelFileDescriptor;
     61 import android.os.RemoteException;
     62 import android.os.SystemClock;
     63 import android.os.SystemProperties;
     64 import android.os.UEventObserver;
     65 import android.os.UserHandle;
     66 import android.os.UserManager;
     67 import android.os.storage.StorageManager;
     68 import android.os.storage.StorageVolume;
     69 import android.provider.Settings;
     70 import android.service.usb.UsbDeviceManagerProto;
     71 import android.service.usb.UsbHandlerProto;
     72 import android.util.Pair;
     73 import android.util.Slog;
     74 
     75 import com.android.internal.annotations.GuardedBy;
     76 import com.android.internal.logging.MetricsLogger;
     77 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     78 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
     79 import com.android.internal.notification.SystemNotificationChannels;
     80 import com.android.internal.os.SomeArgs;
     81 import com.android.internal.util.dump.DualDumpOutputStream;
     82 import com.android.server.FgThread;
     83 import com.android.server.LocalServices;
     84 
     85 import java.io.File;
     86 import java.io.FileDescriptor;
     87 import java.io.FileNotFoundException;
     88 import java.io.IOException;
     89 import java.util.HashMap;
     90 import java.util.HashSet;
     91 import java.util.Iterator;
     92 import java.util.Locale;
     93 import java.util.Map;
     94 import java.util.NoSuchElementException;
     95 import java.util.Scanner;
     96 import java.util.Set;
     97 
     98 /**
     99  * UsbDeviceManager manages USB state in device mode.
    100  */
    101 public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {
    102 
    103     private static final String TAG = UsbDeviceManager.class.getSimpleName();
    104     private static final boolean DEBUG = false;
    105 
    106     /**
    107      * The name of the xml file in which screen unlocked functions are stored.
    108      */
    109     private static final String USB_PREFS_XML = "UsbDeviceManagerPrefs.xml";
    110 
    111     /**
    112      * The SharedPreference setting per user that stores the screen unlocked functions between
    113      * sessions.
    114      */
    115     static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
    116 
    117     /**
    118      * ro.bootmode value when phone boots into usual Android.
    119      */
    120     private static final String NORMAL_BOOT = "normal";
    121 
    122     private static final String USB_STATE_MATCH =
    123             "DEVPATH=/devices/virtual/android_usb/android0";
    124     private static final String ACCESSORY_START_MATCH =
    125             "DEVPATH=/devices/virtual/misc/usb_accessory";
    126     private static final String FUNCTIONS_PATH =
    127             "/sys/class/android_usb/android0/functions";
    128     private static final String STATE_PATH =
    129             "/sys/class/android_usb/android0/state";
    130     private static final String RNDIS_ETH_ADDR_PATH =
    131             "/sys/class/android_usb/android0/f_rndis/ethaddr";
    132     private static final String AUDIO_SOURCE_PCM_PATH =
    133             "/sys/class/android_usb/android0/f_audio_source/pcm";
    134     private static final String MIDI_ALSA_PATH =
    135             "/sys/class/android_usb/android0/f_midi/alsa";
    136 
    137     private static final int MSG_UPDATE_STATE = 0;
    138     private static final int MSG_ENABLE_ADB = 1;
    139     private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
    140     private static final int MSG_SYSTEM_READY = 3;
    141     private static final int MSG_BOOT_COMPLETED = 4;
    142     private static final int MSG_USER_SWITCHED = 5;
    143     private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
    144     private static final int MSG_UPDATE_PORT_STATE = 7;
    145     private static final int MSG_ACCESSORY_MODE_ENTER_TIMEOUT = 8;
    146     private static final int MSG_UPDATE_CHARGING_STATE = 9;
    147     private static final int MSG_UPDATE_HOST_STATE = 10;
    148     private static final int MSG_LOCALE_CHANGED = 11;
    149     private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12;
    150     private static final int MSG_UPDATE_SCREEN_LOCK = 13;
    151     private static final int MSG_SET_CHARGING_FUNCTIONS = 14;
    152     private static final int MSG_SET_FUNCTIONS_TIMEOUT = 15;
    153     private static final int MSG_GET_CURRENT_USB_FUNCTIONS = 16;
    154     private static final int MSG_FUNCTION_SWITCH_TIMEOUT = 17;
    155 
    156     private static final int AUDIO_MODE_SOURCE = 1;
    157 
    158     // Delay for debouncing USB disconnects.
    159     // We often get rapid connect/disconnect events when enabling USB functions,
    160     // which need debouncing.
    161     private static final int UPDATE_DELAY = 1000;
    162 
    163     // Timeout for entering USB request mode.
    164     // Request is cancelled if host does not configure device within 10 seconds.
    165     private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000;
    166 
    167     private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
    168 
    169     private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";
    170     private UsbHandler mHandler;
    171 
    172     private final Object mLock = new Object();
    173 
    174     private final Context mContext;
    175     private final ContentResolver mContentResolver;
    176     @GuardedBy("mLock")
    177     private UsbProfileGroupSettingsManager mCurrentSettings;
    178     private final boolean mHasUsbAccessory;
    179     @GuardedBy("mLock")
    180     private String[] mAccessoryStrings;
    181     private UsbDebuggingManager mDebuggingManager;
    182     private final UEventObserver mUEventObserver;
    183 
    184     private static Set<Integer> sBlackListedInterfaces;
    185     private HashMap<Long, FileDescriptor> mControlFds;
    186 
    187     static {
    188         sBlackListedInterfaces = new HashSet<>();
    189         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_AUDIO);
    190         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_COMM);
    191         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HID);
    192         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_PRINTER);
    193         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_MASS_STORAGE);
    194         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HUB);
    195         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CDC_DATA);
    196         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CSCID);
    197         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CONTENT_SEC);
    198         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_VIDEO);
    199         sBlackListedInterfaces.add(UsbConstants.USB_CLASS_WIRELESS_CONTROLLER);
    200     }
    201 
    202     private class AdbSettingsObserver extends ContentObserver {
    203         public AdbSettingsObserver() {
    204             super(null);
    205         }
    206 
    207         @Override
    208         public void onChange(boolean selfChange) {
    209             boolean enable = (Settings.Global.getInt(mContentResolver,
    210                     Settings.Global.ADB_ENABLED, 0) > 0);
    211             mHandler.sendMessage(MSG_ENABLE_ADB, enable);
    212         }
    213     }
    214 
    215     /*
    216      * Listens for uevent messages from the kernel to monitor the USB state
    217      */
    218     private final class UsbUEventObserver extends UEventObserver {
    219         @Override
    220         public void onUEvent(UEventObserver.UEvent event) {
    221             if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
    222 
    223             String state = event.get("USB_STATE");
    224             String accessory = event.get("ACCESSORY");
    225             if (state != null) {
    226                 mHandler.updateState(state);
    227             } else if ("START".equals(accessory)) {
    228                 if (DEBUG) Slog.d(TAG, "got accessory start");
    229                 startAccessoryMode();
    230             }
    231         }
    232     }
    233 
    234     @Override
    235     public void onKeyguardStateChanged(boolean isShowing) {
    236         int userHandle = ActivityManager.getCurrentUser();
    237         boolean secure = mContext.getSystemService(KeyguardManager.class)
    238                 .isDeviceSecure(userHandle);
    239         if (DEBUG) {
    240             Slog.v(TAG, "onKeyguardStateChanged: isShowing:" + isShowing + " secure:" + secure
    241                     + " user:" + userHandle);
    242         }
    243         // We are unlocked when the keyguard is down or non-secure.
    244         mHandler.sendMessage(MSG_UPDATE_SCREEN_LOCK, (isShowing && secure));
    245     }
    246 
    247     @Override
    248     public void onAwakeStateChanged(boolean isAwake) {
    249         // ignore
    250     }
    251 
    252     /** Called when a user is unlocked. */
    253     public void onUnlockUser(int userHandle) {
    254         onKeyguardStateChanged(false);
    255     }
    256 
    257     public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
    258             UsbSettingsManager settingsManager) {
    259         mContext = context;
    260         mContentResolver = context.getContentResolver();
    261         PackageManager pm = mContext.getPackageManager();
    262         mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
    263         initRndisAddress();
    264 
    265         boolean halNotPresent = false;
    266         try {
    267             IUsbGadget.getService(true);
    268         } catch (RemoteException e) {
    269             Slog.e(TAG, "USB GADGET HAL present but exception thrown", e);
    270         } catch (NoSuchElementException e) {
    271             halNotPresent = true;
    272             Slog.i(TAG, "USB GADGET HAL not present in the device", e);
    273         }
    274 
    275         mControlFds = new HashMap<>();
    276         FileDescriptor mtpFd = nativeOpenControl(UsbManager.USB_FUNCTION_MTP);
    277         if (mtpFd == null) {
    278             Slog.e(TAG, "Failed to open control for mtp");
    279         }
    280         mControlFds.put(UsbManager.FUNCTION_MTP, mtpFd);
    281         FileDescriptor ptpFd = nativeOpenControl(UsbManager.USB_FUNCTION_PTP);
    282         if (mtpFd == null) {
    283             Slog.e(TAG, "Failed to open control for mtp");
    284         }
    285         mControlFds.put(UsbManager.FUNCTION_PTP, ptpFd);
    286 
    287         boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
    288         boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
    289         if (secureAdbEnabled && !dataEncrypted) {
    290             mDebuggingManager = new UsbDebuggingManager(context);
    291         }
    292 
    293         if (halNotPresent) {
    294             /**
    295              * Initialze the legacy UsbHandler
    296              */
    297             mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext, this,
    298                     mDebuggingManager, alsaManager, settingsManager);
    299         } else {
    300             /**
    301              * Initialize HAL based UsbHandler
    302              */
    303             mHandler = new UsbHandlerHal(FgThread.get().getLooper(), mContext, this,
    304                     mDebuggingManager, alsaManager, settingsManager);
    305         }
    306 
    307         if (nativeIsStartRequested()) {
    308             if (DEBUG) Slog.d(TAG, "accessory attached at boot");
    309             startAccessoryMode();
    310         }
    311 
    312         BroadcastReceiver portReceiver = new BroadcastReceiver() {
    313             @Override
    314             public void onReceive(Context context, Intent intent) {
    315                 UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT);
    316                 UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS);
    317                 mHandler.updateHostState(port, status);
    318             }
    319         };
    320 
    321         BroadcastReceiver chargingReceiver = new BroadcastReceiver() {
    322             @Override
    323             public void onReceive(Context context, Intent intent) {
    324                 int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    325                 boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
    326                 mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging);
    327             }
    328         };
    329 
    330         BroadcastReceiver hostReceiver = new BroadcastReceiver() {
    331             @Override
    332             public void onReceive(Context context, Intent intent) {
    333                 Iterator devices = ((UsbManager) context.getSystemService(Context.USB_SERVICE))
    334                         .getDeviceList().entrySet().iterator();
    335                 if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
    336                     mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, true);
    337                 } else {
    338                     mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, false);
    339                 }
    340             }
    341         };
    342 
    343         BroadcastReceiver languageChangedReceiver = new BroadcastReceiver() {
    344             @Override
    345             public void onReceive(Context context, Intent intent) {
    346                 mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED);
    347             }
    348         };
    349 
    350         mContext.registerReceiver(portReceiver,
    351                 new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED));
    352         mContext.registerReceiver(chargingReceiver,
    353                 new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    354 
    355         IntentFilter filter =
    356                 new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
    357         filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
    358         mContext.registerReceiver(hostReceiver, filter);
    359 
    360         mContext.registerReceiver(languageChangedReceiver,
    361                 new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
    362 
    363         // Watch for USB configuration changes
    364         mUEventObserver = new UsbUEventObserver();
    365         mUEventObserver.startObserving(USB_STATE_MATCH);
    366         mUEventObserver.startObserving(ACCESSORY_START_MATCH);
    367 
    368         // register observer to listen for settings changes
    369         mContentResolver.registerContentObserver(
    370                 Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
    371                 false, new AdbSettingsObserver());
    372     }
    373 
    374     UsbProfileGroupSettingsManager getCurrentSettings() {
    375         synchronized (mLock) {
    376             return mCurrentSettings;
    377         }
    378     }
    379 
    380     String[] getAccessoryStrings() {
    381         synchronized (mLock) {
    382             return mAccessoryStrings;
    383         }
    384     }
    385 
    386     public void systemReady() {
    387         if (DEBUG) Slog.d(TAG, "systemReady");
    388 
    389         LocalServices.getService(ActivityManagerInternal.class).registerScreenObserver(this);
    390 
    391         mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
    392     }
    393 
    394     public void bootCompleted() {
    395         if (DEBUG) Slog.d(TAG, "boot completed");
    396         mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
    397     }
    398 
    399     public void setCurrentUser(int newCurrentUserId, UsbProfileGroupSettingsManager settings) {
    400         synchronized (mLock) {
    401             mCurrentSettings = settings;
    402             mHandler.obtainMessage(MSG_USER_SWITCHED, newCurrentUserId, 0).sendToTarget();
    403         }
    404     }
    405 
    406     public void updateUserRestrictions() {
    407         mHandler.sendEmptyMessage(MSG_UPDATE_USER_RESTRICTIONS);
    408     }
    409 
    410     private void startAccessoryMode() {
    411         if (!mHasUsbAccessory) return;
    412 
    413         mAccessoryStrings = nativeGetAccessoryStrings();
    414         boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE);
    415         // don't start accessory mode if our mandatory strings have not been set
    416         boolean enableAccessory = (mAccessoryStrings != null &&
    417                 mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
    418                 mAccessoryStrings[UsbAccessory.MODEL_STRING] != null);
    419 
    420         long functions = UsbManager.FUNCTION_NONE;
    421         if (enableAccessory) {
    422             functions |= UsbManager.FUNCTION_ACCESSORY;
    423         }
    424         if (enableAudio) {
    425             functions |= UsbManager.FUNCTION_AUDIO_SOURCE;
    426         }
    427 
    428         if (functions != UsbManager.FUNCTION_NONE) {
    429             mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_MODE_ENTER_TIMEOUT),
    430                     ACCESSORY_REQUEST_TIMEOUT);
    431             setCurrentFunctions(functions);
    432         }
    433     }
    434 
    435     private static void initRndisAddress() {
    436         // configure RNDIS ethernet address based on our serial number using the same algorithm
    437         // we had been previously using in kernel board files
    438         final int ETH_ALEN = 6;
    439         int address[] = new int[ETH_ALEN];
    440         // first byte is 0x02 to signify a locally administered address
    441         address[0] = 0x02;
    442 
    443         String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF");
    444         int serialLength = serial.length();
    445         // XOR the USB serial across the remaining 5 bytes
    446         for (int i = 0; i < serialLength; i++) {
    447             address[i % (ETH_ALEN - 1) + 1] ^= (int) serial.charAt(i);
    448         }
    449         String addrString = String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
    450                 address[0], address[1], address[2], address[3], address[4], address[5]);
    451         try {
    452             FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString);
    453         } catch (IOException e) {
    454             Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH);
    455         }
    456     }
    457 
    458     abstract static class UsbHandler extends Handler {
    459 
    460         // current USB state
    461         private boolean mConnected;
    462         private boolean mHostConnected;
    463         private boolean mSourcePower;
    464         private boolean mSinkPower;
    465         private boolean mConfigured;
    466         private boolean mAudioAccessoryConnected;
    467         private boolean mAudioAccessorySupported;
    468 
    469         private UsbAccessory mCurrentAccessory;
    470         private int mUsbNotificationId;
    471         private boolean mAdbNotificationShown;
    472         private boolean mUsbCharging;
    473         private boolean mHideUsbNotification;
    474         private boolean mSupportsAllCombinations;
    475         private boolean mScreenLocked;
    476         private boolean mSystemReady;
    477         private Intent mBroadcastedIntent;
    478         private boolean mPendingBootBroadcast;
    479         private boolean mAudioSourceEnabled;
    480         private boolean mMidiEnabled;
    481         private int mMidiCard;
    482         private int mMidiDevice;
    483 
    484         private final Context mContext;
    485         private final UsbDebuggingManager mDebuggingManager;
    486         private final UsbAlsaManager mUsbAlsaManager;
    487         private final UsbSettingsManager mSettingsManager;
    488         private NotificationManager mNotificationManager;
    489 
    490         protected long mScreenUnlockedFunctions;
    491         protected boolean mAdbEnabled;
    492         protected boolean mBootCompleted;
    493         protected boolean mCurrentFunctionsApplied;
    494         protected boolean mUseUsbNotification;
    495         protected long mCurrentFunctions;
    496         protected final UsbDeviceManager mUsbDeviceManager;
    497         protected final ContentResolver mContentResolver;
    498         protected SharedPreferences mSettings;
    499         protected int mCurrentUser;
    500         protected boolean mCurrentUsbFunctionsReceived;
    501 
    502         /**
    503          * The persistent property which stores whether adb is enabled or not.
    504          * May also contain vendor-specific default functions for testing purposes.
    505          */
    506         protected static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
    507 
    508         UsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
    509                 UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
    510                 UsbSettingsManager settingsManager) {
    511             super(looper);
    512             mContext = context;
    513             mDebuggingManager = debuggingManager;
    514             mUsbDeviceManager = deviceManager;
    515             mUsbAlsaManager = alsaManager;
    516             mSettingsManager = settingsManager;
    517             mContentResolver = context.getContentResolver();
    518 
    519             mCurrentUser = ActivityManager.getCurrentUser();
    520             mScreenLocked = true;
    521 
    522             /*
    523              * Use the normal bootmode persistent prop to maintain state of adb across
    524              * all boot modes.
    525              */
    526             mAdbEnabled = UsbHandlerLegacy.containsFunction(getSystemProperty(
    527                     USB_PERSISTENT_CONFIG_PROPERTY, ""), UsbManager.USB_FUNCTION_ADB);
    528 
    529             mSettings = getPinnedSharedPrefs(mContext);
    530             if (mSettings == null) {
    531                 Slog.e(TAG, "Couldn't load shared preferences");
    532             } else {
    533                 mScreenUnlockedFunctions = UsbManager.usbFunctionsFromString(
    534                         mSettings.getString(
    535                                 String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
    536                                 ""));
    537             }
    538 
    539             // We do not show the USB notification if the primary volume supports mass storage.
    540             // The legacy mass storage UI will be used instead.
    541             final StorageManager storageManager = StorageManager.from(mContext);
    542             final StorageVolume primary = storageManager.getPrimaryVolume();
    543 
    544             boolean massStorageSupported = primary != null && primary.allowMassStorage();
    545             mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
    546                     com.android.internal.R.bool.config_usbChargingMessage);
    547         }
    548 
    549         public void sendMessage(int what, boolean arg) {
    550             removeMessages(what);
    551             Message m = Message.obtain(this, what);
    552             m.arg1 = (arg ? 1 : 0);
    553             sendMessage(m);
    554         }
    555 
    556         public void sendMessage(int what, Object arg) {
    557             removeMessages(what);
    558             Message m = Message.obtain(this, what);
    559             m.obj = arg;
    560             sendMessage(m);
    561         }
    562 
    563         public void sendMessage(int what, Object arg, boolean arg1) {
    564             removeMessages(what);
    565             Message m = Message.obtain(this, what);
    566             m.obj = arg;
    567             m.arg1 = (arg1 ? 1 : 0);
    568             sendMessage(m);
    569         }
    570 
    571         public void sendMessage(int what, boolean arg1, boolean arg2) {
    572             removeMessages(what);
    573             Message m = Message.obtain(this, what);
    574             m.arg1 = (arg1 ? 1 : 0);
    575             m.arg2 = (arg2 ? 1 : 0);
    576             sendMessage(m);
    577         }
    578 
    579         public void sendMessageDelayed(int what, boolean arg, long delayMillis) {
    580             removeMessages(what);
    581             Message m = Message.obtain(this, what);
    582             m.arg1 = (arg ? 1 : 0);
    583             sendMessageDelayed(m, delayMillis);
    584         }
    585 
    586         public void updateState(String state) {
    587             int connected, configured;
    588 
    589             if ("DISCONNECTED".equals(state)) {
    590                 connected = 0;
    591                 configured = 0;
    592             } else if ("CONNECTED".equals(state)) {
    593                 connected = 1;
    594                 configured = 0;
    595             } else if ("CONFIGURED".equals(state)) {
    596                 connected = 1;
    597                 configured = 1;
    598             } else {
    599                 Slog.e(TAG, "unknown state " + state);
    600                 return;
    601             }
    602             removeMessages(MSG_UPDATE_STATE);
    603             if (connected == 1) removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
    604             Message msg = Message.obtain(this, MSG_UPDATE_STATE);
    605             msg.arg1 = connected;
    606             msg.arg2 = configured;
    607             // debounce disconnects to avoid problems bringing up USB tethering
    608             sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
    609         }
    610 
    611         public void updateHostState(UsbPort port, UsbPortStatus status) {
    612             if (DEBUG) {
    613                 Slog.i(TAG, "updateHostState " + port + " status=" + status);
    614             }
    615 
    616             SomeArgs args = SomeArgs.obtain();
    617             args.arg1 = port;
    618             args.arg2 = status;
    619 
    620             removeMessages(MSG_UPDATE_PORT_STATE);
    621             Message msg = obtainMessage(MSG_UPDATE_PORT_STATE, args);
    622             // debounce rapid transitions of connect/disconnect on type-c ports
    623             sendMessageDelayed(msg, UPDATE_DELAY);
    624         }
    625 
    626         private void setAdbEnabled(boolean enable) {
    627             if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
    628             if (enable != mAdbEnabled) {
    629                 mAdbEnabled = enable;
    630 
    631                 if (enable) {
    632                     setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_ADB);
    633                 } else {
    634                     setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, "");
    635                 }
    636 
    637                 setEnabledFunctions(mCurrentFunctions, true);
    638                 updateAdbNotification(false);
    639             }
    640 
    641             if (mDebuggingManager != null) {
    642                 mDebuggingManager.setAdbEnabled(mAdbEnabled);
    643             }
    644         }
    645 
    646         protected boolean isUsbTransferAllowed() {
    647             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    648             return !userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
    649         }
    650 
    651         private void updateCurrentAccessory() {
    652             // We are entering accessory mode if we have received a request from the host
    653             // and the request has not timed out yet.
    654             boolean enteringAccessoryMode = hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT);
    655 
    656             if (mConfigured && enteringAccessoryMode) {
    657                 // successfully entered accessory mode
    658                 String[] accessoryStrings = mUsbDeviceManager.getAccessoryStrings();
    659                 if (accessoryStrings != null) {
    660                     mCurrentAccessory = new UsbAccessory(accessoryStrings);
    661                     Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
    662                     // defer accessoryAttached if system is not ready
    663                     if (mBootCompleted) {
    664                         mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory);
    665                     } // else handle in boot completed
    666                 } else {
    667                     Slog.e(TAG, "nativeGetAccessoryStrings failed");
    668                 }
    669             } else {
    670                 if (!enteringAccessoryMode) {
    671                     notifyAccessoryModeExit();
    672                 } else if (DEBUG) {
    673                     Slog.v(TAG, "Debouncing accessory mode exit");
    674                 }
    675             }
    676         }
    677 
    678         private void notifyAccessoryModeExit() {
    679             // make sure accessory mode is off
    680             // and restore default functions
    681             Slog.d(TAG, "exited USB accessory mode");
    682             setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
    683 
    684             if (mCurrentAccessory != null) {
    685                 if (mBootCompleted) {
    686                     mSettingsManager.usbAccessoryRemoved(mCurrentAccessory);
    687                 }
    688                 mCurrentAccessory = null;
    689             }
    690         }
    691 
    692         protected SharedPreferences getPinnedSharedPrefs(Context context) {
    693             final File prefsFile = new File(
    694                     Environment.getDataSystemDeDirectory(UserHandle.USER_SYSTEM), USB_PREFS_XML);
    695             return context.createDeviceProtectedStorageContext()
    696                     .getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
    697         }
    698 
    699         private boolean isUsbStateChanged(Intent intent) {
    700             final Set<String> keySet = intent.getExtras().keySet();
    701             if (mBroadcastedIntent == null) {
    702                 for (String key : keySet) {
    703                     if (intent.getBooleanExtra(key, false)) {
    704                         return true;
    705                     }
    706                 }
    707             } else {
    708                 if (!keySet.equals(mBroadcastedIntent.getExtras().keySet())) {
    709                     return true;
    710                 }
    711                 for (String key : keySet) {
    712                     if (intent.getBooleanExtra(key, false) !=
    713                             mBroadcastedIntent.getBooleanExtra(key, false)) {
    714                         return true;
    715                     }
    716                 }
    717             }
    718             return false;
    719         }
    720 
    721         protected void updateUsbStateBroadcastIfNeeded(long functions) {
    722             // send a sticky broadcast containing current USB state
    723             Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
    724             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
    725                     | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
    726                     | Intent.FLAG_RECEIVER_FOREGROUND);
    727             intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
    728             intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
    729             intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
    730             intent.putExtra(UsbManager.USB_DATA_UNLOCKED,
    731                     isUsbTransferAllowed() && isUsbDataTransferActive(mCurrentFunctions));
    732 
    733             long remainingFunctions = functions;
    734             while (remainingFunctions != 0) {
    735                 intent.putExtra(UsbManager.usbFunctionsToString(
    736                         Long.highestOneBit(remainingFunctions)), true);
    737                 remainingFunctions -= Long.highestOneBit(remainingFunctions);
    738             }
    739 
    740             // send broadcast intent only if the USB state has changed
    741             if (!isUsbStateChanged(intent)) {
    742                 if (DEBUG) {
    743                     Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
    744                 }
    745                 return;
    746             }
    747 
    748             if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
    749             sendStickyBroadcast(intent);
    750             mBroadcastedIntent = intent;
    751         }
    752 
    753         protected void sendStickyBroadcast(Intent intent) {
    754             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    755         }
    756 
    757         private void updateUsbFunctions() {
    758             updateMidiFunction();
    759         }
    760 
    761         private void updateMidiFunction() {
    762             boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_MIDI) != 0;
    763             if (enabled != mMidiEnabled) {
    764                 if (enabled) {
    765                     Scanner scanner = null;
    766                     try {
    767                         scanner = new Scanner(new File(MIDI_ALSA_PATH));
    768                         mMidiCard = scanner.nextInt();
    769                         mMidiDevice = scanner.nextInt();
    770                     } catch (FileNotFoundException e) {
    771                         Slog.e(TAG, "could not open MIDI file", e);
    772                         enabled = false;
    773                     } finally {
    774                         if (scanner != null) {
    775                             scanner.close();
    776                         }
    777                     }
    778                 }
    779                 mMidiEnabled = enabled;
    780             }
    781             mUsbAlsaManager.setPeripheralMidiState(
    782                     mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
    783         }
    784 
    785         private void setScreenUnlockedFunctions() {
    786             setEnabledFunctions(mScreenUnlockedFunctions, false);
    787         }
    788 
    789         /**
    790          * Returns the functions that are passed down to the low level driver once adb and
    791          * charging are accounted for.
    792          */
    793         long getAppliedFunctions(long functions) {
    794             if (functions == UsbManager.FUNCTION_NONE) {
    795                 return getChargingFunctions();
    796             }
    797             if (mAdbEnabled) {
    798                 return functions | UsbManager.FUNCTION_ADB;
    799             }
    800             return functions;
    801         }
    802 
    803         @Override
    804         public void handleMessage(Message msg) {
    805             switch (msg.what) {
    806                 case MSG_UPDATE_STATE:
    807                     mConnected = (msg.arg1 == 1);
    808                     mConfigured = (msg.arg2 == 1);
    809 
    810                     updateUsbNotification(false);
    811                     updateAdbNotification(false);
    812                     if (mBootCompleted) {
    813                         updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
    814                     }
    815                     if ((mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) != 0) {
    816                         updateCurrentAccessory();
    817                     }
    818                     if (mBootCompleted) {
    819                         if (!mConnected && !hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT)
    820                                 && !hasMessages(MSG_FUNCTION_SWITCH_TIMEOUT)) {
    821                             // restore defaults when USB is disconnected
    822                             if (!mScreenLocked
    823                                     && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
    824                                 setScreenUnlockedFunctions();
    825                             } else {
    826                                 setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
    827                             }
    828                         }
    829                         updateUsbFunctions();
    830                     } else {
    831                         mPendingBootBroadcast = true;
    832                     }
    833                     break;
    834                 case MSG_UPDATE_PORT_STATE:
    835                     SomeArgs args = (SomeArgs) msg.obj;
    836                     boolean prevHostConnected = mHostConnected;
    837                     UsbPort port = (UsbPort) args.arg1;
    838                     UsbPortStatus status = (UsbPortStatus) args.arg2;
    839                     mHostConnected = status.getCurrentDataRole() == UsbPort.DATA_ROLE_HOST;
    840                     mSourcePower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE;
    841                     mSinkPower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SINK;
    842                     mAudioAccessoryConnected =
    843                             (status.getCurrentMode() == UsbPort.MODE_AUDIO_ACCESSORY);
    844                     mAudioAccessorySupported = port.isModeSupported(UsbPort.MODE_AUDIO_ACCESSORY);
    845                     // Ideally we want to see if PR_SWAP and DR_SWAP is supported.
    846                     // But, this should be suffice, since, all four combinations are only supported
    847                     // when PR_SWAP and DR_SWAP are supported.
    848                     mSupportsAllCombinations = status.isRoleCombinationSupported(
    849                             UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST)
    850                             && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK,
    851                             UsbPort.DATA_ROLE_HOST)
    852                             && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE,
    853                             UsbPort.DATA_ROLE_DEVICE)
    854                             && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK,
    855                             UsbPort.DATA_ROLE_HOST);
    856 
    857                     args.recycle();
    858                     updateUsbNotification(false);
    859                     if (mBootCompleted) {
    860                         if (mHostConnected || prevHostConnected) {
    861                             updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
    862                         }
    863                     } else {
    864                         mPendingBootBroadcast = true;
    865                     }
    866                     break;
    867                 case MSG_UPDATE_CHARGING_STATE:
    868                     mUsbCharging = (msg.arg1 == 1);
    869                     updateUsbNotification(false);
    870                     break;
    871                 case MSG_UPDATE_HOST_STATE:
    872                     Iterator devices = (Iterator) msg.obj;
    873                     boolean connected = (msg.arg1 == 1);
    874 
    875                     if (DEBUG) {
    876                         Slog.i(TAG, "HOST_STATE connected:" + connected);
    877                     }
    878 
    879                     mHideUsbNotification = false;
    880                     while (devices.hasNext()) {
    881                         Map.Entry pair = (Map.Entry) devices.next();
    882                         if (DEBUG) {
    883                             Slog.i(TAG, pair.getKey() + " = " + pair.getValue());
    884                         }
    885                         UsbDevice device = (UsbDevice) pair.getValue();
    886                         int configurationCount = device.getConfigurationCount() - 1;
    887                         while (configurationCount >= 0) {
    888                             UsbConfiguration config = device.getConfiguration(configurationCount);
    889                             configurationCount--;
    890                             int interfaceCount = config.getInterfaceCount() - 1;
    891                             while (interfaceCount >= 0) {
    892                                 UsbInterface intrface = config.getInterface(interfaceCount);
    893                                 interfaceCount--;
    894                                 if (sBlackListedInterfaces.contains(intrface.getInterfaceClass())) {
    895                                     mHideUsbNotification = true;
    896                                     break;
    897                                 }
    898                             }
    899                         }
    900                     }
    901                     updateUsbNotification(false);
    902                     break;
    903                 case MSG_ENABLE_ADB:
    904                     setAdbEnabled(msg.arg1 == 1);
    905                     break;
    906                 case MSG_SET_CURRENT_FUNCTIONS:
    907                     long functions = (Long) msg.obj;
    908                     setEnabledFunctions(functions, false);
    909                     break;
    910                 case MSG_SET_SCREEN_UNLOCKED_FUNCTIONS:
    911                     mScreenUnlockedFunctions = (Long) msg.obj;
    912                     if (mSettings != null) {
    913                         SharedPreferences.Editor editor = mSettings.edit();
    914                         editor.putString(String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
    915                                 mCurrentUser),
    916                                 UsbManager.usbFunctionsToString(mScreenUnlockedFunctions));
    917                         editor.commit();
    918                     }
    919                     if (!mScreenLocked && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
    920                         // If the screen is unlocked, also set current functions.
    921                         setScreenUnlockedFunctions();
    922                     }
    923                     break;
    924                 case MSG_UPDATE_SCREEN_LOCK:
    925                     if (msg.arg1 == 1 == mScreenLocked) {
    926                         break;
    927                     }
    928                     mScreenLocked = msg.arg1 == 1;
    929                     if (!mBootCompleted) {
    930                         break;
    931                     }
    932                     if (mScreenLocked) {
    933                         if (!mConnected) {
    934                             setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
    935                         }
    936                     } else {
    937                         if (mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE
    938                                 && mCurrentFunctions == UsbManager.FUNCTION_NONE) {
    939                             // Set the screen unlocked functions if current function is charging.
    940                             setScreenUnlockedFunctions();
    941                         }
    942                     }
    943                     break;
    944                 case MSG_UPDATE_USER_RESTRICTIONS:
    945                     // Restart the USB stack if USB transfer is enabled but no longer allowed.
    946                     if (isUsbDataTransferActive(mCurrentFunctions) && !isUsbTransferAllowed()) {
    947                         setEnabledFunctions(UsbManager.FUNCTION_NONE, true);
    948                     }
    949                     break;
    950                 case MSG_SYSTEM_READY:
    951                     mNotificationManager = (NotificationManager)
    952                             mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    953 
    954                     // Ensure that the notification channels are set up
    955                     if (isTv()) {
    956                         // TV-specific notification channel
    957                         mNotificationManager.createNotificationChannel(
    958                                 new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
    959                                         mContext.getString(
    960                                                 com.android.internal.R.string
    961                                                         .adb_debugging_notification_channel_tv),
    962                                         NotificationManager.IMPORTANCE_HIGH));
    963                     }
    964                     mSystemReady = true;
    965                     finishBoot();
    966                     break;
    967                 case MSG_LOCALE_CHANGED:
    968                     updateAdbNotification(true);
    969                     updateUsbNotification(true);
    970                     break;
    971                 case MSG_BOOT_COMPLETED:
    972                     mBootCompleted = true;
    973                     finishBoot();
    974                     break;
    975                 case MSG_USER_SWITCHED: {
    976                     if (mCurrentUser != msg.arg1) {
    977                         if (DEBUG) {
    978                             Slog.v(TAG, "Current user switched to " + msg.arg1);
    979                         }
    980                         mCurrentUser = msg.arg1;
    981                         mScreenLocked = true;
    982                         mScreenUnlockedFunctions = UsbManager.FUNCTION_NONE;
    983                         if (mSettings != null) {
    984                             mScreenUnlockedFunctions = UsbManager.usbFunctionsFromString(
    985                                     mSettings.getString(String.format(Locale.ENGLISH,
    986                                             UNLOCKED_CONFIG_PREF, mCurrentUser), ""));
    987                         }
    988                         setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
    989                     }
    990                     break;
    991                 }
    992                 case MSG_ACCESSORY_MODE_ENTER_TIMEOUT: {
    993                     if (DEBUG) {
    994                         Slog.v(TAG, "Accessory mode enter timeout: " + mConnected);
    995                     }
    996                     if (!mConnected || (mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) == 0) {
    997                         notifyAccessoryModeExit();
    998                     }
    999                     break;
   1000                 }
   1001             }
   1002         }
   1003 
   1004         protected void finishBoot() {
   1005             if (mBootCompleted && mCurrentUsbFunctionsReceived && mSystemReady) {
   1006                 if (mPendingBootBroadcast) {
   1007                     updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
   1008                     mPendingBootBroadcast = false;
   1009                 }
   1010                 if (!mScreenLocked
   1011                         && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
   1012                     setScreenUnlockedFunctions();
   1013                 } else {
   1014                     setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
   1015                 }
   1016                 if (mCurrentAccessory != null) {
   1017                     mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory);
   1018                 }
   1019                 if (mDebuggingManager != null) {
   1020                     mDebuggingManager.setAdbEnabled(mAdbEnabled);
   1021                 }
   1022 
   1023                 // make sure the ADB_ENABLED setting value matches the current state
   1024                 try {
   1025                     putGlobalSettings(mContentResolver, Settings.Global.ADB_ENABLED,
   1026                             mAdbEnabled ? 1 : 0);
   1027                 } catch (SecurityException e) {
   1028                     // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't
   1029                     // be changed.
   1030                     Slog.d(TAG, "ADB_ENABLED is restricted.");
   1031                 }
   1032 
   1033                 updateUsbNotification(false);
   1034                 updateAdbNotification(false);
   1035                 updateUsbFunctions();
   1036             }
   1037         }
   1038 
   1039         protected boolean isUsbDataTransferActive(long functions) {
   1040             return (functions & UsbManager.FUNCTION_MTP) != 0
   1041                     || (functions & UsbManager.FUNCTION_PTP) != 0;
   1042         }
   1043 
   1044         public UsbAccessory getCurrentAccessory() {
   1045             return mCurrentAccessory;
   1046         }
   1047 
   1048         protected void updateUsbNotification(boolean force) {
   1049             if (mNotificationManager == null || !mUseUsbNotification
   1050                     || ("0".equals(getSystemProperty("persist.charging.notify", "")))) {
   1051                 return;
   1052             }
   1053 
   1054             // Dont show the notification when connected to a USB peripheral
   1055             // and the link does not support PR_SWAP and DR_SWAP
   1056             if (mHideUsbNotification && !mSupportsAllCombinations) {
   1057                 if (mUsbNotificationId != 0) {
   1058                     mNotificationManager.cancelAsUser(null, mUsbNotificationId,
   1059                             UserHandle.ALL);
   1060                     mUsbNotificationId = 0;
   1061                     Slog.d(TAG, "Clear notification");
   1062                 }
   1063                 return;
   1064             }
   1065 
   1066             int id = 0;
   1067             int titleRes = 0;
   1068             Resources r = mContext.getResources();
   1069             CharSequence message = r.getText(
   1070                     com.android.internal.R.string.usb_notification_message);
   1071             if (mAudioAccessoryConnected && !mAudioAccessorySupported) {
   1072                 titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
   1073                 id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
   1074             } else if (mConnected) {
   1075                 if (mCurrentFunctions == UsbManager.FUNCTION_MTP) {
   1076                     titleRes = com.android.internal.R.string.usb_mtp_notification_title;
   1077                     id = SystemMessage.NOTE_USB_MTP;
   1078                 } else if (mCurrentFunctions == UsbManager.FUNCTION_PTP) {
   1079                     titleRes = com.android.internal.R.string.usb_ptp_notification_title;
   1080                     id = SystemMessage.NOTE_USB_PTP;
   1081                 } else if (mCurrentFunctions == UsbManager.FUNCTION_MIDI) {
   1082                     titleRes = com.android.internal.R.string.usb_midi_notification_title;
   1083                     id = SystemMessage.NOTE_USB_MIDI;
   1084                 } else if (mCurrentFunctions == UsbManager.FUNCTION_RNDIS) {
   1085                     titleRes = com.android.internal.R.string.usb_tether_notification_title;
   1086                     id = SystemMessage.NOTE_USB_TETHER;
   1087                 } else if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
   1088                     titleRes = com.android.internal.R.string.usb_accessory_notification_title;
   1089                     id = SystemMessage.NOTE_USB_ACCESSORY;
   1090                 }
   1091                 if (mSourcePower) {
   1092                     if (titleRes != 0) {
   1093                         message = r.getText(
   1094                                 com.android.internal.R.string.usb_power_notification_message);
   1095                     } else {
   1096                         titleRes = com.android.internal.R.string.usb_supplying_notification_title;
   1097                         id = SystemMessage.NOTE_USB_SUPPLYING;
   1098                     }
   1099                 } else if (titleRes == 0) {
   1100                     titleRes = com.android.internal.R.string.usb_charging_notification_title;
   1101                     id = SystemMessage.NOTE_USB_CHARGING;
   1102                 }
   1103             } else if (mSourcePower) {
   1104                 titleRes = com.android.internal.R.string.usb_supplying_notification_title;
   1105                 id = SystemMessage.NOTE_USB_SUPPLYING;
   1106             } else if (mHostConnected && mSinkPower && mUsbCharging) {
   1107                 titleRes = com.android.internal.R.string.usb_charging_notification_title;
   1108                 id = SystemMessage.NOTE_USB_CHARGING;
   1109             }
   1110             if (id != mUsbNotificationId || force) {
   1111                 // clear notification if title needs changing
   1112                 if (mUsbNotificationId != 0) {
   1113                     mNotificationManager.cancelAsUser(null, mUsbNotificationId,
   1114                             UserHandle.ALL);
   1115                     Slog.d(TAG, "Clear notification");
   1116                     mUsbNotificationId = 0;
   1117                 }
   1118                 if (id != 0) {
   1119                     CharSequence title = r.getText(titleRes);
   1120                     PendingIntent pi;
   1121                     String channel;
   1122 
   1123                     if (titleRes
   1124                             != com.android.internal.R.string
   1125                             .usb_unsupported_audio_accessory_title) {
   1126                         Intent intent = Intent.makeRestartActivityTask(
   1127                                 new ComponentName("com.android.settings",
   1128                                         "com.android.settings.Settings$UsbDetailsActivity"));
   1129                         pi = PendingIntent.getActivityAsUser(mContext, 0,
   1130                                 intent, 0, null, UserHandle.CURRENT);
   1131                         channel = SystemNotificationChannels.USB;
   1132                     } else {
   1133                         final Intent intent = new Intent();
   1134                         intent.setClassName("com.android.settings",
   1135                                 "com.android.settings.HelpTrampoline");
   1136                         intent.putExtra(Intent.EXTRA_TEXT,
   1137                                 "help_url_audio_accessory_not_supported");
   1138 
   1139                         if (mContext.getPackageManager().resolveActivity(intent, 0) != null) {
   1140                             pi = PendingIntent.getActivity(mContext, 0, intent, 0);
   1141                         } else {
   1142                             pi = null;
   1143                         }
   1144 
   1145                         channel = SystemNotificationChannels.ALERTS;
   1146                         message = r.getText(
   1147                                 com.android.internal.R.string
   1148                                         .usb_unsupported_audio_accessory_message);
   1149                     }
   1150 
   1151                     Notification.Builder builder = new Notification.Builder(mContext, channel)
   1152                             .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
   1153                             .setWhen(0)
   1154                             .setOngoing(true)
   1155                             .setTicker(title)
   1156                             .setDefaults(0)  // please be quiet
   1157                             .setColor(mContext.getColor(
   1158                                     com.android.internal.R.color
   1159                                             .system_notification_accent_color))
   1160                             .setContentTitle(title)
   1161                             .setContentText(message)
   1162                             .setContentIntent(pi)
   1163                             .setVisibility(Notification.VISIBILITY_PUBLIC);
   1164 
   1165                     if (titleRes
   1166                             == com.android.internal.R.string
   1167                             .usb_unsupported_audio_accessory_title) {
   1168                         builder.setStyle(new Notification.BigTextStyle()
   1169                                 .bigText(message));
   1170                     }
   1171                     Notification notification = builder.build();
   1172 
   1173                     mNotificationManager.notifyAsUser(null, id, notification,
   1174                             UserHandle.ALL);
   1175                     Slog.d(TAG, "push notification:" + title);
   1176                     mUsbNotificationId = id;
   1177                 }
   1178             }
   1179         }
   1180 
   1181         protected void updateAdbNotification(boolean force) {
   1182             if (mNotificationManager == null) return;
   1183             final int id = SystemMessage.NOTE_ADB_ACTIVE;
   1184             final int titleRes = com.android.internal.R.string.adb_active_notification_title;
   1185 
   1186             if (mAdbEnabled && mConnected) {
   1187                 if ("0".equals(getSystemProperty("persist.adb.notify", ""))) return;
   1188 
   1189                 if (force && mAdbNotificationShown) {
   1190                     mAdbNotificationShown = false;
   1191                     mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
   1192                 }
   1193 
   1194                 if (!mAdbNotificationShown) {
   1195                     Resources r = mContext.getResources();
   1196                     CharSequence title = r.getText(titleRes);
   1197                     CharSequence message = r.getText(
   1198                             com.android.internal.R.string.adb_active_notification_message);
   1199 
   1200                     Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
   1201                     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   1202                             | Intent.FLAG_ACTIVITY_CLEAR_TASK);
   1203                     PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
   1204                             intent, 0, null, UserHandle.CURRENT);
   1205 
   1206                     Notification notification =
   1207                             new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
   1208                                     .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
   1209                                     .setWhen(0)
   1210                                     .setOngoing(true)
   1211                                     .setTicker(title)
   1212                                     .setDefaults(0)  // please be quiet
   1213                                     .setColor(mContext.getColor(
   1214                                             com.android.internal.R.color
   1215                                                     .system_notification_accent_color))
   1216                                     .setContentTitle(title)
   1217                                     .setContentText(message)
   1218                                     .setContentIntent(pi)
   1219                                     .setVisibility(Notification.VISIBILITY_PUBLIC)
   1220                                     .extend(new Notification.TvExtender()
   1221                                             .setChannelId(ADB_NOTIFICATION_CHANNEL_ID_TV))
   1222                                     .build();
   1223                     mAdbNotificationShown = true;
   1224                     mNotificationManager.notifyAsUser(null, id, notification,
   1225                             UserHandle.ALL);
   1226                 }
   1227             } else if (mAdbNotificationShown) {
   1228                 mAdbNotificationShown = false;
   1229                 mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
   1230             }
   1231         }
   1232 
   1233         private boolean isTv() {
   1234             return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
   1235         }
   1236 
   1237         protected long getChargingFunctions() {
   1238             // if ADB is enabled, reset functions to ADB
   1239             // else enable MTP as usual.
   1240             if (mAdbEnabled) {
   1241                 return UsbManager.FUNCTION_ADB;
   1242             } else {
   1243                 return UsbManager.FUNCTION_MTP;
   1244             }
   1245         }
   1246 
   1247         protected void setSystemProperty(String prop, String val) {
   1248             SystemProperties.set(prop, val);
   1249         }
   1250 
   1251         protected String getSystemProperty(String prop, String def) {
   1252             return SystemProperties.get(prop, def);
   1253         }
   1254 
   1255         protected void putGlobalSettings(ContentResolver contentResolver, String setting, int val) {
   1256             Settings.Global.putInt(contentResolver, setting, val);
   1257         }
   1258 
   1259         public long getEnabledFunctions() {
   1260             return mCurrentFunctions;
   1261         }
   1262 
   1263         public long getScreenUnlockedFunctions() {
   1264             return mScreenUnlockedFunctions;
   1265         }
   1266 
   1267         /**
   1268          * Dump a functions mask either as proto-enums (if dumping to proto) or a string (if dumping
   1269          * to a print writer)
   1270          */
   1271         private void dumpFunctions(DualDumpOutputStream dump, String idName, long id,
   1272                 long functions) {
   1273             // UsbHandlerProto.UsbFunction matches GadgetFunction
   1274             for (int i = 0; i < 63; i++) {
   1275                 if ((functions & (1L << i)) != 0) {
   1276                     if (dump.isProto()) {
   1277                         dump.write(idName, id, 1L << i);
   1278                     } else {
   1279                         dump.write(idName, id, GadgetFunction.toString(1L << i));
   1280                     }
   1281                 }
   1282             }
   1283         }
   1284 
   1285         public void dump(DualDumpOutputStream dump, String idName, long id) {
   1286             long token = dump.start(idName, id);
   1287 
   1288             dumpFunctions(dump, "current_functions", UsbHandlerProto.CURRENT_FUNCTIONS,
   1289                     mCurrentFunctions);
   1290             dump.write("current_functions_applied", UsbHandlerProto.CURRENT_FUNCTIONS_APPLIED,
   1291                     mCurrentFunctionsApplied);
   1292             dumpFunctions(dump, "screen_unlocked_functions",
   1293                     UsbHandlerProto.SCREEN_UNLOCKED_FUNCTIONS, mScreenUnlockedFunctions);
   1294             dump.write("screen_locked", UsbHandlerProto.SCREEN_LOCKED, mScreenLocked);
   1295             dump.write("connected", UsbHandlerProto.CONNECTED, mConnected);
   1296             dump.write("configured", UsbHandlerProto.CONFIGURED, mConfigured);
   1297             if (mCurrentAccessory != null) {
   1298                 writeAccessory(dump, "current_accessory", UsbHandlerProto.CURRENT_ACCESSORY,
   1299                         mCurrentAccessory);
   1300             }
   1301             dump.write("host_connected", UsbHandlerProto.HOST_CONNECTED, mHostConnected);
   1302             dump.write("source_power", UsbHandlerProto.SOURCE_POWER, mSourcePower);
   1303             dump.write("sink_power", UsbHandlerProto.SINK_POWER, mSinkPower);
   1304             dump.write("usb_charging", UsbHandlerProto.USB_CHARGING, mUsbCharging);
   1305             dump.write("hide_usb_notification", UsbHandlerProto.HIDE_USB_NOTIFICATION,
   1306                     mHideUsbNotification);
   1307             dump.write("audio_accessory_connected", UsbHandlerProto.AUDIO_ACCESSORY_CONNECTED,
   1308                     mAudioAccessoryConnected);
   1309             dump.write("adb_enabled", UsbHandlerProto.ADB_ENABLED, mAdbEnabled);
   1310 
   1311             try {
   1312                 writeStringIfNotNull(dump, "kernel_state", UsbHandlerProto.KERNEL_STATE,
   1313                         FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
   1314             } catch (Exception e) {
   1315                 Slog.e(TAG, "Could not read kernel state", e);
   1316             }
   1317 
   1318             try {
   1319                 writeStringIfNotNull(dump, "kernel_function_list",
   1320                         UsbHandlerProto.KERNEL_FUNCTION_LIST,
   1321                         FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
   1322             } catch (Exception e) {
   1323                 Slog.e(TAG, "Could not read kernel function list", e);
   1324             }
   1325 
   1326             dump.end(token);
   1327         }
   1328 
   1329         /**
   1330          * Evaluates USB function policies and applies the change accordingly.
   1331          */
   1332         protected abstract void setEnabledFunctions(long functions, boolean forceRestart);
   1333     }
   1334 
   1335     private static final class UsbHandlerLegacy extends UsbHandler {
   1336         /**
   1337          * The non-persistent property which stores the current USB settings.
   1338          */
   1339         private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
   1340 
   1341         /**
   1342          * The non-persistent property which stores the current USB actual state.
   1343          */
   1344         private static final String USB_STATE_PROPERTY = "sys.usb.state";
   1345 
   1346         private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap;
   1347         private String mCurrentOemFunctions;
   1348         private String mCurrentFunctionsStr;
   1349         private boolean mUsbDataUnlocked;
   1350 
   1351         UsbHandlerLegacy(Looper looper, Context context, UsbDeviceManager deviceManager,
   1352                 UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
   1353                 UsbSettingsManager settingsManager) {
   1354             super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
   1355             try {
   1356                 readOemUsbOverrideConfig(context);
   1357                 // Restore default functions.
   1358                 mCurrentOemFunctions = getSystemProperty(getPersistProp(false),
   1359                         UsbManager.USB_FUNCTION_NONE);
   1360                 if (isNormalBoot()) {
   1361                     mCurrentFunctionsStr = getSystemProperty(USB_CONFIG_PROPERTY,
   1362                             UsbManager.USB_FUNCTION_NONE);
   1363                     mCurrentFunctionsApplied = mCurrentFunctionsStr.equals(
   1364                             getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
   1365                 } else {
   1366                     mCurrentFunctionsStr = getSystemProperty(getPersistProp(true),
   1367                             UsbManager.USB_FUNCTION_NONE);
   1368                     mCurrentFunctionsApplied = getSystemProperty(USB_CONFIG_PROPERTY,
   1369                             UsbManager.USB_FUNCTION_NONE).equals(
   1370                             getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
   1371                 }
   1372                 mCurrentFunctions = UsbManager.FUNCTION_NONE;
   1373                 mCurrentUsbFunctionsReceived = true;
   1374 
   1375                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
   1376                 updateState(state);
   1377             } catch (Exception e) {
   1378                 Slog.e(TAG, "Error initializing UsbHandler", e);
   1379             }
   1380         }
   1381 
   1382         private void readOemUsbOverrideConfig(Context context) {
   1383             String[] configList = context.getResources().getStringArray(
   1384                     com.android.internal.R.array.config_oemUsbModeOverride);
   1385 
   1386             if (configList != null) {
   1387                 for (String config : configList) {
   1388                     String[] items = config.split(":");
   1389                     if (items.length == 3 || items.length == 4) {
   1390                         if (mOemModeMap == null) {
   1391                             mOemModeMap = new HashMap<>();
   1392                         }
   1393                         HashMap<String, Pair<String, String>> overrideMap =
   1394                                 mOemModeMap.get(items[0]);
   1395                         if (overrideMap == null) {
   1396                             overrideMap = new HashMap<>();
   1397                             mOemModeMap.put(items[0], overrideMap);
   1398                         }
   1399 
   1400                         // Favoring the first combination if duplicate exists
   1401                         if (!overrideMap.containsKey(items[1])) {
   1402                             if (items.length == 3) {
   1403                                 overrideMap.put(items[1], new Pair<>(items[2], ""));
   1404                             } else {
   1405                                 overrideMap.put(items[1], new Pair<>(items[2], items[3]));
   1406                             }
   1407                         }
   1408                     }
   1409                 }
   1410             }
   1411         }
   1412 
   1413         private String applyOemOverrideFunction(String usbFunctions) {
   1414             if ((usbFunctions == null) || (mOemModeMap == null)) {
   1415                 return usbFunctions;
   1416             }
   1417 
   1418             String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
   1419             Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);
   1420 
   1421             Map<String, Pair<String, String>> overridesMap =
   1422                     mOemModeMap.get(bootMode);
   1423             // Check to ensure that the oem is not overriding in the normal
   1424             // boot mode
   1425             if (overridesMap != null && !(bootMode.equals(NORMAL_BOOT)
   1426                     || bootMode.equals("unknown"))) {
   1427                 Pair<String, String> overrideFunctions =
   1428                         overridesMap.get(usbFunctions);
   1429                 if (overrideFunctions != null) {
   1430                     Slog.d(TAG, "OEM USB override: " + usbFunctions
   1431                             + " ==> " + overrideFunctions.first
   1432                             + " persist across reboot "
   1433                             + overrideFunctions.second);
   1434                     if (!overrideFunctions.second.equals("")) {
   1435                         String newFunction;
   1436                         if (mAdbEnabled) {
   1437                             newFunction = addFunction(overrideFunctions.second,
   1438                                     UsbManager.USB_FUNCTION_ADB);
   1439                         } else {
   1440                             newFunction = overrideFunctions.second;
   1441                         }
   1442                         Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
   1443                                 + getPersistProp(false));
   1444                         setSystemProperty(getPersistProp(false), newFunction);
   1445                     }
   1446                     return overrideFunctions.first;
   1447                 } else if (mAdbEnabled) {
   1448                     String newFunction = addFunction(UsbManager.USB_FUNCTION_NONE,
   1449                             UsbManager.USB_FUNCTION_ADB);
   1450                     setSystemProperty(getPersistProp(false), newFunction);
   1451                 } else {
   1452                     setSystemProperty(getPersistProp(false), UsbManager.USB_FUNCTION_NONE);
   1453                 }
   1454             }
   1455             // return passed in functions as is.
   1456             return usbFunctions;
   1457         }
   1458 
   1459         private boolean waitForState(String state) {
   1460             // wait for the transition to complete.
   1461             // give up after 1 second.
   1462             String value = null;
   1463             for (int i = 0; i < 20; i++) {
   1464                 // State transition is done when sys.usb.state is set to the new configuration
   1465                 value = getSystemProperty(USB_STATE_PROPERTY, "");
   1466                 if (state.equals(value)) return true;
   1467                 SystemClock.sleep(50);
   1468             }
   1469             Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value);
   1470             return false;
   1471         }
   1472 
   1473         private void setUsbConfig(String config) {
   1474             if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
   1475             /**
   1476              * set the new configuration
   1477              * we always set it due to b/23631400, where adbd was getting killed
   1478              * and not restarted due to property timeouts on some devices
   1479              */
   1480             setSystemProperty(USB_CONFIG_PROPERTY, config);
   1481         }
   1482 
   1483         @Override
   1484         protected void setEnabledFunctions(long usbFunctions, boolean forceRestart) {
   1485             boolean usbDataUnlocked = isUsbDataTransferActive(usbFunctions);
   1486             if (DEBUG) {
   1487                 Slog.d(TAG, "setEnabledFunctions functions=" + usbFunctions + ", "
   1488                         + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
   1489             }
   1490 
   1491             if (usbDataUnlocked != mUsbDataUnlocked) {
   1492                 mUsbDataUnlocked = usbDataUnlocked;
   1493                 updateUsbNotification(false);
   1494                 forceRestart = true;
   1495             }
   1496 
   1497             /**
   1498              * Try to set the enabled functions.
   1499              */
   1500             final long oldFunctions = mCurrentFunctions;
   1501             final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
   1502             if (trySetEnabledFunctions(usbFunctions, forceRestart)) {
   1503                 return;
   1504             }
   1505 
   1506             /**
   1507              * Didn't work.  Try to revert changes.
   1508              * We always reapply the policy in case certain constraints changed such as
   1509              * user restrictions independently of any other new functions we were
   1510              * trying to activate.
   1511              */
   1512             if (oldFunctionsApplied && oldFunctions != usbFunctions) {
   1513                 Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
   1514                 if (trySetEnabledFunctions(oldFunctions, false)) {
   1515                     return;
   1516                 }
   1517             }
   1518 
   1519             /**
   1520              * Still didn't work.  Try to restore the default functions.
   1521              */
   1522             Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
   1523             if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
   1524                 return;
   1525             }
   1526 
   1527             /**
   1528              * Now we're desperate.  Ignore the default functions.
   1529              * Try to get ADB working if enabled.
   1530              */
   1531             Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
   1532             if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
   1533                 return;
   1534             }
   1535 
   1536             /**
   1537              * Ouch.
   1538              */
   1539             Slog.e(TAG, "Unable to set any USB functions!");
   1540         }
   1541 
   1542         private boolean isNormalBoot() {
   1543             String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
   1544             return bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown");
   1545         }
   1546 
   1547         protected String applyAdbFunction(String functions) {
   1548             // Do not pass null pointer to the UsbManager.
   1549             // There isn't a check there.
   1550             if (functions == null) {
   1551                 functions = "";
   1552             }
   1553             if (mAdbEnabled) {
   1554                 functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
   1555             } else {
   1556                 functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
   1557             }
   1558             return functions;
   1559         }
   1560 
   1561         private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
   1562             String functions = null;
   1563             if (usbFunctions != UsbManager.FUNCTION_NONE) {
   1564                 functions = UsbManager.usbFunctionsToString(usbFunctions);
   1565             }
   1566             mCurrentFunctions = usbFunctions;
   1567             if (functions == null || applyAdbFunction(functions)
   1568                     .equals(UsbManager.USB_FUNCTION_NONE)) {
   1569                 functions = UsbManager.usbFunctionsToString(getChargingFunctions());
   1570             }
   1571             functions = applyAdbFunction(functions);
   1572 
   1573             String oemFunctions = applyOemOverrideFunction(functions);
   1574 
   1575             if (!isNormalBoot() && !mCurrentFunctionsStr.equals(functions)) {
   1576                 setSystemProperty(getPersistProp(true), functions);
   1577             }
   1578 
   1579             if ((!functions.equals(oemFunctions)
   1580                     && !mCurrentOemFunctions.equals(oemFunctions))
   1581                     || !mCurrentFunctionsStr.equals(functions)
   1582                     || !mCurrentFunctionsApplied
   1583                     || forceRestart) {
   1584                 Slog.i(TAG, "Setting USB config to " + functions);
   1585                 mCurrentFunctionsStr = functions;
   1586                 mCurrentOemFunctions = oemFunctions;
   1587                 mCurrentFunctionsApplied = false;
   1588 
   1589                 /**
   1590                  * Kick the USB stack to close existing connections.
   1591                  */
   1592                 setUsbConfig(UsbManager.USB_FUNCTION_NONE);
   1593 
   1594                 if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
   1595                     Slog.e(TAG, "Failed to kick USB config");
   1596                     return false;
   1597                 }
   1598 
   1599                 /**
   1600                  * Set the new USB configuration.
   1601                  */
   1602                 setUsbConfig(oemFunctions);
   1603 
   1604                 if (mBootCompleted
   1605                         && (containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
   1606                         || containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
   1607                     /**
   1608                      * Start up dependent services.
   1609                      */
   1610                     updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
   1611                 }
   1612 
   1613                 if (!waitForState(oemFunctions)) {
   1614                     Slog.e(TAG, "Failed to switch USB config to " + functions);
   1615                     return false;
   1616                 }
   1617 
   1618                 mCurrentFunctionsApplied = true;
   1619             }
   1620             return true;
   1621         }
   1622 
   1623         private String getPersistProp(boolean functions) {
   1624             String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
   1625             String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
   1626             if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
   1627                 if (functions) {
   1628                     persistProp = "persist.sys.usb." + bootMode + ".func";
   1629                 } else {
   1630                     persistProp = "persist.sys.usb." + bootMode + ".config";
   1631                 }
   1632             }
   1633             return persistProp;
   1634         }
   1635 
   1636         private static String addFunction(String functions, String function) {
   1637             if (UsbManager.USB_FUNCTION_NONE.equals(functions)) {
   1638                 return function;
   1639             }
   1640             if (!containsFunction(functions, function)) {
   1641                 if (functions.length() > 0) {
   1642                     functions += ",";
   1643                 }
   1644                 functions += function;
   1645             }
   1646             return functions;
   1647         }
   1648 
   1649         private static String removeFunction(String functions, String function) {
   1650             String[] split = functions.split(",");
   1651             for (int i = 0; i < split.length; i++) {
   1652                 if (function.equals(split[i])) {
   1653                     split[i] = null;
   1654                 }
   1655             }
   1656             if (split.length == 1 && split[0] == null) {
   1657                 return UsbManager.USB_FUNCTION_NONE;
   1658             }
   1659             StringBuilder builder = new StringBuilder();
   1660             for (int i = 0; i < split.length; i++) {
   1661                 String s = split[i];
   1662                 if (s != null) {
   1663                     if (builder.length() > 0) {
   1664                         builder.append(",");
   1665                     }
   1666                     builder.append(s);
   1667                 }
   1668             }
   1669             return builder.toString();
   1670         }
   1671 
   1672         static boolean containsFunction(String functions, String function) {
   1673             int index = functions.indexOf(function);
   1674             if (index < 0) return false;
   1675             if (index > 0 && functions.charAt(index - 1) != ',') return false;
   1676             int charAfter = index + function.length();
   1677             if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
   1678             return true;
   1679         }
   1680     }
   1681 
   1682     private static final class UsbHandlerHal extends UsbHandler {
   1683 
   1684         /**
   1685          * Proxy object for the usb gadget hal daemon.
   1686          */
   1687         @GuardedBy("mGadgetProxyLock")
   1688         private IUsbGadget mGadgetProxy;
   1689 
   1690         private final Object mGadgetProxyLock = new Object();
   1691 
   1692         /**
   1693          * Cookie sent for usb gadget hal death notification.
   1694          */
   1695         private static final int USB_GADGET_HAL_DEATH_COOKIE = 2000;
   1696 
   1697         /**
   1698          * Keeps track of the latest setCurrentUsbFunctions request number.
   1699          */
   1700         private int mCurrentRequest = 0;
   1701 
   1702         /**
   1703          * The maximum time for which the UsbDeviceManager would wait once
   1704          * setCurrentUsbFunctions is called.
   1705          */
   1706         private static final int SET_FUNCTIONS_TIMEOUT_MS = 3000;
   1707 
   1708         /**
   1709          * Conseration leeway to make sure that the hal callback arrives before
   1710          * SET_FUNCTIONS_TIMEOUT_MS expires. If the callback does not arrive
   1711          * within SET_FUNCTIONS_TIMEOUT_MS, UsbDeviceManager retries enabling
   1712          * default functions.
   1713          */
   1714         private static final int SET_FUNCTIONS_LEEWAY_MS = 500;
   1715 
   1716         /**
   1717          * While switching functions, a disconnect is excpect as the usb gadget
   1718          * us torn down and brought back up. Wait for SET_FUNCTIONS_TIMEOUT_MS +
   1719          * ENUMERATION_TIME_OUT_MS before switching back to default fumctions when
   1720          * switching functions.
   1721          */
   1722         private static final int ENUMERATION_TIME_OUT_MS = 2000;
   1723 
   1724         /**
   1725          * Command to start native service.
   1726          */
   1727         protected static final String CTL_START = "ctl.start";
   1728 
   1729         /**
   1730          * Command to start native service.
   1731          */
   1732         protected static final String CTL_STOP = "ctl.stop";
   1733 
   1734         /**
   1735          * Adb natvie daemon
   1736          */
   1737         protected static final String ADBD = "adbd";
   1738 
   1739         protected boolean mCurrentUsbFunctionsRequested;
   1740 
   1741         UsbHandlerHal(Looper looper, Context context, UsbDeviceManager deviceManager,
   1742                 UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
   1743                 UsbSettingsManager settingsManager) {
   1744             super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
   1745             try {
   1746                 ServiceNotification serviceNotification = new ServiceNotification();
   1747 
   1748                 boolean ret = IServiceManager.getService()
   1749                         .registerForNotifications("android.hardware.usb.gadget (at) 1.0::IUsbGadget",
   1750                                 "", serviceNotification);
   1751                 if (!ret) {
   1752                     Slog.e(TAG, "Failed to register usb gadget service start notification");
   1753                     return;
   1754                 }
   1755 
   1756                 synchronized (mGadgetProxyLock) {
   1757                     mGadgetProxy = IUsbGadget.getService(true);
   1758                     mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
   1759                             USB_GADGET_HAL_DEATH_COOKIE);
   1760                     mCurrentFunctions = UsbManager.FUNCTION_NONE;
   1761                     mGadgetProxy.getCurrentUsbFunctions(new UsbGadgetCallback());
   1762                     mCurrentUsbFunctionsRequested = true;
   1763                 }
   1764                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
   1765                 updateState(state);
   1766             } catch (NoSuchElementException e) {
   1767                 Slog.e(TAG, "Usb gadget hal not found", e);
   1768             } catch (RemoteException e) {
   1769                 Slog.e(TAG, "Usb Gadget hal not responding", e);
   1770             } catch (Exception e) {
   1771                 Slog.e(TAG, "Error initializing UsbHandler", e);
   1772             }
   1773         }
   1774 
   1775 
   1776         final class UsbGadgetDeathRecipient implements HwBinder.DeathRecipient {
   1777             @Override
   1778             public void serviceDied(long cookie) {
   1779                 if (cookie == USB_GADGET_HAL_DEATH_COOKIE) {
   1780                     Slog.e(TAG, "Usb Gadget hal service died cookie: " + cookie);
   1781                     synchronized (mGadgetProxyLock) {
   1782                         mGadgetProxy = null;
   1783                     }
   1784                 }
   1785             }
   1786         }
   1787 
   1788         final class ServiceNotification extends IServiceNotification.Stub {
   1789             @Override
   1790             public void onRegistration(String fqName, String name, boolean preexisting) {
   1791                 Slog.i(TAG, "Usb gadget hal service started " + fqName + " " + name);
   1792                 synchronized (mGadgetProxyLock) {
   1793                     try {
   1794                         mGadgetProxy = IUsbGadget.getService();
   1795                         mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
   1796                                 USB_GADGET_HAL_DEATH_COOKIE);
   1797                         if (!mCurrentFunctionsApplied && !mCurrentUsbFunctionsRequested) {
   1798                             setEnabledFunctions(mCurrentFunctions, false);
   1799                         }
   1800                     } catch (NoSuchElementException e) {
   1801                         Slog.e(TAG, "Usb gadget hal not found", e);
   1802                     } catch (RemoteException e) {
   1803                         Slog.e(TAG, "Usb Gadget hal not responding", e);
   1804                     }
   1805                 }
   1806             }
   1807         }
   1808 
   1809         @Override
   1810         public void handleMessage(Message msg) {
   1811             switch (msg.what) {
   1812                 case MSG_SET_CHARGING_FUNCTIONS:
   1813                     setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
   1814                     break;
   1815                 case MSG_SET_FUNCTIONS_TIMEOUT:
   1816                     Slog.e(TAG, "Set functions timed out! no reply from usb hal");
   1817                     if (msg.arg1 != 1) {
   1818                         setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
   1819                     }
   1820                     break;
   1821                 case MSG_GET_CURRENT_USB_FUNCTIONS:
   1822                     Slog.e(TAG, "prcessing MSG_GET_CURRENT_USB_FUNCTIONS");
   1823                     mCurrentUsbFunctionsReceived = true;
   1824 
   1825                     if (mCurrentUsbFunctionsRequested) {
   1826                         Slog.e(TAG, "updating mCurrentFunctions");
   1827                         // Mask out adb, since it is stored in mAdbEnabled
   1828                         mCurrentFunctions = ((Long) msg.obj) & ~UsbManager.FUNCTION_ADB;
   1829                         Slog.e(TAG,
   1830                                 "mCurrentFunctions:" + mCurrentFunctions + "applied:" + msg.arg1);
   1831                         mCurrentFunctionsApplied = msg.arg1 == 1;
   1832                     }
   1833                     finishBoot();
   1834                     break;
   1835                 case MSG_FUNCTION_SWITCH_TIMEOUT:
   1836                     /**
   1837                      * Dont force to default when the configuration is already set to default.
   1838                      */
   1839                     if (msg.arg1 != 1) {
   1840                         setEnabledFunctions(UsbManager.FUNCTION_NONE, !mAdbEnabled);
   1841                     }
   1842                     break;
   1843                 default:
   1844                     super.handleMessage(msg);
   1845             }
   1846         }
   1847 
   1848         private class UsbGadgetCallback extends IUsbGadgetCallback.Stub {
   1849             int mRequest;
   1850             long mFunctions;
   1851             boolean mChargingFunctions;
   1852 
   1853             UsbGadgetCallback() {
   1854             }
   1855 
   1856             UsbGadgetCallback(int request, long functions,
   1857                     boolean chargingFunctions) {
   1858                 mRequest = request;
   1859                 mFunctions = functions;
   1860                 mChargingFunctions = chargingFunctions;
   1861             }
   1862 
   1863             @Override
   1864             public void setCurrentUsbFunctionsCb(long functions,
   1865                     int status) {
   1866                 /**
   1867                  * Callback called for a previous setCurrenUsbFunction
   1868                  */
   1869                 if ((mCurrentRequest != mRequest) || !hasMessages(MSG_SET_FUNCTIONS_TIMEOUT)
   1870                         || (mFunctions != functions)) {
   1871                     return;
   1872                 }
   1873 
   1874                 removeMessages(MSG_SET_FUNCTIONS_TIMEOUT);
   1875                 Slog.e(TAG, "notifyCurrentFunction request:" + mRequest + " status:" + status);
   1876                 if (status == Status.SUCCESS) {
   1877                     mCurrentFunctionsApplied = true;
   1878                 } else if (!mChargingFunctions) {
   1879                     Slog.e(TAG, "Setting default fuctions");
   1880                     sendEmptyMessage(MSG_SET_CHARGING_FUNCTIONS);
   1881                 }
   1882             }
   1883 
   1884             @Override
   1885             public void getCurrentUsbFunctionsCb(long functions,
   1886                     int status) {
   1887                 sendMessage(MSG_GET_CURRENT_USB_FUNCTIONS, functions,
   1888                         status == Status.FUNCTIONS_APPLIED);
   1889             }
   1890         }
   1891 
   1892         private void setUsbConfig(long config, boolean chargingFunctions) {
   1893             if (true) Slog.d(TAG, "setUsbConfig(" + config + ") request:" + ++mCurrentRequest);
   1894             /**
   1895              * Cancel any ongoing requests, if present.
   1896              */
   1897             removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
   1898             removeMessages(MSG_SET_FUNCTIONS_TIMEOUT);
   1899             removeMessages(MSG_SET_CHARGING_FUNCTIONS);
   1900 
   1901             synchronized (mGadgetProxyLock) {
   1902                 if (mGadgetProxy == null) {
   1903                     Slog.e(TAG, "setUsbConfig mGadgetProxy is null");
   1904                     return;
   1905                 }
   1906                 try {
   1907                     if ((config & UsbManager.FUNCTION_ADB) != 0) {
   1908                         /**
   1909                          * Start adbd if ADB function is included in the configuration.
   1910                          */
   1911                         setSystemProperty(CTL_START, ADBD);
   1912                     } else {
   1913                         /**
   1914                          * Stop adbd otherwise.
   1915                          */
   1916                         setSystemProperty(CTL_STOP, ADBD);
   1917                     }
   1918                     UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest,
   1919                             config, chargingFunctions);
   1920                     mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback,
   1921                             SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS);
   1922                     sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions,
   1923                             SET_FUNCTIONS_TIMEOUT_MS);
   1924                     sendMessageDelayed(MSG_FUNCTION_SWITCH_TIMEOUT, chargingFunctions,
   1925                             SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS);
   1926                     if (DEBUG) Slog.d(TAG, "timeout message queued");
   1927                 } catch (RemoteException e) {
   1928                     Slog.e(TAG, "Remoteexception while calling setCurrentUsbFunctions", e);
   1929                 }
   1930             }
   1931         }
   1932 
   1933         @Override
   1934         protected void setEnabledFunctions(long functions, boolean forceRestart) {
   1935             if (DEBUG) {
   1936                 Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
   1937                         + "forceRestart=" + forceRestart);
   1938             }
   1939             if (mCurrentFunctions != functions
   1940                     || !mCurrentFunctionsApplied
   1941                     || forceRestart) {
   1942                 Slog.i(TAG, "Setting USB config to " + UsbManager.usbFunctionsToString(functions));
   1943                 mCurrentFunctions = functions;
   1944                 mCurrentFunctionsApplied = false;
   1945                 // set the flag to false as that would be stale value
   1946                 mCurrentUsbFunctionsRequested = false;
   1947 
   1948                 boolean chargingFunctions = functions == UsbManager.FUNCTION_NONE;
   1949                 functions = getAppliedFunctions(functions);
   1950 
   1951                 // Set the new USB configuration.
   1952                 setUsbConfig(functions, chargingFunctions);
   1953 
   1954                 if (mBootCompleted && isUsbDataTransferActive(functions)) {
   1955                     // Start up dependent services.
   1956                     updateUsbStateBroadcastIfNeeded(functions);
   1957                 }
   1958             }
   1959         }
   1960     }
   1961 
   1962     /* returns the currently attached USB accessory */
   1963     public UsbAccessory getCurrentAccessory() {
   1964         return mHandler.getCurrentAccessory();
   1965     }
   1966 
   1967     /**
   1968      * opens the currently attached USB accessory.
   1969      *
   1970      * @param accessory accessory to be openened.
   1971      */
   1972     public ParcelFileDescriptor openAccessory(UsbAccessory accessory,
   1973             UsbUserSettingsManager settings) {
   1974         UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
   1975         if (currentAccessory == null) {
   1976             throw new IllegalArgumentException("no accessory attached");
   1977         }
   1978         if (!currentAccessory.equals(accessory)) {
   1979             String error = accessory.toString()
   1980                     + " does not match current accessory "
   1981                     + currentAccessory;
   1982             throw new IllegalArgumentException(error);
   1983         }
   1984         settings.checkPermission(accessory);
   1985         return nativeOpenAccessory();
   1986     }
   1987 
   1988     public long getCurrentFunctions() {
   1989         return mHandler.getEnabledFunctions();
   1990     }
   1991 
   1992     /**
   1993      * Returns a dup of the control file descriptor for the given function.
   1994      */
   1995     public ParcelFileDescriptor getControlFd(long usbFunction) {
   1996         FileDescriptor fd = mControlFds.get(usbFunction);
   1997         if (fd == null) {
   1998             return null;
   1999         }
   2000         try {
   2001             return ParcelFileDescriptor.dup(fd);
   2002         } catch (IOException e) {
   2003             Slog.e(TAG, "Could not dup fd for " + usbFunction);
   2004             return null;
   2005         }
   2006     }
   2007 
   2008     public long getScreenUnlockedFunctions() {
   2009         return mHandler.getScreenUnlockedFunctions();
   2010     }
   2011 
   2012     /**
   2013      * Adds function to the current USB configuration.
   2014      *
   2015      * @param functions The functions to set, or empty to set the charging function.
   2016      */
   2017     public void setCurrentFunctions(long functions) {
   2018         if (DEBUG) {
   2019             Slog.d(TAG, "setCurrentFunctions(" + UsbManager.usbFunctionsToString(functions) + ")");
   2020         }
   2021         if (functions == UsbManager.FUNCTION_NONE) {
   2022             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_CHARGING);
   2023         } else if (functions == UsbManager.FUNCTION_MTP) {
   2024             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MTP);
   2025         } else if (functions == UsbManager.FUNCTION_PTP) {
   2026             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_PTP);
   2027         } else if (functions == UsbManager.FUNCTION_MIDI) {
   2028             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MIDI);
   2029         } else if (functions == UsbManager.FUNCTION_RNDIS) {
   2030             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_RNDIS);
   2031         } else if (functions == UsbManager.FUNCTION_ACCESSORY) {
   2032             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_ACCESSORY);
   2033         }
   2034         mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions);
   2035     }
   2036 
   2037     /**
   2038      * Sets the functions which are set when the screen is unlocked.
   2039      *
   2040      * @param functions Functions to set.
   2041      */
   2042     public void setScreenUnlockedFunctions(long functions) {
   2043         if (DEBUG) {
   2044             Slog.d(TAG, "setScreenUnlockedFunctions("
   2045                     + UsbManager.usbFunctionsToString(functions) + ")");
   2046         }
   2047         mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions);
   2048     }
   2049 
   2050     public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
   2051         if (mDebuggingManager != null) {
   2052             mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
   2053         }
   2054     }
   2055 
   2056     public void denyUsbDebugging() {
   2057         if (mDebuggingManager != null) {
   2058             mDebuggingManager.denyUsbDebugging();
   2059         }
   2060     }
   2061 
   2062     public void clearUsbDebuggingKeys() {
   2063         if (mDebuggingManager != null) {
   2064             mDebuggingManager.clearUsbDebuggingKeys();
   2065         } else {
   2066             throw new RuntimeException("Cannot clear Usb Debugging keys, "
   2067                     + "UsbDebuggingManager not enabled");
   2068         }
   2069     }
   2070 
   2071     /**
   2072      * Write the state to a dump stream.
   2073      */
   2074     public void dump(DualDumpOutputStream dump, String idName, long id) {
   2075         long token = dump.start(idName, id);
   2076 
   2077         if (mHandler != null) {
   2078             mHandler.dump(dump, "handler", UsbDeviceManagerProto.HANDLER);
   2079         }
   2080         if (mDebuggingManager != null) {
   2081             mDebuggingManager.dump(dump, "debugging_manager",
   2082                     UsbDeviceManagerProto.DEBUGGING_MANAGER);
   2083         }
   2084 
   2085         dump.end(token);
   2086     }
   2087 
   2088     private native String[] nativeGetAccessoryStrings();
   2089 
   2090     private native ParcelFileDescriptor nativeOpenAccessory();
   2091 
   2092     private native FileDescriptor nativeOpenControl(String usbFunction);
   2093 
   2094     private native boolean nativeIsStartRequested();
   2095 
   2096     private native int nativeGetAudioMode();
   2097 }
   2098