summaryrefslogtreecommitdiff
path: root/services/java/com/android/server/usb/UsbService.java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2012-10-01 21:45:52 -0700
committerJeff Sharkey <jsharkey@android.com>2012-10-02 18:09:10 -0700
commitfc3f24b4b60c10e0d3f41f70df37e11ea311cc2c (patch)
treebe61172447392620b42c88517ad58a5210adf5cb /services/java/com/android/server/usb/UsbService.java
parentc6e570dbadc3689bc80c0516492a3209d5f6742b (diff)
Make USB services multi-user aware.
USB settings are now isolated per-user, since they revolve around installed packages. User-specific settings are returned based on calling user, or referenced by UserHandle passed to SystemUI. Each settings Context is wrapped as a specific user, so all broadcasts are sent correctly. Upgrades any existing USB settings to OWNER. Physical events, like new devices, are routed to the currently active user. Switch to using AtomicFile when persisting settings. Bug: 7244888 Change-Id: I8a723ad3d55ac1bff99276c5f3a3f5e8f013432f
Diffstat (limited to 'services/java/com/android/server/usb/UsbService.java')
-rw-r--r--services/java/com/android/server/usb/UsbService.java154
1 files changed, 119 insertions, 35 deletions
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index bebcd5605fb5..629f5fa4bda8 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -17,15 +17,20 @@
package com.android.server.usb;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
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;
import android.hardware.usb.UsbDevice;
-import android.net.Uri;
-import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+import android.util.SparseArray;
+
+import com.android.internal.util.IndentingPrintWriter;
import java.io.File;
import java.io.FileDescriptor;
@@ -37,21 +42,72 @@ import java.io.PrintWriter;
* support is delegated to UsbDeviceManager.
*/
public class UsbService extends IUsbManager.Stub {
+ private static final String TAG = "UsbService";
+
private final Context mContext;
+
private UsbDeviceManager mDeviceManager;
private UsbHostManager mHostManager;
- private final UsbSettingsManager mSettingsManager;
+ private final Object mLock = new Object();
+
+ /** Map from {@link UserHandle} to {@link UsbSettingsManager} */
+ // @GuardedBy("mLock")
+ private final SparseArray<UsbSettingsManager>
+ mSettingsByUser = new SparseArray<UsbSettingsManager>();
+
+ private UsbSettingsManager getSettingsForUser(int userId) {
+ synchronized (mLock) {
+ UsbSettingsManager settings = mSettingsByUser.get(userId);
+ if (settings == null) {
+ settings = new UsbSettingsManager(mContext, new UserHandle(userId));
+ mSettingsByUser.put(userId, settings);
+ }
+ return settings;
+ }
+ }
public UsbService(Context context) {
mContext = context;
- mSettingsManager = new UsbSettingsManager(context);
- PackageManager pm = mContext.getPackageManager();
+
+ final PackageManager pm = mContext.getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
- mHostManager = new UsbHostManager(context, mSettingsManager);
+ mHostManager = new UsbHostManager(context);
}
if (new File("/sys/class/android_usb").exists()) {
- mDeviceManager = new UsbDeviceManager(context, mSettingsManager);
+ mDeviceManager = new UsbDeviceManager(context);
+ }
+
+ 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);
+ }
+
+ private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ final String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ setCurrentUser(userId);
+ } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
+ synchronized (mLock) {
+ mSettingsByUser.remove(userId);
+ }
+ }
+ }
+ };
+
+ private void setCurrentUser(int userId) {
+ final UsbSettingsManager userSettings = getSettingsForUser(userId);
+ if (mHostManager != null) {
+ mHostManager.setCurrentSettings(userSettings);
+ }
+ if (mDeviceManager != null) {
+ mDeviceManager.setCurrentSettings(userSettings);
}
}
@@ -65,6 +121,7 @@ public class UsbService extends IUsbManager.Stub {
}
/* Returns a list of all currently attached USB devices (host mdoe) */
+ @Override
public void getDeviceList(Bundle devices) {
if (mHostManager != null) {
mHostManager.getDeviceList(devices);
@@ -72,6 +129,7 @@ public class UsbService extends IUsbManager.Stub {
}
/* Opens the specified USB device (host mode) */
+ @Override
public ParcelFileDescriptor openDevice(String deviceName) {
if (mHostManager != null) {
return mHostManager.openDevice(deviceName);
@@ -81,6 +139,7 @@ public class UsbService extends IUsbManager.Stub {
}
/* returns the currently attached USB accessory (device mode) */
+ @Override
public UsbAccessory getCurrentAccessory() {
if (mDeviceManager != null) {
return mDeviceManager.getCurrentAccessory();
@@ -90,6 +149,7 @@ public class UsbService extends IUsbManager.Stub {
}
/* opens the currently attached USB accessory (device mode) */
+ @Override
public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
if (mDeviceManager != null) {
return mDeviceManager.openAccessory(accessory);
@@ -98,54 +158,70 @@ public class UsbService extends IUsbManager.Stub {
}
}
- public void setDevicePackage(UsbDevice device, String packageName) {
+ @Override
+ public void setDevicePackage(UsbDevice device, String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- mSettingsManager.setDevicePackage(device, packageName);
+ getSettingsForUser(userId).setDevicePackage(device, packageName);
}
- public void setAccessoryPackage(UsbAccessory accessory, String packageName) {
+ @Override
+ public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- mSettingsManager.setAccessoryPackage(accessory, packageName);
+ getSettingsForUser(userId).setAccessoryPackage(accessory, packageName);
}
+ @Override
public boolean hasDevicePermission(UsbDevice device) {
- return mSettingsManager.hasPermission(device);
+ final int userId = UserHandle.getCallingUserId();
+ return getSettingsForUser(userId).hasPermission(device);
}
+ @Override
public boolean hasAccessoryPermission(UsbAccessory accessory) {
- return mSettingsManager.hasPermission(accessory);
+ final int userId = UserHandle.getCallingUserId();
+ return getSettingsForUser(userId).hasPermission(accessory);
}
- public void requestDevicePermission(UsbDevice device, String packageName,
- PendingIntent pi) {
- mSettingsManager.requestPermission(device, packageName, pi);
+ @Override
+ public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
+ final int userId = UserHandle.getCallingUserId();
+ getSettingsForUser(userId).requestPermission(device, packageName, pi);
}
- public void requestAccessoryPermission(UsbAccessory accessory, String packageName,
- PendingIntent pi) {
- mSettingsManager.requestPermission(accessory, packageName, pi);
+ @Override
+ public void requestAccessoryPermission(
+ UsbAccessory accessory, String packageName, PendingIntent pi) {
+ final int userId = UserHandle.getCallingUserId();
+ getSettingsForUser(userId).requestPermission(accessory, packageName, pi);
}
+ @Override
public void grantDevicePermission(UsbDevice device, int uid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- mSettingsManager.grantDevicePermission(device, uid);
+ final int userId = UserHandle.getUserId(uid);
+ getSettingsForUser(userId).grantDevicePermission(device, uid);
}
+ @Override
public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- mSettingsManager.grantAccessoryPermission(accessory, uid);
+ final int userId = UserHandle.getUserId(uid);
+ getSettingsForUser(userId).grantAccessoryPermission(accessory, uid);
}
- public boolean hasDefaults(String packageName) {
+ @Override
+ public boolean hasDefaults(String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- return mSettingsManager.hasDefaults(packageName);
+ return getSettingsForUser(userId).hasDefaults(packageName);
}
- public void clearDefaults(String packageName) {
+ @Override
+ public void clearDefaults(String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- mSettingsManager.clearDefaults(packageName);
+ getSettingsForUser(userId).clearDefaults(packageName);
}
+ @Override
public void setCurrentFunction(String function, boolean makeDefault) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
if (mDeviceManager != null) {
@@ -155,6 +231,7 @@ public class UsbService extends IUsbManager.Stub {
}
}
+ @Override
public void setMassStorageBackingFile(String path) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
if (mDeviceManager != null) {
@@ -164,34 +241,41 @@ public class UsbService extends IUsbManager.Stub {
}
}
+ @Override
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
}
+ @Override
public void denyUsbDebugging() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.denyUsbDebugging();
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump UsbManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
pw.println("USB Manager State:");
-
if (mDeviceManager != null) {
mDeviceManager.dump(fd, pw);
}
if (mHostManager != null) {
mHostManager.dump(fd, pw);
}
- mSettingsManager.dump(fd, pw);
+
+ synchronized (mLock) {
+ for (int i = 0; i < mSettingsByUser.size(); i++) {
+ final int userId = mSettingsByUser.keyAt(i);
+ final UsbSettingsManager settings = mSettingsByUser.valueAt(i);
+ pw.increaseIndent();
+ pw.println("Settings for user " + userId + ":");
+ settings.dump(fd, pw);
+ pw.decreaseIndent();
+ }
+ }
+ pw.decreaseIndent();
}
}