Merge changes from topic 'usb_bugfixes-mirror-aosp-master'

* changes:
  Refactored setCurrentFunction and setUsbDataUnlocked into single method.
  Clean up persistent usb state on boot.
  Fixed handling of usb state during adb changes.
This commit is contained in:
Jerry Zhang
2016-11-16 23:59:32 +00:00
committed by Gerrit Code Review
6 changed files with 73 additions and 88 deletions

View File

@@ -50,7 +50,7 @@ public class UsbCommand extends Svc.Command {
IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService( IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
Context.USB_SERVICE)); Context.USB_SERVICE));
try { try {
usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null)); usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null), false);
} catch (RemoteException e) { } catch (RemoteException e) {
System.err.println("Error communicating with UsbManager: " + e); System.err.println("Error communicating with UsbManager: " + e);
} }

View File

@@ -87,15 +87,13 @@ interface IUsbManager
/* Returns true if the specified USB function is enabled. */ /* Returns true if the specified USB function is enabled. */
boolean isFunctionEnabled(String function); boolean isFunctionEnabled(String function);
/* Sets the current USB function. */ /* Sets the current USB function as well as whether USB data
void setCurrentFunction(String function); * (for example, MTP exposed pictures) should be made available
* on the USB connection. Unlocking data should only be done with
/* Sets whether USB data (for example, MTP exposed pictures) should be made * user involvement, since exposing pictures or other data could
* available on the USB connection. Unlocking data should only be done with * leak sensitive user information.
* user involvement, since exposing pictures or other data could leak sensitive
* user information.
*/ */
void setUsbDataUnlocked(boolean unlock); void setCurrentFunction(String function, boolean usbDataUnlocked);
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved. * the public key to list of host keys that the user has approved.

View File

@@ -509,33 +509,23 @@ public class UsbManager {
* {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP}, * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
* or {@link #USB_FUNCTION_RNDIS}. * or {@link #USB_FUNCTION_RNDIS}.
* </p><p> * </p><p>
* Also sets whether USB data (for example, MTP exposed pictures) should be made available
* on the USB connection when in device mode. Unlocking usb data should only be done with
* user involvement, since exposing pictures or other data could leak sensitive
* user information.
* </p><p>
* Note: This function is asynchronous and may fail silently without applying * Note: This function is asynchronous and may fail silently without applying
* the requested changes. * the requested changes.
* </p> * </p>
* *
* @param function name of the USB function, or null to restore the default function * @param function name of the USB function, or null to restore the default function
* @param usbDataUnlocked whether user data is accessible
* *
* {@hide} * {@hide}
*/ */
public void setCurrentFunction(String function) { public void setCurrentFunction(String function, boolean usbDataUnlocked) {
try { try {
mService.setCurrentFunction(function); mService.setCurrentFunction(function, usbDataUnlocked);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets whether USB data (for example, MTP exposed pictures) should be made available
* on the USB connection when in device mode. Unlocking usb data should only be done with
* user involvement, since exposing pictures or other data could leak sensitive
* user information.
*
* {@hide}
*/
public void setUsbDataUnlocked(boolean unlocked) {
try {
mService.setUsbDataUnlocked(unlocked);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }

View File

@@ -900,7 +900,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
} }
} else { } else {
mUsbTetherRequested = true; mUsbTetherRequested = true;
usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS); usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
} }
} else { } else {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
@@ -910,7 +910,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
} }
if (mRndisEnabled) { if (mRndisEnabled) {
usbManager.setCurrentFunction(null); usbManager.setCurrentFunction(null, false);
} }
mUsbTetherRequested = false; mUsbTetherRequested = false;
} }

View File

