summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/usb/UsbSettingsManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/usb/UsbSettingsManager.java')
-rw-r--r--services/java/com/android/server/usb/UsbSettingsManager.java147
1 files changed, 108 insertions, 39 deletions
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");
}