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