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

Commit 51fe6cae authored by Bryce Lee's avatar Bryce Lee Committed by Android (Google) Code Review
Browse files

Merge "Address TouchMonitor memory leaks." into main

parents b04ab25b 9ea76811
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -397,6 +397,9 @@ class DreamOverlayServiceTest : SysuiTestCase() {
        verify(mStateController).setOverlayActive(false)
        verify(mStateController).setOverlayActive(false)
        verify(mStateController).setLowLightActive(false)
        verify(mStateController).setLowLightActive(false)
        verify(mStateController).setEntryAnimationsFinished(false)
        verify(mStateController).setEntryAnimationsFinished(false)

        // Verify touch monitor destroyed
        verify(mTouchMonitor).destroy()
    }
    }


    @Test
    @Test
+1 −0
Original line number Original line Diff line number Diff line
@@ -269,6 +269,7 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
            }
            }
            mScrimManager.removeCallback(mScrimManagerCallback);
            mScrimManager.removeCallback(mScrimManagerCallback);
            mCapture = null;
            mCapture = null;
            mTouchSession = null;


            if (!Flags.communalBouncerDoNotModifyPluginOpen()) {
            if (!Flags.communalBouncerDoNotModifyPluginOpen()) {
                mNotificationShadeWindowController.setForcePluginOpen(false, this);
                mNotificationShadeWindowController.setForcePluginOpen(false, this);
+47 −12
Original line number Original line Diff line number Diff line
@@ -49,11 +49,14 @@ import com.android.systemui.util.display.DisplayHelper;


import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFuture;


import kotlinx.coroutines.Job;

import java.util.Collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Iterator;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Collectors;
@@ -78,15 +81,7 @@ public class TouchMonitor {
    private final Lifecycle mLifecycle;
    private final Lifecycle mLifecycle;
    private Rect mExclusionRect = null;
    private Rect mExclusionRect = null;


    private ISystemGestureExclusionListener mGestureExclusionListener =
    private ISystemGestureExclusionListener mGestureExclusionListener;
            new ISystemGestureExclusionListener.Stub() {
                @Override
                public void onSystemGestureExclusionChanged(int displayId,
                        Region systemGestureExclusion,
                        Region systemGestureExclusionUnrestricted) {
                    mExclusionRect = systemGestureExclusion.getBounds();
                }
            };


    private Consumer<Rect> mMaxBoundsConsumer = rect -> mMaxBounds = rect;
    private Consumer<Rect> mMaxBoundsConsumer = rect -> mMaxBounds = rect;


@@ -274,6 +269,14 @@ public class TouchMonitor {
        if (bouncerAreaExclusion()) {
        if (bouncerAreaExclusion()) {
            mBackgroundExecutor.execute(() -> {
            mBackgroundExecutor.execute(() -> {
                try {
                try {
                    mGestureExclusionListener = new ISystemGestureExclusionListener.Stub() {
                        @Override
                        public void onSystemGestureExclusionChanged(int displayId,
                                Region systemGestureExclusion,
                                Region systemGestureExclusionUnrestricted) {
                            mExclusionRect = systemGestureExclusion.getBounds();
                        }
                    };
                    mWindowManagerService.registerSystemGestureExclusionListener(
                    mWindowManagerService.registerSystemGestureExclusionListener(
                            mGestureExclusionListener, mDisplayId);
                            mGestureExclusionListener, mDisplayId);
                } catch (RemoteException e) {
                } catch (RemoteException e) {
@@ -298,8 +301,11 @@ public class TouchMonitor {
        if (bouncerAreaExclusion()) {
        if (bouncerAreaExclusion()) {
            mBackgroundExecutor.execute(() -> {
            mBackgroundExecutor.execute(() -> {
                try {
                try {
                    if (mGestureExclusionListener != null) {
                        mWindowManagerService.unregisterSystemGestureExclusionListener(
                        mWindowManagerService.unregisterSystemGestureExclusionListener(
                                mGestureExclusionListener, mDisplayId);
                                mGestureExclusionListener, mDisplayId);
                        mGestureExclusionListener = null;
                    }
                } catch (RemoteException e) {
                } catch (RemoteException e) {
                    // Handle the exception
                    // Handle the exception
                    Log.e(TAG, "unregisterSystemGestureExclusionListener: failed", e);
                    Log.e(TAG, "unregisterSystemGestureExclusionListener: failed", e);
@@ -494,6 +500,10 @@ public class TouchMonitor {


    private Rect mMaxBounds;
    private Rect mMaxBounds;


    private Job mBoundsFlow;

    private boolean mInitialized;



    /**
    /**
     * Designated constructor for {@link TouchMonitor}
     * Designated constructor for {@link TouchMonitor}
@@ -535,10 +545,35 @@ public class TouchMonitor {
     * Initializes the monitor. should only be called once after creation.
     * Initializes the monitor. should only be called once after creation.
     */
     */
    public void init() {
    public void init() {
        if (mInitialized) {
            throw new IllegalStateException("TouchMonitor already initialized");
        }

        mLifecycle.addObserver(mLifecycleObserver);
        mLifecycle.addObserver(mLifecycleObserver);
        if (Flags.ambientTouchMonitorListenToDisplayChanges()) {
        if (Flags.ambientTouchMonitorListenToDisplayChanges()) {
            collectFlow(mLifecycle, mConfigurationInteractor.getMaxBounds(), mMaxBoundsConsumer);
            mBoundsFlow = collectFlow(mLifecycle, mConfigurationInteractor.getMaxBounds(),
                    mMaxBoundsConsumer);
        }

        mInitialized = true;
    }

    /**
     * Called when the TouchMonitor should be discarded and will not be used anymore.
     */
    public void destroy() {
        if (!mInitialized) {
            throw new IllegalStateException("TouchMonitor not initialized");
        }

        stopMonitoring(true);

        mLifecycle.removeObserver(mLifecycleObserver);
        if (Flags.ambientTouchMonitorListenToDisplayChanges()) {
            mBoundsFlow.cancel(new CancellationException());
        }
        }

        mInitialized = false;
    }
    }


    private void isolate(Set<TouchSessionImpl> sessions) {
    private void isolate(Set<TouchSessionImpl> sessions) {
+5 −1
Original line number Original line Diff line number Diff line
@@ -543,7 +543,11 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
        mStateController.setEntryAnimationsFinished(false);
        mStateController.setEntryAnimationsFinished(false);


        mDreamOverlayContainerViewController = null;
        mDreamOverlayContainerViewController = null;

        if (mTouchMonitor != null) {
            mTouchMonitor.destroy();
            mTouchMonitor = null;
            mTouchMonitor = null;
        }


        mWindow = null;
        mWindow = null;
        mStarted = false;
        mStarted = false;
+2 −2
Original line number Original line Diff line number Diff line
@@ -88,8 +88,8 @@ fun <T> collectFlow(
    flow: Flow<T>,
    flow: Flow<T>,
    consumer: Consumer<T>,
    consumer: Consumer<T>,
    state: Lifecycle.State = Lifecycle.State.CREATED,
    state: Lifecycle.State = Lifecycle.State.CREATED,
) {
): Job {
    lifecycle.coroutineScope.launch {
    return lifecycle.coroutineScope.launch {
        lifecycle.repeatOnLifecycle(state) { flow.collect { consumer.accept(it) } }
        lifecycle.repeatOnLifecycle(state) { flow.collect { consumer.accept(it) } }
    }
    }
}
}
Loading