146d0adf8256a42416584765625852b6e48497c90Mike Lockwood/*
246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Copyright (C) 2011 The Android Open Source Project
346d0adf8256a42416584765625852b6e48497c90Mike Lockwood *
446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
546d0adf8256a42416584765625852b6e48497c90Mike Lockwood * you may not use this file except in compliance with the License.
646d0adf8256a42416584765625852b6e48497c90Mike Lockwood * You may obtain a copy of the License at
746d0adf8256a42416584765625852b6e48497c90Mike Lockwood *
846d0adf8256a42416584765625852b6e48497c90Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
946d0adf8256a42416584765625852b6e48497c90Mike Lockwood *
1046d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Unless required by applicable law or agreed to in writing, software
1146d0adf8256a42416584765625852b6e48497c90Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
1246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * See the License for the specific language governing permissions an
1446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * limitations under the License.
1546d0adf8256a42416584765625852b6e48497c90Mike Lockwood */
1646d0adf8256a42416584765625852b6e48497c90Mike Lockwood
1746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodpackage com.android.server.usb;
1846d0adf8256a42416584765625852b6e48497c90Mike Lockwood
19541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.app.Notification;
20541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.app.NotificationManager;
21fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.app.PendingIntent;
22d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwoodimport android.content.BroadcastReceiver;
23541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.content.ComponentName;
2446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.content.ContentResolver;
2546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.content.Context;
2646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.content.Intent;
2746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.content.IntentFilter;
2846d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.content.pm.PackageManager;
29541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.content.res.Resources;
30541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.database.ContentObserver;
3146d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbAccessory;
3246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbManager;
3302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.FileUtils;
3446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Handler;
3502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.Looper;
3646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Message;
3746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.ParcelFileDescriptor;
38dab2072365565b4892be7910b0cdb870e83689f6RoboErikimport android.os.SystemClock;
39541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.os.SystemProperties;
4046d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.UEventObserver;
41fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.os.UserHandle;
42fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.os.storage.StorageManager;
43fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.os.storage.StorageVolume;
4446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.provider.Settings;
45afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondoimport android.util.Pair;
4646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.util.Slog;
4746d0adf8256a42416584765625852b6e48497c90Mike Lockwood
488b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.GuardedBy;
498d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackbornimport com.android.server.FgThread;
508b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey
5146d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.File;
5246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.FileDescriptor;
5346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.FileNotFoundException;
5402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport java.io.IOException;
5546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.PrintWriter;
56fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport java.util.HashMap;
57afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondoimport java.util.LinkedList;
5846d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.util.List;
59fea17de7aaa5729d3111102b2734b158403d2780Jeff Sharkeyimport java.util.Locale;
60afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondoimport java.util.Map;
619d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwoodimport java.util.Scanner;
6246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
6346d0adf8256a42416584765625852b6e48497c90Mike Lockwood/**
6446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * UsbDeviceManager manages USB state in device mode.
6546d0adf8256a42416584765625852b6e48497c90Mike Lockwood */
6646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodpublic class UsbDeviceManager {
6702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
6846d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private static final String TAG = UsbDeviceManager.class.getSimpleName();
69fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood    private static final boolean DEBUG = false;
7046d0adf8256a42416584765625852b6e48497c90Mike Lockwood
7102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static final String USB_STATE_MATCH =
7202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            "DEVPATH=/devices/virtual/android_usb/android0";
7302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static final String ACCESSORY_START_MATCH =
7402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            "DEVPATH=/devices/virtual/misc/usb_accessory";
7502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static final String FUNCTIONS_PATH =
7602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            "/sys/class/android_usb/android0/functions";
7702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static final String STATE_PATH =
7802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            "/sys/class/android_usb/android0/state";
7902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static final String MASS_STORAGE_FILE_PATH =
80629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood            "/sys/class/android_usb/android0/f_mass_storage/lun/file";
81629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood    private static final String RNDIS_ETH_ADDR_PATH =
82629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood            "/sys/class/android_usb/android0/f_rndis/ethaddr";
839d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwood    private static final String AUDIO_SOURCE_PCM_PATH =
849d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwood            "/sys/class/android_usb/android0/f_audio_source/pcm";
8546d0adf8256a42416584765625852b6e48497c90Mike Lockwood
8646d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private static final int MSG_UPDATE_STATE = 0;
8702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static final int MSG_ENABLE_ADB = 1;
88166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
89f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood    private static final int MSG_SYSTEM_READY = 3;
90d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood    private static final int MSG_BOOT_COMPLETED = 4;
9127bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey    private static final int MSG_USER_SWITCHED = 5;
9246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
93166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    private static final int AUDIO_MODE_NONE = 0;
94166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    private static final int AUDIO_MODE_SOURCE = 1;
95166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood
9646d0adf8256a42416584765625852b6e48497c90Mike Lockwood    // Delay for debouncing USB disconnects.
9746d0adf8256a42416584765625852b6e48497c90Mike Lockwood    // We often get rapid connect/disconnect events when enabling USB functions,
9846d0adf8256a42416584765625852b6e48497c90Mike Lockwood    // which need debouncing.
9946d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private static final int UPDATE_DELAY = 1000;
10046d0adf8256a42416584765625852b6e48497c90Mike Lockwood
101c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood    // Time we received a request to enter USB accessory mode
102c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood    private long mAccessoryModeRequestTime = 0;
103c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood
104c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood    // Timeout for entering USB request mode.
105c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood    // Request is cancelled if host does not configure device within 10 seconds.
106c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood    private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000;
107c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood
108afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
109afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
11002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private UsbHandler mHandler;
111d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood    private boolean mBootCompleted;
11246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
113fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private final Object mLock = new Object();
114fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
11546d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private final Context mContext;
11602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private final ContentResolver mContentResolver;
1178b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @GuardedBy("mLock")
118fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private UsbSettingsManager mCurrentSettings;
119541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood    private NotificationManager mNotificationManager;
12046d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private final boolean mHasUsbAccessory;
1215787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood    private boolean mUseUsbNotification;
122541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood    private boolean mAdbEnabled;
1239d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwood    private boolean mAudioSourceEnabled;
124afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    private Map<String, List<Pair<String, String>>> mOemModeMap;
125166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    private String[] mAccessoryStrings;
1264e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private UsbDebuggingManager mDebuggingManager;
127541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood
128541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood    private class AdbSettingsObserver extends ContentObserver {
129541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood        public AdbSettingsObserver() {
130541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood            super(null);
131541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood        }
132541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood        @Override
133541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood        public void onChange(boolean selfChange) {
134bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown            boolean enable = (Settings.Global.getInt(mContentResolver,
135bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown                    Settings.Global.ADB_ENABLED, 0) > 0);
13602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            mHandler.sendMessage(MSG_ENABLE_ADB, enable);
137541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood        }
138541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood    }
139541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood
14046d0adf8256a42416584765625852b6e48497c90Mike Lockwood    /*
14146d0adf8256a42416584765625852b6e48497c90Mike Lockwood     * Listens for uevent messages from the kernel to monitor the USB state
14246d0adf8256a42416584765625852b6e48497c90Mike Lockwood     */
14346d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private final UEventObserver mUEventObserver = new UEventObserver() {
14446d0adf8256a42416584765625852b6e48497c90Mike Lockwood        @Override
14546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        public void onUEvent(UEventObserver.UEvent event) {
146fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood            if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
14746d0adf8256a42416584765625852b6e48497c90Mike Lockwood
14802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            String state = event.get("USB_STATE");
14902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            String accessory = event.get("ACCESSORY");
15002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            if (state != null) {
15102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                mHandler.updateState(state);
15202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            } else if ("START".equals(accessory)) {
153fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood                if (DEBUG) Slog.d(TAG, "got accessory start");
154205a3ea0e2c49bc4d0ed534469f3a6920c14c4feMike Lockwood                startAccessoryMode();
15546d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
15646d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
15746d0adf8256a42416584765625852b6e48497c90Mike Lockwood    };
15846d0adf8256a42416584765625852b6e48497c90Mike Lockwood
159fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public UsbDeviceManager(Context context) {
16046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        mContext = context;
161541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood        mContentResolver = context.getContentResolver();
16246d0adf8256a42416584765625852b6e48497c90Mike Lockwood        PackageManager pm = mContext.getPackageManager();
16346d0adf8256a42416584765625852b6e48497c90Mike Lockwood        mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
164629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        initRndisAddress();
16546d0adf8256a42416584765625852b6e48497c90Mike Lockwood
166afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        readOemUsbOverrideConfig();
167afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
1688d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn        mHandler = new UsbHandler(FgThread.get().getLooper());
169d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood
170d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood        if (nativeIsStartRequested()) {
171d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood            if (DEBUG) Slog.d(TAG, "accessory attached at boot");
172205a3ea0e2c49bc4d0ed534469f3a6920c14c4feMike Lockwood            startAccessoryMode();
173d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood        }
1744e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
17578a9687fc2eab03b9d764cd27eaa1d56c66960beBenoit Goby        boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
17678a9687fc2eab03b9d764cd27eaa1d56c66960beBenoit Goby        boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
17778a9687fc2eab03b9d764cd27eaa1d56c66960beBenoit Goby        if (secureAdbEnabled && !dataEncrypted) {
1784e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            mDebuggingManager = new UsbDebuggingManager(context);
1794e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
18002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
18102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
182fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void setCurrentSettings(UsbSettingsManager settings) {
183fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        synchronized (mLock) {
184fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            mCurrentSettings = settings;
185fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
186fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
187fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
188fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private UsbSettingsManager getCurrentSettings() {
189fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        synchronized (mLock) {
190fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            return mCurrentSettings;
191fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
192fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
193fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
19402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    public void systemReady() {
195d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood        if (DEBUG) Slog.d(TAG, "systemReady");
19602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
19702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        mNotificationManager = (NotificationManager)
19802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
19946d0adf8256a42416584765625852b6e48497c90Mike Lockwood
2005787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood        // We do not show the USB notification if the primary volume supports mass storage.
2015787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood        // The legacy mass storage UI will be used instead.
2025787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood        boolean massStorageSupported = false;
203b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        final StorageManager storageManager = StorageManager.from(mContext);
204b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        final StorageVolume primary = storageManager.getPrimaryVolume();
205b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        massStorageSupported = primary != null && primary.allowMassStorage();
2065787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood        mUseUsbNotification = !massStorageSupported;
2075787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood
20802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        // make sure the ADB_ENABLED setting value matches the current state
209bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown        Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
210541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood
21102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
21202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
213541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood
214166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    private void startAccessoryMode() {
215c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood        if (!mHasUsbAccessory) return;
216c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood
217166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        mAccessoryStrings = nativeGetAccessoryStrings();
218166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE);
219166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        // don't start accessory mode if our mandatory strings have not been set
220166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        boolean enableAccessory = (mAccessoryStrings != null &&
221166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                        mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
222166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                        mAccessoryStrings[UsbAccessory.MODEL_STRING] != null);
223166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        String functions = null;
224166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood
225166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        if (enableAccessory && enableAudio) {
226166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood            functions = UsbManager.USB_FUNCTION_ACCESSORY + ","
227166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                    + UsbManager.USB_FUNCTION_AUDIO_SOURCE;
228166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        } else if (enableAccessory) {
229166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood            functions = UsbManager.USB_FUNCTION_ACCESSORY;
230166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        } else if (enableAudio) {
231166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood            functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE;
232166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        }
233166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood
234166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        if (functions != null) {
235c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            mAccessoryModeRequestTime = SystemClock.elapsedRealtime();
236166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood            setCurrentFunctions(functions, false);
237166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        }
238166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    }
239166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood
240629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood    private static void initRndisAddress() {
241629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        // configure RNDIS ethernet address based on our serial number using the same algorithm
242629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        // we had been previously using in kernel board files
243629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        final int ETH_ALEN = 6;
244629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        int address[] = new int[ETH_ALEN];
245629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        // first byte is 0x02 to signify a locally administered address
246629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        address[0] = 0x02;
247629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood
248629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF");
249629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        int serialLength = serial.length();
250629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        // XOR the USB serial across the remaining 5 bytes
251629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        for (int i = 0; i < serialLength; i++) {
252629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood            address[i % (ETH_ALEN - 1) + 1] ^= (int)serial.charAt(i);
253629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        }
254fea17de7aaa5729d3111102b2734b158403d2780Jeff Sharkey        String addrString = String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
255629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood            address[0], address[1], address[2], address[3], address[4], address[5]);
256629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        try {
257629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood            FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString);
258629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        } catch (IOException e) {
259629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood           Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH);
260629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood        }
261629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood    }
262629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood
26302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood     private static String addFunction(String functions, String function) {
264dab2072365565b4892be7910b0cdb870e83689f6RoboErik         if ("none".equals(functions)) {
265dab2072365565b4892be7910b0cdb870e83689f6RoboErik             return function;
266dab2072365565b4892be7910b0cdb870e83689f6RoboErik         }
26702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (!containsFunction(functions, function)) {
26802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            if (functions.length() > 0) {
26902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                functions += ",";
27046d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
27102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            functions += function;
27246d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
27302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        return functions;
27446d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
27546d0adf8256a42416584765625852b6e48497c90Mike Lockwood
27602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static String removeFunction(String functions, String function) {
27702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        String[] split = functions.split(",");
27802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        for (int i = 0; i < split.length; i++) {
27902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            if (function.equals(split[i])) {
28002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                split[i] = null;
28102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            }
28202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
283dab2072365565b4892be7910b0cdb870e83689f6RoboErik        if (split.length == 1 && split[0] == null) {
284dab2072365565b4892be7910b0cdb870e83689f6RoboErik            return "none";
285dab2072365565b4892be7910b0cdb870e83689f6RoboErik        }
28602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        StringBuilder builder = new StringBuilder();
28702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood         for (int i = 0; i < split.length; i++) {
28802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            String s = split[i];
28902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            if (s != null) {
29002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                if (builder.length() > 0) {
29102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    builder.append(",");
29202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                }
29302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                builder.append(s);
29402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            }
29502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
29602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        return builder.toString();
29702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
29846d0adf8256a42416584765625852b6e48497c90Mike Lockwood
29902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private static boolean containsFunction(String functions, String function) {
30002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        int index = functions.indexOf(function);
30102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (index < 0) return false;
30202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (index > 0 && functions.charAt(index - 1) != ',') return false;
30302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        int charAfter = index + function.length();
30402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
30502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        return true;
30602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
30702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
30802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    private final class UsbHandler extends Handler {
30902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
31002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        // current USB state
31102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private boolean mConnected;
31202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private boolean mConfigured;
31302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private String mCurrentFunctions;
31402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private String mDefaultFunctions;
31502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private UsbAccessory mCurrentAccessory;
316d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood        private int mUsbNotificationId;
317d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood        private boolean mAdbNotificationShown;
31827bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey        private int mCurrentUser = UserHandle.USER_NULL;
319d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
320d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood        private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
32127bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey            @Override
322d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood            public void onReceive(Context context, Intent intent) {
323d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                if (DEBUG) Slog.d(TAG, "boot completed");
324d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
325d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood            }
326d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood        };
327d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood
32827bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey        private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
32927bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey            @Override
33027bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey            public void onReceive(Context context, Intent intent) {
33127bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
33227bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                mHandler.obtainMessage(MSG_USER_SWITCHED, userId, 0).sendToTarget();
33327bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey            }
33427bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey        };
33527bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey
3363fd13eb6322e09f1ffe5476e28d55732da391151Mike Lockwood        public UsbHandler(Looper looper) {
3373fd13eb6322e09f1ffe5476e28d55732da391151Mike Lockwood            super(looper);
33802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            try {
339c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood                // persist.sys.usb.config should never be unset.  But if it is, set it to "adb"
340c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood                // so we have a chance of debugging what happened.
341c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood                mDefaultFunctions = SystemProperties.get("persist.sys.usb.config", "adb");
342afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
343afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                // Check if USB mode needs to be overridden depending on OEM specific bootmode.
344afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                mDefaultFunctions = processOemUsbOverride(mDefaultFunctions);
345afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
346de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood                // sanity check the sys.usb.config system property
347de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood                // this may be necessary if we crashed while switching USB configurations
348de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood                String config = SystemProperties.get("sys.usb.config", "none");
349c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood                if (!config.equals(mDefaultFunctions)) {
350c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood                    Slog.w(TAG, "resetting config to persistent property: " + mDefaultFunctions);
351c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood                    SystemProperties.set("sys.usb.config", mDefaultFunctions);
352de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood                }
353de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood
354c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood                mCurrentFunctions = mDefaultFunctions;
35502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
35602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                updateState(state);
35702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
35802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
35902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                // Upgrade step for previous versions that used persist.service.adb.enable
36002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                String value = SystemProperties.get("persist.service.adb.enable", "");
36102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                if (value.length() > 0) {
36202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    char enable = value.charAt(0);
36302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    if (enable == '1') {
36402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                        setAdbEnabled(true);
36502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    } else if (enable == '0') {
36602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                        setAdbEnabled(false);
36702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    }
36802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    SystemProperties.set("persist.service.adb.enable", "");
36902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                }
37002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
37102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                // register observer to listen for settings changes
37202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                mContentResolver.registerContentObserver(
373bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
37402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                                false, new AdbSettingsObserver());
37502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
37602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                // Watch for USB configuration changes
37702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                mUEventObserver.startObserving(USB_STATE_MATCH);
37802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                mUEventObserver.startObserving(ACCESSORY_START_MATCH);
379d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood
38027bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                mContext.registerReceiver(
38127bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                        mBootCompletedReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
38227bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                mContext.registerReceiver(
38327bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                        mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
38402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            } catch (Exception e) {
38502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                Slog.e(TAG, "Error initializing UsbHandler", e);
38602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            }
38746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
38802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
38902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        public void sendMessage(int what, boolean arg) {
39002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            removeMessages(what);
39102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            Message m = Message.obtain(this, what);
39202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            m.arg1 = (arg ? 1 : 0);
39302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            sendMessage(m);
39446d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
39546d0adf8256a42416584765625852b6e48497c90Mike Lockwood
39602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        public void sendMessage(int what, Object arg) {
39702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            removeMessages(what);
39802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            Message m = Message.obtain(this, what);
39902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            m.obj = arg;
40002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            sendMessage(m);
40102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
40202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
403f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood        public void sendMessage(int what, Object arg0, boolean arg1) {
404f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            removeMessages(what);
405f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            Message m = Message.obtain(this, what);
406f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            m.obj = arg0;
407f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            m.arg1 = (arg1 ? 1 : 0);
408f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            sendMessage(m);
409f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood        }
410f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood
41102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        public void updateState(String state) {
41202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            int connected, configured;
41302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
41402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            if ("DISCONNECTED".equals(state)) {
41502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                connected = 0;
41602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                configured = 0;
41702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            } else if ("CONNECTED".equals(state)) {
41802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                connected = 1;
41902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                configured = 0;
42002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            } else if ("CONFIGURED".equals(state)) {
42102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                connected = 1;
42202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                configured = 1;
42302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            } else {
42402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                Slog.e(TAG, "unknown state " + state);
42502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                return;
42602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            }
42702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            removeMessages(MSG_UPDATE_STATE);
42802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            Message msg = Message.obtain(this, MSG_UPDATE_STATE);
42902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            msg.arg1 = connected;
43002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            msg.arg2 = configured;
43102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            // debounce disconnects to avoid problems bringing up USB tethering
43202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
43302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
43402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
435f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood        private boolean waitForState(String state) {
43602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            // wait for the transition to complete.
43702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            // give up after 1 second.
43802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            for (int i = 0; i < 20; i++) {
43968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                // State transition is done when sys.usb.state is set to the new configuration
440f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood                if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
441dab2072365565b4892be7910b0cdb870e83689f6RoboErik                SystemClock.sleep(50);
44202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            }
443fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood            Slog.e(TAG, "waitForState(" + state + ") FAILED");
44402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            return false;
44502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
44602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
447f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood        private boolean setUsbConfig(String config) {
448fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood            if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
449f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            // set the new configuration
450f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            SystemProperties.set("sys.usb.config", config);
451f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood            return waitForState(config);
452f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood        }
453f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood
45402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private void setAdbEnabled(boolean enable) {
455de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood            if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
45602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            if (enable != mAdbEnabled) {
45702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                mAdbEnabled = enable;
458f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood                // Due to the persist.sys.usb.config property trigger, changing adb state requires
459f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood                // switching to default function
4601984e79d1593b80adf46b16666862f5787157aedMike Lockwood                setEnabledFunctions(mDefaultFunctions, true);
461d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                updateAdbNotification();
46202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            }
4634e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            if (mDebuggingManager != null) {
4644e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                mDebuggingManager.setAdbEnabled(mAdbEnabled);
4654e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            }
46602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
46702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
46868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood        private void setEnabledFunctions(String functions, boolean makeDefault) {
469c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            if (DEBUG) Slog.d(TAG, "setEnabledFunctions " + functions
470c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood                    + " makeDefault: " + makeDefault);
471afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
472afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            // Do not update persystent.sys.usb.config if the device is booted up
473afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            // with OEM specific mode.
474afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            if (functions != null && makeDefault && !needsOemUsbOverride()) {
475afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
4768b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                if (mAdbEnabled) {
4778b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                    functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
4788b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                } else {
4798b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                    functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
4808b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                }
48168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                if (!mDefaultFunctions.equals(functions)) {
48268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    if (!setUsbConfig("none")) {
48368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        Slog.e(TAG, "Failed to disable USB");
48468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        // revert to previous configuration if we fail
48568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        setUsbConfig(mCurrentFunctions);
48668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        return;
48768736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    }
48868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    // setting this property will also change the current USB state
48968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    // via a property trigger
49068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    SystemProperties.set("persist.sys.usb.config", functions);
49168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    if (waitForState(functions)) {
49268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        mCurrentFunctions = functions;
49368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        mDefaultFunctions = functions;
49468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    } else {
49568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        Slog.e(TAG, "Failed to switch persistent USB config to " + functions);
49668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        // revert to previous configuration if we fail
49768736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        SystemProperties.set("persist.sys.usb.config", mDefaultFunctions);
49868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    }
49968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                }
50068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood            } else {
50168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                if (functions == null) {
50268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    functions = mDefaultFunctions;
50368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                }
504afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
505afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                // Override with bootmode specific usb mode if needed
506afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                functions = processOemUsbOverride(functions);
507afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
5088b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                if (mAdbEnabled) {
5098b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                    functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
5108b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                } else {
5118b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                    functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
5128b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood                }
51368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                if (!mCurrentFunctions.equals(functions)) {
51468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    if (!setUsbConfig("none")) {
51568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        Slog.e(TAG, "Failed to disable USB");
51668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        // revert to previous configuration if we fail
51768736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        setUsbConfig(mCurrentFunctions);
51868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        return;
51968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    }
52068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    if (setUsbConfig(functions)) {
52168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        mCurrentFunctions = functions;
52268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    } else {
52368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        Slog.e(TAG, "Failed to switch USB config to " + functions);
52468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        // revert to previous configuration if we fail
52568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        setUsbConfig(mCurrentFunctions);
52668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                    }
52768736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                }
52802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            }
52902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
53002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
53102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private void updateCurrentAccessory() {
532c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            // We are entering accessory mode if we have received a request from the host
533c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            // and the request has not timed out yet.
534c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            boolean enteringAccessoryMode =
535c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood                    mAccessoryModeRequestTime > 0 &&
536c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood                        SystemClock.elapsedRealtime() <
537c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood                            mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
538c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood
539c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            if (mConfigured && enteringAccessoryMode) {
540c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood                // successfully entered accessory mode
54102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
542166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                if (mAccessoryStrings != null) {
543166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                    mCurrentAccessory = new UsbAccessory(mAccessoryStrings);
544fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood                    Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
54502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    // defer accessoryAttached if system is not ready
546d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                    if (mBootCompleted) {
547fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
548d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                    } // else handle in mBootCompletedReceiver
54902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                } else {
550fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood                    Slog.e(TAG, "nativeGetAccessoryStrings failed");
55102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                }
552c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            } else if (!enteringAccessoryMode) {
55302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                // make sure accessory mode is off
55402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                // and restore default functions
555fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood                Slog.d(TAG, "exited USB accessory mode");
55668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                setEnabledFunctions(mDefaultFunctions, false);
55702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
55802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                if (mCurrentAccessory != null) {
559d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                    if (mBootCompleted) {
560fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                        getCurrentSettings().accessoryDetached(mCurrentAccessory);
56102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    }
56202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    mCurrentAccessory = null;
563166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                    mAccessoryStrings = null;
56446d0adf8256a42416584765625852b6e48497c90Mike Lockwood                }
56546d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
56646d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
56746d0adf8256a42416584765625852b6e48497c90Mike Lockwood
56802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        private void updateUsbState() {
56902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            // send a sticky broadcast containing current USB state
57002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
57102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
57202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
57302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
57402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
57502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            if (mCurrentFunctions != null) {
57602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                String[] functions = mCurrentFunctions.split(",");
57702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                for (int i = 0; i < functions.length; i++) {
57802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    intent.putExtra(functions[i], true);
57902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                }
58046d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
58102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
582c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " connected: " + mConnected
583c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood                                    + " configured: " + mConfigured);
5845ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
58546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
58646d0adf8256a42416584765625852b6e48497c90Mike Lockwood
587bf91046872dd711019e8dec543441601576cc950Mike Lockwood        private void updateAudioSourceFunction() {
588bf91046872dd711019e8dec543441601576cc950Mike Lockwood            boolean enabled = containsFunction(mCurrentFunctions,
589bf91046872dd711019e8dec543441601576cc950Mike Lockwood                    UsbManager.USB_FUNCTION_AUDIO_SOURCE);
590bf91046872dd711019e8dec543441601576cc950Mike Lockwood            if (enabled != mAudioSourceEnabled) {
591bf91046872dd711019e8dec543441601576cc950Mike Lockwood                // send a sticky broadcast containing current USB state
592bf91046872dd711019e8dec543441601576cc950Mike Lockwood                Intent intent = new Intent(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
593bf91046872dd711019e8dec543441601576cc950Mike Lockwood                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
594bf91046872dd711019e8dec543441601576cc950Mike Lockwood                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
595bf91046872dd711019e8dec543441601576cc950Mike Lockwood                intent.putExtra("state", (enabled ? 1 : 0));
596bf91046872dd711019e8dec543441601576cc950Mike Lockwood                if (enabled) {
597bf91046872dd711019e8dec543441601576cc950Mike Lockwood                    try {
598bf91046872dd711019e8dec543441601576cc950Mike Lockwood                        Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
599bf91046872dd711019e8dec543441601576cc950Mike Lockwood                        int card = scanner.nextInt();
600bf91046872dd711019e8dec543441601576cc950Mike Lockwood                        int device = scanner.nextInt();
601bf91046872dd711019e8dec543441601576cc950Mike Lockwood                        intent.putExtra("card", card);
602bf91046872dd711019e8dec543441601576cc950Mike Lockwood                        intent.putExtra("device", device);
603bf91046872dd711019e8dec543441601576cc950Mike Lockwood                    } catch (FileNotFoundException e) {
604bf91046872dd711019e8dec543441601576cc950Mike Lockwood                        Slog.e(TAG, "could not open audio source PCM file", e);
605bf91046872dd711019e8dec543441601576cc950Mike Lockwood                    }
6069d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwood                }
6075ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn                mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
608bf91046872dd711019e8dec543441601576cc950Mike Lockwood                mAudioSourceEnabled = enabled;
6099d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwood            }
6109d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwood        }
6119d5a4be05b6d51ebb768e5fbcfa27ed9a39269b3Mike Lockwood
61202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        @Override
61302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        public void handleMessage(Message msg) {
61402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            switch (msg.what) {
61502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                case MSG_UPDATE_STATE:
61602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    mConnected = (msg.arg1 == 1);
61702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    mConfigured = (msg.arg2 == 1);
618d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    updateUsbNotification();
619d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    updateAdbNotification();
62002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    if (containsFunction(mCurrentFunctions,
62102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                            UsbManager.USB_FUNCTION_ACCESSORY)) {
62202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                        updateCurrentAccessory();
623c62f918e0eabd5c036ba43172d36f587157feed6Mike Lockwood                    } else if (!mConnected) {
62402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                        // restore defaults when USB is disconnected
62568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood                        setEnabledFunctions(mDefaultFunctions, false);
62602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    }
627d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                    if (mBootCompleted) {
62802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                        updateUsbState();
629bf91046872dd711019e8dec543441601576cc950Mike Lockwood                        updateAudioSourceFunction();
63002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    }
63102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    break;
63202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                case MSG_ENABLE_ADB:
63302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    setAdbEnabled(msg.arg1 == 1);
63402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    break;
635166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                case MSG_SET_CURRENT_FUNCTIONS:
636166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                    String functions = (String)msg.obj;
637f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood                    boolean makeDefault = (msg.arg1 == 1);
638166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood                    setEnabledFunctions(functions, makeDefault);
63902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    break;
64002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                case MSG_SYSTEM_READY:
641d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    updateUsbNotification();
642d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    updateAdbNotification();
64302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    updateUsbState();
644bf91046872dd711019e8dec543441601576cc950Mike Lockwood                    updateAudioSourceFunction();
645d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                    break;
646d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                case MSG_BOOT_COMPLETED:
647d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                    mBootCompleted = true;
648d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood                    if (mCurrentAccessory != null) {
649fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
65002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    }
6514e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    if (mDebuggingManager != null) {
6524e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
6534e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    }
65402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood                    break;
65527bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                case MSG_USER_SWITCHED: {
65627bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                    final boolean mtpActive =
65727bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                            containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
65827bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                            || containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
65927bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                    if (mtpActive && mCurrentUser != UserHandle.USER_NULL) {
66027bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                        Slog.v(TAG, "Current user switched; resetting USB host stack for MTP");
66127bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                        setUsbConfig("none");
66227bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                        setUsbConfig(mCurrentFunctions);
66327bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                    }
66427bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                    mCurrentUser = msg.arg1;
66527bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                    break;
66627bd34d9d9fe99f11b80aa0bbdb402fb47ef4158Jeff Sharkey                }
66746d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
66846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
66946d0adf8256a42416584765625852b6e48497c90Mike Lockwood
67002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        public UsbAccessory getCurrentAccessory() {
67102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            return mCurrentAccessory;
67202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
67302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
674d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood        private void updateUsbNotification() {
675d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood            if (mNotificationManager == null || !mUseUsbNotification) return;
676fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood            int id = 0;
677a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood            Resources r = mContext.getResources();
678d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood            if (mConnected) {
679d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
680fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                    id = com.android.internal.R.string.usb_mtp_notification_title;
681d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {
682fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                    id = com.android.internal.R.string.usb_ptp_notification_title;
683d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                } else if (containsFunction(mCurrentFunctions,
684d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                        UsbManager.USB_FUNCTION_MASS_STORAGE)) {
685fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                    id = com.android.internal.R.string.usb_cd_installer_notification_title;
6866e680dea3bc9e2d4ba1a09f428c303cd2a59c051Mike Lockwood                } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) {
687fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                    id = com.android.internal.R.string.usb_accessory_notification_title;
688d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                } else {
689a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood                    // There is a different notification for USB tethering so we don't need one here
6907ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn                    //if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
6917ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn                    //    Slog.e(TAG, "No known USB function in updateUsbNotification");
6927ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn                    //}
693d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                }
694a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood            }
695a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood            if (id != mUsbNotificationId) {
696a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood                // clear notification if title needs changing
697fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                if (mUsbNotificationId != 0) {
69850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    mNotificationManager.cancelAsUser(null, mUsbNotificationId,
69950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            UserHandle.ALL);
700fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                    mUsbNotificationId = 0;
701a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood                }
702fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                if (id != 0) {
703d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    CharSequence message = r.getText(
704d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                            com.android.internal.R.string.usb_notification_message);
705fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                    CharSequence title = r.getText(id);
706d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
707d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    Notification notification = new Notification();
708d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.icon = com.android.internal.R.drawable.stat_sys_data_usb;
709d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.when = 0;
710d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.flags = Notification.FLAG_ONGOING_EVENT;
711d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.tickerText = title;
712d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.defaults = 0; // please be quiet
713d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.sound = null;
714d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.vibrate = null;
71549a2ad1f404622803faba0bc5937b8a39aba02b3Daniel Sandler                    notification.priority = Notification.PRIORITY_MIN;
716d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
717765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate                    Intent intent = Intent.makeRestartActivityTask(
718765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate                            new ComponentName("com.android.settings",
719765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate                                    "com.android.settings.UsbSettings"));
72050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
72150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            intent, 0, null, UserHandle.CURRENT);
722d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.setLatestEventInfo(mContext, title, message, pi);
72350cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    mNotificationManager.notifyAsUser(null, id, notification,
72450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            UserHandle.ALL);
725d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    mUsbNotificationId = id;
726d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                }
727d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood            }
728d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood        }
729d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
730d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood        private void updateAdbNotification() {
731d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood            if (mNotificationManager == null) return;
732fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood            final int id = com.android.internal.R.string.adb_active_notification_title;
733d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood            if (mAdbEnabled && mConnected) {
734d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
735d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
736d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                if (!mAdbNotificationShown) {
737d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    Resources r = mContext.getResources();
738fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood                    CharSequence title = r.getText(id);
739d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    CharSequence message = r.getText(
740d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                            com.android.internal.R.string.adb_active_notification_message);
741d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
742d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    Notification notification = new Notification();
743d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.icon = com.android.internal.R.drawable.stat_sys_adb;
744d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.when = 0;
745d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.flags = Notification.FLAG_ONGOING_EVENT;
746d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.tickerText = title;
747d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.defaults = 0; // please be quiet
748d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.sound = null;
749d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.vibrate = null;
750a25079e6bafcfd77135a852f0e838738d80606efDaniel Sandler                    notification.priority = Notification.PRIORITY_LOW;
751d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
752765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate                    Intent intent = Intent.makeRestartActivityTask(
753765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate                            new ComponentName("com.android.settings",
754765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate                                    "com.android.settings.DevelopmentSettings"));
75550cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
75650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            intent, 0, null, UserHandle.CURRENT);
757d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    notification.setLatestEventInfo(mContext, title, message, pi);
758d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                    mAdbNotificationShown = true;
75950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    mNotificationManager.notifyAsUser(null, id, notification,
76050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            UserHandle.ALL);
761d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                }
762d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood            } else if (mAdbNotificationShown) {
763d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood                mAdbNotificationShown = false;
76450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
765d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood            }
766d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood        }
767d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood
76802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        public void dump(FileDescriptor fd, PrintWriter pw) {
76902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            pw.println("  USB Device State:");
77002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            pw.println("    Current Functions: " + mCurrentFunctions);
77102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            pw.println("    Default Functions: " + mDefaultFunctions);
77202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            pw.println("    mConnected: " + mConnected);
77302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            pw.println("    mConfigured: " + mConfigured);
77402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            pw.println("    mCurrentAccessory: " + mCurrentAccessory);
7756ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood            try {
7766ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood                pw.println("    Kernel state: "
7776ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood                        + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
7786ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood                pw.println("    Kernel function list: "
7796ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood                        + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
7806ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood                pw.println("    Mass storage backing file: "
7816ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood                        + FileUtils.readTextFile(new File(MASS_STORAGE_FILE_PATH), 0, null).trim());
7826ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood            } catch (IOException e) {
7836ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood                pw.println("IOException: " + e);
7846ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood            }
78502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        }
78646d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
78746d0adf8256a42416584765625852b6e48497c90Mike Lockwood
78802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    /* returns the currently attached USB accessory */
78946d0adf8256a42416584765625852b6e48497c90Mike Lockwood    public UsbAccessory getCurrentAccessory() {
79002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        return mHandler.getCurrentAccessory();
79146d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
79246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
79302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    /* opens the currently attached USB accessory */
794abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood    public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
795abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood        UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
796abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood        if (currentAccessory == null) {
797abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood            throw new IllegalArgumentException("no accessory attached");
79846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
799abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood        if (!currentAccessory.equals(accessory)) {
800abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood            String error = accessory.toString()
801abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood                    + " does not match current accessory "
802abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood                    + currentAccessory;
803abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood            throw new IllegalArgumentException(error);
804abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood        }
805fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        getCurrentSettings().checkPermission(accessory);
806abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood        return nativeOpenAccessory();
807abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood    }
80802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood
809166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    public void setCurrentFunctions(String functions, boolean makeDefault) {
810166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ") default: " + makeDefault);
811166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood        mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, makeDefault);
81202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
81346d0adf8256a42416584765625852b6e48497c90Mike Lockwood
81402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    public void setMassStorageBackingFile(String path) {
81502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (path == null) path = "";
81602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        try {
81702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            FileUtils.stringToFile(MASS_STORAGE_FILE_PATH, path);
81802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        } catch (IOException e) {
81902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood           Slog.e(TAG, "failed to write to " + MASS_STORAGE_FILE_PATH);
82046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
82102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood    }
82246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
823afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    private void readOemUsbOverrideConfig() {
824afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        String[] configList = mContext.getResources().getStringArray(
825afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            com.android.internal.R.array.config_oemUsbModeOverride);
826afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
827afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        if (configList != null) {
828afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            for (String config: configList) {
829afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                String[] items = config.split(":");
830afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                if (items.length == 3) {
831afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    if (mOemModeMap == null) {
832afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                        mOemModeMap = new HashMap<String, List<Pair<String, String>>>();
833afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    }
834afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    List overrideList = mOemModeMap.get(items[0]);
835afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    if (overrideList == null) {
836afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                        overrideList = new LinkedList<Pair<String, String>>();
837afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                        mOemModeMap.put(items[0], overrideList);
838afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    }
839afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    overrideList.add(new Pair<String, String>(items[1], items[2]));
840afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                }
841afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            }
842afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        }
843afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    }
844afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
845afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    private boolean needsOemUsbOverride() {
846afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        if (mOemModeMap == null) return false;
847afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
848afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
849afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        return (mOemModeMap.get(bootMode) != null) ? true : false;
850afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    }
851afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
852afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    private String processOemUsbOverride(String usbFunctions) {
853afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        if ((usbFunctions == null) || (mOemModeMap == null)) return usbFunctions;
854afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
855afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
856afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
857afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        List<Pair<String, String>> overrides = mOemModeMap.get(bootMode);
858afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        if (overrides != null) {
859afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            for (Pair<String, String> pair: overrides) {
860afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                if (pair.first.equals(usbFunctions)) {
861afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    Slog.d(TAG, "OEM USB override: " + pair.first + " ==> " + pair.second);
862afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                    return pair.second;
863afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo                }
864afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo            }
865afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        }
866afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        // return passed in functions as is.
867afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo        return usbFunctions;
868afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo    }
869afd8f1820eeee21e960be44b22113dc2cecacf98Kazuhiro Ondo
8704e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
8714e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        if (mDebuggingManager != null) {
8724e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
8734e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
8744e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
8754e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
8764e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void denyUsbDebugging() {
8774e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        if (mDebuggingManager != null) {
8784e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            mDebuggingManager.denyUsbDebugging();
8794e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
8804e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
8814e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
882cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    public void clearUsbDebuggingKeys() {
883cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        if (mDebuggingManager != null) {
884cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby            mDebuggingManager.clearUsbDebuggingKeys();
885cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        } else {
886cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby            throw new RuntimeException("Cannot clear Usb Debugging keys, "
887cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby                        + "UsbDebuggingManager not enabled");
888cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        }
889cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    }
890cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby
89146d0adf8256a42416584765625852b6e48497c90Mike Lockwood    public void dump(FileDescriptor fd, PrintWriter pw) {
89202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood        if (mHandler != null) {
89302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood            mHandler.dump(fd, pw);
89446d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
8954e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        if (mDebuggingManager != null) {
8964e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            mDebuggingManager.dump(fd, pw);
8974e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
89846d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
89946d0adf8256a42416584765625852b6e48497c90Mike Lockwood
90046d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private native String[] nativeGetAccessoryStrings();
90146d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private native ParcelFileDescriptor nativeOpenAccessory();
902d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood    private native boolean nativeIsStartRequested();
903166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood    private native int nativeGetAudioMode();
90446d0adf8256a42416584765625852b6e48497c90Mike Lockwood}
905