diff options
author | Jeff Sharkey <jsharkey@android.com> | 2012-10-01 21:45:52 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2012-10-02 18:09:10 -0700 |
commit | fc3f24b4b60c10e0d3f41f70df37e11ea311cc2c (patch) | |
tree | be61172447392620b42c88517ad58a5210adf5cb /services/java/com/android/server/usb/UsbService.java | |
parent | c6e570dbadc3689bc80c0516492a3209d5f6742b (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.java | 154 |
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(); } } |