Ensure bitmaps aren't freed while referenced from a display list
Also removes the reference queue finalizers. They aren't necessary anymore now that Bitmaps are allocated in the heap.
This commit is contained in:
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,11 +34,6 @@ import android.text.GraphicsOperations;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannedString;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Finalizers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An implementation of Canvas on top of OpenGL ES 2.0.
|
||||
@@ -46,7 +41,11 @@ import java.util.Set;
|
||||
class GLES20Canvas extends HardwareCanvas {
|
||||
private final boolean mOpaque;
|
||||
private int mRenderer;
|
||||
|
||||
|
||||
// The native renderer will be destroyed when this object dies.
|
||||
// DO NOT overwrite this reference once it is set.
|
||||
private CanvasFinalizer mFinalizer;
|
||||
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
|
||||
@@ -78,7 +77,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
this(false, translucent);
|
||||
}
|
||||
|
||||
GLES20Canvas(boolean record, boolean translucent) {
|
||||
protected GLES20Canvas(boolean record, boolean translucent) {
|
||||
mOpaque = !translucent;
|
||||
|
||||
if (record) {
|
||||
@@ -90,7 +89,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
if (mRenderer == 0) {
|
||||
throw new IllegalStateException("Could not create GLES20Canvas renderer");
|
||||
} else {
|
||||
new CanvasFinalizer(this);
|
||||
mFinalizer = new CanvasFinalizer(mRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,22 +98,16 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
private static native void nDestroyRenderer(int renderer);
|
||||
|
||||
private static class CanvasFinalizer extends Finalizers.ReclaimableReference<GLES20Canvas> {
|
||||
private static final Set<CanvasFinalizer> sFinalizers = Collections.synchronizedSet(
|
||||
new HashSet<CanvasFinalizer>());
|
||||
private static class CanvasFinalizer {
|
||||
final int mRenderer;
|
||||
|
||||
private int mRenderer;
|
||||
|
||||
CanvasFinalizer(GLES20Canvas canvas) {
|
||||
super(canvas, Finalizers.getQueue());
|
||||
mRenderer = canvas.mRenderer;
|
||||
sFinalizers.add(this);
|
||||
CanvasFinalizer(int renderer) {
|
||||
mRenderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reclaim() {
|
||||
protected void finalize() throws Throwable {
|
||||
nDestroyRenderer(mRenderer);
|
||||
sFinalizers.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import android.util.Finalizers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An implementation of display list for OpenGL ES 2.0.
|
||||
*/
|
||||
@@ -33,13 +27,18 @@ class GLES20DisplayList extends DisplayList {
|
||||
|
||||
int mNativeDisplayList;
|
||||
|
||||
// The native display list will be destroyed when this object dies.
|
||||
// DO NOT overwrite this reference once it is set.
|
||||
@SuppressWarnings("unused")
|
||||
private DisplayListFinalizer mFinalizer;
|
||||
|
||||
@Override
|
||||
HardwareCanvas start() {
|
||||
if (mStarted) {
|
||||
throw new IllegalStateException("Recording has already started");
|
||||
}
|
||||
|
||||
mCanvas = new GLES20Canvas(true, true);
|
||||
mCanvas = new GLES20RecordingCanvas(true);
|
||||
mStarted = true;
|
||||
mRecorded = false;
|
||||
|
||||
@@ -53,7 +52,7 @@ class GLES20DisplayList extends DisplayList {
|
||||
mRecorded = true;
|
||||
|
||||
mNativeDisplayList = mCanvas.getDisplayList();
|
||||
new DisplayListFinalizer(this);
|
||||
mFinalizer = new DisplayListFinalizer(mNativeDisplayList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,22 +61,16 @@ class GLES20DisplayList extends DisplayList {
|
||||
return !mStarted && mRecorded;
|
||||
}
|
||||
|
||||
private static class DisplayListFinalizer extends Finalizers.ReclaimableReference<DisplayList> {
|
||||
private static final Set<DisplayListFinalizer> sFinalizers = Collections.synchronizedSet(
|
||||
new HashSet<DisplayListFinalizer>());
|
||||
private static class DisplayListFinalizer {
|
||||
int mNativeDisplayList;
|
||||
|
||||
private int mNativeDisplayList;
|
||||
|
||||
DisplayListFinalizer(GLES20DisplayList displayList) {
|
||||
super(displayList, Finalizers.getQueue());
|
||||
mNativeDisplayList = displayList.mNativeDisplayList;
|
||||
sFinalizers.add(this);
|
||||
DisplayListFinalizer(int nativeDisplayList) {
|
||||
mNativeDisplayList = nativeDisplayList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reclaim() {
|
||||
protected void finalize() throws Throwable {
|
||||
GLES20Canvas.destroyDisplayList(mNativeDisplayList);
|
||||
sFinalizers.remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
273
core/java/android/view/GLES20RecordingCanvas.java
Normal file
273
core/java/android/view/GLES20RecordingCanvas.java
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* 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.view;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* An implementation of a GL canvas that records drawing operations.
|
||||
* This is intended for use with a DisplayList. This class keeps a list of all the Paint and
|
||||
* Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
|
||||
* the DisplayList is still holding a native reference to the memory.
|
||||
*/
|
||||
class GLES20RecordingCanvas extends GLES20Canvas {
|
||||
// These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
|
||||
// as the DisplayList is alive.
|
||||
private HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();
|
||||
|
||||
GLES20RecordingCanvas(boolean translucent) {
|
||||
super(true, translucent);
|
||||
}
|
||||
|
||||
private void recordShaderBitmap(Paint paint) {
|
||||
if (paint != null) {
|
||||
final Shader shader = paint.getShader();
|
||||
if (shader instanceof BitmapShader) {
|
||||
mBitmaps.add(((BitmapShader) shader).mBitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
|
||||
Paint paint) {
|
||||
super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
|
||||
super.drawPatch(bitmap, chunks, dst, paint);
|
||||
mBitmaps.add(bitmap);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
|
||||
super.drawBitmap(bitmap, left, top, paint);
|
||||
mBitmaps.add(bitmap);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
|
||||
super.drawBitmap(bitmap, matrix, paint);
|
||||
mBitmaps.add(bitmap);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
|
||||
super.drawBitmap(bitmap, src, dst, paint);
|
||||
mBitmaps.add(bitmap);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
|
||||
super.drawBitmap(bitmap, src, dst, paint);
|
||||
mBitmaps.add(bitmap);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width,
|
||||
int height, boolean hasAlpha, Paint paint) {
|
||||
super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width,
|
||||
int height, boolean hasAlpha, Paint paint) {
|
||||
super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
|
||||
int vertOffset, int[] colors, int colorOffset, Paint paint) {
|
||||
super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
|
||||
paint);
|
||||
mBitmaps.add(bitmap);
|
||||
// Shaders in the Paint are ignored when drawing a Bitmap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawCircle(float cx, float cy, float radius, Paint paint) {
|
||||
super.drawCircle(cx, cy, radius, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
|
||||
super.drawLine(startX, startY, stopX, stopY, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLines(float[] pts, int offset, int count, Paint paint) {
|
||||
super.drawLines(pts, offset, count, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLines(float[] pts, Paint paint) {
|
||||
super.drawLines(pts, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOval(RectF oval, Paint paint) {
|
||||
super.drawOval(oval, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPaint(Paint paint) {
|
||||
super.drawPaint(paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPath(Path path, Paint paint) {
|
||||
super.drawPath(path, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPoint(float x, float y, Paint paint) {
|
||||
super.drawPoint(x, y, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPoints(float[] pts, int offset, int count, Paint paint) {
|
||||
super.drawPoints(pts, offset, count, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPoints(float[] pts, Paint paint) {
|
||||
super.drawPoints(pts, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
|
||||
super.drawPosText(text, index, count, pos, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPosText(String text, float[] pos, Paint paint) {
|
||||
super.drawPosText(text, pos, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRect(float left, float top, float right, float bottom, Paint paint) {
|
||||
super.drawRect(left, top, right, bottom, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRect(Rect r, Paint paint) {
|
||||
super.drawRect(r, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRect(RectF r, Paint paint) {
|
||||
super.drawRect(r, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
|
||||
super.drawRoundRect(rect, rx, ry, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
|
||||
super.drawText(text, index, count, x, y, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
|
||||
super.drawText(text, start, end, x, y, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawText(String text, int start, int end, float x, float y, Paint paint) {
|
||||
super.drawText(text, start, end, x, y, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawText(String text, float x, float y, Paint paint) {
|
||||
super.drawText(text, x, y, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
|
||||
float vOffset, Paint paint) {
|
||||
super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
|
||||
super.drawTextOnPath(text, path, hOffset, vOffset, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
|
||||
float x, float y, int dir, Paint paint) {
|
||||
super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, dir, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTextRun(CharSequence text, int start, int end, int contextStart,
|
||||
int contextEnd, float x, float y, int dir, Paint paint) {
|
||||
super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, dir, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
|
||||
float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
|
||||
int indexOffset, int indexCount, Paint paint) {
|
||||
super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors,
|
||||
colorOffset, indices, indexOffset, indexCount, paint);
|
||||
recordShaderBitmap(paint);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Config;
|
||||
import android.util.Finalizers;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -142,12 +141,6 @@ public class RuntimeInit {
|
||||
Debug.enableEmulatorTraceOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the thread used to reclaim resources without
|
||||
* going through finalizers.
|
||||
*/
|
||||
Finalizers.init();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,10 @@ package android.graphics;
|
||||
public class BitmapShader extends Shader {
|
||||
/**
|
||||
* Prevent garbage collection.
|
||||
* @hide
|
||||
*/
|
||||
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
|
||||
private final Bitmap mBitmap;
|
||||
public final Bitmap mBitmap;
|
||||
|
||||
/**
|
||||
* Call this to create a new shader that will draw with a bitmap.
|
||||
|
||||
@@ -60,9 +60,7 @@ void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType)
|
||||
}
|
||||
|
||||
void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
|
||||
SkPixelRef* pixref = bitmapResource->pixelRef();
|
||||
if (pixref) pixref->globalRef();
|
||||
|
||||
bitmapResource->pixelRef()->safeRef();
|
||||
bitmapResource->getColorTable()->safeRef();
|
||||
incrementRefcount((void*)bitmapResource, kBitmap);
|
||||
}
|
||||
@@ -91,9 +89,7 @@ void ResourceCache::decrementRefcount(void* resource) {
|
||||
}
|
||||
|
||||
void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
|
||||
SkPixelRef* pixref = bitmapResource->pixelRef();
|
||||
if (pixref) pixref->globalUnref();
|
||||
|
||||
bitmapResource->pixelRef()->safeUnref();
|
||||
bitmapResource->getColorTable()->safeUnref();
|
||||
decrementRefcount((void*)bitmapResource);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import com.android.tools.layoutlib.create.OverrideMethod;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface_Delegate;
|
||||
import android.os.Looper;
|
||||
import android.util.Finalizers;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -198,8 +197,6 @@ public final class Bridge extends LayoutBridge {
|
||||
Capability.ANIMATE);
|
||||
|
||||
|
||||
Finalizers.init();
|
||||
|
||||
BridgeAssetManager.initSystem();
|
||||
|
||||
// When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener
|
||||
|
||||
Reference in New Issue
Block a user