summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/AppWarnings.java94
1 files changed, 37 insertions, 57 deletions
diff --git a/services/core/java/com/android/server/wm/AppWarnings.java b/services/core/java/com/android/server/wm/AppWarnings.java
index f7ccc0d91969..0273a30e157c 100644
--- a/services/core/java/com/android/server/wm/AppWarnings.java
+++ b/services/core/java/com/android/server/wm/AppWarnings.java
@@ -16,7 +16,9 @@
package com.android.server.wm;
+import android.annotation.NonNull;
import android.annotation.UiThread;
+import android.annotation.WorkerThread;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -30,14 +32,18 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemProperties;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.Xml;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.IoThread;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -45,9 +51,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Manages warning dialogs shown during application lifecycle.
@@ -61,11 +65,12 @@ class AppWarnings {
public static final int FLAG_HIDE_DEPRECATED_SDK = 0x04;
public static final int FLAG_HIDE_DEPRECATED_ABI = 0x08;
- private final HashMap<String, Integer> mPackageFlags = new HashMap<>();
+ @GuardedBy("mPackageFlags")
+ private final ArrayMap<String, Integer> mPackageFlags = new ArrayMap<>();
private final ActivityTaskManagerService mAtm;
private final Context mUiContext;
- private final ConfigHandler mHandler;
+ private final WriteConfigTask mWriteConfigTask;
private final UiHandler mUiHandler;
private final AtomicFile mConfigFile;
@@ -75,30 +80,20 @@ class AppWarnings {
private DeprecatedAbiDialog mDeprecatedAbiDialog;
/** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */
- private HashSet<ComponentName> mAlwaysShowUnsupportedCompileSdkWarningActivities =
- new HashSet<>();
+ private final ArraySet<ComponentName> mAlwaysShowUnsupportedCompileSdkWarningActivities =
+ new ArraySet<>();
/** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */
void alwaysShowUnsupportedCompileSdkWarning(ComponentName activity) {
mAlwaysShowUnsupportedCompileSdkWarningActivities.add(activity);
}
- /**
- * Creates a new warning dialog manager.
- * <p>
- * <strong>Note:</strong> Must be called from the ActivityManagerService thread.
- *
- * @param atm
- * @param uiContext
- * @param handler
- * @param uiHandler
- * @param systemDir
- */
+ /** Creates a new warning dialog manager. */
public AppWarnings(ActivityTaskManagerService atm, Context uiContext, Handler handler,
Handler uiHandler, File systemDir) {
mAtm = atm;
mUiContext = uiContext;
- mHandler = new ConfigHandler(handler.getLooper());
+ mWriteConfigTask = new WriteConfigTask();
mUiHandler = new UiHandler(uiHandler.getLooper());
mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME), "warnings-config");
@@ -256,8 +251,9 @@ class AppWarnings {
mUiHandler.hideDialogsForPackage(name);
synchronized (mPackageFlags) {
- mPackageFlags.remove(name);
- mHandler.scheduleWrite();
+ if (mPackageFlags.remove(name) != null) {
+ mWriteConfigTask.schedule();
+ }
}
}
@@ -425,7 +421,7 @@ class AppWarnings {
} else {
mPackageFlags.remove(name);
}
- mHandler.scheduleWrite();
+ mWriteConfigTask.schedule();
}
}
}
@@ -556,46 +552,30 @@ class AppWarnings {
}
}
- /**
- * Handles messages on the ActivityTaskManagerService thread.
- */
- private final class ConfigHandler extends Handler {
- private static final int MSG_WRITE = 1;
-
- private static final int DELAY_MSG_WRITE = 10000;
-
- public ConfigHandler(Looper looper) {
- super(looper, null, true);
- }
+ private final class WriteConfigTask implements Runnable {
+ private static final long WRITE_CONFIG_DELAY_MS = 10000;
+ final AtomicReference<ArrayMap<String, Integer>> mPendingPackageFlags =
+ new AtomicReference<>();
@Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_WRITE:
- writeConfigToFileAmsThread();
- break;
+ public void run() {
+ final ArrayMap<String, Integer> packageFlags = mPendingPackageFlags.getAndSet(null);
+ if (packageFlags != null) {
+ writeConfigToFile(packageFlags);
}
}
- public void scheduleWrite() {
- removeMessages(MSG_WRITE);
- sendEmptyMessageDelayed(MSG_WRITE, DELAY_MSG_WRITE);
+ @GuardedBy("mPackageFlags")
+ void schedule() {
+ if (mPendingPackageFlags.getAndSet(new ArrayMap<>(mPackageFlags)) == null) {
+ IoThread.getHandler().postDelayed(this, WRITE_CONFIG_DELAY_MS);
+ }
}
}
- /**
- * Writes the configuration file.
- * <p>
- * <strong>Note:</strong> Should be called from the ActivityManagerService thread unless you
- * don't care where you're doing I/O operations. But you <i>do</i> care, don't you?
- */
- private void writeConfigToFileAmsThread() {
- // Create a shallow copy so that we don't have to synchronize on config.
- final HashMap<String, Integer> packageFlags;
- synchronized (mPackageFlags) {
- packageFlags = new HashMap<>(mPackageFlags);
- }
-
+ /** Writes the configuration file. */
+ @WorkerThread
+ private void writeConfigToFile(@NonNull ArrayMap<String, Integer> packageFlags) {
FileOutputStream fos = null;
try {
fos = mConfigFile.startWrite();
@@ -605,9 +585,9 @@ class AppWarnings {
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
out.startTag(null, "packages");
- for (Map.Entry<String, Integer> entry : packageFlags.entrySet()) {
- String pkg = entry.getKey();
- int mode = entry.getValue();
+ for (int i = 0; i < packageFlags.size(); i++) {
+ final String pkg = packageFlags.keyAt(i);
+ final int mode = packageFlags.valueAt(i);
if (mode == 0) {
continue;
}