DO NOT MERGE: UsbService: Handle the case where a USB accessory connects as the device is booting

Bug: 4129297

Change-Id: I33963b0a667976d8100a60b27d66bfd0d57373e2
Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2011-03-19 12:03:46 -04:00
parent c0604255a7
commit 65de3c7687

View File

@@ -17,9 +17,11 @@
package com.android.server.usb; package com.android.server.usb;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager; import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbAccessory;
@@ -101,35 +103,40 @@ public class UsbService extends IUsbManager.Stub {
private final UsbDeviceSettingsManager mDeviceManager; private final UsbDeviceSettingsManager mDeviceManager;
private final boolean mHasUsbAccessory; 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) * Handles USB function enable/disable events (device mode)
*/ */
private final void functionEnabledLocked(String function, boolean enabled) { private final void functionEnabledLocked(String function, boolean enabled) {
boolean enteringAccessoryMode =
(mHasUsbAccessory && enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function));
if (enabled) { if (enabled) {
if (!mEnabledFunctions.contains(function)) { if (!mEnabledFunctions.contains(function)) {
mEnabledFunctions.add(function); mEnabledFunctions.add(function);
} }
mDisabledFunctions.remove(function); mDisabledFunctions.remove(function);
if (UsbManager.USB_FUNCTION_ACCESSORY.equals(function)) {
readCurrentAccessoryLocked();
}
} else { } else {
if (!mDisabledFunctions.contains(function)) { if (!mDisabledFunctions.contains(function)) {
mDisabledFunctions.add(function); mDisabledFunctions.add(function);
} }
mEnabledFunctions.remove(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");
}
}
} }
/* /*
@@ -182,23 +189,38 @@ public class UsbService extends IUsbManager.Stub {
} }
}; };
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) { public UsbService(Context context) {
mContext = context; mContext = context;
mDeviceManager = new UsbDeviceSettingsManager(context); mDeviceManager = new UsbDeviceSettingsManager(context);
PackageManager pm = mContext.getPackageManager(); PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
init(); // set initial status synchronized (mLock) {
init(); // set initial status
if (mConfiguration >= 0) { // Watch for USB configuration changes
mUEventObserver.startObserving(USB_CONNECTED_MATCH); if (mConfiguration >= 0) {
mUEventObserver.startObserving(USB_CONFIGURATION_MATCH); mUEventObserver.startObserving(USB_CONNECTED_MATCH);
mUEventObserver.startObserving(USB_FUNCTIONS_MATCH); mUEventObserver.startObserving(USB_CONFIGURATION_MATCH);
mUEventObserver.startObserving(USB_FUNCTIONS_MATCH);
}
} }
} }
private final void init() { private final void init() {
char[] buffer = new char[1024]; char[] buffer = new char[1024];
boolean inAccessoryMode = false;
// Read initial USB state (device mode) // Read initial USB state (device mode)
mConfiguration = -1; mConfiguration = -1;
@@ -218,8 +240,10 @@ public class UsbService extends IUsbManager.Stub {
} catch (Exception e) { } catch (Exception e) {
Slog.e(TAG, "" , 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; return;
}
// Read initial list of enabled and disabled functions (device mode) // Read initial list of enabled and disabled functions (device mode)
try { try {
@@ -233,9 +257,13 @@ public class UsbService extends IUsbManager.Stub {
String functionName = files[i].getName(); String functionName = files[i].getName();
if (value == 1) { if (value == 1) {
mEnabledFunctions.add(functionName); mEnabledFunctions.add(functionName);
// adb is enabled/disabled automatically by the adbd daemon, if (UsbManager.USB_FUNCTION_ACCESSORY.equals(functionName)) {
// so don't treat it as a default function // The USB accessory driver is on by default, but it might have been
if (!UsbManager.USB_FUNCTION_ADB.equals(functionName)) { // 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); mDefaultFunctions.add(functionName);
} }
} else { } else {
@@ -247,11 +275,33 @@ public class UsbService extends IUsbManager.Stub {
} catch (Exception e) { } catch (Exception e) {
Slog.e(TAG, "" , 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);
}
}
} }
public void systemReady() { public void systemReady() {
synchronized (mLock) { synchronized (mLock) {
update(false); 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; mSystemReady = true;
} }
} }
@@ -338,20 +388,18 @@ public class UsbService extends IUsbManager.Stub {
if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) { if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
if (mConnected == 0) { if (mConnected == 0) {
// make sure accessory mode is off, and restore default functions // make sure accessory mode is off, and restore default functions
if (UsbManager.setFunctionEnabled( if (mCurrentAccessory != null && UsbManager.setFunctionEnabled(
UsbManager.USB_FUNCTION_ACCESSORY, false)) { UsbManager.USB_FUNCTION_ACCESSORY, false)) {
Log.d(TAG, "exited USB accessory mode"); Log.d(TAG, "exited USB accessory mode");
int count = mDefaultFunctions.size(); int count = mDefaultFunctions.size();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
String function = mDefaultFunctions.get(i); String function = mDefaultFunctions.get(i);
if (UsbManager.setFunctionEnabled(function, true)) { if (!UsbManager.setFunctionEnabled(function, true)) {
Log.e(TAG, "could not reenable function " + function); Log.e(TAG, "could not reenable function " + function);
} }
} }
}
if (mCurrentAccessory != null) {
mDeviceManager.accessoryDetached(mCurrentAccessory); mDeviceManager.accessoryDetached(mCurrentAccessory);
mCurrentAccessory = null; mCurrentAccessory = null;
} }