summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2016-10-11 21:46:48 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2016-10-11 21:46:51 +0000
commitb8c866d6a4dc87134d853b9e59d08ead9fb08eeb (patch)
tree405f940511776421f8b43db44fed42395bd8fe8c
parente9c67f6b2ed53199e8a2abe6165cb4eb6ce849e1 (diff)
parent880389e6cc8044f751dd8569f2172ca61eaf2cd3 (diff)
Merge "Clear USB device defaults when user is removed"
-rw-r--r--services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java156
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java9
-rw-r--r--services/usb/java/com/android/server/usb/UsbSettingsManager.java21
3 files changed, 136 insertions, 50 deletions
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index cc0fb8d3e485..e03a14f41ce2 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -34,6 +34,7 @@ import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
+import android.os.AsyncTask;
import android.os.Environment;
import android.os.UserHandle;
import android.os.UserManager;
@@ -42,6 +43,7 @@ import android.util.Log;
import android.util.Slog;
import android.util.Xml;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.Immutable;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.FastXmlSerializer;
@@ -60,7 +62,9 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import libcore.io.IoUtils;
@@ -87,14 +91,24 @@ class UsbProfileGroupSettingsManager {
private final UserManager mUserManager;
private final @NonNull UsbSettingsManager mSettingsManager;
- // Maps DeviceFilter to user preferred application package
+ /** Maps DeviceFilter to user preferred application package */
+ @GuardedBy("mLock")
private final HashMap<DeviceFilter, UserPackage> mDevicePreferenceMap = new HashMap<>();
- // Maps AccessoryFilter to user preferred application package
+
+ /** Maps AccessoryFilter to user preferred application package */
+ @GuardedBy("mLock")
private final HashMap<AccessoryFilter, UserPackage> mAccessoryPreferenceMap = new HashMap<>();
private final Object mLock = new Object();
/**
+ * If a async task to persist the mDevicePreferenceMap and mAccessoryPreferenceMap is currently
+ * scheduled.
+ */
+ @GuardedBy("mLock")
+ private boolean mIsWriteSettingsScheduled;
+
+ /**
* A package of a user.
*/
@Immutable
@@ -591,6 +605,42 @@ class UsbProfileGroupSettingsManager {
});
}
+ /**
+ * Remove all defaults for a user.
+ *
+ * @param userToRemove The user the defaults belong to.
+ */
+ void removeAllDefaultsForUser(@NonNull UserHandle userToRemove) {
+ synchronized (mLock) {
+ boolean needToPersist = false;
+ Iterator<Map.Entry<DeviceFilter, UserPackage>> devicePreferenceIt = mDevicePreferenceMap
+ .entrySet().iterator();
+ while (devicePreferenceIt.hasNext()) {
+ Map.Entry<DeviceFilter, UserPackage> entry = devicePreferenceIt.next();
+
+ if (entry.getValue().user.equals(userToRemove)) {
+ devicePreferenceIt.remove();
+ needToPersist = true;
+ }
+ }
+
+ Iterator<Map.Entry<AccessoryFilter, UserPackage>> accessoryPreferenceIt =
+ mAccessoryPreferenceMap.entrySet().iterator();
+ while (accessoryPreferenceIt.hasNext()) {
+ Map.Entry<AccessoryFilter, UserPackage> entry = accessoryPreferenceIt.next();
+
+ if (entry.getValue().user.equals(userToRemove)) {
+ accessoryPreferenceIt.remove();
+ needToPersist = true;
+ }
+ }
+
+ if (needToPersist) {
+ scheduleWriteSettingsLocked();
+ }
+ }
+ }
+
private void readPreference(XmlPullParser parser)
throws XmlPullParserException, IOException {
String packageName = null;
@@ -657,7 +707,7 @@ class UsbProfileGroupSettingsManager {
IoUtils.closeQuietly(fis);
}
- writeSettingsLocked();
+ scheduleWriteSettingsLocked();
// Success or failure, we delete single-user file
sSingleUserSettingsFile.delete();
@@ -695,48 +745,68 @@ class UsbProfileGroupSettingsManager {
}
}
- private void writeSettingsLocked() {
- if (DEBUG) Slog.v(TAG, "writeSettingsLocked()");
-
- FileOutputStream fos = null;
- try {
- fos = mSettingsFile.startWrite();
+ /**
+ * Schedule a async task to persist {@link #mDevicePreferenceMap} and
+ * {@link #mAccessoryPreferenceMap}. If a task is already scheduled but not completed, do
+ * nothing as the currently scheduled one will do the work.
+ * <p>Called with {@link #mLock} held.</p>
+ * <p>In the uncommon case that the system crashes in between the scheduling and the write the
+ * update is lost.</p>
+ */
+ private void scheduleWriteSettingsLocked() {
+ if (mIsWriteSettingsScheduled) {
+ return;
+ } else {
+ mIsWriteSettingsScheduled = true;
+ }
- FastXmlSerializer serializer = new FastXmlSerializer();
- serializer.setOutput(fos, StandardCharsets.UTF_8.name());
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- serializer.startTag(null, "settings");
+ AsyncTask.execute(() -> {
+ synchronized (mLock) {
+ FileOutputStream fos = null;
+ try {
+ fos = mSettingsFile.startWrite();
+
+ FastXmlSerializer serializer = new FastXmlSerializer();
+ serializer.setOutput(fos, StandardCharsets.UTF_8.name());
+ serializer.startDocument(null, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+ true);
+ serializer.startTag(null, "settings");
+
+ for (DeviceFilter filter : mDevicePreferenceMap.keySet()) {
+ serializer.startTag(null, "preference");
+ serializer.attribute(null, "package",
+ mDevicePreferenceMap.get(filter).packageName);
+ serializer.attribute(null, "user",
+ String.valueOf(getSerial(mDevicePreferenceMap.get(filter).user)));
+ filter.write(serializer);
+ serializer.endTag(null, "preference");
+ }
- for (DeviceFilter filter : mDevicePreferenceMap.keySet()) {
- serializer.startTag(null, "preference");
- serializer.attribute(null, "package", mDevicePreferenceMap.get(filter).packageName);
- serializer.attribute(null, "user",
- String.valueOf(getSerial(mDevicePreferenceMap.get(filter).user)));
- filter.write(serializer);
- serializer.endTag(null, "preference");
- }
+ for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) {
+ serializer.startTag(null, "preference");
+ serializer.attribute(null, "package",
+ mAccessoryPreferenceMap.get(filter).packageName);
+ serializer.attribute(null, "user", String.valueOf(
+ getSerial(mAccessoryPreferenceMap.get(filter).user)));
+ filter.write(serializer);
+ serializer.endTag(null, "preference");
+ }
- for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) {
- serializer.startTag(null, "preference");
- serializer.attribute(null, "package",
- mAccessoryPreferenceMap.get(filter).packageName);
- serializer.attribute(null, "user",
- String.valueOf(getSerial(mAccessoryPreferenceMap.get(filter).user)));
- filter.write(serializer);
- serializer.endTag(null, "preference");
- }
+ serializer.endTag(null, "settings");
+ serializer.endDocument();
- serializer.endTag(null, "settings");
- serializer.endDocument();
+ mSettingsFile.finishWrite(fos);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to write settings", e);
+ if (fos != null) {
+ mSettingsFile.failWrite(fos);
+ }
+ }
- mSettingsFile.finishWrite(fos);
- } catch (IOException e) {
- Slog.e(TAG, "Failed to write settings", e);
- if (fos != null) {
- mSettingsFile.failWrite(fos);
+ mIsWriteSettingsScheduled = false;
}
- }
+ });
}
// Checks to see if a package matches a device or accessory.
@@ -1141,7 +1211,7 @@ class UsbProfileGroupSettingsManager {
}
if (changed) {
- writeSettingsLocked();
+ scheduleWriteSettingsLocked();
}
}
}
@@ -1178,7 +1248,7 @@ class UsbProfileGroupSettingsManager {
}
}
if (changed) {
- writeSettingsLocked();
+ scheduleWriteSettingsLocked();
}
}
}
@@ -1204,7 +1274,7 @@ class UsbProfileGroupSettingsManager {
}
}
if (changed) {
- writeSettingsLocked();
+ scheduleWriteSettingsLocked();
}
}
}
@@ -1237,7 +1307,7 @@ class UsbProfileGroupSettingsManager {
synchronized (mLock) {
if (clearPackageDefaultsLocked(userPackage)) {
- writeSettingsLocked();
+ scheduleWriteSettingsLocked();
}
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 02c7214b2b19..c85b363494e8 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -16,6 +16,7 @@
package com.android.server.usb;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
@@ -83,7 +84,7 @@ public class UsbService extends IUsbManager.Stub {
@Override
public void onStopUser(int userHandle) {
- mUsbService.onStopUser(userHandle);
+ mUsbService.onStopUser(UserHandle.of(userHandle));
}
}
@@ -177,10 +178,10 @@ public class UsbService extends IUsbManager.Stub {
/**
* Execute operations when a user is stopped.
*
- * @param stoppedUserId The id of the used that is stopped
+ * @param stoppedUser The user that is stopped
*/
- private void onStopUser(@UserIdInt int stoppedUserId) {
- mSettingsManager.remove(stoppedUserId);
+ private void onStopUser(@NonNull UserHandle stoppedUser) {
+ mSettingsManager.remove(stoppedUser);
}
public void systemReady() {
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index b251d261eb53..24d5f0955e9a 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -108,11 +108,26 @@ class UsbSettingsManager {
/**
* Remove the settings for a user.
*
- * @param userIdToRemove The user o remove
+ * @param userToRemove The user to remove
*/
- void remove(@UserIdInt int userIdToRemove) {
+ void remove(@NonNull UserHandle userToRemove) {
synchronized (mSettingsByUser) {
- mSettingsByUser.remove(userIdToRemove);
+ mSettingsByUser.remove(userToRemove.getIdentifier());
+ }
+
+ synchronized (mSettingsByProfileGroup) {
+ if (mSettingsByProfileGroup.indexOfKey(userToRemove.getIdentifier()) >= 0) {
+ // The user to remove is the parent user of the group. The parent is the last user
+ // that gets removed. All state will be removed with the user
+ mSettingsByProfileGroup.remove(userToRemove.getIdentifier());
+ } else {
+ // We cannot find the parent user of the user that is removed, hence try to remove
+ // it from all profile groups.
+ int numProfileGroups = mSettingsByProfileGroup.size();
+ for (int i = 0; i < numProfileGroups; i++) {
+ mSettingsByProfileGroup.valueAt(i).removeAllDefaultsForUser(userToRemove);
+ }
+ }
}
}