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