Merge "Make USB services multi-user aware." into jb-mr1-dev

This commit is contained in:
Jeff Sharkey
2012-10-02 18:11:48 -07:00
committed by Android (Google) Code Review
10 changed files with 311 additions and 146 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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");
}