summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@android.com>2011-01-20 15:56:47 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-01-20 15:56:47 -0800
commit9358bd39dc8829ef8413294da70d44cd928ca878 (patch)
treed816b6afd6f024af0c070c05cfe472845b90f411
parente69e0fde6cf0e6302d5a05363a3db7a9c555e9dc (diff)
parent5f8b5c191cae77f536ee64f0b625e4a7f8596787 (diff)
downloadframeworks_base-9358bd39dc8829ef8413294da70d44cd928ca878.zip
frameworks_base-9358bd39dc8829ef8413294da70d44cd928ca878.tar.gz
frameworks_base-9358bd39dc8829ef8413294da70d44cd928ca878.tar.bz2
Merge "Fixes for StrictMode instance count checking." into honeycomb
-rw-r--r--core/java/android/app/Activity.java1
-rw-r--r--core/java/android/app/ActivityThread.java5
-rw-r--r--core/java/android/os/StrictMode.java96
3 files changed, 74 insertions, 28 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 2aef860..22971a2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -859,7 +859,6 @@ public class Activity extends ContextThemeWrapper
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
- StrictMode.noteActivityClass(this.getClass());
mFragments.dispatchCreate();
mCalled = true;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7cf60f9..2389f01 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1616,6 +1616,7 @@ public final class ActivityThread {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
+ StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
@@ -2686,8 +2687,10 @@ public final class ActivityThread {
private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = mActivities.get(token);
+ Class activityClass = null;
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
if (r != null) {
+ activityClass = r.activity.getClass();
r.activity.mConfigChangeFlags |= configChanges;
if (finishing) {
r.activity.mFinished = true;
@@ -2765,7 +2768,7 @@ public final class ActivityThread {
}
}
mActivities.remove(token);
-
+ StrictMode.decrementExpectedActivityCount(activityClass);
return r;
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index ae92b09..a53818e 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -37,6 +37,7 @@ import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -1370,8 +1371,9 @@ public final class StrictMode {
}
Runtime.getRuntime().gc();
// Note: classInstanceLimit is immutable, so this is lock-free
- for (Class klass : policy.classInstanceLimit.keySet()) {
- int limit = policy.classInstanceLimit.get(klass);
+ for (Map.Entry<Class, Integer> entry : policy.classInstanceLimit.entrySet()) {
+ Class klass = entry.getKey();
+ int limit = entry.getValue();
long instances = VMDebug.countInstancesOfClass(klass, false);
if (instances <= limit) {
continue;
@@ -1382,7 +1384,7 @@ public final class StrictMode {
}
private static long sLastInstanceCountCheckMillis = 0;
- private static boolean sIsIdlerRegistered = false; // guarded by sProcessIdleHandler
+ private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
private static final MessageQueue.IdleHandler sProcessIdleHandler =
new MessageQueue.IdleHandler() {
public boolean queueIdle() {
@@ -1403,14 +1405,14 @@ public final class StrictMode {
* @param policy the policy to put into place
*/
public static void setVmPolicy(final VmPolicy policy) {
- sVmPolicy = policy;
- sVmPolicyMask = policy.mask;
- setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
-
- Looper looper = Looper.getMainLooper();
- if (looper != null) {
- MessageQueue mq = looper.mQueue;
- synchronized (sProcessIdleHandler) {
+ synchronized (StrictMode.class) {
+ sVmPolicy = policy;
+ sVmPolicyMask = policy.mask;
+ setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
+
+ Looper looper = Looper.getMainLooper();
+ if (looper != null) {
+ MessageQueue mq = looper.mQueue;
if (policy.classInstanceLimit.size() == 0) {
mq.removeIdleHandler(sProcessIdleHandler);
} else if (!sIsIdlerRegistered) {
@@ -1425,7 +1427,9 @@ public final class StrictMode {
* Gets the current VM policy.
*/
public static VmPolicy getVmPolicy() {
- return sVmPolicy;
+ synchronized (StrictMode.class) {
+ return sVmPolicy;
+ }
}
/**
@@ -1480,6 +1484,11 @@ public final class StrictMode {
final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
+ // Erase stuff not relevant for process-wide violations
+ info.numAnimationsRunning = 0;
+ info.tags = null;
+ info.broadcastIntentAction = null;
+
final Integer fingerprint = info.hashCode();
final long now = SystemClock.uptimeMillis();
long lastViolationTime = 0;
@@ -1494,8 +1503,6 @@ public final class StrictMode {
}
}
- Log.d(TAG, "Time since last vm violation: " + timeSinceLastViolationMillis);
-
if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Log.e(TAG, message, originStack);
}
@@ -1799,18 +1806,57 @@ public final class StrictMode {
((AndroidBlockGuardPolicy) policy).onWriteToDisk();
}
+ // Guarded by StrictMode.class
+ private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
+ new HashMap<Class, Integer>();
+
/**
* @hide
*/
- public static void noteActivityClass(Class klass) {
- if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
+ public static void incrementExpectedActivityCount(Class klass) {
+ if (klass == null || (sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
return;
}
- if (sVmPolicy.classInstanceLimit.containsKey(klass)) {
+ synchronized (StrictMode.class) {
+ Integer expected = sExpectedActivityInstanceCount.get(klass);
+ Integer newExpected = expected == null ? 1 : expected + 1;
+ sExpectedActivityInstanceCount.put(klass, newExpected);
+ // Note: adding 1 here to give some breathing room during
+ // orientation changes. (shouldn't be necessary, though?)
+ setExpectedClassInstanceCount(klass, newExpected + 1);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public static void decrementExpectedActivityCount(Class klass) {
+ if (klass == null || (sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
return;
}
- // Note: capping at 2, not 1, to give some breathing room.
- setVmPolicy(new VmPolicy.Builder(sVmPolicy).setClassInstanceLimit(klass, 2).build());
+ synchronized (StrictMode.class) {
+ Integer expected = sExpectedActivityInstanceCount.get(klass);
+ Integer newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
+ if (newExpected == 0) {
+ sExpectedActivityInstanceCount.remove(klass);
+ } else {
+ sExpectedActivityInstanceCount.put(klass, newExpected);
+ }
+ // Note: adding 1 here to give some breathing room during
+ // orientation changes. (shouldn't be necessary, though?)
+ setExpectedClassInstanceCount(klass, newExpected + 1);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public static void setExpectedClassInstanceCount(Class klass, int count) {
+ synchronized (StrictMode.class) {
+ setVmPolicy(new VmPolicy.Builder(sVmPolicy)
+ .setClassInstanceLimit(klass, count)
+ .build());
+ }
}
/**
@@ -2020,15 +2066,13 @@ public final class StrictMode {
final long mInstances;
final int mLimit;
- private static final StackTraceElement[] FAKE_STACK = new StackTraceElement[1];
- static {
- FAKE_STACK[0] = new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
- "StrictMode.java", 1);
- }
+ private static final StackTraceElement[] FAKE_STACK = {
+ new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
+ "StrictMode.java", 1)
+ };
public InstanceCountViolation(Class klass, long instances, int limit) {
- // Note: now including instances here, otherwise signatures would all be different.
- super(klass.toString() + "; limit=" + limit);
+ super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
setStackTrace(FAKE_STACK);
mClass = klass;
mInstances = instances;