Skip to content
This repository has been archived by the owner on Nov 8, 2023. It is now read-only.

Commit

Permalink
Add eventMask to DM.registerDisplayListener
Browse files Browse the repository at this point in the history
Add a new parameter to DisplayManager.registDisplayListener
which clients can use to specify in which events
they are interested.

Test: atest DisplayManagerServiceTest
      atest DisplayManagerGlobalTest

Bug: 171240622
Change-Id: Icc71bdd9ddb390bc5406b298a557c84194a53c00
  • Loading branch information
Marin Shalamanov committed Mar 19, 2021
1 parent d96c819 commit 204eba6
Show file tree
Hide file tree
Showing 6 changed files with 488 additions and 68 deletions.
64 changes: 62 additions & 2 deletions core/java/android/hardware/display/DisplayManager.java
Expand Up @@ -20,6 +20,7 @@

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
Expand Down Expand Up @@ -376,6 +377,43 @@ public final class DisplayManager {
@TestApi
public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2;

/**
* @hide
*/
@LongDef(flag = true, prefix = {"EVENT_FLAG_"}, value = {
EVENT_FLAG_DISPLAY_ADDED,
EVENT_FLAG_DISPLAY_CHANGED,
EVENT_FLAG_DISPLAY_REMOVED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventsMask {}

/**
* Event type for when a new display is added.
*
* @see #registerDisplayListener(DisplayListener, Handler, long)
*
* @hide
*/
public static final long EVENT_FLAG_DISPLAY_ADDED = 1L << 0;

/**
* Event type for when a display is removed.
*
* @see #registerDisplayListener(DisplayListener, Handler, long)
*
* @hide
*/
public static final long EVENT_FLAG_DISPLAY_REMOVED = 1L << 1;

/**
* Event type for when a display is changed.
*
* @see #registerDisplayListener(DisplayListener, Handler, long)
*
* @hide
*/
public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;

/** @hide */
public DisplayManager(Context context) {
Expand Down Expand Up @@ -486,7 +524,7 @@ private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) {
}

/**
* Registers an display listener to receive notifications about when
* Registers a display listener to receive notifications about when
* displays are added, removed or changed.
*
* @param listener The listener to register.
Expand All @@ -496,7 +534,29 @@ private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) {
* @see #unregisterDisplayListener
*/
public void registerDisplayListener(DisplayListener listener, Handler handler) {
mGlobal.registerDisplayListener(listener, handler);
registerDisplayListener(listener, handler, EVENT_FLAG_DISPLAY_ADDED
| EVENT_FLAG_DISPLAY_CHANGED | EVENT_FLAG_DISPLAY_REMOVED);
}

/**
* Registers a display listener to receive notifications about given display event types.
*
* @param listener The listener to register.
* @param handler The handler on which the listener should be invoked, or null
* if the listener should be invoked on the calling thread's looper.
* @param eventsMask A bitmask of the event types for which this listener is subscribed.
*
* @see #EVENT_FLAG_DISPLAY_ADDED
* @see #EVENT_FLAG_DISPLAY_CHANGED
* @see #EVENT_FLAG_DISPLAY_REMOVED
* @see #registerDisplayListener(DisplayListener, Handler)
* @see #unregisterDisplayListener
*
* @hide
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
@Nullable Handler handler, @EventsMask long eventsMask) {
mGlobal.registerDisplayListener(listener, handler, eventsMask);
}

/**
Expand Down
85 changes: 70 additions & 15 deletions core/java/android/hardware/display/DisplayManagerGlobal.java
Expand Up @@ -16,6 +16,9 @@

package android.hardware.display;

import static android.hardware.display.DisplayManager.EventsMask;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PropertyInvalidatedCache;
Expand All @@ -42,6 +45,10 @@
import android.view.DisplayInfo;
import android.view.Surface;

import com.android.internal.annotations.VisibleForTesting;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -66,6 +73,14 @@ public final class DisplayManagerGlobal {
// orientation change before the display info cache has actually been invalidated.
private static final boolean USE_CACHE = false;

@IntDef(prefix = {"SWITCHING_TYPE_"}, value = {
EVENT_DISPLAY_ADDED,
EVENT_DISPLAY_CHANGED,
EVENT_DISPLAY_REMOVED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayEvent {}

public static final int EVENT_DISPLAY_ADDED = 1;
public static final int EVENT_DISPLAY_CHANGED = 2;
public static final int EVENT_DISPLAY_REMOVED = 3;
Expand All @@ -81,16 +96,17 @@ public final class DisplayManagerGlobal {
private final IDisplayManager mDm;

private DisplayManagerCallback mCallback;
private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
new ArrayList<DisplayListenerDelegate>();
private @EventsMask long mRegisteredEventsMask = 0;
private final ArrayList<DisplayListenerDelegate> mDisplayListeners = new ArrayList<>();

private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<>();
private final ColorSpace mWideColorSpace;
private int[] mDisplayIdCache;

private int mWifiDisplayScanNestCount;

private DisplayManagerGlobal(IDisplayManager dm) {
@VisibleForTesting
public DisplayManagerGlobal(IDisplayManager dm) {
mDm = dm;
try {
mWideColorSpace =
Expand Down Expand Up @@ -274,18 +290,25 @@ public Display getRealDisplay(int displayId) {
* If that is still null, a runtime exception will be thrown.
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
@Nullable Handler handler) {
@Nullable Handler handler, @EventsMask long eventsMask) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}

if (eventsMask == 0) {
throw new IllegalArgumentException("The set of events to listen to must not be empty.");
}

synchronized (mLock) {
int index = findDisplayListenerLocked(listener);
if (index < 0) {
Looper looper = getLooperForHandler(handler);
mDisplayListeners.add(new DisplayListenerDelegate(listener, looper));
mDisplayListeners.add(new DisplayListenerDelegate(listener, looper, eventsMask));
registerCallbackIfNeededLocked();
} else {
mDisplayListeners.get(index).setEventsMask(eventsMask);
}
updateCallbackIfNeededLocked();
}
}

Expand All @@ -300,6 +323,7 @@ public void unregisterDisplayListener(DisplayListener listener) {
DisplayListenerDelegate d = mDisplayListeners.get(index);
d.clearEvents();
mDisplayListeners.remove(index);
updateCallbackIfNeededLocked();
}
}
}
Expand All @@ -325,18 +349,36 @@ private int findDisplayListenerLocked(DisplayListener listener) {
return -1;
}

@EventsMask
private int calculateEventsMaskLocked() {
int mask = 0;
final int numListeners = mDisplayListeners.size();
for (int i = 0; i < numListeners; i++) {
mask |= mDisplayListeners.get(i).mEventsMask;
}
return mask;
}

private void registerCallbackIfNeededLocked() {
if (mCallback == null) {
mCallback = new DisplayManagerCallback();
updateCallbackIfNeededLocked();
}
}

private void updateCallbackIfNeededLocked() {
int mask = calculateEventsMaskLocked();
if (mask != mRegisteredEventsMask) {
try {
mDm.registerCallback(mCallback);
mDm.registerCallbackWithEventMask(mCallback, mask);
mRegisteredEventsMask = mask;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}

private void handleDisplayEvent(int displayId, int event) {
private void handleDisplayEvent(int displayId, @DisplayEvent int event) {
synchronized (mLock) {
if (USE_CACHE) {
mDisplayInfoCache.remove(displayId);
Expand Down Expand Up @@ -754,7 +796,7 @@ public int getRefreshRateSwitchingType() {

private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
@Override
public void onDisplayEvent(int displayId, int event) {
public void onDisplayEvent(int displayId, @DisplayEvent int event) {
if (DEBUG) {
Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
}
Expand All @@ -764,13 +806,16 @@ public void onDisplayEvent(int displayId, int event) {

private static final class DisplayListenerDelegate extends Handler {
public final DisplayListener mListener;
public long mEventsMask;

DisplayListenerDelegate(DisplayListener listener, @NonNull Looper looper) {
DisplayListenerDelegate(DisplayListener listener, @NonNull Looper looper,
@EventsMask long eventsMask) {
super(looper, null, true /*async*/);
mListener = listener;
mEventsMask = eventsMask;
}

public void sendDisplayEvent(int displayId, int event) {
public void sendDisplayEvent(int displayId, @DisplayEvent int event) {
Message msg = obtainMessage(event, displayId, 0);
sendMessage(msg);
}
Expand All @@ -779,17 +824,27 @@ public void clearEvents() {
removeCallbacksAndMessages(null);
}

public synchronized void setEventsMask(@EventsMask long newEventsMask) {
mEventsMask = newEventsMask;
}

@Override
public void handleMessage(Message msg) {
public synchronized void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_DISPLAY_ADDED:
mListener.onDisplayAdded(msg.arg1);
if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0) {
mListener.onDisplayAdded(msg.arg1);
}
break;
case EVENT_DISPLAY_CHANGED:
mListener.onDisplayChanged(msg.arg1);
if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0) {
mListener.onDisplayChanged(msg.arg1);
}
break;
case EVENT_DISPLAY_REMOVED:
mListener.onDisplayRemoved(msg.arg1);
if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0) {
mListener.onDisplayRemoved(msg.arg1);
}
break;
}
}
Expand Down
1 change: 1 addition & 0 deletions core/java/android/hardware/display/IDisplayManager.aidl
Expand Up @@ -38,6 +38,7 @@ interface IDisplayManager {
boolean isUidPresentOnDisplay(int uid, int displayId);

void registerCallback(in IDisplayManagerCallback callback);
void registerCallbackWithEventMask(in IDisplayManagerCallback callback, long eventsMask);

// Requires CONFIGURE_WIFI_DISPLAY permission.
// The process must have previously registered a callback.
Expand Down

0 comments on commit 204eba6

Please sign in to comment.