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