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 1946d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.app.PendingIntent; 20541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.app.Notification; 21541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.app.NotificationManager; 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; 3346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.net.Uri; 3446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Binder; 3546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Bundle; 3602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.FileUtils; 3746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Handler; 3802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.HandlerThread; 3902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.Looper; 4046d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Message; 4146d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Parcelable; 4246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.ParcelFileDescriptor; 4302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.Process; 4402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.storage.StorageManager; 4502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwoodimport android.os.storage.StorageVolume; 46541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwoodimport android.os.SystemProperties; 4746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.UEventObserver; 4846d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.provider.Settings; 4946d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.util.Slog; 5046d0adf8256a42416584765625852b6e48497c90Mike Lockwood 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; 5646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.util.ArrayList; 5746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.util.List; 5846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 5946d0adf8256a42416584765625852b6e48497c90Mike Lockwood/** 6046d0adf8256a42416584765625852b6e48497c90Mike Lockwood * UsbDeviceManager manages USB state in device mode. 6146d0adf8256a42416584765625852b6e48497c90Mike Lockwood */ 6246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodpublic class UsbDeviceManager { 6302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 6446d0adf8256a42416584765625852b6e48497c90Mike Lockwood private static final String TAG = UsbDeviceManager.class.getSimpleName(); 65fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood private static final boolean DEBUG = false; 6646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 6702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static final String USB_STATE_MATCH = 6802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood "DEVPATH=/devices/virtual/android_usb/android0"; 6902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static final String ACCESSORY_START_MATCH = 7002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood "DEVPATH=/devices/virtual/misc/usb_accessory"; 7102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static final String FUNCTIONS_PATH = 7202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood "/sys/class/android_usb/android0/functions"; 7302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static final String STATE_PATH = 7402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood "/sys/class/android_usb/android0/state"; 7502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static final String MASS_STORAGE_FILE_PATH = 76629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood "/sys/class/android_usb/android0/f_mass_storage/lun/file"; 77629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood private static final String RNDIS_ETH_ADDR_PATH = 78629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood "/sys/class/android_usb/android0/f_rndis/ethaddr"; 7946d0adf8256a42416584765625852b6e48497c90Mike Lockwood 8046d0adf8256a42416584765625852b6e48497c90Mike Lockwood private static final int MSG_UPDATE_STATE = 0; 8102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static final int MSG_ENABLE_ADB = 1; 82f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood private static final int MSG_SET_CURRENT_FUNCTION = 2; 83f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood private static final int MSG_SYSTEM_READY = 3; 84d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood private static final int MSG_BOOT_COMPLETED = 4; 8546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 8646d0adf8256a42416584765625852b6e48497c90Mike Lockwood // Delay for debouncing USB disconnects. 8746d0adf8256a42416584765625852b6e48497c90Mike Lockwood // We often get rapid connect/disconnect events when enabling USB functions, 8846d0adf8256a42416584765625852b6e48497c90Mike Lockwood // which need debouncing. 8946d0adf8256a42416584765625852b6e48497c90Mike Lockwood private static final int UPDATE_DELAY = 1000; 9046d0adf8256a42416584765625852b6e48497c90Mike Lockwood 9102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private UsbHandler mHandler; 92d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood private boolean mBootCompleted; 9346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 9446d0adf8256a42416584765625852b6e48497c90Mike Lockwood private final Context mContext; 9502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private final ContentResolver mContentResolver; 9646d0adf8256a42416584765625852b6e48497c90Mike Lockwood private final UsbSettingsManager mSettingsManager; 97541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood private NotificationManager mNotificationManager; 9846d0adf8256a42416584765625852b6e48497c90Mike Lockwood private final boolean mHasUsbAccessory; 995787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood private boolean mUseUsbNotification; 100541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood private boolean mAdbEnabled; 101541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood 102541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood private class AdbSettingsObserver extends ContentObserver { 103541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood public AdbSettingsObserver() { 104541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood super(null); 105541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood } 106541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood @Override 107541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood public void onChange(boolean selfChange) { 10802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood boolean enable = (Settings.Secure.getInt(mContentResolver, 10902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Settings.Secure.ADB_ENABLED, 0) > 0); 11002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mHandler.sendMessage(MSG_ENABLE_ADB, enable); 111541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood } 112541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood } 113541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood 11446d0adf8256a42416584765625852b6e48497c90Mike Lockwood /* 11546d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Listens for uevent messages from the kernel to monitor the USB state 11646d0adf8256a42416584765625852b6e48497c90Mike Lockwood */ 11746d0adf8256a42416584765625852b6e48497c90Mike Lockwood private final UEventObserver mUEventObserver = new UEventObserver() { 11846d0adf8256a42416584765625852b6e48497c90Mike Lockwood @Override 11946d0adf8256a42416584765625852b6e48497c90Mike Lockwood public void onUEvent(UEventObserver.UEvent event) { 120fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString()); 12146d0adf8256a42416584765625852b6e48497c90Mike Lockwood 12202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String state = event.get("USB_STATE"); 12302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String accessory = event.get("ACCESSORY"); 12402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (state != null) { 12502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mHandler.updateState(state); 12602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else if ("START".equals(accessory)) { 127fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood if (DEBUG) Slog.d(TAG, "got accessory start"); 128f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false); 12946d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 13046d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 13146d0adf8256a42416584765625852b6e48497c90Mike Lockwood }; 13246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 13346d0adf8256a42416584765625852b6e48497c90Mike Lockwood public UsbDeviceManager(Context context, UsbSettingsManager settingsManager) { 13446d0adf8256a42416584765625852b6e48497c90Mike Lockwood mContext = context; 135541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood mContentResolver = context.getContentResolver(); 13646d0adf8256a42416584765625852b6e48497c90Mike Lockwood mSettingsManager = settingsManager; 13746d0adf8256a42416584765625852b6e48497c90Mike Lockwood PackageManager pm = mContext.getPackageManager(); 13846d0adf8256a42416584765625852b6e48497c90Mike Lockwood mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); 139629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood initRndisAddress(); 14046d0adf8256a42416584765625852b6e48497c90Mike Lockwood 14102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // create a thread for our Handler 14202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood HandlerThread thread = new HandlerThread("UsbDeviceManager", 1433fd13eb6322e09f1ffe5476e28d55732da391151Mike Lockwood Process.THREAD_PRIORITY_BACKGROUND); 14402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood thread.start(); 1453fd13eb6322e09f1ffe5476e28d55732da391151Mike Lockwood mHandler = new UsbHandler(thread.getLooper()); 146d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood 147d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (nativeIsStartRequested()) { 148d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (DEBUG) Slog.d(TAG, "accessory attached at boot"); 149d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false); 150d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood } 15102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 15202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 15302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public void systemReady() { 154d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (DEBUG) Slog.d(TAG, "systemReady"); 15502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 15602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mNotificationManager = (NotificationManager) 15702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mContext.getSystemService(Context.NOTIFICATION_SERVICE); 15846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1595787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood // We do not show the USB notification if the primary volume supports mass storage. 1605787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood // The legacy mass storage UI will be used instead. 1615787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood boolean massStorageSupported = false; 1625787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood StorageManager storageManager = (StorageManager) 1635787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood mContext.getSystemService(Context.STORAGE_SERVICE); 1645787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood StorageVolume[] volumes = storageManager.getVolumeList(); 1655787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood if (volumes.length > 0) { 1665787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood massStorageSupported = volumes[0].allowMassStorage(); 1675787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood } 1685787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood mUseUsbNotification = !massStorageSupported; 1695787a2d5b4e5bd60087eb7fbb13c97c7d0ba113eMike Lockwood 17002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // make sure the ADB_ENABLED setting value matches the current state 17102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED, mAdbEnabled ? 1 : 0); 172541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood 17302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mHandler.sendEmptyMessage(MSG_SYSTEM_READY); 17402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 175541c9949ae9c05636d3e0442aa5080815121a042Mike Lockwood 176629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood private static void initRndisAddress() { 177629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood // configure RNDIS ethernet address based on our serial number using the same algorithm 178629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood // we had been previously using in kernel board files 179629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood final int ETH_ALEN = 6; 180629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood int address[] = new int[ETH_ALEN]; 181629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood // first byte is 0x02 to signify a locally administered address 182629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood address[0] = 0x02; 183629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood 184629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF"); 185629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood int serialLength = serial.length(); 186629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood // XOR the USB serial across the remaining 5 bytes 187629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood for (int i = 0; i < serialLength; i++) { 188629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood address[i % (ETH_ALEN - 1) + 1] ^= (int)serial.charAt(i); 189629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood } 190629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood String addrString = String.format("%02X:%02X:%02X:%02X:%02X:%02X", 191629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood address[0], address[1], address[2], address[3], address[4], address[5]); 192629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood try { 193629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString); 194629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood } catch (IOException e) { 195629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH); 196629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood } 197629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood } 198629b149ff584bc247f68014a676101d1d5787d27Mike Lockwood 19902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static String addFunction(String functions, String function) { 20002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (!containsFunction(functions, function)) { 20102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (functions.length() > 0) { 20202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood functions += ","; 20346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 20402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood functions += function; 20546d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 20602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return functions; 20746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 20846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 20902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static String removeFunction(String functions, String function) { 21002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String[] split = functions.split(","); 21102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood for (int i = 0; i < split.length; i++) { 21202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (function.equals(split[i])) { 21302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood split[i] = null; 21402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 21502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 21602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood StringBuilder builder = new StringBuilder(); 21702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood for (int i = 0; i < split.length; i++) { 21802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String s = split[i]; 21902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (s != null) { 22002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (builder.length() > 0) { 22102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood builder.append(","); 22202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 22302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood builder.append(s); 22402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 22502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 22602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return builder.toString(); 22702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 22846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 22902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private static boolean containsFunction(String functions, String function) { 23002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood int index = functions.indexOf(function); 23102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (index < 0) return false; 23202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (index > 0 && functions.charAt(index - 1) != ',') return false; 23302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood int charAfter = index + function.length(); 23402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false; 23502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return true; 23602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 23702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 23802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private final class UsbHandler extends Handler { 23902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 24002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // current USB state 24102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private boolean mConnected; 24202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private boolean mConfigured; 24302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private String mCurrentFunctions; 24402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private String mDefaultFunctions; 24502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private UsbAccessory mCurrentAccessory; 246d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood private int mUsbNotificationId; 247d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood private boolean mAdbNotificationShown; 248d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 249d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() { 250d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood public void onReceive(Context context, Intent intent) { 251d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (DEBUG) Slog.d(TAG, "boot completed"); 252d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); 253d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood } 254d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood }; 255d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood 2563fd13eb6322e09f1ffe5476e28d55732da391151Mike Lockwood public UsbHandler(Looper looper) { 2573fd13eb6322e09f1ffe5476e28d55732da391151Mike Lockwood super(looper); 25802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood try { 259c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood // persist.sys.usb.config should never be unset. But if it is, set it to "adb" 260c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood // so we have a chance of debugging what happened. 261c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood mDefaultFunctions = SystemProperties.get("persist.sys.usb.config", "adb"); 262de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood // sanity check the sys.usb.config system property 263de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood // this may be necessary if we crashed while switching USB configurations 264de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood String config = SystemProperties.get("sys.usb.config", "none"); 265c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood if (!config.equals(mDefaultFunctions)) { 266c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood Slog.w(TAG, "resetting config to persistent property: " + mDefaultFunctions); 267c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood SystemProperties.set("sys.usb.config", mDefaultFunctions); 268de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood } 269de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood 270c264afeb5528733a215a472e761b51cc59bba454Mike Lockwood mCurrentFunctions = mDefaultFunctions; 27102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim(); 27202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood updateState(state); 27302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB); 27402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 27502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // Upgrade step for previous versions that used persist.service.adb.enable 27602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String value = SystemProperties.get("persist.service.adb.enable", ""); 27702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (value.length() > 0) { 27802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood char enable = value.charAt(0); 27902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (enable == '1') { 28002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood setAdbEnabled(true); 28102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else if (enable == '0') { 28202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood setAdbEnabled(false); 28302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 28402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood SystemProperties.set("persist.service.adb.enable", ""); 28502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 28602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 28702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // register observer to listen for settings changes 28802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mContentResolver.registerContentObserver( 28902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED), 29002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood false, new AdbSettingsObserver()); 29102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 29202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // Watch for USB configuration changes 29302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mUEventObserver.startObserving(USB_STATE_MATCH); 29402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mUEventObserver.startObserving(ACCESSORY_START_MATCH); 295d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood 296d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood mContext.registerReceiver(mBootCompletedReceiver, 297d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); 29802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } catch (Exception e) { 29902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Slog.e(TAG, "Error initializing UsbHandler", e); 30002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 30146d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 30202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 30302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public void sendMessage(int what, boolean arg) { 30402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood removeMessages(what); 30502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Message m = Message.obtain(this, what); 30602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood m.arg1 = (arg ? 1 : 0); 30702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood sendMessage(m); 30846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 30946d0adf8256a42416584765625852b6e48497c90Mike Lockwood 31002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public void sendMessage(int what, Object arg) { 31102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood removeMessages(what); 31202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Message m = Message.obtain(this, what); 31302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood m.obj = arg; 31402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood sendMessage(m); 31502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 31602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 317f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood public void sendMessage(int what, Object arg0, boolean arg1) { 318f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood removeMessages(what); 319f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood Message m = Message.obtain(this, what); 320f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood m.obj = arg0; 321f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood m.arg1 = (arg1 ? 1 : 0); 322f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood sendMessage(m); 323f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood } 324f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood 32502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public void updateState(String state) { 32602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood int connected, configured; 32702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 32802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if ("DISCONNECTED".equals(state)) { 32902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood connected = 0; 33002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood configured = 0; 33102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else if ("CONNECTED".equals(state)) { 33202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood connected = 1; 33302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood configured = 0; 33402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else if ("CONFIGURED".equals(state)) { 33502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood connected = 1; 33602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood configured = 1; 33702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else { 33802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Slog.e(TAG, "unknown state " + state); 33902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return; 34002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 34102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood removeMessages(MSG_UPDATE_STATE); 34202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Message msg = Message.obtain(this, MSG_UPDATE_STATE); 34302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood msg.arg1 = connected; 34402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood msg.arg2 = configured; 34502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // debounce disconnects to avoid problems bringing up USB tethering 34602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0); 34702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 34802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 349f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood private boolean waitForState(String state) { 35002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // wait for the transition to complete. 35102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // give up after 1 second. 35202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood for (int i = 0; i < 20; i++) { 35368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood // State transition is done when sys.usb.state is set to the new configuration 354f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood if (state.equals(SystemProperties.get("sys.usb.state"))) return true; 35502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood try { 35602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // try again in 50ms 35702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Thread.sleep(50); 35802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } catch (InterruptedException e) { 35902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 36002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 361fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood Slog.e(TAG, "waitForState(" + state + ") FAILED"); 36202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return false; 36302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 36402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 365f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood private boolean setUsbConfig(String config) { 366fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")"); 367f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood // set the new configuration 368f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood SystemProperties.set("sys.usb.config", config); 369f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood return waitForState(config); 370f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood } 371f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood 37202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private void setAdbEnabled(boolean enable) { 373de296f64483713fdf164f3e8bf41dc12d1cff59eMike Lockwood if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable); 37402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (enable != mAdbEnabled) { 37502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mAdbEnabled = enable; 376f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood // Due to the persist.sys.usb.config property trigger, changing adb state requires 377f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood // switching to default function 3781984e79d1593b80adf46b16666862f5787157aedMike Lockwood setEnabledFunctions(mDefaultFunctions, true); 379d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood updateAdbNotification(); 38002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 38102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 38202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 38368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood private void setEnabledFunctions(String functions, boolean makeDefault) { 38468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (functions != null && makeDefault) { 3858b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood if (mAdbEnabled) { 3868b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB); 3878b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood } else { 3888b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB); 3898b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood } 39068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (!mDefaultFunctions.equals(functions)) { 39168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (!setUsbConfig("none")) { 39268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood Slog.e(TAG, "Failed to disable USB"); 39368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood // revert to previous configuration if we fail 39468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood setUsbConfig(mCurrentFunctions); 39568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood return; 39668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } 39768736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood // setting this property will also change the current USB state 39868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood // via a property trigger 39968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood SystemProperties.set("persist.sys.usb.config", functions); 40068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (waitForState(functions)) { 40168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood mCurrentFunctions = functions; 40268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood mDefaultFunctions = functions; 40368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } else { 40468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood Slog.e(TAG, "Failed to switch persistent USB config to " + functions); 40568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood // revert to previous configuration if we fail 40668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood SystemProperties.set("persist.sys.usb.config", mDefaultFunctions); 40768736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } 40868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } 40968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } else { 41068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (functions == null) { 41168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood functions = mDefaultFunctions; 41268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } 4138b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood if (mAdbEnabled) { 4148b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB); 4158b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood } else { 4168b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB); 4178b4d36e8661e25fcb893e00be15ba02da0950055Mike Lockwood } 41868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (!mCurrentFunctions.equals(functions)) { 41968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (!setUsbConfig("none")) { 42068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood Slog.e(TAG, "Failed to disable USB"); 42168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood // revert to previous configuration if we fail 42268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood setUsbConfig(mCurrentFunctions); 42368736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood return; 42468736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } 42568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood if (setUsbConfig(functions)) { 42668736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood mCurrentFunctions = functions; 42768736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } else { 42868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood Slog.e(TAG, "Failed to switch USB config to " + functions); 42968736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood // revert to previous configuration if we fail 43068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood setUsbConfig(mCurrentFunctions); 43168736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } 43268736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood } 43302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 43402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 43502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 43602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private void updateCurrentAccessory() { 43702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (!mHasUsbAccessory) return; 43802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 43902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (mConfigured) { 44002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String[] strings = nativeGetAccessoryStrings(); 44102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (strings != null) { 44202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mCurrentAccessory = new UsbAccessory(strings); 443fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory); 44402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // defer accessoryAttached if system is not ready 445d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (mBootCompleted) { 44602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mSettingsManager.accessoryAttached(mCurrentAccessory); 447d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood } // else handle in mBootCompletedReceiver 44802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else { 449fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood Slog.e(TAG, "nativeGetAccessoryStrings failed"); 45002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 45102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } else if (!mConnected) { 45202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // make sure accessory mode is off 45302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // and restore default functions 454fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood Slog.d(TAG, "exited USB accessory mode"); 45568736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood setEnabledFunctions(mDefaultFunctions, false); 45602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 45702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (mCurrentAccessory != null) { 458d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (mBootCompleted) { 45902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mSettingsManager.accessoryDetached(mCurrentAccessory); 46002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 46102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mCurrentAccessory = null; 46246d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 46346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 46446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 46546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 46602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood private void updateUsbState() { 46702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // send a sticky broadcast containing current USB state 46802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Intent intent = new Intent(UsbManager.ACTION_USB_STATE); 46902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 47002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood intent.putExtra(UsbManager.USB_CONNECTED, mConnected); 47102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured); 47202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 47302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (mCurrentFunctions != null) { 47402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood String[] functions = mCurrentFunctions.split(","); 47502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood for (int i = 0; i < functions.length; i++) { 47602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood intent.putExtra(functions[i], true); 47702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 47846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 47902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 48002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mContext.sendStickyBroadcast(intent); 48146d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 48246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 48302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood @Override 48402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public void handleMessage(Message msg) { 48502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood switch (msg.what) { 48602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood case MSG_UPDATE_STATE: 48702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mConnected = (msg.arg1 == 1); 48802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mConfigured = (msg.arg2 == 1); 489d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood updateUsbNotification(); 490d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood updateAdbNotification(); 49102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (containsFunction(mCurrentFunctions, 49202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood UsbManager.USB_FUNCTION_ACCESSORY)) { 49302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood updateCurrentAccessory(); 49402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 49502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 49602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (!mConnected) { 49702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood // restore defaults when USB is disconnected 49868736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood setEnabledFunctions(mDefaultFunctions, false); 49902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 500d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (mBootCompleted) { 50102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood updateUsbState(); 50202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 50302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood break; 50402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood case MSG_ENABLE_ADB: 50502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood setAdbEnabled(msg.arg1 == 1); 50602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood break; 507f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood case MSG_SET_CURRENT_FUNCTION: 508f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood String function = (String)msg.obj; 509f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood boolean makeDefault = (msg.arg1 == 1); 51068736cbf938935f7d7e1eb2b3f9ec911fcb0da72Mike Lockwood setEnabledFunctions(function, makeDefault); 51102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood break; 51202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood case MSG_SYSTEM_READY: 513d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood updateUsbNotification(); 514d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood updateAdbNotification(); 51502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood updateUsbState(); 516d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood break; 517d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood case MSG_BOOT_COMPLETED: 518d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood mBootCompleted = true; 519d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (mCurrentAccessory != null) { 52002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mSettingsManager.accessoryAttached(mCurrentAccessory); 52102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 52202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood break; 52346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 52446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 52546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 52602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public UsbAccessory getCurrentAccessory() { 52702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return mCurrentAccessory; 52802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 52902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 530d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood private void updateUsbNotification() { 531d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood if (mNotificationManager == null || !mUseUsbNotification) return; 532fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood int id = 0; 533a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood Resources r = mContext.getResources(); 534d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood if (mConnected) { 535d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) { 536fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood id = com.android.internal.R.string.usb_mtp_notification_title; 537d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) { 538fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood id = com.android.internal.R.string.usb_ptp_notification_title; 539d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } else if (containsFunction(mCurrentFunctions, 540d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood UsbManager.USB_FUNCTION_MASS_STORAGE)) { 541fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood id = com.android.internal.R.string.usb_cd_installer_notification_title; 5426e680dea3bc9e2d4ba1a09f428c303cd2a59c051Mike Lockwood } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) { 543fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood id = com.android.internal.R.string.usb_accessory_notification_title; 544d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } else { 545a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood // There is a different notification for USB tethering so we don't need one here 546a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) { 547a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood Slog.e(TAG, "No known USB function in updateUsbNotification"); 548d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 549d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 550a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood } 551a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood if (id != mUsbNotificationId) { 552a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood // clear notification if title needs changing 553fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood if (mUsbNotificationId != 0) { 554a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood mNotificationManager.cancel(mUsbNotificationId); 555fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood mUsbNotificationId = 0; 556a5010431bfcdff88ac9d96e68d8308071c13472bMike Lockwood } 557fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood if (id != 0) { 558d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood CharSequence message = r.getText( 559d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood com.android.internal.R.string.usb_notification_message); 560fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood CharSequence title = r.getText(id); 561d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 562d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood Notification notification = new Notification(); 563d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.icon = com.android.internal.R.drawable.stat_sys_data_usb; 564d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.when = 0; 565d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.flags = Notification.FLAG_ONGOING_EVENT; 566d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.tickerText = title; 567d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.defaults = 0; // please be quiet 568d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.sound = null; 569d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.vibrate = null; 570d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 571765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate Intent intent = Intent.makeRestartActivityTask( 572765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate new ComponentName("com.android.settings", 573765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate "com.android.settings.UsbSettings")); 574d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood PendingIntent pi = PendingIntent.getActivity(mContext, 0, 575d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood intent, 0); 576d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.setLatestEventInfo(mContext, title, message, pi); 577d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood mNotificationManager.notify(id, notification); 578d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood mUsbNotificationId = id; 579d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 580d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 581d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 582d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 583d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood private void updateAdbNotification() { 584d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood if (mNotificationManager == null) return; 585fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood final int id = com.android.internal.R.string.adb_active_notification_title; 586d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood if (mAdbEnabled && mConnected) { 587d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood if ("0".equals(SystemProperties.get("persist.adb.notify"))) return; 588d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 589d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood if (!mAdbNotificationShown) { 590d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood Resources r = mContext.getResources(); 591fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood CharSequence title = r.getText(id); 592d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood CharSequence message = r.getText( 593d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood com.android.internal.R.string.adb_active_notification_message); 594d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 595d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood Notification notification = new Notification(); 596d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.icon = com.android.internal.R.drawable.stat_sys_adb; 597d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.when = 0; 598d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.flags = Notification.FLAG_ONGOING_EVENT; 599d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.tickerText = title; 600d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.defaults = 0; // please be quiet 601d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.sound = null; 602d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.vibrate = null; 603d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 604765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate Intent intent = Intent.makeRestartActivityTask( 605765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate new ComponentName("com.android.settings", 606765f97d5e608031bc1de4156c6e681e4d178c7eeChristopher Tate "com.android.settings.DevelopmentSettings")); 607d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood PendingIntent pi = PendingIntent.getActivity(mContext, 0, 608d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood intent, 0); 609d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood notification.setLatestEventInfo(mContext, title, message, pi); 610d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood mAdbNotificationShown = true; 611fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood mNotificationManager.notify(id, notification); 612d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 613d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } else if (mAdbNotificationShown) { 614d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood mAdbNotificationShown = false; 615fadd2b8e0ffea0d5b4bf3ca16af4d5cea001b561Mike Lockwood mNotificationManager.cancel(id); 616d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 617d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood } 618d8404d2fdd7036435748548a6791063fb6d6c909Mike Lockwood 61902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public void dump(FileDescriptor fd, PrintWriter pw) { 62002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood pw.println(" USB Device State:"); 62102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood pw.println(" Current Functions: " + mCurrentFunctions); 62202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood pw.println(" Default Functions: " + mDefaultFunctions); 62302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood pw.println(" mConnected: " + mConnected); 62402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood pw.println(" mConfigured: " + mConfigured); 62502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood pw.println(" mCurrentAccessory: " + mCurrentAccessory); 6266ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood try { 6276ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood pw.println(" Kernel state: " 6286ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim()); 6296ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood pw.println(" Kernel function list: " 6306ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim()); 6316ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood pw.println(" Mass storage backing file: " 6326ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood + FileUtils.readTextFile(new File(MASS_STORAGE_FILE_PATH), 0, null).trim()); 6336ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood } catch (IOException e) { 6346ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood pw.println("IOException: " + e); 6356ea146c239f2468563b4e8766b446d14ae4a1ff5Mike Lockwood } 63602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 63746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 63846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 63902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood /* returns the currently attached USB accessory */ 64046d0adf8256a42416584765625852b6e48497c90Mike Lockwood public UsbAccessory getCurrentAccessory() { 64102e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood return mHandler.getCurrentAccessory(); 64246d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 64346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 64402e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood /* opens the currently attached USB accessory */ 645abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { 646abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood UsbAccessory currentAccessory = mHandler.getCurrentAccessory(); 647abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood if (currentAccessory == null) { 648abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood throw new IllegalArgumentException("no accessory attached"); 64946d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 650abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood if (!currentAccessory.equals(accessory)) { 651abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood String error = accessory.toString() 652abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood + " does not match current accessory " 653abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood + currentAccessory; 654abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood throw new IllegalArgumentException(error); 655abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood } 656abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood mSettingsManager.checkPermission(accessory); 657abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood return nativeOpenAccessory(); 658abc4ac6d48c52bd8b69026441bf261e5c68c24f4Mike Lockwood } 65902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood 660f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood public void setCurrentFunction(String function, boolean makeDefault) { 661fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood if (DEBUG) Slog.d(TAG, "setCurrentFunction(" + function + ") default: " + makeDefault); 662f59717ddb5ef324ee3fdb12b83e7d1b709793d28Mike Lockwood mHandler.sendMessage(MSG_SET_CURRENT_FUNCTION, function, makeDefault); 66302e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 66446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 66502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood public void setMassStorageBackingFile(String path) { 66602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (path == null) path = ""; 66702e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood try { 66802e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood FileUtils.stringToFile(MASS_STORAGE_FILE_PATH, path); 66902e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } catch (IOException e) { 67002e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood Slog.e(TAG, "failed to write to " + MASS_STORAGE_FILE_PATH); 67146d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 67202e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood } 67346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 67446d0adf8256a42416584765625852b6e48497c90Mike Lockwood public void dump(FileDescriptor fd, PrintWriter pw) { 67502e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood if (mHandler != null) { 67602e4569b5f126ca916a7473117ddd17d4f2ccbbbMike Lockwood mHandler.dump(fd, pw); 67746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 67846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 67946d0adf8256a42416584765625852b6e48497c90Mike Lockwood 68046d0adf8256a42416584765625852b6e48497c90Mike Lockwood private native String[] nativeGetAccessoryStrings(); 68146d0adf8256a42416584765625852b6e48497c90Mike Lockwood private native ParcelFileDescriptor nativeOpenAccessory(); 682d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood private native boolean nativeIsStartRequested(); 68346d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 684