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

Commit 19bd5bcc authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Fix ActivityLeak through text reference

Bug: 296064689
Test: atest CtsTextTestCases
Test: atest CtsWidgetTestCases
Change-Id: I038c28819d6aaf8518c28fb0ab223925357d4d0a
parent 2a70a73d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -622,7 +622,7 @@ public class DynamicLayout extends Layout {
            sBuilder = null;
        }

        if (reflowed == null) {
        if (b == null) {
            b = StaticLayout.Builder.obtain(text, where, where + after, getPaint(), getWidth());
        }

@@ -641,7 +641,7 @@ public class DynamicLayout extends Layout {
                .setAddLastLineLineSpacing(!islast)
                .setIncludePad(false);

        reflowed = b.regenerate(true /* trackpadding */, reflowed);
        reflowed = b.buildPartialStaticLayoutForDynamicLayout(true /* trackpadding */, reflowed);
        int n = reflowed.getLineCount();
        // If the new layout has a blank line at the end, but it is not
        // the very end of the buffer, then we already have a line that
+48 −5
Original line number Diff line number Diff line
@@ -437,14 +437,26 @@ public class StaticLayout extends Layout {
            return result;
        }

        /* package */ @NonNull StaticLayout regenerate(boolean trackpadding, StaticLayout recycle) {
        /**
         * DO NOT USE THIS METHOD OTHER THAN DynamicLayout.
         *
         * This class generates a very weird StaticLayout only for getting a result of line break.
         * Since DynamicLayout keeps StaticLayout reference in the static context for object
         * recycling but keeping text reference in static context will end up with leaking Context
         * due to TextWatcher via TextView.
         *
         * So, this is a dirty work around that creating StaticLayout without passing text reference
         * to the super constructor, but calculating the text layout by calling generate function
         * directly.
         */
        /* package */ @NonNull StaticLayout buildPartialStaticLayoutForDynamicLayout(
                boolean trackpadding, StaticLayout recycle) {
            if (recycle == null) {
                return new StaticLayout(this, trackpadding, COLUMNS_ELLIPSIZE);
            } else {
                recycle = new StaticLayout();
            }
            recycle.generate(this, mIncludePad, trackpadding);
            return recycle;
        }
        }

        private CharSequence mText;
        private int mStart;
@@ -473,6 +485,37 @@ public class StaticLayout extends Layout {
        private static final SynchronizedPool<Builder> sPool = new SynchronizedPool<>(3);
    }

    /**
     * DO NOT USE THIS CONSTRUCTOR OTHER THAN FOR DYNAMIC LAYOUT.
     * See Builder#buildPartialStaticLayoutForDynamicLayout for the reason of this constructor.
     */
    private StaticLayout() {
        super(
                null,  // text
                null,  // paint
                0,  // width
                null, // alignment
                null, // textDir
                1, // spacing multiplier
                0, // spacing amount
                false, // include font padding
                false, // fallback line spacing
                0,  // ellipsized width
                null, // ellipsize
                1,  // maxLines
                BREAK_STRATEGY_SIMPLE,
                HYPHENATION_FREQUENCY_NONE,
                null,  // leftIndents
                null,  // rightIndents
                JUSTIFICATION_MODE_NONE,
                null  // lineBreakConfig
        );

        mColumns = COLUMNS_ELLIPSIZE;
        mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2);
        mLines  = ArrayUtils.newUnpaddedIntArray(2 * mColumns);
    }

    /**
     * @deprecated Use {@link Builder} instead.
     */