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

Commit a7af7b50 authored by Kenneth Ford's avatar Kenneth Ford
Browse files

Cancels dual display state when all activities for process are invisible

Uses a ProcessObserver instead of a TaskStackListener to be notified
when a process has no foreground activities. This is a more stable
and correct signal than the onTaskMovedToFront notification.
cancel the dual display request. Fixes bugs previously seen with
tapping on navigation bars or multi-window scenarios.

Fixes: 295195310
Test: DeviceStateManagerServiceTest
Change-Id: I5aed2b204dcbdbf1e439811780a94b3f499b31a3
parent cd15fed5
Loading
Loading
Loading
Loading
+28 −20
Original line number Diff line number Diff line
@@ -37,7 +37,8 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.TaskStackListener;
import android.app.ActivityManagerInternal;
import android.app.IProcessObserver;
import android.content.Context;
import android.hardware.devicestate.DeviceStateInfo;
import android.hardware.devicestate.DeviceStateManager;
@@ -184,7 +185,30 @@ public final class DeviceStateManagerService extends SystemService {
    private final SystemPropertySetter mSystemPropertySetter;

    @VisibleForTesting
    TaskStackListener mOverrideRequestTaskStackListener = new OverrideRequestTaskStackListener();
    final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
        @Override
        public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
            synchronized (mLock) {
                if (!shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
                    return;
                }

                OverrideRequest request = mActiveOverride.get();
                if (pid != request.getPid() || uid != request.getUid()) {
                    return;
                }
                if (!fg) {
                    mOverrideRequestController.cancelRequest(request);
                }
            }
        }

        @Override
        public void onProcessDied(int pid, int uid) {}

        @Override
        public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {}
    };
    @VisibleForTesting
    ActivityTaskManagerInternal.ScreenObserver mOverrideRequestScreenObserver =
            new OverrideRequestScreenObserver();
@@ -239,8 +263,9 @@ public final class DeviceStateManagerService extends SystemService {
            mFoldedDeviceStates = readFoldedStates();
        }

        mActivityTaskManagerInternal.registerTaskStackListener(mOverrideRequestTaskStackListener);
        mActivityTaskManagerInternal.registerScreenObserver(mOverrideRequestScreenObserver);
        LocalServices.getService(ActivityManagerInternal.class).registerProcessObserver(
                mProcessObserver);
    }

    @VisibleForTesting
@@ -1289,23 +1314,6 @@ public final class DeviceStateManagerService extends SystemService {
        return deviceState.hasFlag(DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
    }

    private class OverrideRequestTaskStackListener extends TaskStackListener {
        @Override
        public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
                throws RemoteException {
            synchronized (mLock) {
                if (!shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
                    return;
                }

                OverrideRequest request = mActiveOverride.get();
                if (!isTopApp(request.getPid())) {
                    mOverrideRequestController.cancelRequest(request);
                }
            }
        }
    }

    private class OverrideRequestScreenObserver implements
            ActivityTaskManagerInternal.ScreenObserver {

+8 −6
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertThrows;

import android.app.ActivityManager;
import android.hardware.devicestate.DeviceStateInfo;
import android.hardware.devicestate.DeviceStateRequest;
import android.hardware.devicestate.IDeviceStateManagerCallback;
@@ -582,10 +581,10 @@ public final class DeviceStateManagerServiceTest {
                // When the app is foreground, the state should not change
                () -> {
                    int pid = Binder.getCallingPid();
                    when(mWindowProcessController.getPid()).thenReturn(pid);
                    int uid = Binder.getCallingUid();
                    try {
                        mService.mOverrideRequestTaskStackListener.onTaskMovedToFront(
                                new ActivityManager.RunningTaskInfo());
                        mService.mProcessObserver.onForegroundActivitiesChanged(pid, uid,
                                true /* foregroundActivities */);
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }
@@ -594,8 +593,11 @@ public final class DeviceStateManagerServiceTest {
                () -> {
                    when(mWindowProcessController.getPid()).thenReturn(FAKE_PROCESS_ID);
                    try {
                        mService.mOverrideRequestTaskStackListener.onTaskMovedToFront(
                                new ActivityManager.RunningTaskInfo());
                        int pid = Binder.getCallingPid();
                        int uid = Binder.getCallingUid();
                        mService.mProcessObserver.onForegroundActivitiesChanged(pid, uid,
                                false /* foregroundActivities */);

                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }