Extract display properties tracker

`DisplayMonitor` listens for system display events. Move the
event-handling logic into a separate class (`DisplayPropertiesTracker`),
as it will become more complex in the following commit.
This commit is contained in:
Romain Vimont 2026-04-15 19:40:17 +02:00
parent 3e9e408017
commit 92ae7de289
2 changed files with 59 additions and 38 deletions

View file

@ -25,6 +25,8 @@ public class DisplayMonitor {
// So use the default method only before Android 14.
private static final boolean USE_DEFAULT_METHOD = Build.VERSION.SDK_INT < AndroidVersions.API_34_ANDROID_14;
private final DisplayPropertiesTracker tracker = new DisplayPropertiesTracker();
private DisplayManager.DisplayListenerHandle displayListenerHandle;
private HandlerThread handlerThread;
@ -32,8 +34,6 @@ public class DisplayMonitor {
private int displayId = Device.DISPLAY_ID_NONE;
private DisplayProperties props;
private Listener listener;
public void start(int displayId, Listener listener) {
@ -48,15 +48,16 @@ public class DisplayMonitor {
handlerThread = new HandlerThread("DisplayListener");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
displayListenerHandle = ServiceManager.getDisplayManager().registerDisplayListener(eventDisplayId -> {
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v("DisplayMonitor: onDisplayChanged(" + eventDisplayId + ")");
}
displayListenerHandle = ServiceManager.getDisplayManager().registerDisplayListener(
eventDisplayId -> {
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v("DisplayMonitor: onDisplayChanged(" + eventDisplayId + ")");
}
if (eventDisplayId == displayId) {
checkDisplayPropertiesChanged();
}
}, handler);
if (eventDisplayId == displayId) {
checkDisplayPropertiesChanged();
}
}, handler);
} else {
displayWindowListener = new DisplayWindowListener() {
@Override
@ -96,39 +97,16 @@ public class DisplayMonitor {
}
}
private synchronized DisplayProperties getAndSetDisplayProperties(DisplayProperties props) {
DisplayProperties oldProps = this.props;
this.props = props;
return oldProps;
}
public synchronized void setSessionDisplayProperties(DisplayProperties props) {
this.props = props;
public void setSessionDisplayProperties(DisplayProperties props) {
tracker.setCurrent(props);
}
private void checkDisplayPropertiesChanged() {
DisplayInfo di = ServiceManager.getDisplayManager().getDisplayInfo(displayId);
if (di == null) {
Ln.w("DisplayInfo for " + displayId + " cannot be retrieved");
// We can't compare with the current properties, so reset unconditionally
DisplayProperties oldProps = getAndSetDisplayProperties(null); // exchange with synchronization
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v("DisplayMonitor: requestReset(): " + oldProps + " -> (unknown)");
}
DisplayProperties props = di != null ? new DisplayProperties(di.getSize(), di.getRotation()) : null;
boolean trigger = tracker.onDisplayPropertiesChanged(props);
if (trigger) {
listener.onDisplayPropertiesChanged();
} else {
DisplayProperties newProps = new DisplayProperties(di.getSize(), di.getRotation());
DisplayProperties oldProps = getAndSetDisplayProperties(newProps); // exchange with synchronization
if (!newProps.equals(oldProps)) {
// Reset only if the properties are different
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v("DisplayMonitor: requestReset(): " + oldProps + " -> " + newProps);
}
listener.onDisplayPropertiesChanged();
} else if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v("DisplayMonitor: DisplayProperties not changed (" + newProps + "): do not requestReset()");
}
}
}
}

View file

@ -0,0 +1,43 @@
package com.genymobile.scrcpy.display;
import com.genymobile.scrcpy.util.Ln;
public final class DisplayPropertiesTracker {
private DisplayProperties props;
public synchronized void setCurrent(DisplayProperties props) {
this.props = props;
}
/**
* Set the current display properties, and indicate whether the capture must be reset.
*
* @param props the current display properties
* @return {@code true} if the capture must be reset
*/
public synchronized boolean onDisplayPropertiesChanged(DisplayProperties props) {
DisplayProperties prev = this.props;
this.props = props;
if (props == null) {
// The display properties have changed, but are unknown, a resize event must be triggered
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v(getClass().getSimpleName() + ": " + prev + " -> (unknown)");
}
return true;
}
if (props.equals(prev)) {
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v(getClass().getSimpleName() + ": " + props + "(unchanged)");
}
return false;
}
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
Ln.v(getClass().getSimpleName() + ": " + prev + " -> " + props);
}
return true;
}
}