UsbDeviceManager.java revision 72ec482be00c34d9e8e9486010388e5f347ecdda
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2011 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions an
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.server.usb;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
198f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.Notification;
20629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.app.NotificationChannel;
21629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.app.NotificationManager;
2231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.app.PendingIntent;
2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.BroadcastReceiver;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.ComponentName;
255c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.ContentResolver;
2631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
279c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onoratoimport android.content.Intent;
2831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.IntentFilter;
2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.pm.PackageManager;
30f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.content.res.Resources;
315c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.database.ContentObserver;
32080d9b614e609826dce2606f9e474af674ead933Joe Onoratoimport android.hardware.usb.UsbAccessory;
33080d9b614e609826dce2606f9e474af674ead933Joe Onoratoimport android.hardware.usb.UsbManager;
3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.hardware.usb.UsbPort;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.hardware.usb.UsbPortStatus;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.BatteryManager;
3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.FileUtils;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Handler;
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Looper;
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Message;
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.ParcelFileDescriptor;
42f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.os.SystemClock;
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.SystemProperties;
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.UEventObserver;
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.UserHandle;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.UserManager;
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.storage.StorageManager;
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.storage.StorageVolume;
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.provider.Settings;
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.Pair;
5185a02a8d13eced310aee4c2a795e9c9c5435038fJoe Onoratoimport android.util.Slog;
52e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy
533a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onoratoimport com.android.internal.annotations.GuardedBy;
5431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport com.android.internal.notification.SystemNotificationChannels;
5570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkeyimport com.android.internal.os.SomeArgs;
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport com.android.internal.util.IndentingPrintWriter;
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport com.android.server.FgThread;
5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.io.File;
6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.io.FileNotFoundException;
618f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport java.io.IOException;
628f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport java.util.HashMap;
6331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.LinkedList;
6431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.List;
6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.Locale;
6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.Map;
6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.Scanner;
6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.Set;
6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * UsbDeviceManager manages USB state in device mode.
7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectpublic class UsbDeviceManager {
7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String TAG = "UsbDeviceManager";
7670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private static final boolean DEBUG = false;
7770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
7870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
7970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * The persistent property which stores whether adb is enabled or not.
8070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * May also contain vendor-specific default functions for testing purposes.
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
84f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron    /**
8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * The non-persistent property which stores the current USB settings.
8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * The property which stores the current build type (user/userdebug/eng).
9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String BUILD_TYPE_PROPERTY = "ro.build.type";
9300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private static final String BUILD_TYPE_USERDEBUG = "userdebug";
9570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private static final String BUILD_TYPE_ENG = "eng";
9670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
9770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
9870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * The non-persistent property which stores the current USB actual state.
9970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String USB_STATE_PROPERTY = "sys.usb.state";
10170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
103a9c28f6f97a4b34d9527c786e3aa8f02d92d9e07Joe Onorato     * ro.bootmode value when phone boots into usual Android.
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String NORMAL_BOOT = "normal";
106a206daaed1318005d1534cca2e4eeec56144d104Romain Guy
10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String USB_STATE_MATCH =
1088a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy            "DEVPATH=/devices/virtual/android_usb/android0";
1098a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private static final String ACCESSORY_START_MATCH =
1108a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy            "DEVPATH=/devices/virtual/misc/usb_accessory";
11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String FUNCTIONS_PATH =
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            "/sys/class/android_usb/android0/functions";
11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String STATE_PATH =
11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            "/sys/class/android_usb/android0/state";
11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String RNDIS_ETH_ADDR_PATH =
11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            "/sys/class/android_usb/android0/f_rndis/ethaddr";
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String AUDIO_SOURCE_PCM_PATH =
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            "/sys/class/android_usb/android0/f_audio_source/pcm";
11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String MIDI_ALSA_PATH =
12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            "/sys/class/android_usb/android0/f_midi/alsa";
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_UPDATE_STATE = 0;
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_ENABLE_ADB = 1;
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_SYSTEM_READY = 3;
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_BOOT_COMPLETED = 4;
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_USER_SWITCHED = 5;
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_UPDATE_HOST_STATE = 7;
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int MSG_ACCESSORY_MODE_ENTER_TIMEOUT = 8;
1318f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private static final int MSG_UPDATE_CHARGING_STATE = 9;
1328f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int AUDIO_MODE_SOURCE = 1;
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    // Delay for debouncing USB disconnects.
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    // We often get rapid connect/disconnect events when enabling USB functions,
1370d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato    // which need debouncing.
13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int UPDATE_DELAY = 1000;
13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    // Timeout for entering USB request mode.
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    // Request is cancelled if host does not configure device within 10 seconds.
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000;
14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private UsbHandler mHandler;
149a206daaed1318005d1534cca2e4eeec56144d104Romain Guy    private boolean mBootCompleted;
150a206daaed1318005d1534cca2e4eeec56144d104Romain Guy
151a206daaed1318005d1534cca2e4eeec56144d104Romain Guy    private final Object mLock = new Object();
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final Context mContext;
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final ContentResolver mContentResolver;
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @GuardedBy("mLock")
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private UsbProfileGroupSettingsManager mCurrentSettings;
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private NotificationManager mNotificationManager;
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final boolean mHasUsbAccessory;
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mUseUsbNotification;
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mAdbEnabled;
16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mAudioSourceEnabled;
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mMidiEnabled;
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mMidiCard;
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mMidiDevice;
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap;
16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private String[] mAccessoryStrings;
16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private UsbDebuggingManager mDebuggingManager;
16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final UsbAlsaManager mUsbAlsaManager;
16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final UsbSettingsManager mSettingsManager;
17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Intent mBroadcastedIntent;
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mPendingBootBroadcast;
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private class AdbSettingsObserver extends ContentObserver {
17431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public AdbSettingsObserver() {
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            super(null);
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        @Override
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void onChange(boolean selfChange) {
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean enable = (Settings.Global.getInt(mContentResolver,
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Settings.Global.ADB_ENABLED, 0) > 0);
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mHandler.sendMessage(MSG_ENABLE_ADB, enable);
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /*
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Listens for uevent messages from the kernel to monitor the USB state
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final UEventObserver mUEventObserver = new UEventObserver() {
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        @Override
19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void onUEvent(UEventObserver.UEvent event) {
19231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
19331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            String state = event.get("USB_STATE");
19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            String accessory = event.get("ACCESSORY");
19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (state != null) {
19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mHandler.updateState(state);
19831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else if ("START".equals(accessory)) {
19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (DEBUG) Slog.d(TAG, "got accessory start");
20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                startAccessoryMode();
20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    };
20431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
20531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final BroadcastReceiver mHostReceiver = new BroadcastReceiver() {
20631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        @Override
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void onReceive(Context context, Intent intent) {
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT);
20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS);
21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mHandler.updateHostState(port, status);
21131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    };
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() {
21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        @Override
21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void onReceive(Context context, Intent intent) {
21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
21831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
21931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging);
22031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    };
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            UsbSettingsManager settingsManager) {
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mContext = context;
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mUsbAlsaManager = alsaManager;
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mSettingsManager = settingsManager;
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mContentResolver = context.getContentResolver();
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        PackageManager pm = mContext.getPackageManager();
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initRndisAddress();
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        readOemUsbOverrideConfig();
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mHandler = new UsbHandler(FgThread.get().getLooper());
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (nativeIsStartRequested()) {
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (DEBUG) Slog.d(TAG, "accessory attached at boot");
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            startAccessoryMode();
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (secureAdbEnabled && !dataEncrypted) {
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mDebuggingManager = new UsbDebuggingManager(context);
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mContext.registerReceiver(mHostReceiver,
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED));
249c45b16862918a0c6c253bba12032165b030565afJoe Onorato        mContext.registerReceiver(mChargingReceiver,
2504c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private UsbProfileGroupSettingsManager getCurrentSettings() {
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        synchronized (mLock) {
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return mCurrentSettings;
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void systemReady() {
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (DEBUG) Slog.d(TAG, "systemReady");
26131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mNotificationManager = (NotificationManager)
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Ensure that the notification channels are set up
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (isTv()) {
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // TV-specific notification channel
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mNotificationManager.createNotificationChannel(
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            mContext.getString(
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                    com.android.internal.R.string
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                            .adb_debugging_notification_channel_tv),
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            NotificationManager.IMPORTANCE_HIGH));
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // We do not show the USB notification if the primary volume supports mass storage.
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // The legacy mass storage UI will be used instead.
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        boolean massStorageSupported = false;
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final StorageManager storageManager = StorageManager.from(mContext);
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final StorageVolume primary = storageManager.getPrimaryVolume();
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        massStorageSupported = primary != null && primary.allowMassStorage();
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                com.android.internal.R.bool.config_usbChargingMessage);
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // make sure the ADB_ENABLED setting value matches the current state
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        try {
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Settings.Global.putInt(mContentResolver,
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } catch (SecurityException e) {
29031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.d(TAG, "ADB_ENABLED is restricted.");
29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void bootCompleted() {
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (DEBUG) Slog.d(TAG, "boot completed");
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void setCurrentUser(int newCurrentUserId, UsbProfileGroupSettingsManager settings) {
30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        synchronized (mLock) {
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mCurrentSettings = settings;
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mHandler.obtainMessage(MSG_USER_SWITCHED, newCurrentUserId, 0).sendToTarget();
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void updateUserRestrictions() {
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mHandler.sendEmptyMessage(MSG_UPDATE_USER_RESTRICTIONS);
31031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
31131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private void startAccessoryMode() {
31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!mHasUsbAccessory) return;
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mAccessoryStrings = nativeGetAccessoryStrings();
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE);
3174c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        // don't start accessory mode if our mandatory strings have not been set
3184c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        boolean enableAccessory = (mAccessoryStrings != null &&
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAccessoryStrings[UsbAccessory.MODEL_STRING] != null);
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        String functions = null;
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (enableAccessory && enableAudio) {
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            functions = UsbManager.USB_FUNCTION_ACCESSORY + ","
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    + UsbManager.USB_FUNCTION_AUDIO_SOURCE;
32631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else if (enableAccessory) {
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            functions = UsbManager.USB_FUNCTION_ACCESSORY;
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else if (enableAudio) {
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE;
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
3310d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (functions != null) {
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_MODE_ENTER_TIMEOUT),
33400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    ACCESSORY_REQUEST_TIMEOUT);
33500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            setCurrentFunctions(functions, false);
33600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static void initRndisAddress() {
34031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // configure RNDIS ethernet address based on our serial number using the same algorithm
34131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // we had been previously using in kernel board files
34270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        final int ETH_ALEN = 6;
34331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int address[] = new int[ETH_ALEN];
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // first byte is 0x02 to signify a locally administered address
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        address[0] = 0x02;
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3474c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF");
3484c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        int serialLength = serial.length();
3494c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        // XOR the USB serial across the remaining 5 bytes
3504c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        for (int i = 0; i < serialLength; i++) {
3514c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy            address[i % (ETH_ALEN - 1) + 1] ^= (int) serial.charAt(i);
3524c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        }
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        String addrString = String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                address[0], address[1], address[2], address[3], address[4], address[5]);
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        try {
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString);
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } catch (IOException e) {
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH);
35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
36131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean isTv() {
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final class UsbHandler extends Handler {
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3688f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        // current USB state
369798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        private boolean mConnected;
370798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        private boolean mHostConnected;
371798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        private boolean mSourcePower;
372798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        private boolean mSinkPower;
373c07c79b10b663a02ef67da57bdda60a1ea299eb5Marco Nelissen        private boolean mConfigured;
37449cdb1b18c12a81cac9817c4800e43d5b507e0c4Dianne Hackborn        private boolean mUsbDataUnlocked;
3758f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        private String mCurrentFunctions;
3768f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        private boolean mCurrentFunctionsApplied;
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private UsbAccessory mCurrentAccessory;
37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private int mUsbNotificationId;
37931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private boolean mAdbNotificationShown;
38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private int mCurrentUser = UserHandle.USER_NULL;
38131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private boolean mUsbCharging;
3828f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        private String mCurrentOemFunctions;
38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public UsbHandler(Looper looper) {
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            super(looper);
3868a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy            try {
3878a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy                // Restore default functions.
38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (isNormalBoot()) {
39031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            UsbManager.USB_FUNCTION_NONE);
39231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mCurrentFunctionsApplied = mCurrentFunctions.equals(
39331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            SystemProperties.get(USB_STATE_PROPERTY));
39431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else {
39531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mCurrentFunctions = SystemProperties.get(getPersistProp(true),
3967376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project                            UsbManager.USB_FUNCTION_NONE);
397e77c08d15f23c403293dbb40c6a36967de822c89Joe Onorato                    mCurrentFunctionsApplied = SystemProperties.get(USB_CONFIG_PROPERTY,
398e77c08d15f23c403293dbb40c6a36967de822c89Joe Onorato                            UsbManager.USB_FUNCTION_NONE).equals(
39931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            SystemProperties.get(USB_STATE_PROPERTY));
40031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
40131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
40231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                /**
40331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                 * Use the normal bootmode persistent prop to maintain state of adb across
404f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy                 * all boot modes.
40531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                 */
40631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAdbEnabled = UsbManager.containsFunction(
40731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY),
40831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        UsbManager.USB_FUNCTION_ADB);
40931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
41031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                /**
41131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                 * Remove MTP from persistent config, to bring usb to a good state
41231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                 * after fixes to b/31814300. This block can be removed after the update
41331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                 */
41431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
41531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)) {
41631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
41731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            UsbManager.removeFunction(persisted, UsbManager.USB_FUNCTION_MTP));
41831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
41931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
42031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
42131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                updateState(state);
42231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4237376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project                // register observer to listen for settings changes
4247376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project                mContentResolver.registerContentObserver(
425e77c08d15f23c403293dbb40c6a36967de822c89Joe Onorato                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
4267376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project                        false, new AdbSettingsObserver());
42731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
42831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Watch for USB configuration changes
42900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mUEventObserver.startObserving(USB_STATE_MATCH);
43000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mUEventObserver.startObserving(ACCESSORY_START_MATCH);
43100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            } catch (Exception e) {
43200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                Slog.e(TAG, "Error initializing UsbHandler", e);
43300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
43531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void sendMessage(int what, boolean arg) {
43731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            removeMessages(what);
43831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Message m = Message.obtain(this, what);
43931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            m.arg1 = (arg ? 1 : 0);
44031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sendMessage(m);
44131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
44231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
44331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void sendMessage(int what, Object arg) {
44431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            removeMessages(what);
44531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Message m = Message.obtain(this, what);
44631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            m.obj = arg;
44731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sendMessage(m);
44831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
44931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void sendMessage(int what, Object arg, boolean arg1) {
45131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            removeMessages(what);
45231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Message m = Message.obtain(this, what);
45331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            m.obj = arg;
45431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            m.arg1 = (arg1 ? 1 : 0);
4553a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron            sendMessage(m);
45631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
4573a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron
45831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void updateState(String state) {
4593a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron            int connected, configured;
460798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
46131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if ("DISCONNECTED".equals(state)) {
46231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                connected = 0;
46331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                configured = 0;
46431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else if ("CONNECTED".equals(state)) {
46531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                connected = 1;
46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                configured = 0;
46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else if ("CONFIGURED".equals(state)) {
46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                connected = 1;
46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                configured = 1;
47031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
47131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                Slog.e(TAG, "unknown state " + state);
47231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return;
47331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
47431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            removeMessages(MSG_UPDATE_STATE);
47531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Message msg = Message.obtain(this, MSG_UPDATE_STATE);
47631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            msg.arg1 = connected;
47731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            msg.arg2 = configured;
47831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // debounce disconnects to avoid problems bringing up USB tethering
47931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
48031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
48131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
48231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void updateHostState(UsbPort port, UsbPortStatus status) {
48331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean hostConnected = status.getCurrentDataRole() == UsbPort.DATA_ROLE_HOST;
48431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean sourcePower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE;
48531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean sinkPower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SINK;
48631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
48731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (DEBUG) {
48831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                Slog.i(TAG, "updateHostState " + port + " status=" + status);
48931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
49031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            SomeArgs args = SomeArgs.obtain();
49231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            args.argi1 = hostConnected ? 1 : 0;
49331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            args.argi2 = sourcePower ? 1 : 0;
494678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato            args.argi3 = sinkPower ? 1 : 0;
49531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            removeMessages(MSG_UPDATE_HOST_STATE);
49731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Message msg = obtainMessage(MSG_UPDATE_HOST_STATE, args);
49831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // debounce rapid transitions of connect/disconnect on type-c ports
49931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sendMessageDelayed(msg, UPDATE_DELAY);
50031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
50131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
50231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private boolean waitForState(String state) {
50331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // wait for the transition to complete.
50431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // give up after 1 second.
50531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            String value = null;
50631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < 20; i++) {
50731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // State transition is done when sys.usb.state is set to the new configuration
50831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                value = SystemProperties.get(USB_STATE_PROPERTY);
50931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (state.equals(value)) return true;
51031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                SystemClock.sleep(50);
51131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
51231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value);
51331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return false;
51431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
51531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
51631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void setUsbConfig(String config) {
51731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
51831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // set the new configuration
51931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // we always set it due to b/23631400, where adbd was getting killed
52031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // and not restarted due to property timeouts on some devices
52131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            SystemProperties.set(USB_CONFIG_PROPERTY, config);
52231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
52331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
52431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void setAdbEnabled(boolean enable) {
52531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
52631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (enable != mAdbEnabled) {
52731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAdbEnabled = enable;
528c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy                String oldFunctions = mCurrentFunctions;
529678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato
53031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Persist the adb setting
53131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                String newFunction = applyAdbFunction(SystemProperties.get(
53231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE));
53331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunction);
53431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
53531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Remove mtp from the config if file transfer is not enabled
53631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (oldFunctions.equals(UsbManager.USB_FUNCTION_MTP) &&
53731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        !mUsbDataUnlocked && enable) {
53831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    oldFunctions = UsbManager.USB_FUNCTION_NONE;
53931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
54031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
54131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
54231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                updateAdbNotification();
54331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
54431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
54531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDebuggingManager != null) {
54631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mDebuggingManager.setAdbEnabled(mAdbEnabled);
54731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
54831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
5497bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
5507bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        /**
5517bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato         * Evaluates USB function policies and applies the change accordingly.
5527bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato         */
5537bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        private void setEnabledFunctions(String functions, boolean forceRestart,
5547bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                boolean usbDataUnlocked) {
5557bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            if (DEBUG) {
5567bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
5577bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                        + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
5587bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
55931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
56068ba5ca5d7f17df65f0cc8813603de2d3f215bf4Joe Onorato            if (usbDataUnlocked != mUsbDataUnlocked) {
56168ba5ca5d7f17df65f0cc8813603de2d3f215bf4Joe Onorato                mUsbDataUnlocked = usbDataUnlocked;
56268ba5ca5d7f17df65f0cc8813603de2d3f215bf4Joe Onorato                updateUsbNotification();
5637c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato                forceRestart = true;
56431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
56531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
56631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Try to set the enabled functions.
56731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final String oldFunctions = mCurrentFunctions;
56831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
56931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (trySetEnabledFunctions(functions, forceRestart)) {
57031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return;
57131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
57231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
57331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Didn't work.  Try to revert changes.
57431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // We always reapply the policy in case certain constraints changed such as
57531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // user restrictions independently of any other new functions we were
57631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // trying to activate.
57731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (oldFunctionsApplied && !oldFunctions.equals(functions)) {
57831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
57931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (trySetEnabledFunctions(oldFunctions, false)) {
58031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return;
58131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
58231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
58331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
58431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Still didn't work.  Try to restore the default functions.
58531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
58631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (trySetEnabledFunctions(null, false)) {
58731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return;
58831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
58931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Now we're desperate.  Ignore the default functions.
59131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Try to get ADB working if enabled.
59231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
59331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) {
59431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return;
59531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
59631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Ouch.
59831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.e(TAG, "Unable to set any USB functions!");
59931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
60031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
60131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private boolean isNormalBoot() {
60231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
60331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown")) {
60431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return true;
60531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
60631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return false;
60731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
6083a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron
60931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
61031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (functions == null || applyAdbFunction(functions)
61131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    .equals(UsbManager.USB_FUNCTION_NONE)) {
61231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                functions = getDefaultFunctions();
61331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
61431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            functions = applyAdbFunction(functions);
61531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
61631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            String oemFunctions = applyOemOverrideFunction(functions);
61731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
61831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (!isNormalBoot() && !mCurrentFunctions.equals(functions)) {
61931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                SystemProperties.set(getPersistProp(true), functions);
62031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
62131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
62231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if ((!functions.equals(oemFunctions) &&
62331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    (mCurrentOemFunctions == null ||
62431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            !mCurrentOemFunctions.equals(oemFunctions)))
62531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    || !mCurrentFunctions.equals(functions)
62631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    || !mCurrentFunctionsApplied
62731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    || forceRestart) {
62831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                Slog.i(TAG, "Setting USB config to " + functions);
62931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mCurrentFunctions = functions;
63031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mCurrentOemFunctions = oemFunctions;
63131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mCurrentFunctionsApplied = false;
63231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
63331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Kick the USB stack to close existing connections.
63431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                setUsbConfig(UsbManager.USB_FUNCTION_NONE);
63531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
63631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
63731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Slog.e(TAG, "Failed to kick USB config");
638f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                    return false;
639f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                }
640f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron
641f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                // Set the new USB configuration.
642f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                setUsbConfig(oemFunctions);
643f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron
644f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                if (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
645f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                        || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP)) {
646f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                    // Start up dependent services.
647f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                    updateUsbStateBroadcastIfNeeded(true);
648f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                }
64931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
65031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (!waitForState(oemFunctions)) {
65131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Slog.e(TAG, "Failed to switch USB config to " + functions);
65231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return false;
653f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron                }
65431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
65531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mCurrentFunctionsApplied = true;
65631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
65731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return true;
65831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
65931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
66031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private String applyAdbFunction(String functions) {
66131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Do not pass null pointer to the UsbManager.
66231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // There isnt a check there.
66331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (functions == null) {
6643a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                functions = "";
6653a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            }
6663a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            if (mAdbEnabled) {
6673a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                functions = UsbManager.addFunction(functions, UsbManager.USB_FUNCTION_ADB);
6683a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            } else {
6693a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
6703a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            }
6713a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            return functions;
6723a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato        }
6733a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato
6743a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato        private boolean isUsbTransferAllowed() {
6753a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
6763a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            return !userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
6773a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato        }
6783a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato
6793a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato        private void updateCurrentAccessory() {
6803a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            // We are entering accessory mode if we have received a request from the host
6813a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            // and the request has not timed out yet.
6823a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            boolean enteringAccessoryMode = hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT);
6833a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato
6843a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato            if (mConfigured && enteringAccessoryMode) {
6853a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                // successfully entered accessory mode
6863a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                if (mAccessoryStrings != null) {
6873a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                    mCurrentAccessory = new UsbAccessory(mAccessoryStrings);
6883a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                    Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
6893a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                    // defer accessoryAttached if system is not ready
6903a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                    if (mBootCompleted) {
6913a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
6923a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                    } // else handle in boot completed
6933a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                } else {
6943a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                    Slog.e(TAG, "nativeGetAccessoryStrings failed");
6953a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                }
6963a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron            } else {
6973a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                if (!enteringAccessoryMode) {
69831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    notifyAccessoryModeExit();
6993a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                } else if (DEBUG) {
7003a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                    Slog.v(TAG, "Debouncing accessory mode exit");
7013a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                }
7023a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron            }
7033a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
70431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
70531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void notifyAccessoryModeExit() {
70631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // make sure accessory mode is off
70731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // and restore default functions
70831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.d(TAG, "exited USB accessory mode");
70931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            setEnabledFunctions(null, false, false);
71031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
71131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mCurrentAccessory != null) {
71231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mBootCompleted) {
71331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mSettingsManager.usbAccessoryRemoved(mCurrentAccessory);
71431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
71531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mCurrentAccessory = null;
71631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAccessoryStrings = null;
71731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
71831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
71931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
720f8bbd34d7d4705b49db202be92b920196bc7ea38Mike Cleron        private boolean isUsbStateChanged(Intent intent) {
7212bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            final Set<String> keySet = intent.getExtras().keySet();
7222bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (mBroadcastedIntent == null) {
7232bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                for (String key : keySet) {
7242bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                    if (intent.getBooleanExtra(key, false)) {
7252bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                        return true;
7262bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                    }
7272bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                }
7282bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            } else {
7292bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                if (!keySet.equals(mBroadcastedIntent.getExtras().keySet())) {
7307c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato                    return true;
73131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
73231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                for (String key : keySet) {
73331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (intent.getBooleanExtra(key, false) !=
73431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            mBroadcastedIntent.getBooleanExtra(key, false)) {
73531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return true;
73631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
73731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
73831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
73931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return false;
74031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
74131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
74231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void updateUsbStateBroadcastIfNeeded(boolean configChanged) {
74331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // send a sticky broadcast containing current USB state
74431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
74531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
74631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
74731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    | Intent.FLAG_RECEIVER_FOREGROUND);
74831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
74931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
75031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
75131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            intent.putExtra(UsbManager.USB_DATA_UNLOCKED,
75231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    isUsbTransferAllowed() && mUsbDataUnlocked);
75331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            intent.putExtra(UsbManager.USB_CONFIG_CHANGED, configChanged);
75431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
75531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mCurrentFunctions != null) {
75631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                String[] functions = mCurrentFunctions.split(",");
75731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                for (int i = 0; i < functions.length; i++) {
75831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    final String function = functions[i];
75931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (UsbManager.USB_FUNCTION_NONE.equals(function)) {
76031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        continue;
76131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
76231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    intent.putExtra(function, true);
7638f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn                }
76431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
76531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
76631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // send broadcast intent only if the USB state has changed
76731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (!isUsbStateChanged(intent)) {
76831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (DEBUG) {
76931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
7708f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn                }
77131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return;
7723a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron            }
7733a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron
77431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
77531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
77631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mBroadcastedIntent = intent;
77731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
77831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
77931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void updateUsbFunctions() {
780a206daaed1318005d1534cca2e4eeec56144d104Romain Guy            updateAudioSourceFunction();
78131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            updateMidiFunction();
78231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
78331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
78431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void updateAudioSourceFunction() {
78531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
78631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    UsbManager.USB_FUNCTION_AUDIO_SOURCE);
78731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (enabled != mAudioSourceEnabled) {
78831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                int card = -1;
78931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                int device = -1;
79031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
79131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (enabled) {
79231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Scanner scanner = null;
79331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    try {
79431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
79531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        card = scanner.nextInt();
79631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        device = scanner.nextInt();
79731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    } catch (FileNotFoundException e) {
79831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        Slog.e(TAG, "could not open audio source PCM file", e);
79931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    } finally {
80031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        if (scanner != null) {
80131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            scanner.close();
80231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        }
80331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
80431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
80531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mUsbAlsaManager.setAccessoryAudioState(enabled, card, device);
80631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAudioSourceEnabled = enabled;
80731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
80831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
80931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
81031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void updateMidiFunction() {
81131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
81231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    UsbManager.USB_FUNCTION_MIDI);
81331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (enabled != mMidiEnabled) {
81431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (enabled) {
815e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy                    Scanner scanner = null;
81682d94d9e9ee4eb6b14db3c8df2f47dcae5ce4ab0Romain Guy                    try {
8173a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                        scanner = new Scanner(new File(MIDI_ALSA_PATH));
8183a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                        mMidiCard = scanner.nextInt();
8194c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                        mMidiDevice = scanner.nextInt();
8203a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                    } catch (FileNotFoundException e) {
82131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        Slog.e(TAG, "could not open MIDI file", e);
8223a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron                        enabled = false;
82331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    } finally {
82431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        if (scanner != null) {
825e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy                            scanner.close();
826e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy                        }
827e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy                    }
82831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
82931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mMidiEnabled = enabled;
8303a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron            }
83131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mUsbAlsaManager.setPeripheralMidiState(
83231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
83331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
83431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
83531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        @Override
8363a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        public void handleMessage(Message msg) {
8373a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron            switch (msg.what) {
838f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy                case MSG_UPDATE_STATE:
839f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy                    mConnected = (msg.arg1 == 1);
840c45b16862918a0c6c253bba12032165b030565afJoe Onorato                    mConfigured = (msg.arg2 == 1);
84131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
84231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    updateUsbNotification();
84331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    updateAdbNotification();
84431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (UsbManager.containsFunction(mCurrentFunctions,
84531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            UsbManager.USB_FUNCTION_ACCESSORY)) {
84631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        updateCurrentAccessory();
84731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
8487984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert                    if (mBootCompleted) {
84931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        if (!mConnected) {
85031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            // restore defaults when USB is disconnected
85131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            setEnabledFunctions(null, false, false);
85231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        }
85331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        updateUsbStateBroadcastIfNeeded(false);
85431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        updateUsbFunctions();
85531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    } else {
85631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mPendingBootBroadcast = true;
85731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
85800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    break;
85931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_UPDATE_HOST_STATE:
86031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    SomeArgs args = (SomeArgs) msg.obj;
86131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mHostConnected = (args.argi1 == 1);
86231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mSourcePower = (args.argi2 == 1);
86331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mSinkPower = (args.argi3 == 1);
86431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    args.recycle();
86531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    updateUsbNotification();
86631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (mBootCompleted) {
86731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        updateUsbStateBroadcastIfNeeded(false);
86831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    } else {
86931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mPendingBootBroadcast = true;
87031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
87131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
87231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_UPDATE_CHARGING_STATE:
87331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mUsbCharging = (msg.arg1 == 1);
87431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    updateUsbNotification();
87531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
87631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_ENABLE_ADB:
87731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    setAdbEnabled(msg.arg1 == 1);
87831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
87931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_SET_CURRENT_FUNCTIONS:
88031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    String functions = (String) msg.obj;
88131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    setEnabledFunctions(functions, false, msg.arg1 == 1);
88231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
88331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_UPDATE_USER_RESTRICTIONS:
88431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    // Restart the USB stack if USB transfer is enabled but no longer allowed.
88531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    final boolean forceRestart = mUsbDataUnlocked
88631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            && isUsbDataTransferActive()
88731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            && !isUsbTransferAllowed();
88831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    setEnabledFunctions(
88931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart);
89031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
89131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_SYSTEM_READY:
89200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    updateUsbNotification();
89300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    updateAdbNotification();
89470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    updateUsbFunctions();
89531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
89631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_BOOT_COMPLETED:
89731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mBootCompleted = true;
89831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (mPendingBootBroadcast) {
89931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        updateUsbStateBroadcastIfNeeded(false);
90031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mPendingBootBroadcast = false;
90152d9cb32608e7c3d065b4fb8e97269e238f1683eRomain Guy                    }
90252d9cb32608e7c3d065b4fb8e97269e238f1683eRomain Guy                    setEnabledFunctions(null, false, false);
90331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (mCurrentAccessory != null) {
90431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
90531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
90631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (mDebuggingManager != null) {
907263e019baafb3b6cbcfdef9c81d74a4bea769180Romain Guy                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
90870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    }
90970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    break;
91031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                case MSG_USER_SWITCHED: {
91184f296c106cb1c7b6d3ae6c6d5508a17f1324e29Romain Guy                    if (mCurrentUser != msg.arg1) {
91231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        // Restart the USB stack and re-apply user restrictions for MTP or PTP.
91331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        if (mUsbDataUnlocked
91452d9cb32608e7c3d065b4fb8e97269e238f1683eRomain Guy                                && isUsbDataTransferActive()
91531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                && mCurrentUser != UserHandle.USER_NULL) {
91631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            Slog.v(TAG, "Current user switched to " + msg.arg1
91731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                    + "; resetting USB host stack for MTP or PTP");
91831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            // avoid leaking sensitive data from previous user
91931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            setEnabledFunctions(mCurrentFunctions, true, false);
92000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                        }
9214c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                        mCurrentUser = msg.arg1;
92231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
92331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
92431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
92500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                case MSG_ACCESSORY_MODE_ENTER_TIMEOUT: {
92631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (DEBUG) {
92731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        Slog.v(TAG, "Accessory mode enter timeout: " + mConnected);
92831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
92900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    if (!mConnected) {
9304c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                        notifyAccessoryModeExit();
93131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
93231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
93331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
93431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
93531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
93631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
93731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private boolean isUsbDataTransferActive() {
93831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
93931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    || UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
94031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
94131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
94231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public UsbAccessory getCurrentAccessory() {
94331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return mCurrentAccessory;
94431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
94531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
94631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private void updateUsbNotification() {
94731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mNotificationManager == null || !mUseUsbNotification
94831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    || ("0".equals(SystemProperties.get("persist.charging.notify")))) {
94931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return;
95031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
95131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int id = 0;
95231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Resources r = mContext.getResources();
95331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mConnected) {
95431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (!mUsbDataUnlocked) {
95531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (mSourcePower) {
95631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        id = com.android.internal.R.string.usb_supplying_notification_title;
95731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    } else {
95831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        id = com.android.internal.R.string.usb_charging_notification_title;
95931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
96031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else if (UsbManager.containsFunction(mCurrentFunctions,
96131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        UsbManager.USB_FUNCTION_MTP)) {
96231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    id = com.android.internal.R.string.usb_mtp_notification_title;
9630d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato                } else if (UsbManager.containsFunction(mCurrentFunctions,
96431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        UsbManager.USB_FUNCTION_PTP)) {
96500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    id = com.android.internal.R.string.usb_ptp_notification_title;
966207e40ee66fddded52a028b8f68be3605da3df37Romain Guy                } else if (UsbManager.containsFunction(mCurrentFunctions,
96700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                        UsbManager.USB_FUNCTION_MIDI)) {
96800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    id = com.android.internal.R.string.usb_midi_notification_title;
969263e019baafb3b6cbcfdef9c81d74a4bea769180Romain Guy                } else if (UsbManager.containsFunction(mCurrentFunctions,
97070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                        UsbManager.USB_FUNCTION_ACCESSORY)) {
97131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    id = com.android.internal.R.string.usb_accessory_notification_title;
97231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else if (mSourcePower) {
97331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    id = com.android.internal.R.string.usb_supplying_notification_title;
97431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else {
97531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    id = com.android.internal.R.string.usb_charging_notification_title;
97670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                }
97770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            } else if (mSourcePower) {
97870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                id = com.android.internal.R.string.usb_supplying_notification_title;
97970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            } else if (mHostConnected && mSinkPower && mUsbCharging) {
98070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                id = com.android.internal.R.string.usb_charging_notification_title;
98170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            }
98270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            if (id != mUsbNotificationId) {
98370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                // clear notification if title needs changing
98470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                if (mUsbNotificationId != 0) {
98531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mNotificationManager.cancelAsUser(null, mUsbNotificationId,
98670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                            UserHandle.ALL);
98770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    mUsbNotificationId = 0;
98870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                }
98970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                if (id != 0) {
99000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    CharSequence message = r.getText(
9914c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                            com.android.internal.R.string.usb_notification_message);
9924c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                    CharSequence title = r.getText(id);
9934c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
9944c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                    Intent intent = Intent.makeRestartActivityTask(
9954c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                            new ComponentName("com.android.settings",
9964c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                                    "com.android.settings.deviceinfo.UsbModeChooserActivity"));
9974c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                    PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
9984c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                            intent, 0, null, UserHandle.CURRENT);
9994c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
10004c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                    Notification notification =
10014c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                            new Notification.Builder(mContext, SystemNotificationChannels.USB)
100270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
100370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setWhen(0)
100470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setOngoing(true)
100570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setTicker(title)
100670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setDefaults(0)  // please be quiet
100770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setColor(mContext.getColor(
100800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                                            com.android.internal.R.color
100970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                                    .system_notification_accent_color))
101070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setContentTitle(title)
101131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                    .setContentText(message)
101270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setContentIntent(pi)
101370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setVisibility(Notification.VISIBILITY_PUBLIC)
101470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .build();
101570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    mNotificationManager.notifyAsUser(null, id, notification,
101670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                            UserHandle.ALL);
101770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    mUsbNotificationId = id;
101870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                }
1019263e019baafb3b6cbcfdef9c81d74a4bea769180Romain Guy            }
102070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        }
102170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
102270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        private void updateAdbNotification() {
102370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            if (mNotificationManager == null) return;
102470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            final int id = com.android.internal.R.string.adb_active_notification_title;
102570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            if (mAdbEnabled && mConnected) {
102670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
102770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
102870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                if (!mAdbNotificationShown) {
102970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    Resources r = mContext.getResources();
103070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    CharSequence title = r.getText(id);
103170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    CharSequence message = r.getText(
103270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                            com.android.internal.R.string.adb_active_notification_message);
103370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
103470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
103531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
103631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            | Intent.FLAG_ACTIVITY_CLEAR_TASK);
103770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                    PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
103870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                            intent, 0, null, UserHandle.CURRENT);
103970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
1040263e019baafb3b6cbcfdef9c81d74a4bea769180Romain Guy                    Notification notification =
104170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                            new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
104270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
104370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setWhen(0)
104470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setOngoing(true)
104570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setTicker(title)
104670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setDefaults(0)  // please be quiet
104770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setColor(mContext.getColor(
104870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                            com.android.internal.R.color
104970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                                    .system_notification_accent_color))
105070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setContentTitle(title)
105170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey                                    .setContentText(message)
105231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                    .setContentIntent(pi)
105331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                    .setVisibility(Notification.VISIBILITY_PUBLIC)
105431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                    .extend(new Notification.TvExtender()
105531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                            .setChannel(ADB_NOTIFICATION_CHANNEL_ID_TV))
105600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                                    .build();
105700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mAdbNotificationShown = true;
105831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mNotificationManager.notifyAsUser(null, id, notification,
105931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            UserHandle.ALL);
106031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
1061207e40ee66fddded52a028b8f68be3605da3df37Romain Guy            } else if (mAdbNotificationShown) {
1062207e40ee66fddded52a028b8f68be3605da3df37Romain Guy                mAdbNotificationShown = false;
106331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
106431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
106531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
106631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
106700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        private String getDefaultFunctions() {
106800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            String func = SystemProperties.get(getPersistProp(true),
106900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    UsbManager.USB_FUNCTION_NONE);
1070207e40ee66fddded52a028b8f68be3605da3df37Romain Guy            if (UsbManager.USB_FUNCTION_NONE.equals(func)) {
107131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                func = UsbManager.USB_FUNCTION_MTP;
107231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
107331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return func;
107431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
107531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
107631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void dump(IndentingPrintWriter pw) {
107731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            pw.println("USB Device State:");
107831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            pw.println("  mCurrentFunctions: " + mCurrentFunctions);
107931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            pw.println("  mCurrentOemFunctions: " + mCurrentOemFunctions);
108031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            pw.println("  mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
108131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            pw.println("  mConnected: " + mConnected);
108231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            pw.println("  mConfigured: " + mConfigured);
10834c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy            pw.println("  mUsbDataUnlocked: " + mUsbDataUnlocked);
1084f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy            pw.println("  mCurrentAccessory: " + mCurrentAccessory);
1085f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy            pw.println("  mHostConnected: " + mHostConnected);
1086f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy            pw.println("  mSourcePower: " + mSourcePower);
1087f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy            pw.println("  mSinkPower: " + mSinkPower);
108831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            pw.println("  mUsbCharging: " + mUsbCharging);
108931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            try {
109031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                pw.println("  Kernel state: "
109131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
10924c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy                pw.println("  Kernel function list: "
1093f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy                        + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
1094f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy            } catch (IOException e) {
1095f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy                pw.println("IOException: " + e);
1096f8e6a80acd4e5558fdf7e0559f1043a2b183a8faRomain Guy            }
109731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
109831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
109931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
110031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /* returns the currently attached USB accessory */
110131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public UsbAccessory getCurrentAccessory() {
110231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return mHandler.getCurrentAccessory();
110331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
110431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
110531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /* opens the currently attached USB accessory */
110631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public ParcelFileDescriptor openAccessory(UsbAccessory accessory,
110731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            UsbUserSettingsManager settings) {
110831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
110931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (currentAccessory == null) {
111031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("no accessory attached");
111131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
111231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!currentAccessory.equals(accessory)) {
1113138a04170d964da9cdec228e95b976875ae52481Karl Rosaen            String error = accessory.toString()
111431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    + " does not match current accessory "
111531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    + currentAccessory;
111631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException(error);
111731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
111831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        settings.checkPermission(accessory);
111931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return nativeOpenAccessory();
112031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
112131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
112231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean isFunctionEnabled(String function) {
112331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function);
112431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
112531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
112631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void setCurrentFunctions(String functions, boolean usbDataUnlocked) {
112731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (DEBUG) {
112831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Slog.d(TAG, "setCurrentFunctions(" + functions + ", " +
112931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    usbDataUnlocked + ")");
113031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
113131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
113231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
113331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
113431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private void readOemUsbOverrideConfig() {
113531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        String[] configList = mContext.getResources().getStringArray(
113631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                com.android.internal.R.array.config_oemUsbModeOverride);
113731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
113831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (configList != null) {
113931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (String config : configList) {
114031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                String[] items = config.split(":");
114131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (items.length == 3 || items.length == 4) {
114231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (mOemModeMap == null) {
114331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mOemModeMap = new HashMap<String, HashMap<String,
114431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                Pair<String, String>>>();
114531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
114631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    HashMap<String, Pair<String, String>> overrideMap
114731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            = mOemModeMap.get(items[0]);
114831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (overrideMap == null) {
114931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        overrideMap = new HashMap<String,
115031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                Pair<String, String>>();
115131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mOemModeMap.put(items[0], overrideMap);
115231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
115331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1154ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                    // Favoring the first combination if duplicate exists
1155ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                    if (!overrideMap.containsKey(items[1])) {
1156ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                        if (items.length == 3) {
1157ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                            overrideMap.put(items[1],
1158ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                                    new Pair<String, String>(items[2], ""));
1159ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                        } else {
1160ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                            overrideMap.put(items[1],
1161ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project                                    new Pair<String, String>(items[2], items[3]));
116231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        }
1163629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    }
116431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
11655c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy            }
1166629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1167574d20ec84551370987dde530c27ec493bdef564Romain Guy    }
116831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
116931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private String applyOemOverrideFunction(String usbFunctions) {
1170629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if ((usbFunctions == null) || (mOemModeMap == null)) {
1171629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            return usbFunctions;
1172629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1173629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1174629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
1175629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);
1176629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1177629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        Map<String, Pair<String, String>> overridesMap =
1178629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                mOemModeMap.get(bootMode);
1179629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        // Check to ensure that the oem is not overriding in the normal
1180629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        // boot mode
1181629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if (overridesMap != null && !(bootMode.equals(NORMAL_BOOT) ||
1182629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                bootMode.equals("unknown"))) {
1183629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            Pair<String, String> overrideFunctions =
1184629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    overridesMap.get(usbFunctions);
1185629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            if (overrideFunctions != null) {
1186629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                Slog.d(TAG, "OEM USB override: " + usbFunctions
1187629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        + " ==> " + overrideFunctions.first
1188629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        + " persist across reboot "
1189629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        + overrideFunctions.second);
1190629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                if (!overrideFunctions.second.equals("")) {
1191629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    String newFunction;
1192629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (mAdbEnabled) {
1193629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        newFunction = UsbManager.addFunction(overrideFunctions.second,
1194629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                UsbManager.USB_FUNCTION_ADB);
1195629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    } else {
1196629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE,
1197629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                UsbManager.USB_FUNCTION_ADB);
1198629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    }
1199629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
1200629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            + UsbDeviceManager.getPersistProp(false));
1201629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    SystemProperties.set(UsbDeviceManager.getPersistProp(false),
1202629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            newFunction);
1203629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                }
1204629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                return overrideFunctions.first;
1205629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            } else if (mAdbEnabled) {
1206629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                String newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE,
1207629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        UsbManager.USB_FUNCTION_ADB);
1208629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                SystemProperties.set(UsbDeviceManager.getPersistProp(false),
1209629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        newFunction);
1210629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            } else {
1211629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                SystemProperties.set(UsbDeviceManager.getPersistProp(false),
1212629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        UsbManager.USB_FUNCTION_NONE);
1213629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            }
1214629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1215629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        // return passed in functions as is.
1216629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        return usbFunctions;
1217629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    }
1218629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1219629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    public static String getPersistProp(boolean functions) {
1220629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
1221629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
1222629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
1223629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            if (functions == true) {
1224629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                persistProp = "persist.sys.usb." + bootMode + ".func";
1225629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            } else {
1226629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                persistProp = "persist.sys.usb." + bootMode + ".config";
1227629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            }
1228629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1229629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1230629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        return persistProp;
1231629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    }
1232629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1233629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1234629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
1235629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if (mDebuggingManager != null) {
1236629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
1237629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1238629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    }
1239629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1240629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    public void denyUsbDebugging() {
1241629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if (mDebuggingManager != null) {
1242629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            mDebuggingManager.denyUsbDebugging();
1243629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1244629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    }
1245574d20ec84551370987dde530c27ec493bdef564Romain Guy
1246574d20ec84551370987dde530c27ec493bdef564Romain Guy    public void clearUsbDebuggingKeys() {
1247629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if (mDebuggingManager != null) {
1248629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            mDebuggingManager.clearUsbDebuggingKeys();
1249629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        } else {
1250629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            throw new RuntimeException("Cannot clear Usb Debugging keys, "
1251629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    + "UsbDebuggingManager not enabled");
1252629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1253629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    }
1254629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1255574d20ec84551370987dde530c27ec493bdef564Romain Guy    public void dump(IndentingPrintWriter pw) {
1256629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if (mHandler != null) {
1257629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            mHandler.dump(pw);
1258629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        }
1259629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        if (mDebuggingManager != null) {
12605c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy            mDebuggingManager.dump(pw);
126131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1262629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy    }
126331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
126431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private native String[] nativeGetAccessoryStrings();
1265f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1266f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    private native ParcelFileDescriptor nativeOpenAccessory();
12679c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
12689c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    private native boolean nativeIsStartRequested();
1269f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1270f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    private native int nativeGetAudioMode();
1271f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project}
1272f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project