am dd76dc02: Merge "UsbService: Handle the case where a USB accessory connects as the device is booting" into honeycomb-mr1
* commit 'dd76dc0297f4c39fefbbc1ac23d9b1add187d9e9':
UsbService: Handle the case where a USB accessory connects as the device is booting
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 8b419f3..b7f6346 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -17,9 +17,11 @@
package com.android.server.usb;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbAccessory;
@@ -112,35 +114,40 @@
private final boolean mHasUsbHost;
private final boolean mHasUsbAccessory;
+ private final void readCurrentAccessoryLocked() {
+ if (mHasUsbAccessory) {
+ String[] strings = nativeGetAccessoryStrings();
+ if (strings != null) {
+ mCurrentAccessory = new UsbAccessory(strings);
+ Log.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
+ if (mSystemReady) {
+ mDeviceManager.accessoryAttached(mCurrentAccessory);
+ }
+ } else {
+ Log.e(TAG, "nativeGetAccessoryStrings failed");
+ }
+ }
+ }
+
/*
* Handles USB function enable/disable events (device mode)
*/
private final void functionEnabledLocked(String function, boolean enabled) {
- boolean enteringAccessoryMode =
- (mHasUsbAccessory && enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function));
-
if (enabled) {
if (!mEnabledFunctions.contains(function)) {
mEnabledFunctions.add(function);
}
mDisabledFunctions.remove(function);
+
+ if (UsbManager.USB_FUNCTION_ACCESSORY.equals(function)) {
+ readCurrentAccessoryLocked();
+ }
} else {
if (!mDisabledFunctions.contains(function)) {
mDisabledFunctions.add(function);
}
mEnabledFunctions.remove(function);
}
-
- if (enteringAccessoryMode) {
- String[] strings = nativeGetAccessoryStrings();
- if (strings != null) {
- mCurrentAccessory = new UsbAccessory(strings);
- Log.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
- mDeviceManager.accessoryAttached(mCurrentAccessory);
- } else {
- Log.e(TAG, "nativeGetAccessoryStrings failed");
- }
- }
}
/*
@@ -193,6 +200,17 @@
}
};
+ private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ // handle accessories attached at boot time
+ synchronized (mLock) {
+ if (mCurrentAccessory != null) {
+ mDeviceManager.accessoryAttached(mCurrentAccessory);
+ }
+ }
+ }
+ };
+
public UsbService(Context context) {
mContext = context;
mDeviceManager = new UsbDeviceSettingsManager(context);
@@ -203,17 +221,21 @@
mHostBlacklist = context.getResources().getStringArray(
com.android.internal.R.array.config_usbHostBlacklist);
- init(); // set initial status
+ synchronized (mLock) {
+ init(); // set initial status
- if (mConfiguration >= 0) {
- mUEventObserver.startObserving(USB_CONNECTED_MATCH);
- mUEventObserver.startObserving(USB_CONFIGURATION_MATCH);
- mUEventObserver.startObserving(USB_FUNCTIONS_MATCH);
+ // Watch for USB configuration changes
+ if (mConfiguration >= 0) {
+ mUEventObserver.startObserving(USB_CONNECTED_MATCH);
+ mUEventObserver.startObserving(USB_CONFIGURATION_MATCH);
+ mUEventObserver.startObserving(USB_FUNCTIONS_MATCH);
+ }
}
}
private final void init() {
char[] buffer = new char[1024];
+ boolean inAccessoryMode = false;
// Read initial USB state (device mode)
mConfiguration = -1;
@@ -233,8 +255,10 @@
} catch (Exception e) {
Slog.e(TAG, "" , e);
}
- if (mConfiguration < 0)
+ if (mConfiguration < 0) {
+ // This may happen in the emulator or devices without USB device mode support
return;
+ }
// Read initial list of enabled and disabled functions (device mode)
try {
@@ -248,9 +272,13 @@
String functionName = files[i].getName();
if (value == 1) {
mEnabledFunctions.add(functionName);
- // adb is enabled/disabled automatically by the adbd daemon,
- // so don't treat it as a default function
- if (!UsbManager.USB_FUNCTION_ADB.equals(functionName)) {
+ if (UsbManager.USB_FUNCTION_ACCESSORY.equals(functionName)) {
+ // The USB accessory driver is on by default, but it might have been
+ // enabled before the USB service has initialized.
+ inAccessoryMode = true;
+ } else if (!UsbManager.USB_FUNCTION_ADB.equals(functionName)) {
+ // adb is enabled/disabled automatically by the adbd daemon,
+ // so don't treat it as a default function.
mDefaultFunctions.add(functionName);
}
} else {
@@ -262,6 +290,21 @@
} catch (Exception e) {
Slog.e(TAG, "" , e);
}
+
+ // handle the case where an accessory switched the driver to accessory mode
+ // before the framework finished booting
+ if (inAccessoryMode) {
+ readCurrentAccessoryLocked();
+
+ // FIXME - if we booted in accessory mode, then we have no way to figure out
+ // which functions are enabled by default.
+ // For now, assume that MTP or mass storage are the only possibilities
+ if (mDisabledFunctions.contains(UsbManager.USB_FUNCTION_MTP)) {
+ mDefaultFunctions.add(UsbManager.USB_FUNCTION_MTP);
+ } else if (mDisabledFunctions.contains(UsbManager.USB_FUNCTION_MASS_STORAGE)) {
+ mDefaultFunctions.add(UsbManager.USB_FUNCTION_MASS_STORAGE);
+ }
+ }
}
private boolean isBlackListed(String deviceName) {
@@ -381,6 +424,13 @@
}
update(false);
+ if (mCurrentAccessory != null) {
+ Log.d(TAG, "accessoryAttached at systemReady");
+ // its still too early to handle accessories, so add a BOOT_COMPLETED receiver
+ // to handle this later.
+ mContext.registerReceiver(mBootCompletedReceiver,
+ new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ }
mSystemReady = true;
}
}
@@ -512,20 +562,18 @@
if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
if (mConnected == 0) {
// make sure accessory mode is off, and restore default functions
- if (UsbManager.setFunctionEnabled(
+ if (mCurrentAccessory != null && UsbManager.setFunctionEnabled(
UsbManager.USB_FUNCTION_ACCESSORY, false)) {
Log.d(TAG, "exited USB accessory mode");
int count = mDefaultFunctions.size();
for (int i = 0; i < count; i++) {
String function = mDefaultFunctions.get(i);
- if (UsbManager.setFunctionEnabled(function, true)) {
+ if (!UsbManager.setFunctionEnabled(function, true)) {
Log.e(TAG, "could not reenable function " + function);
}
}
- }
- if (mCurrentAccessory != null) {
mDeviceManager.accessoryDetached(mCurrentAccessory);
mCurrentAccessory = null;
}