@@ -108,9 +108,8 @@ public class UsbDeviceManager {
private static final int MSG_SYSTEM_READY = 3; private static final int MSG_SYSTEM_READY = 3;
private static final int MSG_BOOT_COMPLETED = 4; private static final int MSG_BOOT_COMPLETED = 4;
private static final int MSG_USER_SWITCHED = 5; private static final int MSG_USER_SWITCHED = 5;
private static final int MSG_SET_USB_DATA_UNLOCKED = 6; private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
private static final int MSG_UPDATE_USER_RESTRICTIONS = 7; private static final int MSG_UPDATE_HOST_STATE = 7;
private static final int MSG_UPDATE_HOST_STATE = 8;
private static final int AUDIO_MODE_SOURCE = 1; private static final int AUDIO_MODE_SOURCE = 1;
@@ -287,7 +286,7 @@ public class UsbDeviceManager {
if (functions != null) { if (functions != null) {
mAccessoryModeRequestTime = SystemClock.elapsedRealtime(); mAccessoryModeRequestTime = SystemClock.elapsedRealtime();
setCurrentFunctions(functions); setCurrentFunctions(functions, false);
} }
} }
@@ -335,14 +334,22 @@ public class UsbDeviceManager {
// Restore default functions. // Restore default functions.
mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY, mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE); UsbManager.USB_FUNCTION_NONE);
if (UsbManager.USB_FUNCTION_NONE.equals(mCurrentFunctions)) {
mCurrentFunctions = UsbManager.USB_FUNCTION_MTP;
}
mCurrentFunctionsApplied = mCurrentFunctions.equals( mCurrentFunctionsApplied = mCurrentFunctions.equals(
SystemProperties.get(USB_STATE_PROPERTY)); SystemProperties.get(USB_STATE_PROPERTY));
mAdbEnabled = UsbManager.containsFunction(getDefaultFunctions(), mAdbEnabled = UsbManager.containsFunction(getDefaultFunctions(),
UsbManager.USB_FUNCTION_ADB); UsbManager.USB_FUNCTION_ADB);
setEnabledFunctions(null, false);
/**
* Remove MTP from persistent config, to bring usb to a good state
* after fixes to b/31814300. This block can be removed after the update
*/
String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)) {
SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
UsbManager.removeFunction(persisted, UsbManager.USB_FUNCTION_MTP));
}
setEnabledFunctions(null, false, false);
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim(); String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state); updateState(state);
@@ -374,6 +381,14 @@ public class UsbDeviceManager {
sendMessage(m); sendMessage(m);
} }
public void sendMessage(int what, Object arg, boolean arg1) {
removeMessages(what);
Message m = Message.obtain(this, what);
m.obj = arg;
m.arg1 = (arg1 ? 1 : 0);
sendMessage(m);
}
public void updateState(String state) { public void updateState(String state) {
int connected, configured; int connected, configured;
@@ -427,29 +442,24 @@ public class UsbDeviceManager {
return waitForState(config); return waitForState(config);
} }
private void setUsbDataUnlocked(boolean enable) {
if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked: " + enable);
mUsbDataUnlocked = enable;
updateUsbNotification();
updateUsbStateBroadcastIfNeeded();
setEnabledFunctions(mCurrentFunctions, true);
}
private void setAdbEnabled(boolean enable) { private void setAdbEnabled(boolean enable) {
if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable); if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
if (enable != mAdbEnabled) { if (enable != mAdbEnabled) {
mAdbEnabled = enable; mAdbEnabled = enable;
String oldFunctions = mCurrentFunctions;
// Due to the persist.sys.usb.config property trigger, changing adb state requires // Persist the adb setting
// persisting default function String newFunction = applyAdbFunction(SystemProperties.get(
String oldFunctions = getDefaultFunctions(); USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE));
String newFunctions = applyAdbFunction(oldFunctions); SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunction);
if (!oldFunctions.equals(newFunctions)) {
SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunctions); // Remove mtp from the config if file transfer is not enabled
if (oldFunctions.equals(UsbManager.USB_FUNCTION_MTP) &&
!mUsbDataUnlocked && enable) {
oldFunctions = UsbManager.USB_FUNCTION_NONE;
} }
// After persisting them use the lock-down aware function set setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
setEnabledFunctions(mCurrentFunctions, false);
updateAdbNotification(); updateAdbNotification();
} }
@@ -461,10 +471,17 @@ public class UsbDeviceManager {
/** /**
* Evaluates USB function policies and applies the change accordingly. * Evaluates USB function policies and applies the change accordingly.
*/ */
private void setEnabledFunctions(String functions, boolean forceRestart) { private void setEnabledFunctions(String functions, boolean forceRestart,
boolean usbDataUnlocked) {
if (DEBUG) Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", " if (DEBUG) Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
+ "forceRestart=" + forceRestart); + "forceRestart=" + forceRestart);
if (usbDataUnlocked != mUsbDataUnlocked) {
mUsbDataUnlocked = usbDataUnlocked;
updateUsbNotification();
forceRestart = true;
}
// Try to set the enabled functions. // Try to set the enabled functions.
final String oldFunctions = mCurrentFunctions; final String oldFunctions = mCurrentFunctions;
final boolean oldFunctionsApplied = mCurrentFunctionsApplied; final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
@@ -501,7 +518,8 @@ public class UsbDeviceManager {
} }
private boolean trySetEnabledFunctions(String functions, boolean forceRestart) { private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
if (functions == null) { if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
functions = getDefaultFunctions(); functions = getDefaultFunctions();
} }
functions = applyAdbFunction(functions); functions = applyAdbFunction(functions);
@@ -566,7 +584,7 @@ public class UsbDeviceManager {
// make sure accessory mode is off // make sure accessory mode is off
// and restore default functions // and restore default functions
Slog.d(TAG, "exited USB accessory mode"); Slog.d(TAG, "exited USB accessory mode");
setEnabledFunctions(null, false); setEnabledFunctions(null, false, false);
if (mCurrentAccessory != null) { if (mCurrentAccessory != null) {
if (mBootCompleted) { if (mBootCompleted) {
@@ -583,10 +601,6 @@ public class UsbDeviceManager {
if (mBroadcastedIntent == null) { if (mBroadcastedIntent == null) {
for (String key : keySet) { for (String key : keySet) {
if (intent.getBooleanExtra(key, false)) { if (intent.getBooleanExtra(key, false)) {
// MTP function is enabled by default.
if (UsbManager.USB_FUNCTION_MTP.equals(key)) {
continue;
}
return true; return true;
} }
} }
@@ -699,10 +713,7 @@ public class UsbDeviceManager {
case MSG_UPDATE_STATE: case MSG_UPDATE_STATE:
mConnected = (msg.arg1 == 1); mConnected = (msg.arg1 == 1);
mConfigured = (msg.arg2 == 1); mConfigured = (msg.arg2 == 1);
if (!mConnected) {
// When a disconnect occurs, relock access to sensitive user data
mUsbDataUnlocked = false;
}
updateUsbNotification(); updateUsbNotification();
updateAdbNotification(); updateAdbNotification();
if (UsbManager.containsFunction(mCurrentFunctions, if (UsbManager.containsFunction(mCurrentFunctions,
@@ -710,7 +721,7 @@ public class UsbDeviceManager {
updateCurrentAccessory(); updateCurrentAccessory();
} else if (!mConnected) { } else if (!mConnected) {
// restore defaults when USB is disconnected // restore defaults when USB is disconnected
setEnabledFunctions(null, false); setEnabledFunctions(null, false, false);
} }
if (mBootCompleted) { if (mBootCompleted) {
updateUsbStateBroadcastIfNeeded(); updateUsbStateBroadcastIfNeeded();
@@ -730,13 +741,10 @@ public class UsbDeviceManager {
break; break;
case MSG_SET_CURRENT_FUNCTIONS: case MSG_SET_CURRENT_FUNCTIONS:
String functions = (String)msg.obj; String functions = (String)msg.obj;
setEnabledFunctions(functions, false); setEnabledFunctions(functions, false, msg.arg1 == 1);
break; break;
case MSG_UPDATE_USER_RESTRICTIONS: case MSG_UPDATE_USER_RESTRICTIONS:
setEnabledFunctions(mCurrentFunctions, false); setEnabledFunctions(mCurrentFunctions, false, mUsbDataUnlocked);
break;
case MSG_SET_USB_DATA_UNLOCKED:
setUsbDataUnlocked(msg.arg1 == 1);
break; break;
case MSG_SYSTEM_READY: case MSG_SYSTEM_READY:
updateUsbNotification(); updateUsbNotification();
@@ -764,8 +772,7 @@ public class UsbDeviceManager {
Slog.v(TAG, "Current user switched to " + mCurrentUser Slog.v(TAG, "Current user switched to " + mCurrentUser
+ "; resetting USB host stack for MTP or PTP"); + "; resetting USB host stack for MTP or PTP");
// avoid leaking sensitive data from previous user // avoid leaking sensitive data from previous user
mUsbDataUnlocked = false; setEnabledFunctions(mCurrentFunctions, true, false);
setEnabledFunctions(mCurrentFunctions, true);
} }
mCurrentUser = msg.arg1; mCurrentUser = msg.arg1;
} }
@@ -944,14 +951,10 @@ public class UsbDeviceManager {
return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function); return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function);
} }
public void setCurrentFunctions(String functions) { public void setCurrentFunctions(String functions, boolean usbDataUnlocked) {
if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ")"); if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ", " +
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions); usbDataUnlocked + ")");
} mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
public void setUsbDataUnlocked(boolean unlocked) {
if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked(" + unlocked + ")");
mHandler.sendMessage(MSG_SET_USB_DATA_UNLOCKED, unlocked);
} }
private void readOemUsbOverrideConfig() { private void readOemUsbOverrideConfig() {

View File

@@ -287,7 +287,7 @@ public class UsbService extends IUsbManager.Stub {
} }
@Override @Override
public void setCurrentFunction(String function) { public void setCurrentFunction(String function, boolean usbDataUnlocked) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
if (!isSupportedCurrentFunction(function)) { if (!isSupportedCurrentFunction(function)) {
@@ -297,7 +297,7 @@ public class UsbService extends IUsbManager.Stub {
} }
if (mDeviceManager != null) { if (mDeviceManager != null) {
mDeviceManager.setCurrentFunctions(function); mDeviceManager.setCurrentFunctions(function, usbDataUnlocked);
} else { } else {
throw new IllegalStateException("USB device mode not supported"); throw new IllegalStateException("USB device mode not supported");
} }
@@ -319,12 +319,6 @@ public class UsbService extends IUsbManager.Stub {
return false; return false;
} }
@Override
public void setUsbDataUnlocked(boolean unlocked) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.setUsbDataUnlocked(unlocked);
}
@Override @Override
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);