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

Commit a27e4b7b authored by Jackal Guo's avatar Jackal Guo
Browse files

Stop recycling in AccessibilityCache

Explicitly allocate windows and nodes instead of obtain/recycle in
AccessibilityCache.

Bug: 117999988
Test: build and boot
Test: a11y CTS & unit tests
Change-Id: I269c6b9d8bc67568fd90f8690a7bfb7a782e7fe7
parent 22640b9a
Loading
Loading
Loading
Loading
+6 −26
Original line number Diff line number Diff line
@@ -105,11 +105,7 @@ public class AccessibilityCache {
                Log.i(LOG_TAG, "Caching window: " + window.getId());
            }
            final int windowId = window.getId();
            AccessibilityWindowInfo oldWindow = mWindowCache.get(windowId);
            if (oldWindow != null) {
                oldWindow.recycle();
            }
            mWindowCache.put(windowId, AccessibilityWindowInfo.obtain(window));
            mWindowCache.put(windowId, new AccessibilityWindowInfo(window));
        }
    }

@@ -225,7 +221,7 @@ public class AccessibilityCache {
            if (info != null) {
                // Return a copy since the client calls to AccessibilityNodeInfo#recycle()
                // will wipe the data of the cached info.
                info = AccessibilityNodeInfo.obtain(info);
                info = new AccessibilityNodeInfo(info);
            }
            if (DEBUG) {
                Log.i(LOG_TAG, "get(" + accessibilityNodeId + ") = " + info);
@@ -257,7 +253,7 @@ public class AccessibilityCache {
                List<AccessibilityWindowInfo> windows = new ArrayList<>(sortedWindowCount);
                for (int i = sortedWindowCount - 1; i >= 0; i--) {
                    AccessibilityWindowInfo window = sortedWindows.valueAt(i);
                    windows.add(AccessibilityWindowInfo.obtain(window));
                    windows.add(new AccessibilityWindowInfo(window));
                    sortedWindows.removeAt(i);
                }

@@ -271,7 +267,7 @@ public class AccessibilityCache {
        synchronized (mLock) {
            AccessibilityWindowInfo window = mWindowCache.get(windowId);
            if (window != null) {
               return AccessibilityWindowInfo.obtain(window);
                return new AccessibilityWindowInfo(window);
            }
            return null;
        }
@@ -326,14 +322,12 @@ public class AccessibilityCache {
                final long oldParentId = oldInfo.getParentNodeId();
                if (info.getParentNodeId() != oldParentId) {
                    clearSubTreeLocked(windowId, oldParentId);
                } else {
                    oldInfo.recycle();
                }
           }

            // Cache a copy since the client calls to AccessibilityNodeInfo#recycle()
            // will wipe the data of the cached info.
            AccessibilityNodeInfo clone = AccessibilityNodeInfo.obtain(info);
            AccessibilityNodeInfo clone = new AccessibilityNodeInfo(info);
            nodes.put(sourceId, clone);
            if (clone.isAccessibilityFocused()) {
                if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
@@ -371,12 +365,7 @@ public class AccessibilityCache {
    }

    private void clearWindowCache() {
        final int windowCount = mWindowCache.size();
        for (int i = windowCount - 1; i >= 0; i--) {
            AccessibilityWindowInfo window = mWindowCache.valueAt(i);
            window.recycle();
            mWindowCache.removeAt(i);
        }
        mWindowCache.clear();
        mIsAllWindowsCached = false;
    }

@@ -391,13 +380,6 @@ public class AccessibilityCache {
        if (nodes == null) {
            return;
        }
        // Recycle the nodes before clearing the cache.
        final int nodeCount = nodes.size();
        for (int i = nodeCount - 1; i >= 0; i--) {
            AccessibilityNodeInfo info = nodes.valueAt(i);
            nodes.removeAt(i);
            info.recycle();
        }
        mNodeCache.remove(windowId);
    }

@@ -440,11 +422,9 @@ public class AccessibilityCache {
        for (int i = 0; i < childCount; i++) {
            final long childNodeId = current.getChildId(i);
            if (clearSubTreeRecursiveLocked(nodes, childNodeId)) {
                current.recycle();
                return true;
            }
        }
        current.recycle();
        return false;
    }

+6 −0
Original line number Diff line number Diff line
@@ -654,6 +654,7 @@ public class AccessibilityNodeInfo implements Parcelable {
     */
    private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;

    // TODO(b/129300068): Remove sNumInstancesInUse.
    private static AtomicInteger sNumInstancesInUse;

    /**
@@ -766,6 +767,11 @@ public class AccessibilityNodeInfo implements Parcelable {
        /* do nothing */
    }

    /** @hide */
    AccessibilityNodeInfo(AccessibilityNodeInfo info) {
        init(info);
    }

    /**
     * Sets the source.
     * <p>
+33 −20
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
    private static final int MAX_POOL_SIZE = 10;
    private static final SynchronizedPool<AccessibilityWindowInfo> sPool =
            new SynchronizedPool<AccessibilityWindowInfo>(MAX_POOL_SIZE);
    // TODO(b/129300068): Remove sNumInstancesInUse.
    private static AtomicInteger sNumInstancesInUse;

    // Data.
@@ -115,6 +116,11 @@ public final class AccessibilityWindowInfo implements Parcelable {
        /* do nothing - hide constructor */
    }

    /** @hide */
    AccessibilityWindowInfo(AccessibilityWindowInfo info) {
        init(info);
    }

    /**
     * Gets the title of the window.
     *
@@ -448,26 +454,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
     */
    public static AccessibilityWindowInfo obtain(AccessibilityWindowInfo info) {
        AccessibilityWindowInfo infoClone = obtain();

        infoClone.mType = info.mType;
        infoClone.mLayer = info.mLayer;
        infoClone.mBooleanProperties = info.mBooleanProperties;
        infoClone.mId = info.mId;
        infoClone.mParentId = info.mParentId;
        infoClone.mBoundsInScreen.set(info.mBoundsInScreen);
        infoClone.mTitle = info.mTitle;
        infoClone.mAnchorId = info.mAnchorId;

        if (info.mChildIds != null && info.mChildIds.size() > 0) {
            if (infoClone.mChildIds == null) {
                infoClone.mChildIds = info.mChildIds.clone();
            } else {
                infoClone.mChildIds.addAll(info.mChildIds);
            }
        }

        infoClone.mConnectionId = info.mConnectionId;

        infoClone.init(info);
        return infoClone;
    }

@@ -529,6 +516,32 @@ public final class AccessibilityWindowInfo implements Parcelable {
        parcel.writeInt(mConnectionId);
    }

    /**
     * Initializes this instance from another one.
     *
     * @param other The other instance.
     */
    private void init(AccessibilityWindowInfo other) {
        mType = other.mType;
        mLayer = other.mLayer;
        mBooleanProperties = other.mBooleanProperties;
        mId = other.mId;
        mParentId = other.mParentId;
        mBoundsInScreen.set(other.mBoundsInScreen);
        mTitle = other.mTitle;
        mAnchorId = other.mAnchorId;

        if (other.mChildIds != null && other.mChildIds.size() > 0) {
            if (mChildIds == null) {
                mChildIds = other.mChildIds.clone();
            } else {
                mChildIds.addAll(other.mChildIds);
            }
        }

        mConnectionId = other.mConnectionId;
    }

    private void initFromParcel(Parcel parcel) {
        mType = parcel.readInt();
        mLayer = parcel.readInt();
+0 −7
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ import org.mockito.stubbing.Answer;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@LargeTest
@RunWith(AndroidJUnit4.class)
@@ -61,16 +60,12 @@ public class AccessibilityCacheTest {

    AccessibilityCache mAccessibilityCache;
    AccessibilityCache.AccessibilityNodeRefresher mAccessibilityNodeRefresher;
    AtomicInteger mNumA11yNodeInfosInUse = new AtomicInteger(0);
    AtomicInteger mNumA11yWinInfosInUse = new AtomicInteger(0);

    @Before
    public void setUp() {
        mAccessibilityNodeRefresher = mock(AccessibilityCache.AccessibilityNodeRefresher.class);
        when(mAccessibilityNodeRefresher.refreshNode(anyObject(), anyBoolean())).thenReturn(true);
        mAccessibilityCache = new AccessibilityCache(mAccessibilityNodeRefresher);
        AccessibilityNodeInfo.setNumInstancesInUseCounter(mNumA11yNodeInfosInUse);
        AccessibilityWindowInfo.setNumInstancesInUseCounter(mNumA11yWinInfosInUse);
    }

    @After
@@ -78,8 +73,6 @@ public class AccessibilityCacheTest {
        // Make sure we're recycling all of our window and node infos
        mAccessibilityCache.clear();
        AccessibilityInteractionClient.getInstance().clearCache();
        assertEquals(0, mNumA11yWinInfosInUse.get());
        assertEquals(0, mNumA11yNodeInfosInUse.get());
    }

    @Test