summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/usb
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
parentc6e570dbadc3689bc80c0516492a3209d5f6742b (diff)
downloadframeworks_base-fc3f24b4b60c10e0d3f41f70df37e11ea311cc2c.zip
frameworks_base-fc3f24b4b60c10e0d3f41f70df37e11ea311cc2c.tar.gz
frameworks_base-fc3f24b4b60c10e0d3f41f70df37e11ea311cc2c.tar.bz2
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')
-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
4 files changed, 274 insertions, 115 deletions
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");
}