summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java11
-rw-r--r--services/core/java/com/android/server/display/DisplayGroup.java10
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java14
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java17
-rw-r--r--services/core/java/com/android/server/power/Notifier.java53
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java4
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java42
-rw-r--r--services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java92
8 files changed, 241 insertions, 2 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 73b5d947c0fe..e5980972d590 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -431,6 +431,17 @@ public abstract class DisplayManagerInternal {
*/
public abstract IntArray getDisplayGroupIds();
+
+ /**
+ * Get all display ids belonging to the display group with given id.
+ */
+ public abstract int[] getDisplayIdsForGroup(int groupId);
+
+ /**
+ * Get the mapping of display group ids to the display ids that belong to them.
+ */
+ public abstract SparseArray<int[]> getDisplayIdsByGroupsIds();
+
/**
* Get all available display ids.
*/
diff --git a/services/core/java/com/android/server/display/DisplayGroup.java b/services/core/java/com/android/server/display/DisplayGroup.java
index 2dcd5ccaf557..f73b66c78fce 100644
--- a/services/core/java/com/android/server/display/DisplayGroup.java
+++ b/services/core/java/com/android/server/display/DisplayGroup.java
@@ -87,4 +87,14 @@ public class DisplayGroup {
int getIdLocked(int index) {
return mDisplays.get(index).getDisplayIdLocked();
}
+
+ /** Returns the IDs of the {@link LogicalDisplay}s belonging to the DisplayGroup. */
+ int[] getIdsLocked() {
+ final int numDisplays = mDisplays.size();
+ final int[] displayIds = new int[numDisplays];
+ for (int i = 0; i < numDisplays; i++) {
+ displayIds[i] = mDisplays.get(i).getDisplayIdLocked();
+ }
+ return displayIds;
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 67e2ca2b312c..d25b51d6434c 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -5575,6 +5575,20 @@ public final class DisplayManagerService extends SystemService {
}
@Override
+ public int[] getDisplayIdsForGroup(int groupId) {
+ synchronized (mSyncRoot) {
+ return mLogicalDisplayMapper.getDisplayIdsForGroupLocked(groupId);
+ }
+ }
+
+ @Override
+ public SparseArray<int[]> getDisplayIdsByGroupsIds() {
+ synchronized (mSyncRoot) {
+ return mLogicalDisplayMapper.getDisplayIdsByGroupIdLocked();
+ }
+ }
+
+ @Override
public IntArray getDisplayIds() {
IntArray displayIds = new IntArray();
synchronized (mSyncRoot) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index c3f6a5285ae3..bcb600d0f91c 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -344,6 +344,23 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
return displayIds;
}
+ public int[] getDisplayIdsForGroupLocked(int groupId) {
+ DisplayGroup displayGroup = mDisplayGroups.get(groupId);
+ if (displayGroup == null) {
+ return new int[]{};
+ }
+ return displayGroup.getIdsLocked();
+ }
+
+ public SparseArray<int[]> getDisplayIdsByGroupIdLocked() {
+ SparseArray<int[]> displayIdsByGroupIds = new SparseArray<>();
+ for (int i = 0; i < mDisplayGroups.size(); i++) {
+ int groupId = mDisplayGroups.get(i).getGroupId();
+ displayIdsByGroupIds.put(groupId, getDisplayIdsForGroupLocked(groupId));
+ }
+ return displayIdsByGroupIds;
+ }
+
public void forEachLocked(Consumer<LogicalDisplay> consumer) {
forEachLocked(consumer, /* includeDisabled= */ true);
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 0cdf537b3455..4fae798f0cef 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -164,6 +164,7 @@ public class Notifier {
}
private final SparseArray<Interactivity> mInteractivityByGroupId = new SparseArray<>();
+ private SparseBooleanArray mDisplayInteractivities = new SparseBooleanArray();
// The current global interactive state. This is set as soon as an interactive state
// transition begins so as to capture the reason that it happened. At some point
@@ -690,6 +691,42 @@ public class Notifier {
}
/**
+ * Update the interactivities of the displays in given DisplayGroup.
+ *
+ * @param groupId The group id of the DisplayGroup to update display interactivities for.
+ */
+ private void updateDisplayInteractivities(int groupId, boolean interactive) {
+ final int[] displayIds = mDisplayManagerInternal.getDisplayIdsForGroup(groupId);
+ for (int displayId : displayIds) {
+ mDisplayInteractivities.put(displayId, interactive);
+ }
+
+ }
+
+ private void resetDisplayInteractivities() {
+ final SparseArray<int[]> displaysByGroupId =
+ mDisplayManagerInternal.getDisplayIdsByGroupsIds();
+ SparseBooleanArray newDisplayInteractivities = new SparseBooleanArray();
+ for (int i = 0; i < displaysByGroupId.size(); i++) {
+ final int groupId = displaysByGroupId.keyAt(i);
+ for (int displayId : displaysByGroupId.get(i)) {
+ // If we already know display interactivity, use that
+ if (mDisplayInteractivities.indexOfKey(displayId) > 0) {
+ newDisplayInteractivities.put(
+ displayId, mDisplayInteractivities.get(displayId));
+ } else { // If display is new to Notifier, use the power group's interactive value
+ final Interactivity groupInteractivity = mInteractivityByGroupId.get(groupId);
+ // If group Interactivity hasn't been initialized, assume group is interactive
+ final boolean groupInteractive =
+ groupInteractivity == null || groupInteractivity.isInteractive;
+ newDisplayInteractivities.put(displayId, groupInteractive);
+ }
+ }
+ }
+ mDisplayInteractivities = newDisplayInteractivities;
+ }
+
+ /**
* Called when an individual PowerGroup changes wakefulness.
*/
public void onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason,
@@ -717,6 +754,12 @@ public class Notifier {
handleEarlyInteractiveChange(groupId);
mWakefulnessSessionObserver.onWakefulnessChangeStarted(groupId, wakefulness,
changeReason, eventTime);
+
+ // Update input on which displays are interactive
+ if (mFlags.isPerDisplayWakeByTouchEnabled()) {
+ updateDisplayInteractivities(groupId, isInteractive);
+ mInputManagerInternal.setDisplayInteractivities(mDisplayInteractivities);
+ }
}
}
@@ -731,6 +774,16 @@ public class Notifier {
}
/**
+ * Called when a PowerGroup has been changed.
+ */
+ public void onGroupChanged() {
+ if (mFlags.isPerDisplayWakeByTouchEnabled()) {
+ resetDisplayInteractivities();
+ mInputManagerInternal.setDisplayInteractivities(mDisplayInteractivities);
+ }
+ }
+
+ /**
* Called when there has been user activity.
*/
public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event,
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index e0539647d061..21ab7812e604 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -125,7 +125,6 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.LatencyTracker;
import com.android.internal.util.Preconditions;
-import com.android.server.crashrecovery.CrashRecoveryHelper;
import com.android.server.EventLogTags;
import com.android.server.LockGuard;
import com.android.server.ServiceThread;
@@ -133,6 +132,7 @@ import com.android.server.SystemService;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
+import com.android.server.crashrecovery.CrashRecoveryHelper;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
@@ -2445,6 +2445,8 @@ public final class PowerManagerService extends SystemService
mClock.uptimeMillis());
} else if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) {
mNotifier.onGroupRemoved(groupId);
+ } else if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_CHANGED) {
+ mNotifier.onGroupChanged();
}
if (oldWakefulness != newWakefulness) {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 255dcb083518..342c87a6b5f6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -37,6 +37,7 @@ import static com.android.server.display.config.DisplayDeviceConfigTestUtilsKt.c
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -1524,6 +1525,47 @@ public class DisplayManagerServiceTest {
}
@Test
+ public void testGetDisplayIdsForGroup() throws Exception {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+ DisplayManagerInternal localService = displayManager.new LocalService();
+ LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
+ // Create display 1
+ FakeDisplayDevice displayDevice1 =
+ createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+ LogicalDisplay display1 = logicalDisplayMapper.getDisplayLocked(displayDevice1);
+ final int groupId1 = display1.getDisplayInfoLocked().displayGroupId;
+ // Create display 2
+ FakeDisplayDevice displayDevice2 =
+ createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+ LogicalDisplay display2 = logicalDisplayMapper.getDisplayLocked(displayDevice2);
+ final int groupId2 = display2.getDisplayInfoLocked().displayGroupId;
+ // Both displays should be in the same display group
+ assertEquals(groupId1, groupId2);
+ final int[] expectedDisplayIds = new int[]{
+ display1.getDisplayIdLocked(), display2.getDisplayIdLocked()};
+
+ final int[] displayIds = localService.getDisplayIdsForGroup(groupId1);
+
+ assertArrayEquals(expectedDisplayIds, displayIds);
+ }
+
+ @Test
+ public void testGetDisplayIdsForUnknownGroup() throws Exception {
+ final int unknownDisplayGroupId = 999;
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+ DisplayManagerInternal localService = displayManager.new LocalService();
+ LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
+ // Verify that display manager does not have display group
+ assertNull(logicalDisplayMapper.getDisplayGroupLocked(unknownDisplayGroupId));
+
+ final int[] displayIds = localService.getDisplayIdsForGroup(unknownDisplayGroupId);
+
+ assertEquals(0, displayIds.length);
+ }
+
+ @Test
public void testCreateVirtualDisplay_isValidProjection_notValid()
throws RemoteException {
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
diff --git a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
index 07029268661e..a1db18232c09 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
@@ -268,7 +268,7 @@ public class NotifierTest {
}
@Test
- public void testOnGlobalWakefulnessChangeStarted() throws Exception {
+ public void testOnGlobalWakefulnessChangeStarted() {
createNotifier();
// GIVEN system is currently non-interactive
when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
@@ -294,6 +294,96 @@ public class NotifierTest {
}
@Test
+ public void testOnGroupWakefulnessChangeStarted_newPowerGroup_perDisplayWakeDisabled() {
+ createNotifier();
+ // GIVEN power group is not yet known to Notifier and per-display wake by touch is disabled
+ final int groupId = 123;
+ final int changeReason = PowerManager.WAKE_REASON_TAP;
+ when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
+
+ // WHEN a power group wakefulness change starts
+ mNotifier.onGroupWakefulnessChangeStarted(
+ groupId, WAKEFULNESS_AWAKE, changeReason, /* eventTime= */ 999);
+ mTestLooper.dispatchAll();
+
+ // THEN window manager policy is informed that device has started waking up
+ verify(mPolicy).startedWakingUp(groupId, changeReason);
+ verify(mDisplayManagerInternal, never()).getDisplayIds();
+ verify(mInputManagerInternal, never()).setDisplayInteractivities(any());
+ }
+
+ @Test
+ public void testOnGroupWakefulnessChangeStarted_interactivityNoChange_perDisplayWakeDisabled() {
+ createNotifier();
+ // GIVEN power group is not interactive and per-display wake by touch is disabled
+ final int groupId = 234;
+ final int changeReason = PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
+ when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
+ mNotifier.onGroupWakefulnessChangeStarted(
+ groupId, WAKEFULNESS_ASLEEP, changeReason, /* eventTime= */ 999);
+ mTestLooper.dispatchAll();
+ verify(mPolicy, times(1)).startedGoingToSleep(groupId, changeReason);
+
+ // WHEN a power wakefulness change to not interactive starts
+ mNotifier.onGroupWakefulnessChangeStarted(
+ groupId, WAKEFULNESS_ASLEEP, changeReason, /* eventTime= */ 999);
+ mTestLooper.dispatchAll();
+
+ // THEN policy is only informed once of non-interactive wakefulness change
+ verify(mPolicy, times(1)).startedGoingToSleep(groupId, changeReason);
+ verify(mDisplayManagerInternal, never()).getDisplayIds();
+ verify(mInputManagerInternal, never()).setDisplayInteractivities(any());
+ }
+
+ @Test
+ public void testOnGroupWakefulnessChangeStarted_interactivityChange_perDisplayWakeDisabled() {
+ createNotifier();
+ // GIVEN power group is not interactive and per-display wake by touch is disabled
+ final int groupId = 345;
+ final int firstChangeReason = PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
+ when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
+ mNotifier.onGroupWakefulnessChangeStarted(
+ groupId, WAKEFULNESS_ASLEEP, firstChangeReason, /* eventTime= */ 999);
+ mTestLooper.dispatchAll();
+
+ // WHEN a power wakefulness change to interactive starts
+ final int secondChangeReason = PowerManager.WAKE_REASON_TAP;
+ mNotifier.onGroupWakefulnessChangeStarted(
+ groupId, WAKEFULNESS_AWAKE, secondChangeReason, /* eventTime= */ 999);
+ mTestLooper.dispatchAll();
+
+ // THEN policy is informed of the change
+ verify(mPolicy).startedWakingUp(groupId, secondChangeReason);
+ verify(mDisplayManagerInternal, never()).getDisplayIds();
+ verify(mInputManagerInternal, never()).setDisplayInteractivities(any());
+ }
+
+ @Test
+ public void testOnGroupWakefulnessChangeStarted_perDisplayWakeByTouchEnabled() {
+ createNotifier();
+ // GIVEN per-display wake by touch flag is enabled
+ when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(true);
+ final int groupId = 456;
+ final int displayId1 = 1001;
+ final int displayId2 = 1002;
+ final int[] displays = new int[]{displayId1, displayId2};
+ when(mDisplayManagerInternal.getDisplayIds()).thenReturn(IntArray.wrap(displays));
+ when(mDisplayManagerInternal.getDisplayIdsForGroup(groupId)).thenReturn(displays);
+ final int changeReason = PowerManager.WAKE_REASON_TAP;
+
+ // WHEN power group wakefulness change started
+ mNotifier.onGroupWakefulnessChangeStarted(
+ groupId, WAKEFULNESS_AWAKE, changeReason, /* eventTime= */ 999);
+ mTestLooper.dispatchAll();
+
+ // THEN native input manager is updated that the displays are interactive
+ final SparseBooleanArray expectedDisplayInteractivities = new SparseBooleanArray();
+ expectedDisplayInteractivities.put(displayId1, true);
+ expectedDisplayInteractivities.put(displayId2, true);
+ verify(mInputManagerInternal).setDisplayInteractivities(expectedDisplayInteractivities);
+ }
+
+ @Test
public void testOnWakeLockListener_RemoteException_NoRethrow() throws RemoteException {
when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(true);
createNotifier();