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