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

Commit dd97b42d authored by Rupesh Bansal's avatar Rupesh Bansal Committed by Android (Google) Code Review
Browse files

Merge "Dont send RR events if not in foreground" into main

parents 5af0b389 14a8feaa
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.Manifest.permission.MODIFY_HDR_CONVERSION_MODE;
import static android.Manifest.permission.RESTRICT_DISPLAY_MODES;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
import static android.hardware.display.DisplayManagerGlobal.InternalEventFlag;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
@@ -380,6 +381,8 @@ public final class DisplayManagerService extends SystemService {
    private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
            new SparseArray<>();

    private int mMaxImportanceForRRCallbacks = IMPORTANCE_VISIBLE;

    /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
    private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
        // Synchronized to avoid race conditions when updating multiple display states.
@@ -3636,6 +3639,7 @@ public final class DisplayManagerService extends SystemService {
            pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
            pw.println("  mStableDisplaySize=" + mStableDisplaySize);
            pw.println("  mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
            pw.println("  mMaxImportanceForRRCallbacks=" + mMaxImportanceForRRCallbacks);

            if (mUserPreferredMode != null) {
                pw.println(" mUserPreferredMode=" + mUserPreferredMode);
@@ -3764,6 +3768,10 @@ public final class DisplayManagerService extends SystemService {
        }
    }

    void overrideMaxImportanceForRRCallbacks(int importance) {
        mMaxImportanceForRRCallbacks = importance;
    }

    boolean requestDisplayPower(int displayId, int requestedState) {
        synchronized (mSyncRoot) {
            final var display = mLogicalDisplayMapper.getDisplayLocked(displayId);
@@ -4147,6 +4155,18 @@ public final class DisplayManagerService extends SystemService {
            mPackageName = packageNames == null ? null : packageNames[0];
        }

        public boolean shouldReceiveRefreshRateWithChangeUpdate(int event) {
            if (mFlags.isRefreshRateEventForForegroundAppsEnabled()
                    && event == DisplayManagerGlobal.EVENT_DISPLAY_REFRESH_RATE_CHANGED) {
                int procState = mActivityManagerInternal.getUidProcessState(mUid);
                int importance = ActivityManager.RunningAppProcessInfo
                        .procStateToImportance(procState);
                return importance <= mMaxImportanceForRRCallbacks || mUid <= Process.SYSTEM_UID;
            }

            return true;
        }

        public void updateEventFlagsMask(@InternalEventFlag long internalEventFlag) {
            mInternalEventFlagsMask.set(internalEventFlag);
        }
@@ -4254,6 +4274,11 @@ public final class DisplayManagerService extends SystemService {
                }
            }

            if (!shouldReceiveRefreshRateWithChangeUpdate(event)) {
                // The client is not visible to the user and is not a system service, so do nothing.
                return true;
            }

            try {
                transmitDisplayEvent(displayId, event);
                return true;
@@ -4405,6 +4430,11 @@ public final class DisplayManagerService extends SystemService {
                                + displayEvent.displayId + "/"
                                + displayEvent.event + " to " + mUid + "/" + mPid);
                    }

                    if (!shouldReceiveRefreshRateWithChangeUpdate(displayEvent.event)) {
                        continue;
                    }

                    transmitDisplayEvent(displayEvent.displayId, displayEvent.event);
                }
                return true;
+19 −0
Original line number Diff line number Diff line
@@ -112,6 +112,8 @@ class DisplayManagerShellCommand extends ShellCommand {
                return requestDisplayPower(Display.STATE_UNKNOWN);
            case "power-off":
                return requestDisplayPower(Display.STATE_OFF);
            case "override-max-importance-rr-callbacks":
                return overrideMaxImportanceForRRCallbacks();
            default:
                return handleDefaultCommands(cmd);
        }
@@ -631,4 +633,21 @@ class DisplayManagerShellCommand extends ShellCommand {
        mService.requestDisplayPower(displayId, state);
        return 0;
    }

    private int overrideMaxImportanceForRRCallbacks() {
        final String importanceString = getNextArg();
        if (importanceString == null) {
            getErrPrintWriter().println("Error: no importance specified");
            return 1;
        }
        final int importance;
        try {
            importance = Integer.parseInt(importanceString);
        } catch (NumberFormatException e) {
            getErrPrintWriter().println("Error: invalid importance: '" + importanceString + "'");
            return 1;
        }
        mService.overrideMaxImportanceForRRCallbacks(importance);
        return 0;
    }
}
+14 −1
Original line number Diff line number Diff line
@@ -268,6 +268,11 @@ public class DisplayManagerFlags {
            Flags::framerateOverrideTriggersRrCallbacks
    );

    private final FlagState mRefreshRateEventForForegroundApps = new FlagState(
            Flags.FLAG_REFRESH_RATE_EVENT_FOR_FOREGROUND_APPS,
            Flags::refreshRateEventForForegroundApps
    );

    /**
     * @return {@code true} if 'port' is allowed in display layout configuration file.
     */
@@ -578,6 +583,14 @@ public class DisplayManagerFlags {
    }


    /**
     * @return {@code true} if the flag for sending refresh rate events only for the apps in
     * foreground is enabled
     */
    public boolean isRefreshRateEventForForegroundAppsEnabled() {
        return mRefreshRateEventForForegroundApps.isEnabled();
    }

    /**
     * dumps all flagstates
     * @param pw printWriter
@@ -634,7 +647,7 @@ public class DisplayManagerFlags {
        pw.println(" " + mEnableDisplayContentModeManagementFlagState);
        pw.println(" " + mBaseDensityForExternalDisplays);
        pw.println(" " + mFramerateOverrideTriggersRrCallbacks);

        pw.println(" " + mRefreshRateEventForForegroundApps);
    }

    private static class FlagState {
+11 −0
Original line number Diff line number Diff line
@@ -490,3 +490,14 @@ flag {
          purpose: PURPOSE_BUGFIX
        }
}

flag {
    name: "refresh_rate_event_for_foreground_apps"
    namespace: "display_manager"
    description: "Send Refresh Rate events only for the apps in foreground."
    bug: "390107600"
    is_fixed_read_only: true
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}
+24 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT;
import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS;
import static android.Manifest.permission.MANAGE_DISPLAYS;
import static android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE;
import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
@@ -2344,6 +2345,29 @@ public class DisplayManagerServiceTest {
        callback.clear();
    }

    @Test
    public void test_doesNotNotifyRefreshRateChanged_whenAppInBackground() {
        when(mMockFlags.isRefreshRateEventForForegroundAppsEnabled()).thenReturn(true);
        DisplayManagerService displayManager =
                new DisplayManagerService(mContext, mBasicInjector);
        DisplayManagerService.BinderService displayManagerBinderService =
                displayManager.new BinderService();
        displayManager.windowManagerAndInputReady();
        registerDefaultDisplays(displayManager);
        displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager, new float[]{60f});
        FakeDisplayManagerCallback callback = registerDisplayListenerCallback(displayManager,
                displayManagerBinderService, displayDevice);

        when(mMockActivityManagerInternal.getUidProcessState(Process.myUid()))
                .thenReturn(PROCESS_STATE_TRANSIENT_BACKGROUND);
        updateRenderFrameRate(displayManager, displayDevice, 30f);
        waitForIdleHandler(displayManager.getDisplayHandler());
        assertEquals(0, callback.receivedEvents().size());
        callback.clear();
    }

    /**
     * Tests that the DisplayInfo is updated correctly with a render frame rate
     */