Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc4977d0 authored by Xavier Ducrohet's avatar Xavier Ducrohet
Browse files

LayoutLib: Hold onto delegate references.

When an object is given a delegate to hold onto, keep
the reference to the delegate instead of its native integer.

Also change the way the finalizer works by not explicitely deleting
the delegate. Instead we want the delegate to be deleted when
nothing holds a reference to it. To do this, instead of using
a regular SparseArray, we use a SparseArray of WeakReferences.
Because the main Java object that "owns" the delegate does not
actually holds a reference to the delegate, we fake this by
having the delegate manager hold a reference to delegates for
the main object. This is added/removed as the object is created
and the native finalized is called.

This makes layoutlib behave more like the JNI code where the native
objects are reference counted, and where the Java object can be
deleted but the delegate it owns is kept around (usually because
another type of delegates hold a reference on it.)

To properly handle the WeakReferences, we need to be able to
regularly clear the SparseArray of WeakReference that were
referencing objects that have been GC'ed.
Since the SparseArray is regularly being compacted (actually only
when items are removed), we use a custom SparseWeakArray (started
as a straight copy of SparseArray) that handles the WeakReference
and takes care of compacting the array by removing deleted indices
and WeakReference that returns null. Since our specific use case
doesn't call actually delete() or remove(), the compacting
only happens when the array needs to be resized.

Change-Id: Iacc5c1ff5b21732b8816fda87eb090da12d034e0
parent 8cb6fc18
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ public class AvoidXfermode_Delegate extends Xfermode_Delegate {
    @LayoutlibDelegate
    /*package*/ static int nativeCreate(int opColor, int tolerance, int nativeMode) {
        AvoidXfermode_Delegate newDelegate = new AvoidXfermode_Delegate();
        return sManager.addDelegate(newDelegate);
        return sManager.addNewDelegate(newDelegate);
    }

    // ---- Private delegate/helper methods ----
+1 −1
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ public class BitmapShader_Delegate extends Shader_Delegate {
                bitmap.getImage(),
                Shader_Delegate.getTileMode(shaderTileModeX),
                Shader_Delegate.getTileMode(shaderTileModeY));
        return sManager.addDelegate(newDelegate);
        return sManager.addNewDelegate(newDelegate);
    }

    @LayoutlibDelegate
+3 −3
Original line number Diff line number Diff line
@@ -245,12 +245,12 @@ public final class Bitmap_Delegate {

    @LayoutlibDelegate
    /*package*/ static void nativeDestructor(int nativeBitmap) {
        sManager.removeDelegate(nativeBitmap);
        sManager.removeJavaReferenceFor(nativeBitmap);
    }

    @LayoutlibDelegate
    /*package*/ static void nativeRecycle(int nativeBitmap) {
        sManager.removeDelegate(nativeBitmap);
        sManager.removeJavaReferenceFor(nativeBitmap);
    }

    @LayoutlibDelegate
@@ -522,7 +522,7 @@ public final class Bitmap_Delegate {

    private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
        // get its native_int
        int nativeInt = sManager.addDelegate(delegate);
        int nativeInt = sManager.addNewDelegate(delegate);

        // and create/return a new Bitmap with it
        return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density);
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ public class BlurMaskFilter_Delegate extends MaskFilter_Delegate {
    @LayoutlibDelegate
    /*package*/ static int nativeConstructor(float radius, int style) {
        BlurMaskFilter_Delegate newDelegate = new BlurMaskFilter_Delegate();
        return sManager.addDelegate(newDelegate);
        return sManager.addNewDelegate(newDelegate);
    }

    // ---- Private delegate/helper methods ----
+10 −18
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ public final class Canvas_Delegate {
    private Bitmap_Delegate mBitmap;
    private GcSnapshot mSnapshot;

    private int mDrawFilter = 0;
    private DrawFilter_Delegate mDrawFilter = null;

    // ---- Public Helper methods ----

@@ -95,7 +95,7 @@ public final class Canvas_Delegate {
     * @return the delegate or null.
     */
    public DrawFilter_Delegate getDrawFilter() {
        return DrawFilter_Delegate.getDelegate(mDrawFilter);
        return mDrawFilter;
    }

    // ---- native methods ----
@@ -313,12 +313,12 @@ public final class Canvas_Delegate {
            // create a new Canvas_Delegate with the given bitmap and return its new native int.
            Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);

            return sManager.addDelegate(newDelegate);
            return sManager.addNewDelegate(newDelegate);
        } else {
            // create a new Canvas_Delegate and return its new native int.
            Canvas_Delegate newDelegate = new Canvas_Delegate();

            return sManager.addDelegate(newDelegate);
            return sManager.addNewDelegate(newDelegate);
        }
    }

@@ -510,26 +510,18 @@ public final class Canvas_Delegate {
    }

    @LayoutlibDelegate
    /*package*/ static void nativeSetDrawFilter(int nativeCanvas,
                                                   int nativeFilter) {
    /*package*/ static void nativeSetDrawFilter(int nativeCanvas, int nativeFilter) {
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            return;
        }

        canvasDelegate.mDrawFilter = nativeFilter;
        canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);

        // get the delegate only because we don't support them at all for the moment, so
        // we can display the message now.

        DrawFilter_Delegate filterDelegate = DrawFilter_Delegate.getDelegate(nativeFilter);
        if (canvasDelegate == null) {
            return;
        }

        if (filterDelegate.isSupported() == false) {
        if (canvasDelegate.mDrawFilter != null &&
                canvasDelegate.mDrawFilter.isSupported() == false) {
            Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
                    filterDelegate.getSupportMessage(), null, null /*data*/);
                    canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
        }
    }

@@ -1139,7 +1131,7 @@ public final class Canvas_Delegate {
        canvasDelegate.dispose();

        // remove it from the manager.
        sManager.removeDelegate(nativeCanvas);
        sManager.removeJavaReferenceFor(nativeCanvas);
    }

    // ---- Private delegate/helper methods ----
Loading