diff options
7 files changed, 151 insertions, 52 deletions
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index e31adcfd699e..f2373fbfa858 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -341,6 +341,9 @@ public final class DisplayInfo implements Parcelable { @Nullable public DisplayShape displayShape; + /** + * Refresh rate range limitation based on the current device layout + */ @Nullable public SurfaceControl.RefreshRateRange layoutLimitedRefreshRate; @@ -354,7 +357,7 @@ public final class DisplayInfo implements Parcelable { * RefreshRateRange limitation for @Temperature.ThrottlingStatus */ @NonNull - public SparseArray<SurfaceControl.RefreshRateRange> refreshRateThermalThrottling = + public SparseArray<SurfaceControl.RefreshRateRange> thermalRefreshRateThrottling = new SparseArray<>(); public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { @@ -434,7 +437,7 @@ public final class DisplayInfo implements Parcelable { && Objects.equals(displayShape, other.displayShape) && Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate) && BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio) - && refreshRateThermalThrottling.contentEquals(other.refreshRateThermalThrottling); + && thermalRefreshRateThrottling.contentEquals(other.thermalRefreshRateThrottling); } @Override @@ -491,7 +494,7 @@ public final class DisplayInfo implements Parcelable { displayShape = other.displayShape; layoutLimitedRefreshRate = other.layoutLimitedRefreshRate; hdrSdrRatio = other.hdrSdrRatio; - refreshRateThermalThrottling = other.refreshRateThermalThrottling; + thermalRefreshRateThrottling = other.thermalRefreshRateThrottling; } public void readFromParcel(Parcel source) { @@ -554,7 +557,7 @@ public final class DisplayInfo implements Parcelable { displayShape = source.readTypedObject(DisplayShape.CREATOR); layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR); hdrSdrRatio = source.readFloat(); - refreshRateThermalThrottling = source.readSparseArray(null, + thermalRefreshRateThrottling = source.readSparseArray(null, SurfaceControl.RefreshRateRange.class); } @@ -616,7 +619,7 @@ public final class DisplayInfo implements Parcelable { dest.writeTypedObject(displayShape, flags); dest.writeTypedObject(layoutLimitedRefreshRate, flags); dest.writeFloat(hdrSdrRatio); - dest.writeSparseArray(refreshRateThermalThrottling); + dest.writeSparseArray(thermalRefreshRateThrottling); } @Override @@ -884,8 +887,8 @@ public final class DisplayInfo implements Parcelable { } else { sb.append(hdrSdrRatio); } - sb.append(", refreshRateThermalThrottling "); - sb.append(refreshRateThermalThrottling); + sb.append(", thermalRefreshRateThrottling "); + sb.append(thermalRefreshRateThrottling); sb.append("}"); return sb.toString(); } diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index dab00d8070d4..0b6d1c851dc4 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -181,6 +181,19 @@ final class LogicalDisplay { */ private String mThermalBrightnessThrottlingDataId; + /** + * Refresh rate range limitation based on the current device layout + */ + @Nullable + private SurfaceControl.RefreshRateRange mLayoutLimitedRefreshRate; + + /** + * RefreshRateRange limitation for @Temperature.ThrottlingStatus + */ + @NonNull + private SparseArray<SurfaceControl.RefreshRateRange> mThermalRefreshRateThrottling = + new SparseArray<>(); + public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) { mDisplayId = displayId; mLayerStack = layerStack; @@ -339,24 +352,24 @@ final class LogicalDisplay { */ public void updateLayoutLimitedRefreshRateLocked( @Nullable SurfaceControl.RefreshRateRange layoutLimitedRefreshRate) { - if (!Objects.equals(layoutLimitedRefreshRate, mBaseDisplayInfo.layoutLimitedRefreshRate)) { - mBaseDisplayInfo.layoutLimitedRefreshRate = layoutLimitedRefreshRate; - mInfo.set(null); + if (!Objects.equals(layoutLimitedRefreshRate, mLayoutLimitedRefreshRate)) { + mLayoutLimitedRefreshRate = layoutLimitedRefreshRate; + mDirty = true; } } /** - * Updates refreshRateThermalThrottling + * Updates thermalRefreshRateThrottling * - * @param refreshRanges new refreshRateThermalThrottling ranges limited by layout or default + * @param refreshRanges new thermalRefreshRateThrottling ranges limited by layout or default */ public void updateThermalRefreshRateThrottling( @Nullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges) { if (refreshRanges == null) { refreshRanges = new SparseArray<>(); } - if (!mBaseDisplayInfo.refreshRateThermalThrottling.contentEquals(refreshRanges)) { - mBaseDisplayInfo.refreshRateThermalThrottling = refreshRanges; - mInfo.set(null); + if (!mThermalRefreshRateThrottling.contentEquals(refreshRanges)) { + mThermalRefreshRateThrottling = refreshRanges; + mDirty = true; } } @@ -499,6 +512,9 @@ final class LogicalDisplay { mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT; } + mBaseDisplayInfo.layoutLimitedRefreshRate = mLayoutLimitedRefreshRate; + mBaseDisplayInfo.thermalRefreshRateThrottling = mThermalRefreshRateThrottling; + mPrimaryDisplayDeviceInfo = deviceInfo; mInfo.set(null); mDirty = false; @@ -952,6 +968,8 @@ final class LogicalDisplay { pw.println("mDisplayGroupName=" + mDisplayGroupName); pw.println("mThermalBrightnessThrottlingDataId=" + mThermalBrightnessThrottlingDataId); pw.println("mLeadDisplayId=" + mLeadDisplayId); + pw.println("mLayoutLimitedRefreshRate=" + mLayoutLimitedRefreshRate); + pw.println("mThermalRefreshRateThrottling=" + mThermalRefreshRateThrottling); } @Override diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java index 03b49f088c2f..06b7698e9df2 100644 --- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java @@ -1705,14 +1705,13 @@ public class DisplayModeDirector { } public void observe() { - DisplayManager dm = mContext.getSystemService(DisplayManager.class); - dm.registerDisplayListener(this, mHandler); + mInjector.registerDisplayListener(this, mHandler); // Populate existing displays SparseArray<Display.Mode[]> modes = new SparseArray<>(); SparseArray<Display.Mode> defaultModes = new SparseArray<>(); DisplayInfo info = new DisplayInfo(); - Display[] displays = dm.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED); + Display[] displays = mInjector.getDisplays(); for (Display d : displays) { final int displayId = d.getDisplayId(); d.getDisplayInfo(info); @@ -1751,17 +1750,9 @@ public class DisplayModeDirector { updateLayoutLimitedFrameRate(displayId, displayInfo); } - @Nullable private DisplayInfo getDisplayInfo(int displayId) { - Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId); - if (d == null) { - // We can occasionally get a display added or changed event for a display that was - // subsequently removed, which means this returns null. Check this case and bail - // out early; if it gets re-attached we'll eventually get another call back for it. - return null; - } DisplayInfo info = new DisplayInfo(); - d.getDisplayInfo(info); + mInjector.getDisplayInfo(displayId, info); return info; } @@ -2432,8 +2423,7 @@ public class DisplayModeDirector { } private void updateDefaultDisplayState() { - Display display = mContext.getSystemService(DisplayManager.class) - .getDisplay(Display.DEFAULT_DISPLAY); + Display display = mInjector.getDisplay(Display.DEFAULT_DISPLAY); if (display == null) { return; } @@ -2750,8 +2740,7 @@ public class DisplayModeDirector { sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this); synchronized (mSensorObserverLock) { - for (Display d : mDisplayManager.getDisplays( - DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) { + for (Display d : mInjector.getDisplays()) { mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d)); } } @@ -2762,8 +2751,7 @@ public class DisplayModeDirector { } private void recalculateVotesLocked() { - final Display[] displays = mDisplayManager.getDisplays( - DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED); + final Display[] displays = mInjector.getDisplays(); for (Display d : displays) { int displayId = d.getDisplayId(); Vote vote = null; @@ -2794,7 +2782,7 @@ public class DisplayModeDirector { @Override public void onDisplayAdded(int displayId) { - boolean isDozeState = mInjector.isDozeState(mDisplayManager.getDisplay(displayId)); + boolean isDozeState = mInjector.isDozeState(mInjector.getDisplay(displayId)); synchronized (mSensorObserverLock) { mDozeStateByDisplay.put(displayId, isDozeState); recalculateVotesLocked(); @@ -2806,7 +2794,7 @@ public class DisplayModeDirector { boolean wasDozeState = mDozeStateByDisplay.get(displayId); synchronized (mSensorObserverLock) { mDozeStateByDisplay.put(displayId, - mInjector.isDozeState(mDisplayManager.getDisplay(displayId))); + mInjector.isDozeState(mInjector.getDisplay(displayId))); if (wasDozeState != mDozeStateByDisplay.get(displayId)) { recalculateVotesLocked(); } @@ -3176,8 +3164,13 @@ public class DisplayModeDirector { @NonNull ContentObserver observer); void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener, + Handler handler); + + void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener, Handler handler, long flags); + Display getDisplay(int displayId); + Display[] getDisplays(); boolean getDisplayInfo(int displayId, DisplayInfo displayInfo); @@ -3222,11 +3215,22 @@ public class DisplayModeDirector { @Override public void registerDisplayListener(DisplayManager.DisplayListener listener, + Handler handler) { + getDisplayManager().registerDisplayListener(listener, handler); + } + + @Override + public void registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler, long flags) { getDisplayManager().registerDisplayListener(listener, handler, flags); } @Override + public Display getDisplay(int displayId) { + return getDisplayManager().getDisplay(displayId); + } + + @Override public Display[] getDisplays() { return getDisplayManager().getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED); } @@ -3234,10 +3238,13 @@ public class DisplayModeDirector { @Override public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) { Display display = getDisplayManager().getDisplay(displayId); - if (display != null) { - return display.getDisplayInfo(displayInfo); + if (display == null) { + // We can occasionally get a display added or changed event for a display that was + // subsequently removed, which means this returns null. Check this case and bail + // out early; if it gets re-attached we'll eventually get another call back for it. + return false; } - return false; + return display.getDisplayInfo(displayInfo); } @Override diff --git a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java index c04735d8f7e2..8a3b329211cf 100644 --- a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java +++ b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java @@ -138,7 +138,7 @@ final class SkinThermalStatusObserver extends IThermalEventListener.Stub impleme for (Display d : displays) { final int displayId = d.getDisplayId(); d.getDisplayInfo(info); - localMap.put(displayId, info.refreshRateThermalThrottling); + localMap.put(displayId, info.thermalRefreshRateThrottling); } synchronized (mThermalObserverLock) { for (int i = 0; i < size; i++) { @@ -154,7 +154,7 @@ final class SkinThermalStatusObserver extends IThermalEventListener.Stub impleme DisplayInfo displayInfo = new DisplayInfo(); mInjector.getDisplayInfo(displayId, displayInfo); SparseArray<SurfaceControl.RefreshRateRange> throttlingMap = - displayInfo.refreshRateThermalThrottling; + displayInfo.thermalRefreshRateThrottling; synchronized (mThermalObserverLock) { mThermalThrottlingByDisplay.put(displayId, throttlingMap); diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java index ff89be75c5d4..5ea30298890f 100644 --- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java +++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java @@ -17,6 +17,8 @@ package com.android.server.display; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; @@ -26,6 +28,7 @@ import static org.mockito.Mockito.when; import android.app.PropertyInvalidatedCache; import android.graphics.Point; +import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; @@ -47,6 +50,7 @@ public class LogicalDisplayTest { private static final int LAYER_STACK = 0; private static final int DISPLAY_WIDTH = 100; private static final int DISPLAY_HEIGHT = 200; + private static final int MODE_ID = 1; private LogicalDisplay mLogicalDisplay; private DisplayDevice mDisplayDevice; @@ -65,6 +69,9 @@ public class LogicalDisplayTest { mDisplayDeviceInfo.height = DISPLAY_HEIGHT; mDisplayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; + mDisplayDeviceInfo.modeId = MODE_ID; + mDisplayDeviceInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID, + DISPLAY_WIDTH, DISPLAY_HEIGHT, /* refreshRate= */ 60)}; when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(mDisplayDeviceInfo); // Disable binder caches in this process. @@ -168,14 +175,34 @@ public class LogicalDisplayTest { } @Test - public void testLayoutLimitedRefreshRateNotClearedAfterUpdate() { - SurfaceControl.RefreshRateRange refreshRateRange = new SurfaceControl.RefreshRateRange(1, - 2); - mLogicalDisplay.updateLayoutLimitedRefreshRateLocked(refreshRateRange); - mLogicalDisplay.updateDisplayGroupIdLocked(1); + public void testUpdateLayoutLimitedRefreshRate() { + SurfaceControl.RefreshRateRange layoutLimitedRefreshRate = + new SurfaceControl.RefreshRateRange(0, 120); + DisplayInfo info1 = mLogicalDisplay.getDisplayInfoLocked(); + mLogicalDisplay.updateLayoutLimitedRefreshRateLocked(layoutLimitedRefreshRate); + DisplayInfo info2 = mLogicalDisplay.getDisplayInfoLocked(); + // Display info should only be updated when updateLocked is called + assertEquals(info2, info1); - DisplayInfo result = mLogicalDisplay.getDisplayInfoLocked(); + mLogicalDisplay.updateLocked(mDeviceRepo); + DisplayInfo info3 = mLogicalDisplay.getDisplayInfoLocked(); + assertNotEquals(info3, info2); + assertEquals(layoutLimitedRefreshRate, info3.layoutLimitedRefreshRate); + } - assertEquals(refreshRateRange, result.layoutLimitedRefreshRate); + @Test + public void testUpdateRefreshRateThermalThrottling() { + SparseArray<SurfaceControl.RefreshRateRange> refreshRanges = new SparseArray<>(); + refreshRanges.put(0, new SurfaceControl.RefreshRateRange(0, 120)); + DisplayInfo info1 = mLogicalDisplay.getDisplayInfoLocked(); + mLogicalDisplay.updateThermalRefreshRateThrottling(refreshRanges); + DisplayInfo info2 = mLogicalDisplay.getDisplayInfoLocked(); + // Display info should only be updated when updateLocked is called + assertEquals(info2, info1); + + mLogicalDisplay.updateLocked(mDeviceRepo); + DisplayInfo info3 = mLogicalDisplay.getDisplayInfoLocked(); + assertNotEquals(info3, info2); + assertTrue(refreshRanges.contentEquals(info3.thermalRefreshRateThrottling)); } } diff --git a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java index 42c1fd9e3321..4cfcee5005b4 100644 --- a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java @@ -127,7 +127,8 @@ public class DisplayModeDirectorTest { private static final String TAG = "DisplayModeDirectorTest"; private static final boolean DEBUG = false; private static final float FLOAT_TOLERANCE = 0.01f; - private static final int DISPLAY_ID = 0; + private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY; + private static final int MODE_ID = 1; private static final float TRANSITION_POINT = 0.763f; private static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY; @@ -2644,6 +2645,33 @@ public class DisplayModeDirectorTest { assertNull(vote); } + @Test + public void testUpdateLayoutLimitedRefreshRate() { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + director.start(createMockSensorManager()); + + ArgumentCaptor<DisplayListener> displayListenerCaptor = + ArgumentCaptor.forClass(DisplayListener.class); + verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), + any(Handler.class)); + DisplayListener displayListener = displayListenerCaptor.getValue(); + + float refreshRate = 60; + mInjector.mDisplayInfo.layoutLimitedRefreshRate = + new RefreshRateRange(refreshRate, refreshRate); + displayListener.onDisplayChanged(DISPLAY_ID); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE); + assertVoteForPhysicalRefreshRate(vote, /* refreshRate= */ refreshRate); + + mInjector.mDisplayInfo.layoutLimitedRefreshRate = null; + displayListener.onDisplayChanged(DISPLAY_ID); + + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE); + assertNull(vote); + } + private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) { return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status); } @@ -2850,12 +2878,19 @@ public class DisplayModeDirectorTest { public static class FakesInjector implements DisplayModeDirector.Injector { private final FakeDeviceConfig mDeviceConfig; + private final DisplayInfo mDisplayInfo; + private final Display mDisplay; private ContentObserver mBrightnessObserver; private ContentObserver mSmoothDisplaySettingObserver; private ContentObserver mForcePeakRefreshRateSettingObserver; FakesInjector() { mDeviceConfig = new FakeDeviceConfig(); + mDisplayInfo = new DisplayInfo(); + mDisplayInfo.defaultModeId = MODE_ID; + mDisplayInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID, + 800, 600, /* refreshRate= */ 60)}; + mDisplay = createDisplay(DISPLAY_ID); } @NonNull @@ -2876,16 +2911,25 @@ public class DisplayModeDirectorTest { } @Override + public void registerDisplayListener(DisplayListener listener, Handler handler) {} + + @Override public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {} @Override + public Display getDisplay(int displayId) { + return mDisplay; + } + + @Override public Display[] getDisplays() { - return new Display[] { createDisplay(DISPLAY_ID) }; + return new Display[] { mDisplay }; } @Override public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) { - return false; + displayInfo.copyFrom(mDisplayInfo); + return true; } @Override @@ -2909,7 +2953,7 @@ public class DisplayModeDirectorTest { } protected Display createDisplay(int id) { - return new Display(DisplayManagerGlobal.getInstance(), id, new DisplayInfo(), + return new Display(DisplayManagerGlobal.getInstance(), id, mDisplayInfo, ApplicationProvider.getApplicationContext().getResources()); } diff --git a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java index fd1889ca0982..13540d60b930 100644 --- a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java +++ b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java @@ -253,7 +253,7 @@ public class SkinThermalStatusObserverTest { public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) { SparseArray<SurfaceControl.RefreshRateRange> config = mOverriddenConfig.get(displayId); if (config != null) { - displayInfo.refreshRateThermalThrottling = config; + displayInfo.thermalRefreshRateThrottling = config; return true; } return false; |