summaryrefslogtreecommitdiffstats
path: root/services/usb
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2015-07-09 20:03:26 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-07-09 20:03:29 +0000
commitc1aebfa02c393471fb344c3a94ee2ae62bb78f93 (patch)
treea7ad5a19b182f4e668f5e815f8c2c2e0c4219f5f /services/usb
parent968f9fdf8b2042b4d7b408f4b2a9db5008eaca6e (diff)
parent460a146eb8f827e4e70f2dd93d1ba852d0feb06b (diff)
downloadframeworks_base-c1aebfa02c393471fb344c3a94ee2ae62bb78f93.zip
frameworks_base-c1aebfa02c393471fb344c3a94ee2ae62bb78f93.tar.gz
frameworks_base-c1aebfa02c393471fb344c3a94ee2ae62bb78f93.tar.bz2
Merge "Clean up USB Manager and fix ADB." into mnc-dev
Diffstat (limited to 'services/usb')
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java364
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java63
2 files changed, 232 insertions, 195 deletions
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index e7716c2..81b4857 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -19,12 +19,10 @@ package com.android.server.usb;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -54,7 +52,6 @@ import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -67,9 +64,25 @@ import java.util.Scanner;
*/
public class UsbDeviceManager {
- private static final String TAG = UsbDeviceManager.class.getSimpleName();
+ private static final String TAG = "UsbDeviceManager";
private static final boolean DEBUG = false;
+ /**
+ * The persistent property which stores whether adb is enabled or not.
+ * May also contain vendor-specific default functions for testing purposes.
+ */
+ private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
+
+ /**
+ * The non-persistent property which stores the current USB settings.
+ */
+ private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
+
+ /**
+ * The non-persistent property which stores the current USB actual state.
+ */
+ private static final String USB_STATE_PROPERTY = "sys.usb.state";
+
private static final String USB_STATE_MATCH =
"DEVPATH=/devices/virtual/android_usb/android0";
private static final String ACCESSORY_START_MATCH =
@@ -92,6 +105,7 @@ public class UsbDeviceManager {
private static final int MSG_BOOT_COMPLETED = 4;
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 = 7;
private static final int AUDIO_MODE_SOURCE = 1;
@@ -184,12 +198,6 @@ public class UsbDeviceManager {
}
}
- public void setCurrentSettings(UsbSettingsManager settings) {
- synchronized (mLock) {
- mCurrentSettings = settings;
- }
- }
-
private UsbSettingsManager getCurrentSettings() {
synchronized (mLock) {
return mCurrentSettings;
@@ -221,6 +229,22 @@ public class UsbDeviceManager {
mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
+ public void bootCompleted() {
+ if (DEBUG) Slog.d(TAG, "boot completed");
+ mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
+ }
+
+ public void setCurrentUser(int userId, UsbSettingsManager settings) {
+ synchronized (mLock) {
+ mCurrentSettings = settings;
+ mHandler.obtainMessage(MSG_USER_SWITCHED, userId, 0).sendToTarget();
+ }
+ }
+
+ public void updateUserRestrictions() {
+ mHandler.sendEmptyMessage(MSG_UPDATE_USER_RESTRICTIONS);
+ }
+
private void startAccessoryMode() {
if (!mHasUsbAccessory) return;
@@ -270,46 +294,6 @@ public class UsbDeviceManager {
}
}
- private static String addFunction(String functions, String function) {
- if ("none".equals(functions)) {
- return function;
- }
- if (!containsFunction(functions, function)) {
- if (functions.length() > 0) {
- functions += ",";
- }
- functions += function;
- }
- return functions;
- }
-
- private static String removeFunction(String functions, String function) {
- String[] split = functions.split(",");
- for (int i = 0; i < split.length; i++) {
- if (function.equals(split[i])) {
- split[i] = null;
- }
- }
- if (split.length == 1 && split[0] == null) {
- return "none";
- }
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < split.length; i++) {
- String s = split[i];
- if (s != null) {
- if (builder.length() > 0) {
- builder.append(",");
- }
- builder.append(s);
- }
- }
- return builder.toString();
- }
-
- private static boolean containsFunction(String functions, String function) {
- return Arrays.asList(functions.split(",")).contains(function);
- }
-
private final class UsbHandler extends Handler {
// current USB state
@@ -317,49 +301,24 @@ public class UsbDeviceManager {
private boolean mConfigured;
private boolean mUsbDataUnlocked;
private String mCurrentFunctions;
+ private boolean mCurrentFunctionsApplied;
private UsbAccessory mCurrentAccessory;
private int mUsbNotificationId;
- private String mDefaultFunctions;
private boolean mAdbNotificationShown;
private int mCurrentUser = UserHandle.USER_NULL;
- private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (DEBUG) Slog.d(TAG, "boot completed");
- mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
- }
- };
-
- private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- mHandler.obtainMessage(MSG_USER_SWITCHED, userId, 0).sendToTarget();
- }
- };
-
public UsbHandler(Looper looper) {
super(looper);
try {
- // TODO: rename persist.sys.usb.config to something more descriptive.
- // persist.sys.usb.config should never be unset. But if it is, set it to "adb"
- // so we have a chance of debugging what happened.
- mDefaultFunctions = SystemProperties.get("persist.sys.usb.config", "adb");
-
- // sanity check the sys.usb.config system property
- // this may be necessary if we crashed while switching USB configurations
- String config = SystemProperties.get("sys.usb.config", "none");
- if (!config.equals(mDefaultFunctions)) {
- Slog.w(TAG, "resetting config to persistent property: " + mDefaultFunctions);
- SystemProperties.set("sys.usb.config", mDefaultFunctions);
- }
-
- mAdbEnabled = containsFunction(
- SystemProperties.get(UsbManager.ADB_PERSISTENT_PROPERTY, "adb"),
+ // Restore default functions.
+ mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
+ UsbManager.USB_FUNCTION_NONE);
+ mCurrentFunctionsApplied = mCurrentFunctions.equals(
+ SystemProperties.get(USB_STATE_PROPERTY));
+ mAdbEnabled = UsbManager.containsFunction(getDefaultFunctions(),
UsbManager.USB_FUNCTION_ADB);
+ setEnabledFunctions(null, false);
- mCurrentFunctions = getDefaultFunctions();
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
@@ -371,12 +330,6 @@ public class UsbDeviceManager {
// Watch for USB configuration changes
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
-
- IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(mBootCompletedReceiver, filter);
- mContext.registerReceiver(
- mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
} catch (Exception e) {
Slog.e(TAG, "Error initializing UsbHandler", e);
}
@@ -420,34 +373,26 @@ public class UsbDeviceManager {
sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
}
- private void updatePersistentProperty() {
- String newValue = getDefaultFunctions();
- String value = SystemProperties.get(UsbManager.ADB_PERSISTENT_PROPERTY);
- if (DEBUG) { Slog.d(TAG, "updatePersistentProperty newValue=" + newValue + " value=" + value); }
- if (!newValue.equals(value)) {
- SystemProperties.set(UsbManager.ADB_PERSISTENT_PROPERTY, getDefaultFunctions());
- }
- waitForState(newValue);
- }
-
private boolean waitForState(String state) {
// wait for the transition to complete.
// give up after 1 second.
+ String value = null;
for (int i = 0; i < 20; i++) {
// State transition is done when sys.usb.state is set to the new configuration
- if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
+ value = SystemProperties.get(USB_STATE_PROPERTY);
+ if (state.equals(value)) return true;
SystemClock.sleep(50);
}
- Slog.e(TAG, "waitForState(" + state + ") FAILED");
+ Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value);
return false;
}
private boolean setUsbConfig(String config) {
if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
// set the new configuration
- String oldConfig = SystemProperties.get(UsbManager.USB_SETTINGS_PROPERTY);
+ String oldConfig = SystemProperties.get(USB_CONFIG_PROPERTY);
if (!config.equals(oldConfig)) {
- SystemProperties.set(UsbManager.USB_SETTINGS_PROPERTY, config);
+ SystemProperties.set(USB_CONFIG_PROPERTY, config);
}
return waitForState(config);
}
@@ -456,54 +401,110 @@ public class UsbDeviceManager {
if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
if (enable != mAdbEnabled) {
mAdbEnabled = enable;
+
// Due to the persist.sys.usb.config property trigger, changing adb state requires
// persisting default function
- updatePersistentProperty();
+ String oldFunctions = getDefaultFunctions();
+ String newFunctions = applyAdbFunction(oldFunctions);
+ if (!oldFunctions.equals(newFunctions)) {
+ SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunctions);
+ }
+
// After persisting them use the lock-down aware function set
- setEnabledFunctions(getDefaultFunctions());
+ setEnabledFunctions(mCurrentFunctions, false);
updateAdbNotification();
}
+
if (mDebuggingManager != null) {
mDebuggingManager.setAdbEnabled(mAdbEnabled);
}
}
/**
- * Stop and start the USB driver. This is needed to close all outstanding
- * USB connections.
+ * Evaluates USB function policies and applies the change accordingly.
*/
- private void restartCurrentFunction() {
- setUsbConfig("none");
- setUsbConfig(mCurrentFunctions);
- }
+ private void setEnabledFunctions(String functions, boolean forceRestart) {
+ if (DEBUG) Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
+ + "forceRestart=" + forceRestart);
+
+ // Try to set the enabled functions.
+ final String oldFunctions = mCurrentFunctions;
+ final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
+ if (trySetEnabledFunctions(functions, forceRestart)) {
+ return;
+ }
- private void setEnabledFunctions(String functions) {
- if (DEBUG) Slog.d(TAG, "setEnabledFunctions " + functions);
+ // Didn't work. Try to revert changes.
+ // We always reapply the policy in case certain constraints changed such as
+ // user restrictions independently of any other new functions we were
+ // trying to activate.
+ if (oldFunctionsApplied && !oldFunctions.equals(functions)) {
+ Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
+ if (trySetEnabledFunctions(oldFunctions, false)) {
+ return;
+ }
+ }
+ // Still didn't work. Try to restore the default functions.
+ Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
+ if (trySetEnabledFunctions(null, false)) {
+ return;
+ }
+
+ // Now we're desperate. Ignore the default functions.
+ // Try to get ADB working if enabled.
+ Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
+ if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) {
+ return;
+ }
+
+ // Ouch.
+ Slog.e(TAG, "Unable to set any USB functions!");
+ }
+
+ private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
if (functions == null) {
functions = getDefaultFunctions();
}
+ functions = applyAdbFunction(functions);
+ functions = applyUserRestrictions(functions);
+
+ if (!mCurrentFunctions.equals(functions) || !mCurrentFunctionsApplied
+ || forceRestart) {
+ Slog.i(TAG, "Setting USB config to " + functions);
+ mCurrentFunctions = functions;
+ mCurrentFunctionsApplied = false;
+
+ // Kick the USB stack to close existing connections.
+ setUsbConfig(UsbManager.USB_FUNCTION_NONE);
+
+ // Set the new USB configuration.
+ if (!setUsbConfig(functions)) {
+ Slog.e(TAG, "Failed to switch USB config to " + functions);
+ return false;
+ }
+
+ mCurrentFunctionsApplied = true;
+ }
+ return true;
+ }
+ private String applyAdbFunction(String functions) {
if (mAdbEnabled) {
- functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
+ functions = UsbManager.addFunction(functions, UsbManager.USB_FUNCTION_ADB);
} else {
- functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
+ functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
}
- if (!mCurrentFunctions.equals(functions)) {
- if (!setUsbConfig("none")) {
- Slog.e(TAG, "Failed to disable USB");
- // revert to previous configuration if we fail
- setUsbConfig(mCurrentFunctions);
- return;
- }
- if (setUsbConfig(functions)) {
- mCurrentFunctions = functions;
- } else {
- Slog.e(TAG, "Failed to switch USB config to " + functions);
- // revert to previous configuration if we fail
- setUsbConfig(mCurrentFunctions);
- }
+ return functions;
+ }
+
+ private String applyUserRestrictions(String functions) {
+ UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
+ functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_MTP);
+ functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_PTP);
}
+ return functions;
}
private void updateCurrentAccessory() {
@@ -523,7 +524,7 @@ public class UsbDeviceManager {
// defer accessoryAttached if system is not ready
if (mBootCompleted) {
getCurrentSettings().accessoryAttached(mCurrentAccessory);
- } // else handle in mBootCompletedReceiver
+ } // else handle in boot completed
} else {
Slog.e(TAG, "nativeGetAccessoryStrings failed");
}
@@ -531,7 +532,7 @@ public class UsbDeviceManager {
// make sure accessory mode is off
// and restore default functions
Slog.d(TAG, "exited USB accessory mode");
- setEnabledFunctions(getDefaultFunctions());
+ setEnabledFunctions(null, false);
if (mCurrentAccessory != null) {
if (mBootCompleted) {
@@ -543,10 +544,11 @@ public class UsbDeviceManager {
}
}
- private void updateUsbState() {
+ private void updateUsbStateBroadcast() {
// send a sticky broadcast containing current USB state
Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
intent.putExtra(UsbManager.USB_DATA_UNLOCKED, mUsbDataUnlocked);
@@ -563,8 +565,13 @@ public class UsbDeviceManager {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+ private void updateUsbFunctions() {
+ updateAudioSourceFunction();
+ updateMidiFunction();
+ }
+
private void updateAudioSourceFunction() {
- boolean enabled = containsFunction(mCurrentFunctions,
+ boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
UsbManager.USB_FUNCTION_AUDIO_SOURCE);
if (enabled != mAudioSourceEnabled) {
int card = -1;
@@ -590,7 +597,8 @@ public class UsbDeviceManager {
}
private void updateMidiFunction() {
- boolean enabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI);
+ boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_MIDI);
if (enabled != mMidiEnabled) {
if (enabled) {
Scanner scanner = null;
@@ -624,17 +632,16 @@ public class UsbDeviceManager {
}
updateUsbNotification();
updateAdbNotification();
- if (containsFunction(mCurrentFunctions,
+ if (UsbManager.containsFunction(mCurrentFunctions,
UsbManager.USB_FUNCTION_ACCESSORY)) {
updateCurrentAccessory();
} else if (!mConnected) {
// restore defaults when USB is disconnected
- setEnabledFunctions(getDefaultFunctions());
+ setEnabledFunctions(null, false);
}
if (mBootCompleted) {
- updateUsbState();
- updateAudioSourceFunction();
- updateMidiFunction();
+ updateUsbStateBroadcast();
+ updateUsbFunctions();
}
break;
case MSG_ENABLE_ADB:
@@ -642,26 +649,25 @@ public class UsbDeviceManager {
break;
case MSG_SET_CURRENT_FUNCTIONS:
String functions = (String)msg.obj;
- setEnabledFunctions(functions);
+ setEnabledFunctions(functions, false);
+ break;
+ case MSG_UPDATE_USER_RESTRICTIONS:
+ setEnabledFunctions(mCurrentFunctions, false);
break;
case MSG_SET_USB_DATA_UNLOCKED:
mUsbDataUnlocked = (msg.arg1 == 1);
updateUsbNotification();
- updateUsbState();
- restartCurrentFunction();
+ updateUsbStateBroadcast();
+ setEnabledFunctions(mCurrentFunctions, true);
break;
case MSG_SYSTEM_READY:
- setUsbConfig(mCurrentFunctions);
- updatePersistentProperty();
updateUsbNotification();
updateAdbNotification();
- updateUsbState();
- updateAudioSourceFunction();
- updateMidiFunction();
+ updateUsbStateBroadcast();
+ updateUsbFunctions();
break;
case MSG_BOOT_COMPLETED:
mBootCompleted = true;
- setUsbConfig(mCurrentFunctions);
if (mCurrentAccessory != null) {
getCurrentSettings().accessoryAttached(mCurrentAccessory);
}
@@ -670,27 +676,19 @@ public class UsbDeviceManager {
}
break;
case MSG_USER_SWITCHED: {
- UserManager userManager =
- (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- UserHandle userHandle = new UserHandle(msg.arg1);
- if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
- userHandle)) {
- Slog.v(TAG, "Switched to user " + msg.arg1 +
- " with DISALLOW_USB_FILE_TRANSFER restriction; disabling USB.");
- setUsbConfig("none");
+ if (mCurrentUser != msg.arg1) {
+ // Restart the USB stack and re-apply user restrictions for MTP or PTP.
+ final boolean active = UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_MTP)
+ || UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_PTP);
+ if (active && mCurrentUser != UserHandle.USER_NULL) {
+ Slog.v(TAG, "Current user switched to " + mCurrentUser
+ + "; resetting USB host stack for MTP or PTP");
+ setEnabledFunctions(mCurrentFunctions, true);
+ }
mCurrentUser = msg.arg1;
- break;
- }
-
- final boolean mtpActive =
- containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
- || containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
- if (mtpActive && mCurrentUser != UserHandle.USER_NULL) {
- Slog.v(TAG, "Current user switched; resetting USB host stack for MTP");
- setUsbConfig("none");
- setUsbConfig(mCurrentFunctions);
}
- mCurrentUser = msg.arg1;
break;
}
}
@@ -707,16 +705,17 @@ public class UsbDeviceManager {
if (mConnected) {
if (!mUsbDataUnlocked) {
id = com.android.internal.R.string.usb_charging_notification_title;
- } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
+ } else if (UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_MTP)) {
id = com.android.internal.R.string.usb_mtp_notification_title;
- } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {
+ } else if (UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_PTP)) {
id = com.android.internal.R.string.usb_ptp_notification_title;
- } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI)) {
+ } else if (UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_MIDI)) {
id = com.android.internal.R.string.usb_midi_notification_title;
- } else if (containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MASS_STORAGE)) {
- id = com.android.internal.R.string.usb_cd_installer_notification_title;
- } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) {
+ } else if (UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_ACCESSORY)) {
id = com.android.internal.R.string.usb_accessory_notification_title;
} else {
id = com.android.internal.R.string.usb_charging_notification_title;
@@ -804,17 +803,14 @@ public class UsbDeviceManager {
}
private String getDefaultFunctions() {
- UserManager userManager = (UserManager)mContext.getSystemService(Context.USER_SERVICE);
- if(userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
- new UserHandle(mCurrentUser))) {
- return "none";
- }
- return mDefaultFunctions;
+ return SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY,
+ UsbManager.USB_FUNCTION_ADB);
}
public void dump(FileDescriptor fd, PrintWriter pw) {
pw.println(" USB Device State:");
- pw.println(" Current Functions: " + mCurrentFunctions);
+ pw.println(" mCurrentFunctions: " + mCurrentFunctions);
+ pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
pw.println(" mConnected: " + mConnected);
pw.println(" mConfigured: " + mConfigured);
pw.println(" mCurrentAccessory: " + mCurrentAccessory);
@@ -850,6 +846,10 @@ public class UsbDeviceManager {
return nativeOpenAccessory();
}
+ public boolean isFunctionEnabled(String function) {
+ return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function);
+ }
+
public void setCurrentFunctions(String functions) {
if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ")");
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 987a79f..d90ade8 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -17,6 +17,7 @@
package com.android.server.usb;
import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -25,10 +26,11 @@ import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
-import android.os.UserManager;
+import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -63,6 +65,8 @@ public class UsbService extends IUsbManager.Stub {
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
mUsbService.systemReady();
+ } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ mUsbService.bootCompleted();
}
}
}
@@ -108,13 +112,15 @@ public class UsbService extends IUsbManager.Stub {
setCurrentUser(UserHandle.USER_OWNER);
- final IntentFilter userFilter = new IntentFilter();
- userFilter.addAction(Intent.ACTION_USER_SWITCHED);
- userFilter.addAction(Intent.ACTION_USER_STOPPED);
- mContext.registerReceiver(mUserReceiver, userFilter, null, null);
+ final IntentFilter filter = new IntentFilter();
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_USER_STOPPED);
+ filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ mContext.registerReceiver(mReceiver, filter, null, null);
}
- private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
@@ -125,6 +131,11 @@ public class UsbService extends IUsbManager.Stub {
synchronized (mLock) {
mSettingsByUser.remove(userId);
}
+ } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
+ .equals(action)) {
+ if (mDeviceManager != null) {
+ mDeviceManager.updateUserRestrictions();
+ }
}
}
};
@@ -135,7 +146,7 @@ public class UsbService extends IUsbManager.Stub {
mHostManager.setCurrentSettings(userSettings);
}
if (mDeviceManager != null) {
- mDeviceManager.setCurrentSettings(userSettings);
+ mDeviceManager.setCurrentUser(userId, userSettings);
}
}
@@ -150,6 +161,12 @@ public class UsbService extends IUsbManager.Stub {
}
}
+ public void bootCompleted() {
+ if (mDeviceManager != null) {
+ mDeviceManager.bootCompleted();
+ }
+ }
+
/* Returns a list of all currently attached USB devices (host mdoe) */
@Override
public void getDeviceList(Bundle devices) {
@@ -252,15 +269,19 @@ public class UsbService extends IUsbManager.Stub {
}
@Override
+ public boolean isFunctionEnabled(String function) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function);
+ }
+
+ @Override
public void setCurrentFunction(String function) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- // If attempt to change USB function while file transfer is restricted, ensure that
- // the current function is set to "none", and return.
- UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
- if (mDeviceManager != null) mDeviceManager.setCurrentFunctions("none");
- return;
+ if (!isSupportedCurrentFunction(function)) {
+ Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: "
+ + function);
+ function = UsbManager.USB_FUNCTION_NONE;
}
if (mDeviceManager != null) {
@@ -270,6 +291,22 @@ public class UsbService extends IUsbManager.Stub {
}
}
+ private static boolean isSupportedCurrentFunction(String function) {
+ if (function == null) return true;
+
+ switch (function) {
+ case UsbManager.USB_FUNCTION_NONE:
+ case UsbManager.USB_FUNCTION_AUDIO_SOURCE:
+ case UsbManager.USB_FUNCTION_MIDI:
+ case UsbManager.USB_FUNCTION_MTP:
+ case UsbManager.USB_FUNCTION_PTP:
+ case UsbManager.USB_FUNCTION_RNDIS:
+ return true;
+ }
+
+ return false;
+ }
+
@Override
public void setUsbDataUnlocked(boolean unlocked) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);