Merge changes Ia95ff014,Ib31708c3
* changes:
MTP: Add debug code for printing names of MTP format and property codes.
MTP: Fix some typos
diff --git a/core/java/android/util/Finalizers.java b/core/java/android/util/Finalizers.java
new file mode 100644
index 0000000..671f2d4
--- /dev/null
+++ b/core/java/android/util/Finalizers.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+
+/**
+ * This class can be used to implement reliable finalizers.
+ *
+ * @hide
+ */
+public final class Finalizers {
+ private static final String LOG_TAG = "Finalizers";
+
+ private static final Object[] sLock = new Object[0];
+ private static boolean sInit;
+ private static Reclaimer sReclaimer;
+
+ /**
+ * Subclass of PhantomReference used to reclaim resources.
+ */
+ public static abstract class ReclaimableReference<T> extends PhantomReference<T> {
+ public ReclaimableReference(T r, ReferenceQueue<Object> q) {
+ super(r, q);
+ }
+
+ public abstract void reclaim();
+ }
+
+ /**
+ * Returns the queue used to reclaim ReclaimableReferences.
+ *
+ * @return A reference queue or null before initialization
+ */
+ public static ReferenceQueue<Object> getQueue() {
+ synchronized (sLock) {
+ if (!sInit) {
+ return null;
+ }
+ if (!sReclaimer.isRunning()) {
+ sReclaimer = new Reclaimer(sReclaimer.mQueue);
+ sReclaimer.start();
+ }
+ return sReclaimer.mQueue;
+ }
+ }
+
+ /**
+ * Invoked by Zygote. Don't touch!
+ */
+ public static void init() {
+ synchronized (sLock) {
+ if (!sInit && sReclaimer == null) {
+ sReclaimer = new Reclaimer();
+ sReclaimer.start();
+ sInit = true;
+ }
+ }
+ }
+
+ private static class Reclaimer extends Thread {
+ ReferenceQueue<Object> mQueue;
+
+ private volatile boolean mRunning = false;
+
+ Reclaimer() {
+ this(new ReferenceQueue<Object>());
+ }
+
+ Reclaimer(ReferenceQueue<Object> queue) {
+ super("Reclaimer");
+ setDaemon(true);
+ mQueue = queue;
+ }
+
+ @Override
+ public void start() {
+ mRunning = true;
+ super.start();
+ }
+
+ boolean isRunning() {
+ return mRunning;
+ }
+
+ @SuppressWarnings({"InfiniteLoopStatement"})
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ try {
+ cleanUp(mQueue.remove());
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Reclaimer thread exiting: ", e);
+ } finally {
+ mRunning = false;
+ }
+ }
+
+ private void cleanUp(Reference<?> reference) {
+ do {
+ reference.clear();
+ ((ReclaimableReference<?>) reference).reclaim();
+ } while ((reference = mQueue.poll()) != null);
+ }
+ }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7c644e4..735b35a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1828,8 +1828,8 @@
private int[] mDrawableState = null;
- private SoftReference<Bitmap> mDrawingCache;
- private SoftReference<Bitmap> mUnscaledDrawingCache;
+ private Bitmap mDrawingCache;
+ private Bitmap mUnscaledDrawingCache;
/**
* When this view has focus and the next focus is {@link #FOCUS_LEFT},
@@ -6916,8 +6916,7 @@
if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
buildDrawingCache(autoScale);
}
- return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
- (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
+ return autoScale ? mDrawingCache : mUnscaledDrawingCache;
}
/**
@@ -6932,13 +6931,11 @@
*/
public void destroyDrawingCache() {
if (mDrawingCache != null) {
- final Bitmap bitmap = mDrawingCache.get();
- if (bitmap != null) bitmap.recycle();
+ mDrawingCache.recycle();
mDrawingCache = null;
}
if (mUnscaledDrawingCache != null) {
- final Bitmap bitmap = mUnscaledDrawingCache.get();
- if (bitmap != null) bitmap.recycle();
+ mUnscaledDrawingCache.recycle();
mUnscaledDrawingCache = null;
}
}
@@ -6999,8 +6996,7 @@
*/
public void buildDrawingCache(boolean autoScale) {
if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
- (mDrawingCache == null || mDrawingCache.get() == null) :
- (mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) {
+ mDrawingCache == null : mUnscaledDrawingCache == null)) {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
@@ -7033,8 +7029,7 @@
}
boolean clear = true;
- Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
- (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
+ Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
Bitmap.Config quality;
@@ -7066,9 +7061,9 @@
bitmap = Bitmap.createBitmap(width, height, quality);
bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
if (autoScale) {
- mDrawingCache = new SoftReference<Bitmap>(bitmap);
+ mDrawingCache = bitmap;
} else {
- mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap);
+ mUnscaledDrawingCache = bitmap;
}
if (opaque && translucentWindow) bitmap.setHasAlpha(false);
} catch (OutOfMemoryError e) {
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 59600dc..5767832 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -24,6 +24,7 @@
import android.os.Process;
import android.os.SystemProperties;
import android.util.Config;
+import android.util.Finalizers;
import android.util.Log;
import android.util.Slog;
@@ -141,6 +142,12 @@
Debug.enableEmulatorTraceOutput();
}
+ /**
+ * Initialize the thread used to reclaim resources without
+ * going through finalizers.
+ */
+ Finalizers.init();
+
initialized = true;
}
@@ -331,9 +338,6 @@
}
}
- /** Counter used to prevent reentrancy in {@link #reportException}. */
- private static final AtomicInteger sInReportException = new AtomicInteger();
-
/**
* Set the object identifying this application/process, for reporting VM
* errors.
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 537dd3a..d9ee3ec 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -19,12 +19,16 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;
+import android.util.Finalizers;
import java.io.OutputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
public final class Bitmap implements Parcelable {
/**
@@ -55,7 +59,7 @@
private static volatile Matrix sScaleMatrix;
private static volatile int sDefaultDensity = -1;
-
+
/**
* For backwards compatibility, allows the app layer to change the default
* density when running old apps.
@@ -81,8 +85,7 @@
This can be called from JNI code.
*/
- private Bitmap(int nativeBitmap, boolean isMutable, byte[] ninePatchChunk,
- int density) {
+ private Bitmap(int nativeBitmap, boolean isMutable, byte[] ninePatchChunk, int density) {
if (nativeBitmap == 0) {
throw new RuntimeException("internal error: native bitmap is 0");
}
@@ -94,6 +97,13 @@
if (density >= 0) {
mDensity = density;
}
+
+ // If the finalizers queue is null, we are running in zygote and the
+ // bitmap will never be reclaimed, so we don't need to run our native
+ // destructor
+ if (Finalizers.getQueue() != null) {
+ new BitmapFinalizer(this);
+ }
}
/**
@@ -1016,12 +1026,22 @@
nativePrepareToDraw(mNativeBitmap);
}
- @Override
- protected void finalize() throws Throwable {
- try {
+ private static class BitmapFinalizer extends Finalizers.ReclaimableReference<Bitmap> {
+ private static final Set<BitmapFinalizer> sFinalizers = Collections.synchronizedSet(
+ new HashSet<BitmapFinalizer>());
+
+ private int mNativeBitmap;
+
+ BitmapFinalizer(Bitmap b) {
+ super(b, Finalizers.getQueue());
+ mNativeBitmap = b.mNativeBitmap;
+ sFinalizers.add(this);
+ }
+
+ @Override
+ public void reclaim() {
nativeDestructor(mNativeBitmap);
- } finally {
- super.finalize();
+ sFinalizers.remove(this);
}
}