Merge "Send events when DisplayGroups are added/modified/removed" into sc-dev

This commit is contained in:
Sean Stout
2021-02-03 00:05:55 +00:00
committed by Android (Google) Code Review
6 changed files with 204 additions and 30 deletions

View File

@@ -47,20 +47,22 @@ public abstract class DisplayManagerInternal {
* begins adjusting the power state to match what was requested.
* </p>
*
* @param groupId The identifier for the display group being requested to change power state
* @param request The requested power state.
* @param waitForNegativeProximity If true, issues a request to wait for
* @param waitForNegativeProximity If {@code true}, issues a request to wait for
* negative proximity before turning the screen back on, assuming the screen
* was turned off by the proximity sensor.
* @return True if display is ready, false if there are important changes that must
* be made asynchronously (such as turning the screen on), in which case the caller
* should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
* then try the request again later until the state converges.
* @return {@code true} if display group is ready, {@code false} if there are important
* changes that must be made asynchronously (such as turning the screen on), in which case
* the caller should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged}
* then try the request again later until the state converges. If the provided {@code groupId}
* cannot be found then {@code true} will be returned.
*/
public abstract boolean requestPowerState(DisplayPowerRequest request,
public abstract boolean requestPowerState(int groupId, DisplayPowerRequest request,
boolean waitForNegativeProximity);
/**
* Returns true if the proximity sensor screen-off function is available.
* Returns {@code true} if the proximity sensor screen-off function is available.
*/
public abstract boolean isProximitySensorAvailable();
@@ -70,6 +72,22 @@ public abstract class DisplayManagerInternal {
*/
public abstract int getDisplayGroupId(int displayId);
/**
* Registers a display group listener which will be informed of the addition, removal, or change
* of display groups.
*
* @param listener The listener to register.
*/
public abstract void registerDisplayGroupListener(DisplayGroupListener listener);
/**
* Unregisters a display group listener which will be informed of the addition, removal, or
* change of display groups.
*
* @param listener The listener to unregister.
*/
public abstract void unregisterDisplayGroupListener(DisplayGroupListener listener);
/**
* Screenshot for internal system-only use such as rotation, etc. This method includes
* secure layers and the result should never be exposed to non-system applications.

View File

@@ -21,7 +21,8 @@ import java.util.List;
/**
* Represents a collection of {@link LogicalDisplay}s which act in unison for certain behaviors and
* operations.
* operations; particularly display-state.
*
* @hide
*/
public class DisplayGroup {
@@ -33,17 +34,44 @@ public class DisplayGroup {
mGroupId = groupId;
}
/** Returns the identifier for the Group. */
int getGroupId() {
return mGroupId;
}
void addDisplay(LogicalDisplay display) {
/**
* Adds the provided {@code display} to the Group
*
* @param display the {@link LogicalDisplay} to add to the Group
*/
void addDisplayLocked(LogicalDisplay display) {
if (!mDisplays.contains(display)) {
mDisplays.add(display);
}
}
boolean removeDisplay(LogicalDisplay display) {
/**
* Removes the provided {@code display} from the Group.
*
* @param display The {@link LogicalDisplay} to remove from the Group.
* @return {@code true} if the {@code display} was removed; otherwise {@code false}
*/
boolean removeDisplayLocked(LogicalDisplay display) {
return mDisplays.remove(display);
}
/** Returns {@code true} if there are no {@link LogicalDisplay LogicalDisplays} in the Group. */
boolean isEmptyLocked() {
return mDisplays.isEmpty();
}
/** Returns the number of {@link LogicalDisplay LogicalDisplays} in the Group. */
int getSizeLocked() {
return mDisplays.size();
}
/** Returns the ID of the {@link LogicalDisplay} at the provided {@code index}. */
int getIdLocked(int index) {
return mDisplays.get(index).getDisplayIdLocked();
}
}

View File

@@ -57,6 +57,7 @@ import android.hardware.display.Curve;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
@@ -190,6 +191,7 @@ public final class DisplayManagerService extends SystemService {
private static final int MSG_UPDATE_VIEWPORT = 5;
private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 6;
private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;
private final Context mContext;
private final DisplayManagerHandler mHandler;
@@ -237,6 +239,10 @@ public final class DisplayManagerService extends SystemService {
private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
new CopyOnWriteArrayList<DisplayTransactionListener>();
/** List of all display group listeners. */
private final CopyOnWriteArrayList<DisplayGroupListener> mDisplayGroupListeners =
new CopyOnWriteArrayList<>();
/** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
new SparseArray<>();
@@ -1677,6 +1683,11 @@ public final class DisplayManagerService extends SystemService {
mHandler.sendMessage(msg);
}
private void sendDisplayGroupEvent(int groupId, int event) {
Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_GROUP_EVENT, groupId, event);
mHandler.sendMessage(msg);
}
private void sendDisplayEventFrameRateOverrideLocked(int displayId) {
Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
@@ -1721,6 +1732,35 @@ public final class DisplayManagerService extends SystemService {
mTempCallbacks.clear();
}
// Runs on Handler thread.
// Delivers display group event notifications to callbacks.
private void deliverDisplayGroupEvent(int groupId, int event) {
if (DEBUG) {
Slog.d(TAG, "Delivering display group event: groupId=" + groupId + ", event="
+ event);
}
switch (event) {
case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED:
for (DisplayGroupListener listener : mDisplayGroupListeners) {
listener.onDisplayGroupAdded(groupId);
}
break;
case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED:
for (DisplayGroupListener listener : mDisplayGroupListeners) {
listener.onDisplayGroupChanged(groupId);
}
break;
case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED:
for (DisplayGroupListener listener : mDisplayGroupListeners) {
listener.onDisplayGroupRemoved(groupId);
}
break;
}
}
private IMediaProjectionManager getProjectionService() {
if (mProjectionService == null) {
IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
@@ -1943,6 +1983,11 @@ public final class DisplayManagerService extends SystemService {
}
deliverDisplayEvent(msg.arg1, uids, msg.arg2);
break;
case MSG_DELIVER_DISPLAY_GROUP_EVENT:
deliverDisplayGroupEvent(msg.arg1, msg.arg2);
break;
}
}
}
@@ -1973,6 +2018,11 @@ public final class DisplayManagerService extends SystemService {
}
}
@Override
public void onDisplayGroupEventLocked(int groupId, int event) {
sendDisplayGroupEvent(groupId, event);
}
@Override
public void onTraversalRequested() {
synchronized (mSyncRoot) {
@@ -2708,11 +2758,25 @@ public final class DisplayManagerService extends SystemService {
}
@Override
public boolean requestPowerState(DisplayPowerRequest request,
public boolean requestPowerState(int groupId, DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mSyncRoot) {
return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
.requestPowerState(request, waitForNegativeProximity);
final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked(
groupId);
if (displayGroup == null) {
return true;
}
final int size = displayGroup.getSizeLocked();
boolean ready = true;
for (int i = 0; i < size; i++) {
final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(displayGroup.getIdLocked(i));
ready &= displayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
return ready;
}
}
@@ -2731,6 +2795,16 @@ public final class DisplayManagerService extends SystemService {
}
}
@Override
public void registerDisplayGroupListener(DisplayGroupListener listener) {
mDisplayGroupListeners.add(listener);
}
@Override
public void unregisterDisplayGroupListener(DisplayGroupListener listener) {
mDisplayGroupListeners.remove(listener);
}
@Override
public SurfaceControl.ScreenshotHardwareBuffer systemScreenshot(int displayId) {
return systemScreenshotInternal(displayId);

View File

@@ -55,6 +55,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
public static final int LOGICAL_DISPLAY_EVENT_SWAPPED = 4;
public static final int LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED = 5;
public static final int DISPLAY_GROUP_EVENT_ADDED = 1;
public static final int DISPLAY_GROUP_EVENT_CHANGED = 2;
public static final int DISPLAY_GROUP_EVENT_REMOVED = 3;
/**
* Temporary display info, used for comparing display configurations.
*/
@@ -99,7 +103,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private int mNextNonDefaultGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
/** A mapping from logical display id to display group. */
private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>();
private final SparseArray<DisplayGroup> mDisplayIdToGroupMap = new SparseArray<>();
private final DisplayDeviceRepository mDisplayDeviceRepo;
private final Listener mListener;
@@ -183,7 +187,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
public int getDisplayGroupIdLocked(int displayId) {
final DisplayGroup displayGroup = mDisplayGroups.get(displayId);
final DisplayGroup displayGroup = mDisplayIdToGroupMap.get(displayId);
if (displayGroup != null) {
return displayGroup.getGroupId();
}
@@ -191,6 +195,18 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
return -1;
}
public DisplayGroup getDisplayGroupLocked(int groupId) {
final int size = mDisplayIdToGroupMap.size();
for (int i = 0; i < size; i++) {
final DisplayGroup displayGroup = mDisplayIdToGroupMap.valueAt(i);
if (displayGroup.getGroupId() == groupId) {
return displayGroup;
}
}
return null;
}
public void dumpLocked(PrintWriter pw) {
pw.println("LogicalDisplayMapper:");
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
@@ -320,7 +336,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
final int groupId = assignDisplayGroupIdLocked(isDefault);
displayGroup = new DisplayGroup(groupId);
} else {
displayGroup = mDisplayGroups.get(Display.DEFAULT_DISPLAY);
displayGroup = mDisplayIdToGroupMap.get(Display.DEFAULT_DISPLAY);
}
LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
@@ -335,11 +351,23 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
mLogicalDisplays.put(displayId, display);
displayGroup.addDisplay(display);
mDisplayGroups.append(displayId, displayGroup);
displayGroup.addDisplayLocked(display);
mDisplayIdToGroupMap.append(displayId, displayGroup);
if (addNewDisplayGroup) {
// Group added events happen before Logical Display added events.
mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(),
LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED);
}
mListener.onLogicalDisplayEventLocked(display,
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED);
if (!addNewDisplayGroup) {
// Group changed events happen after Logical Display added events.
mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(),
LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED);
}
}
/**
@@ -356,33 +384,47 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
DisplayEventReceiver.FrameRateOverride[] frameRatesOverrides =
display.getFrameRateOverrides();
display.updateLocked(mDisplayDeviceRepo);
final DisplayGroup changedDisplayGroup;
if (!display.isValidLocked()) {
mLogicalDisplays.removeAt(i);
mDisplayGroups.removeReturnOld(displayId).removeDisplay(display);
final DisplayGroup displayGroup = mDisplayIdToGroupMap.removeReturnOld(displayId);
displayGroup.removeDisplayLocked(display);
mListener.onLogicalDisplayEventLocked(display,
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED);
changedDisplayGroup = displayGroup;
} else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
final int flags = display.getDisplayInfoLocked().flags;
final DisplayGroup defaultDisplayGroup = mDisplayGroups.get(
final DisplayGroup defaultDisplayGroup = mDisplayIdToGroupMap.get(
Display.DEFAULT_DISPLAY);
if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) {
// The display should have its own DisplayGroup.
if (defaultDisplayGroup.removeDisplay(display)) {
if (defaultDisplayGroup.removeDisplayLocked(display)) {
final int groupId = assignDisplayGroupIdLocked(false);
final DisplayGroup displayGroup = new DisplayGroup(groupId);
displayGroup.addDisplay(display);
mDisplayGroups.append(display.getDisplayIdLocked(), displayGroup);
displayGroup.addDisplayLocked(display);
display.updateDisplayGroupIdLocked(groupId);
mDisplayIdToGroupMap.append(display.getDisplayIdLocked(), displayGroup);
mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(),
LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED);
changedDisplayGroup = defaultDisplayGroup;
} else {
changedDisplayGroup = null;
}
} else {
// The display should be a part of the default DisplayGroup.
final DisplayGroup displayGroup = mDisplayGroups.get(displayId);
final DisplayGroup displayGroup = mDisplayIdToGroupMap.get(displayId);
if (displayGroup != defaultDisplayGroup) {
displayGroup.removeDisplay(display);
defaultDisplayGroup.addDisplay(display);
mDisplayGroups.put(displayId, defaultDisplayGroup);
displayGroup.removeDisplayLocked(display);
defaultDisplayGroup.addDisplayLocked(display);
display.updateDisplayGroupIdLocked(defaultDisplayGroup.getGroupId());
mListener.onDisplayGroupEventLocked(defaultDisplayGroup.getGroupId(),
LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED);
mDisplayIdToGroupMap.put(displayId, defaultDisplayGroup);
changedDisplayGroup = displayGroup;
} else {
changedDisplayGroup = null;
}
}
@@ -394,6 +436,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
} else if (!display.getPendingFrameRateOverrideUids().isEmpty()) {
mListener.onLogicalDisplayEventLocked(display,
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);
changedDisplayGroup = null;
} else {
// While applications shouldn't know nor care about the non-overridden info, we
// still need to let WindowManager know so it can update its own internal state for
@@ -403,6 +446,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
mListener.onLogicalDisplayEventLocked(display,
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED);
}
changedDisplayGroup = null;
}
// CHANGED and REMOVED DisplayGroup events should always fire after Display events.
if (changedDisplayGroup != null) {
final int event = changedDisplayGroup.isEmptyLocked()
? LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED
: LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED;
mListener.onDisplayGroupEventLocked(changedDisplayGroup.getGroupId(), event);
}
}
}
@@ -438,6 +490,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
public interface Listener {
void onLogicalDisplayEventLocked(LogicalDisplay display, int event);
void onDisplayGroupEventLocked(int groupId, int event);
void onTraversalRequested();
}
}

View File

@@ -2892,8 +2892,8 @@ public final class PowerManagerService extends SystemService
PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
mDisplayReady = mDisplayManagerInternal.requestPowerState(displayPowerRequest,
mRequestWaitForNegativeProximity);
mDisplayReady = mDisplayManagerInternal.requestPowerState(Display.DEFAULT_DISPLAY_GROUP,
displayPowerRequest, mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if (DEBUG_SPEW) {

View File

@@ -179,7 +179,8 @@ public class PowerManagerServiceTest {
.thenReturn(mPowerSaveState);
when(mBatteryManagerInternalMock.isPowered(anyInt())).thenReturn(false);
when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(false);
when(mDisplayManagerInternalMock.requestPowerState(any(), anyBoolean())).thenReturn(true);
when(mDisplayManagerInternalMock.requestPowerState(anyInt(), any(), anyBoolean()))
.thenReturn(true);
when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), anyString())).thenReturn("");
when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(true);