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