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