summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ContextImpl.java1
-rw-r--r--core/java/android/hardware/usb/IUsbManager.aidl8
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java18
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java43
-rw-r--r--services/java/com/android/server/usb/UsbHostManager.java45
-rw-r--r--services/java/com/android/server/usb/UsbService.java154
-rw-r--r--services/java/com/android/server/usb/UsbSettingsManager.java147
10 files changed, 311 insertions, 146 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c41405b..59fa1e0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1703,6 +1703,7 @@ class ContextImpl extends Context {
if (packageName.equals("system") || packageName.equals("android")) {
final ContextImpl context = new ContextImpl(mMainThread.getSystemContext());
context.mBasePackageName = mBasePackageName;
+ context.mUser = user;
return context;
}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 98bd4f5..8286686 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -44,12 +44,12 @@ interface IUsbManager
/* Sets the default package for a USB device
* (or clears it if the package name is null)
*/
- void setDevicePackage(in UsbDevice device, String packageName);
+ void setDevicePackage(in UsbDevice device, String packageName, int userId);
/* Sets the default package for a USB accessory
* (or clears it if the package name is null)
*/
- void setAccessoryPackage(in UsbAccessory accessory, String packageName);
+ void setAccessoryPackage(in UsbAccessory accessory, String packageName, int userId);
/* Returns true if the caller has permission to access the device. */
boolean hasDevicePermission(in UsbDevice device);
@@ -77,10 +77,10 @@ interface IUsbManager
void grantAccessoryPermission(in UsbAccessory accessory, int uid);
/* Returns true if the USB manager has default preferences or permissions for the package */
- boolean hasDefaults(String packageName);
+ boolean hasDefaults(String packageName, int userId);
/* Clears default preferences and permissions for the package */
- void clearDefaults(String packageName);
+ void clearDefaults(String packageName, int userId);
/* Sets the current USB function. */
void setCurrentFunction(String function, boolean makeDefault);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
index 5007cf4..ff06630 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
@@ -26,6 +26,7 @@ import android.net.Uri;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
+import android.os.UserHandle;
import android.util.Log;
import com.android.internal.app.AlertActivity;
@@ -90,7 +91,7 @@ public class UsbAccessoryUriActivity extends AlertActivity
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
- startActivity(intent);
+ startActivityAsUser(intent, UserHandle.CURRENT);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "startActivity failed for " + mUri);
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 030a261..3eccccd 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -16,23 +16,21 @@
package com.android.systemui.usb;
-import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.hardware.usb.IUsbManager;
-import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,7 +40,6 @@ import android.widget.TextView;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
-
import com.android.systemui.R;
public class UsbConfirmActivity extends AlertActivity
@@ -62,10 +59,10 @@ public class UsbConfirmActivity extends AlertActivity
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- Intent intent = getIntent();
- mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ Intent intent = getIntent();
+ mDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
- mResolveInfo = (ResolveInfo)intent.getParcelableExtra("rinfo");
+ mResolveInfo = (ResolveInfo) intent.getParcelableExtra("rinfo");
PackageManager packageManager = getPackageManager();
String appName = mResolveInfo.loadLabel(packageManager).toString();
@@ -117,7 +114,8 @@ public class UsbConfirmActivity extends AlertActivity
try {
IBinder b = ServiceManager.getService(USB_SERVICE);
IUsbManager service = IUsbManager.Stub.asInterface(b);
- int uid = mResolveInfo.activityInfo.applicationInfo.uid;
+ final int uid = mResolveInfo.activityInfo.applicationInfo.uid;
+ final int userId = UserHandle.myUserId();
boolean alwaysUse = mAlwaysUse.isChecked();
Intent intent = null;
@@ -129,9 +127,10 @@ public class UsbConfirmActivity extends AlertActivity
service.grantDevicePermission(mDevice, uid);
// set or clear default setting
if (alwaysUse) {
- service.setDevicePackage(mDevice, mResolveInfo.activityInfo.packageName);
+ service.setDevicePackage(
+ mDevice, mResolveInfo.activityInfo.packageName, userId);
} else {
- service.setDevicePackage(mDevice, null);
+ service.setDevicePackage(mDevice, null, userId);
}
} else if (mAccessory != null) {
intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
@@ -141,10 +140,10 @@ public class UsbConfirmActivity extends AlertActivity
service.grantAccessoryPermission(mAccessory, uid);
// set or clear default setting
if (alwaysUse) {
- service.setAccessoryPackage(mAccessory,
- mResolveInfo.activityInfo.packageName);
+ service.setAccessoryPackage(
+ mAccessory, mResolveInfo.activityInfo.packageName, userId);
} else {
- service.setAccessoryPackage(mAccessory, null);
+ service.setAccessoryPackage(mAccessory, null, userId);
}
}
@@ -152,7 +151,7 @@ public class UsbConfirmActivity extends AlertActivity
intent.setComponent(
new ComponentName(mResolveInfo.activityInfo.packageName,
mResolveInfo.activityInfo.name));
- startActivity(intent);
+ startActivityAsUser(intent, new UserHandle(userId));
} catch (Exception e) {
Log.e(TAG, "Unable to start activity", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index c384f50..6e88d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -32,6 +32,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -67,7 +68,7 @@ public class UsbPermissionActivity extends AlertActivity
mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT);
- mUid = intent.getIntExtra("uid", 0);
+ mUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
mPackageName = intent.getStringExtra("package");
PackageManager packageManager = getPackageManager();
@@ -128,7 +129,8 @@ public class UsbPermissionActivity extends AlertActivity
if (mPermissionGranted) {
service.grantDevicePermission(mDevice, mUid);
if (mAlwaysUse.isChecked()) {
- service.setDevicePackage(mDevice, mPackageName);
+ final int userId = UserHandle.getUserId(mUid);
+ service.setDevicePackage(mDevice, mPackageName, userId);
}
}
}
@@ -137,7 +139,8 @@ public class UsbPermissionActivity extends AlertActivity
if (mPermissionGranted) {
service.grantAccessoryPermission(mAccessory, mUid);
if (mAlwaysUse.isChecked()) {
- service.setAccessoryPackage(mAccessory, mPackageName);
+ final int userId = UserHandle.getUserId(mUid);
+ service.setAccessoryPackage(mAccessory, mPackageName, userId);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index f61ecb1..9928f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -16,8 +16,6 @@
package com.android.systemui.usb;
-import com.android.internal.app.ResolverActivity;
-
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.ResolveInfo;
@@ -30,9 +28,11 @@ import android.os.IBinder;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.Log;
import android.widget.CheckBox;
+import com.android.internal.app.ResolverActivity;
import com.android.systemui.R;
import java.util.ArrayList;
@@ -92,34 +92,36 @@ public class UsbResolverActivity extends ResolverActivity {
super.onDestroy();
}
+ @Override
protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
try {
IBinder b = ServiceManager.getService(USB_SERVICE);
IUsbManager service = IUsbManager.Stub.asInterface(b);
- int uid = ri.activityInfo.applicationInfo.uid;
+ final int uid = ri.activityInfo.applicationInfo.uid;
+ final int userId = UserHandle.myUserId();
if (mDevice != null) {
// grant permission for the device
service.grantDevicePermission(mDevice, uid);
// set or clear default setting
if (alwaysCheck) {
- service.setDevicePackage(mDevice, ri.activityInfo.packageName);
+ service.setDevicePackage(mDevice, ri.activityInfo.packageName, userId);
} else {
- service.setDevicePackage(mDevice, null);
+ service.setDevicePackage(mDevice, null, userId);
}
} else if (mAccessory != null) {
// grant permission for the accessory
service.grantAccessoryPermission(mAccessory, uid);
// set or clear default setting
if (alwaysCheck) {
- service.setAccessoryPackage(mAccessory, ri.activityInfo.packageName);
+ service.setAccessoryPackage(mAccessory, ri.activityInfo.packageName, userId);
} else {
- service.setAccessoryPackage(mAccessory, null);
+ service.setAccessoryPackage(mAccessory, null, userId);
}
}
try {
- startActivity(intent);
+ startActivityAsUser(intent, new UserHandle(userId));
} catch (ActivityNotFoundException e) {
Log.e(TAG, "startActivity failed", e);
}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 10011aa..95797ef 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -16,9 +16,9 @@
package com.android.server.usb;
-import android.app.PendingIntent;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -30,23 +30,19 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
-import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.UserHandle;
-import android.os.storage.StorageManager;
-import android.os.storage.StorageVolume;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
+import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
import android.provider.Settings;
import android.util.Pair;
import android.util.Slog;
@@ -56,10 +52,9 @@ import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.ArrayList;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
-import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
@@ -106,9 +101,12 @@ public class UsbDeviceManager {
private UsbHandler mHandler;
private boolean mBootCompleted;
+ private final Object mLock = new Object();
+
private final Context mContext;
private final ContentResolver mContentResolver;
- private final UsbSettingsManager mSettingsManager;
+ // @GuardedBy("mLock")
+ private UsbSettingsManager mCurrentSettings;
private NotificationManager mNotificationManager;
private final boolean mHasUsbAccessory;
private boolean mUseUsbNotification;
@@ -149,10 +147,9 @@ public class UsbDeviceManager {
}
};
- public UsbDeviceManager(Context context, UsbSettingsManager settingsManager) {
+ public UsbDeviceManager(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
- mSettingsManager = settingsManager;
PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
initRndisAddress();
@@ -175,6 +172,18 @@ public class UsbDeviceManager {
}
}
+ public void setCurrentSettings(UsbSettingsManager settings) {
+ synchronized (mLock) {
+ mCurrentSettings = settings;
+ }
+ }
+
+ private UsbSettingsManager getCurrentSettings() {
+ synchronized (mLock) {
+ return mCurrentSettings;
+ }
+ }
+
public void systemReady() {
if (DEBUG) Slog.d(TAG, "systemReady");
@@ -516,7 +525,7 @@ public class UsbDeviceManager {
Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
// defer accessoryAttached if system is not ready
if (mBootCompleted) {
- mSettingsManager.accessoryAttached(mCurrentAccessory);
+ getCurrentSettings().accessoryAttached(mCurrentAccessory);
} // else handle in mBootCompletedReceiver
} else {
Slog.e(TAG, "nativeGetAccessoryStrings failed");
@@ -529,7 +538,7 @@ public class UsbDeviceManager {
if (mCurrentAccessory != null) {
if (mBootCompleted) {
- mSettingsManager.accessoryDetached(mCurrentAccessory);
+ getCurrentSettings().accessoryDetached(mCurrentAccessory);
}
mCurrentAccessory = null;
mAccessoryStrings = null;
@@ -618,7 +627,7 @@ public class UsbDeviceManager {
case MSG_BOOT_COMPLETED:
mBootCompleted = true;
if (mCurrentAccessory != null) {
- mSettingsManager.accessoryAttached(mCurrentAccessory);
+ getCurrentSettings().accessoryAttached(mCurrentAccessory);
}
if (mDebuggingManager != null) {
mDebuggingManager.setAdbEnabled(mAdbEnabled);
@@ -774,7 +783,7 @@ public class UsbDeviceManager {
+ currentAccessory;
throw new IllegalArgumentException(error);
}
- mSettingsManager.checkPermission(accessory);
+ getCurrentSettings().checkPermission(accessory);
return nativeOpenAccessory();
}
diff --git a/services/java/com/android/server/usb/UsbHostManager.java b/services/java/com/android/server/usb/UsbHostManager.java
index 0a0ff59..175ae6f 100644
--- a/services/java/com/android/server/usb/UsbHostManager.java
+++ b/services/java/com/android/server/usb/UsbHostManager.java
@@ -16,35 +16,19 @@
package com.android.server.usb;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
-import android.hardware.usb.UsbManager;
-import android.net.Uri;
-import android.os.Binder;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
-import android.os.UEventObserver;
-import android.provider.Settings;
+import android.os.Parcelable;
import android.util.Slog;
-import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileReader;
import java.io.PrintWriter;
import java.util.HashMap;
-import java.util.List;
/**
* UsbHostManager manages USB state in host mode.
@@ -54,22 +38,35 @@ public class UsbHostManager {
private static final boolean LOG = false;
// contains all connected USB devices
- private final HashMap<String,UsbDevice> mDevices = new HashMap<String,UsbDevice>();
+ private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
// USB busses to exclude from USB host support
private final String[] mHostBlacklist;
private final Context mContext;
private final Object mLock = new Object();
- private final UsbSettingsManager mSettingsManager;
- public UsbHostManager(Context context, UsbSettingsManager settingsManager) {
+ // @GuardedBy("mLock")
+ private UsbSettingsManager mCurrentSettings;
+
+ public UsbHostManager(Context context) {
mContext = context;
- mSettingsManager = settingsManager;
mHostBlacklist = context.getResources().getStringArray(
com.android.internal.R.array.config_usbHostBlacklist);
}
+ public void setCurrentSettings(UsbSettingsManager settings) {
+ synchronized (mLock) {
+ mCurrentSettings = settings;
+ }
+ }
+
+ private UsbSettingsManager getCurrentSettings() {
+ synchronized (mLock) {
+ return mCurrentSettings;
+ }
+ }
+
private boolean isBlackListed(String deviceName) {
int count = mHostBlacklist.length;
for (int i = 0; i < count; i++) {
@@ -154,7 +151,7 @@ public class UsbHostManager {
UsbDevice device = new UsbDevice(deviceName, vendorID, productID,
deviceClass, deviceSubclass, deviceProtocol, interfaces);
mDevices.put(deviceName, device);
- mSettingsManager.deviceAttached(device);
+ getCurrentSettings().deviceAttached(device);
}
}
@@ -163,7 +160,7 @@ public class UsbHostManager {
synchronized (mLock) {
UsbDevice device = mDevices.remove(deviceName);
if (device != null) {
- mSettingsManager.deviceDetached(device);
+ getCurrentSettings().deviceDetached(device);
}
}
}
@@ -202,7 +199,7 @@ public class UsbHostManager {
throw new IllegalArgumentException(
"device " + deviceName + " does not exist or is restricted");
}
- mSettingsManager.checkPermission(device);
+ getCurrentSettings().checkPermission(device);
return nativeOpenDevice(deviceName);
}
}
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index bebcd56..629f5fa 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();
}
}
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index a8453d3..4b2bbfe 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -33,9 +33,10 @@ import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Binder;
-import android.os.FileUtils;
-import android.os.Process;
+import android.os.Environment;
import android.os.UserHandle;
+import android.util.AtomicFile;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.Xml;
@@ -48,7 +49,6 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -60,13 +60,21 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-class UsbSettingsManager {
+import libcore.io.IoUtils;
+class UsbSettingsManager {
private static final String TAG = "UsbSettingsManager";
private static final boolean DEBUG = false;
- private static final File sSettingsFile = new File("/data/system/usb_device_manager.xml");
+
+ /** Legacy settings file, before multi-user */
+ private static final File sSingleUserSettingsFile = new File(
+ "/data/system/usb_device_manager.xml");
+
+ private final UserHandle mUser;
+ private final AtomicFile mSettingsFile;
private final Context mContext;
+ private final Context mUserContext;
private final PackageManager mPackageManager;
// Temporary mapping USB device name to list of UIDs with permissions for the device
@@ -350,28 +358,49 @@ class UsbSettingsManager {
}
private class MyPackageMonitor extends PackageMonitor {
-
+ @Override
public void onPackageAdded(String packageName, int uid) {
handlePackageUpdate(packageName);
}
+ @Override
public void onPackageChanged(String packageName, int uid, String[] components) {
handlePackageUpdate(packageName);
}
+ @Override
public void onPackageRemoved(String packageName, int uid) {
clearDefaults(packageName);
}
}
+
MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
- public UsbSettingsManager(Context context) {
+ public UsbSettingsManager(Context context, UserHandle user) {
+ if (DEBUG) Slog.v(TAG, "Creating settings for " + user);
+
+ try {
+ mUserContext = context.createPackageContextAsUser("android", 0, user);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException("Missing android package");
+ }
+
mContext = context;
- mPackageManager = context.getPackageManager();
+ mPackageManager = mUserContext.getPackageManager();
+
+ mUser = user;
+ mSettingsFile = new AtomicFile(new File(
+ Environment.getUserSystemDirectory(user.getIdentifier()),
+ "usb_device_manager.xml"));
+
synchronized (mLock) {
+ if (UserHandle.OWNER.equals(user)) {
+ upgradeSingleUserLocked();
+ }
readSettingsLocked();
}
- mPackageMonitor.register(context, null, true);
+
+ mPackageMonitor.register(mUserContext, null, true);
}
private void readPreference(XmlPullParser parser)
@@ -395,10 +424,54 @@ class UsbSettingsManager {
XmlUtils.nextElement(parser);
}
+ /**
+ * Upgrade any single-user settings from {@link #sSingleUserSettingsFile}.
+ * Should only by called by owner.
+ */
+ private void upgradeSingleUserLocked() {
+ if (sSingleUserSettingsFile.exists()) {
+ mDevicePreferenceMap.clear();
+ mAccessoryPreferenceMap.clear();
+
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(sSingleUserSettingsFile);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(fis, null);
+
+ XmlUtils.nextElement(parser);
+ while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+ final String tagName = parser.getName();
+ if ("preference".equals(tagName)) {
+ readPreference(parser);
+ } else {
+ XmlUtils.nextElement(parser);
+ }
+ }
+ } catch (IOException e) {
+ Log.wtf(TAG, "Failed to read single-user settings", e);
+ } catch (XmlPullParserException e) {
+ Log.wtf(TAG, "Failed to read single-user settings", e);
+ } finally {
+ IoUtils.closeQuietly(fis);
+ }
+
+ writeSettingsLocked();
+
+ // Success or failure, we delete single-user file
+ sSingleUserSettingsFile.delete();
+ }
+ }
+
private void readSettingsLocked() {
+ if (DEBUG) Slog.v(TAG, "readSettingsLocked()");
+
+ mDevicePreferenceMap.clear();
+ mAccessoryPreferenceMap.clear();
+
FileInputStream stream = null;
try {
- stream = new FileInputStream(sSettingsFile);
+ stream = mSettingsFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(stream, null);
@@ -407,7 +480,7 @@ class UsbSettingsManager {
String tagName = parser.getName();
if ("preference".equals(tagName)) {
readPreference(parser);
- } else {
+ } else {
XmlUtils.nextElement(parser);
}
}
@@ -415,25 +488,21 @@ class UsbSettingsManager {
if (DEBUG) Slog.d(TAG, "settings file not found");
} catch (Exception e) {
Slog.e(TAG, "error reading settings file, deleting to start fresh", e);
- sSettingsFile.delete();
+ mSettingsFile.delete();
} finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException e) {
- }
- }
+ IoUtils.closeQuietly(stream);
}
}
private void writeSettingsLocked() {
+ if (DEBUG) Slog.v(TAG, "writeSettingsLocked()");
+
FileOutputStream fos = null;
try {
- FileOutputStream fstr = new FileOutputStream(sSettingsFile);
- if (DEBUG) Slog.d(TAG, "writing settings to " + fstr);
- BufferedOutputStream str = new BufferedOutputStream(fstr);
+ fos = mSettingsFile.startWrite();
+
FastXmlSerializer serializer = new FastXmlSerializer();
- serializer.setOutput(str, "utf-8");
+ serializer.setOutput(fos, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, "settings");
@@ -455,12 +524,12 @@ class UsbSettingsManager {
serializer.endTag(null, "settings");
serializer.endDocument();
- str.flush();
- FileUtils.sync(fstr);
- str.close();
- } catch (Exception e) {
- Slog.e(TAG, "error writing settings file, deleting to start fresh", e);
- sSettingsFile.delete();
+ mSettingsFile.finishWrite(fos);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to write settings", e);
+ if (fos != null) {
+ mSettingsFile.failWrite(fos);
+ }
}
}
@@ -547,7 +616,7 @@ class UsbSettingsManager {
}
// Send broadcast to running activity with registered intent
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ mUserContext.sendBroadcast(intent);
// Start activity with registered intent
resolveActivity(intent, matches, defaultPackage, device, null);
@@ -608,7 +677,7 @@ class UsbSettingsManager {
dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
dialogIntent.putExtra("uri", uri);
try {
- mContext.startActivity(dialogIntent);
+ mUserContext.startActivityAsUser(dialogIntent, mUser);
} catch (ActivityNotFoundException e) {
Slog.e(TAG, "unable to start UsbAccessoryUriActivity");
}
@@ -656,7 +725,7 @@ class UsbSettingsManager {
intent.setComponent(
new ComponentName(defaultRI.activityInfo.packageName,
defaultRI.activityInfo.name));
- mContext.startActivity(intent);
+ mUserContext.startActivityAsUser(intent, mUser);
} catch (ActivityNotFoundException e) {
Slog.e(TAG, "startActivity failed", e);
}
@@ -683,7 +752,7 @@ class UsbSettingsManager {
resolverIntent.putExtra(Intent.EXTRA_INTENT, intent);
}
try {
- mContext.startActivity(resolverIntent);
+ mUserContext.startActivityAsUser(resolverIntent, mUser);
} catch (ActivityNotFoundException e) {
Slog.e(TAG, "unable to start activity " + resolverIntent);
}
@@ -814,7 +883,7 @@ class UsbSettingsManager {
}
private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) {
- int uid = Binder.getCallingUid();
+ final int uid = Binder.getCallingUid();
// compare uid with packageName to foil apps pretending to be someone else
try {
@@ -833,9 +902,9 @@ class UsbSettingsManager {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_INTENT, pi);
intent.putExtra("package", packageName);
- intent.putExtra("uid", uid);
+ intent.putExtra(Intent.EXTRA_UID, uid);
try {
- mContext.startActivity(intent);
+ mUserContext.startActivityAsUser(intent, mUser);
} catch (ActivityNotFoundException e) {
Slog.e(TAG, "unable to start UsbPermissionActivity");
} finally {
@@ -851,7 +920,7 @@ class UsbSettingsManager {
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
try {
- pi.send(mContext, 0, intent);
+ pi.send(mUserContext, 0, intent);
} catch (PendingIntent.CanceledException e) {
if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
}
@@ -864,14 +933,14 @@ class UsbSettingsManager {
}
public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) {
- Intent intent = new Intent();
+ Intent intent = new Intent();
// respond immediately if permission has already been granted
if (hasPermission(accessory)) {
intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
- try {
- pi.send(mContext, 0, intent);
+ try {
+ pi.send(mUserContext, 0, intent);
} catch (PendingIntent.CanceledException e) {
if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
}