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