Merge "Generalize physical display management"
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 5dcb392b..46917e4 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -252,10 +252,12 @@
status_t BootAnimation::readyToRun() {
mAssets.addDefaultAssets();
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
+ mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
+ if (mDisplayToken == nullptr)
+ return -1;
+
DisplayInfo dinfo;
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
+ status_t status = SurfaceComposerClient::getDisplayInfo(mDisplayToken, &dinfo);
if (status)
return -1;
@@ -1014,16 +1016,13 @@
// At the end of the animation, we switch to the viewport that DisplayManager will apply
// later. This changes the coordinate system, and means we must move the surface up by
// the inset amount.
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
-
Rect layerStackRect(0, 0, mWidth, mHeight - mTargetInset);
Rect displayRect(0, mTargetInset, mWidth, mHeight);
SurfaceComposerClient::Transaction t;
t.setPosition(mFlingerSurfaceControl, 0, -mTargetInset)
.setCrop(mFlingerSurfaceControl, Rect(0, mTargetInset, mWidth, mHeight));
- t.setDisplayProjection(dtoken, 0 /* orientation */, layerStackRect, displayRect);
+ t.setDisplayProjection(mDisplayToken, 0 /* orientation */, layerStackRect, displayRect);
t.apply();
mTargetInset = mCurrentInset = 0;
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 04d4f9a..19616cb 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -171,6 +171,7 @@
EGLDisplay mDisplay;
EGLDisplay mContext;
EGLDisplay mSurface;
+ sp<IBinder> mDisplayToken;
sp<SurfaceControl> mFlingerSurfaceControl;
sp<Surface> mFlingerSurface;
bool mClockEnabled;
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 3d74f8b..c497667 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -46,23 +46,22 @@
using namespace android;
-static uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain;
-
#define COLORSPACE_UNKNOWN 0
#define COLORSPACE_SRGB 1
#define COLORSPACE_DISPLAY_P3 2
-static void usage(const char* pname)
+static void usage(const char* pname, PhysicalDisplayId displayId)
{
fprintf(stderr,
"usage: %s [-hp] [-d display-id] [FILENAME]\n"
" -h: this message\n"
" -p: save the file as a png.\n"
- " -d: specify the display id to capture, default %d.\n"
+ " -d: specify the physical display ID to capture (default: %"
+ ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ")\n"
+ " see \"dumpsys SurfaceFlinger --display-id\" for valid display IDs.\n"
"If FILENAME ends with .png it will be saved as a png.\n"
"If FILENAME is not given, the results will be printed to stdout.\n",
- pname, DEFAULT_DISPLAY_ID
- );
+ pname, displayId);
}
static SkColorType flinger2skia(PixelFormat f)
@@ -127,9 +126,14 @@
int main(int argc, char** argv)
{
+ std::optional<PhysicalDisplayId> displayId = SurfaceComposerClient::getInternalDisplayId();
+ if (!displayId) {
+ fprintf(stderr, "Failed to get token for internal display\n");
+ return 1;
+ }
+
const char* pname = argv[0];
bool png = false;
- int32_t displayId = DEFAULT_DISPLAY_ID;
int c;
while ((c = getopt(argc, argv, "phd:")) != -1) {
switch (c) {
@@ -137,11 +141,11 @@
png = true;
break;
case 'd':
- displayId = atoi(optarg);
+ displayId = atoll(optarg);
break;
case '?':
case 'h':
- usage(pname);
+ usage(pname, *displayId);
return 1;
}
}
@@ -166,7 +170,7 @@
}
if (fd == -1) {
- usage(pname);
+ usage(pname, *displayId);
return 1;
}
@@ -192,9 +196,10 @@
ProcessState::self()->setThreadPoolMaxThreadCount(0);
ProcessState::self()->startThreadPool();
- sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
- if (display == NULL) {
- fprintf(stderr, "Unable to get handle for display %d\n", displayId);
+ const sp<IBinder> display = SurfaceComposerClient::getPhysicalDisplayToken(*displayId);
+ if (display == nullptr) {
+ fprintf(stderr, "Failed to get token for invalid display %"
+ ANDROID_PHYSICAL_DISPLAY_ID_FORMAT "\n", *displayId);
return 1;
}
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 6061b66..7edd128 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -33456,7 +33456,6 @@
HSPLandroid/view/SurfaceControl;->finalize()V
HSPLandroid/view/SurfaceControl;->getActiveColorMode(Landroid/os/IBinder;)I
HSPLandroid/view/SurfaceControl;->getActiveConfig(Landroid/os/IBinder;)I
-HSPLandroid/view/SurfaceControl;->getBuiltInDisplay(I)Landroid/os/IBinder;
HSPLandroid/view/SurfaceControl;->getDisplayColorModes(Landroid/os/IBinder;)[I
HSPLandroid/view/SurfaceControl;->getDisplayConfigs(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;
HSPLandroid/view/SurfaceControl;->getHandle()Landroid/os/IBinder;
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index ccd0fc1..03e8a0f 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -22,7 +22,6 @@
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.graphics.FrameInfo;
-import android.graphics.Insets;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
import android.os.Handler;
@@ -914,25 +913,11 @@
super(looper, vsyncSource);
}
+ // TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
+ // the internal display and DisplayEventReceiver#scheduleVsync only allows requesting VSYNC
+ // for the internal display implicitly.
@Override
- public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
- // Ignore vsync from secondary display.
- // This can be problematic because the call to scheduleVsync() is a one-shot.
- // We need to ensure that we will still receive the vsync from the primary
- // display which is the one we really care about. Ideally we should schedule
- // vsync for a particular display.
- // At this time Surface Flinger won't send us vsyncs for secondary displays
- // but that could change in the future so let's log a message to help us remember
- // that we need to fix this.
- if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
- Log.d(TAG, "Received vsync from secondary display, but we don't support "
- + "this case yet. Choreographer needs a way to explicitly request "
- + "vsync for a specific display to ensure it doesn't lose track "
- + "of its scheduled vsync.");
- scheduleVsync();
- return;
- }
-
+ public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
// Post the vsync event to the Handler.
// The idea is to prevent incoming vsync events from completely starving
// the message queue. If there are no messages in the queue with timestamps
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index edd3f1a..3e8002f 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -136,12 +136,11 @@
*
* @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
* timebase.
- * @param builtInDisplayId The surface flinger built-in display id such as
- * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}.
+ * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
* @param frame The frame number. Increases by one for each vertical sync interval.
*/
@UnsupportedAppUsage
- public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
+ public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
}
/**
@@ -149,12 +148,11 @@
*
* @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
* timebase.
- * @param builtInDisplayId The surface flinger built-in display id such as
- * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}.
+ * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
* @param connected True if the display is connected, false if it disconnected.
*/
@UnsupportedAppUsage
- public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
+ public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
}
/**
@@ -174,14 +172,14 @@
// Called from native code.
@SuppressWarnings("unused")
@UnsupportedAppUsage
- private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
- onVsync(timestampNanos, builtInDisplayId, frame);
+ private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
+ onVsync(timestampNanos, physicalDisplayId, frame);
}
// Called from native code.
@SuppressWarnings("unused")
@UnsupportedAppUsage
- private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
- onHotplug(timestampNanos, builtInDisplayId, connected);
+ private void dispatchHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
+ onHotplug(timestampNanos, physicalDisplayId, connected);
}
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 4d36be38..c0a4028 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -132,7 +132,8 @@
private static native boolean nativeClearAnimationFrameStats();
private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
- private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
+ private static native long[] nativeGetPhysicalDisplayIds();
+ private static native IBinder nativeGetPhysicalDisplayToken(long physicalDisplayId);
private static native IBinder nativeCreateDisplay(String name, boolean secure);
private static native void nativeDestroyDisplay(IBinder displayToken);
private static native void nativeSetDisplaySurface(long transactionObj,
@@ -330,24 +331,6 @@
*/
private static final int SURFACE_OPAQUE = 0x02;
-
- /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
- * these are different from the logical display ids used elsewhere in the framework */
-
- /**
- * Built-in physical display id: Main display.
- * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.
- * @hide
- */
- public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
-
- /**
- * Built-in physical display id: Attached HDMI display.
- * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.
- * @hide
- */
- public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
-
// Display power modes.
/**
* Display power mode off: used while blanking the screen.
@@ -1730,9 +1713,28 @@
/**
* @hide
*/
- @UnsupportedAppUsage
- public static IBinder getBuiltInDisplay(int builtInDisplayId) {
- return nativeGetBuiltInDisplay(builtInDisplayId);
+ public static long[] getPhysicalDisplayIds() {
+ return nativeGetPhysicalDisplayIds();
+ }
+
+ /**
+ * @hide
+ */
+ public static IBinder getPhysicalDisplayToken(long physicalDisplayId) {
+ return nativeGetPhysicalDisplayToken(physicalDisplayId);
+ }
+
+ /**
+ * TODO(116025192): Remove this stopgap once framework is display-agnostic.
+ *
+ * @hide
+ */
+ public static IBinder getInternalDisplayToken() {
+ final long[] physicalDisplayIds = getPhysicalDisplayIds();
+ if (physicalDisplayIds.length == 0) {
+ return null;
+ }
+ return getPhysicalDisplayToken(physicalDisplayIds[0]);
}
/**
@@ -1791,8 +1793,12 @@
public static Bitmap screenshot(Rect sourceCrop, int width, int height,
boolean useIdentityTransform, int rotation) {
// TODO: should take the display as a parameter
- IBinder displayToken = SurfaceControl.getBuiltInDisplay(
- SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ if (displayToken == null) {
+ Log.w(TAG, "Failed to take screenshot because internal display is disconnected");
+ return null;
+ }
+
if (rotation == ROTATION_90 || rotation == ROTATION_270) {
rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
}
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index c1b5aae..191472d 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -59,8 +59,8 @@
sp<MessageQueue> mMessageQueue;
DisplayEventReceiver mReceiver;
- virtual void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
- virtual void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
+ void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override;
+ void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
};
@@ -84,28 +84,30 @@
DisplayEventDispatcher::dispose();
}
-void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
+void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
+ uint32_t count) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
ALOGV("receiver %p ~ Invoking vsync handler.", this);
env->CallVoidMethod(receiverObj.get(),
- gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
+ gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, displayId, count);
ALOGV("receiver %p ~ Returned from vsync handler.", this);
}
mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}
-void NativeDisplayEventReceiver::dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected) {
+void NativeDisplayEventReceiver::dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
+ bool connected) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
ALOGV("receiver %p ~ Invoking hotplug handler.", this);
env->CallVoidMethod(receiverObj.get(),
- gDisplayEventReceiverClassInfo.dispatchHotplug, timestamp, id, connected);
+ gDisplayEventReceiverClassInfo.dispatchHotplug, timestamp, displayId, connected);
ALOGV("receiver %p ~ Returned from hotplug handler.", this);
}
@@ -175,9 +177,9 @@
gDisplayEventReceiverClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
gDisplayEventReceiverClassInfo.dispatchVsync = GetMethodIDOrDie(env,
- gDisplayEventReceiverClassInfo.clazz, "dispatchVsync", "(JII)V");
+ gDisplayEventReceiverClassInfo.clazz, "dispatchVsync", "(JJI)V");
gDisplayEventReceiverClassInfo.dispatchHotplug = GetMethodIDOrDie(env,
- gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug", "(JIZ)V");
+ gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug", "(JJZ)V");
return res;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index fad2fe0..68be005 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -483,8 +483,29 @@
transaction->setLayerStack(ctrl, layerStack);
}
-static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
- sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
+static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) {
+ const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
+ jlongArray array = env->NewLongArray(displayIds.size());
+ if (array == nullptr) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+ return nullptr;
+ }
+
+ if (displayIds.empty()) {
+ return array;
+ }
+
+ jlong* values = env->GetLongArrayElements(array, 0);
+ for (size_t i = 0; i < displayIds.size(); ++i) {
+ values[i] = static_cast<jlong>(displayIds[i]);
+ }
+
+ env->ReleaseLongArrayElements(array, values, 0);
+ return array;
+}
+
+static jobject nativeGetPhysicalDisplayToken(JNIEnv* env, jclass clazz, jlong physicalDisplayId) {
+ sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(physicalDisplayId);
return javaObjectForIBinder(env, token);
}
@@ -1145,8 +1166,10 @@
(void*)nativeSetCornerRadius },
{"nativeSetLayerStack", "(JJI)V",
(void*)nativeSetLayerStack },
- {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
- (void*)nativeGetBuiltInDisplay },
+ {"nativeGetPhysicalDisplayIds", "()[J",
+ (void*)nativeGetPhysicalDisplayIds },
+ {"nativeGetPhysicalDisplayToken", "(J)Landroid/os/IBinder;",
+ (void*)nativeGetPhysicalDisplayToken },
{"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
(void*)nativeCreateDisplay },
{"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
@@ -1314,4 +1337,4 @@
return err;
}
-};
+} // namespace android
diff --git a/libs/androidfw/DisplayEventDispatcher.cpp b/libs/androidfw/DisplayEventDispatcher.cpp
index 7708e43..3b9a348 100644
--- a/libs/androidfw/DisplayEventDispatcher.cpp
+++ b/libs/androidfw/DisplayEventDispatcher.cpp
@@ -68,7 +68,7 @@
// Drain all pending events.
nsecs_t vsyncTimestamp;
- int32_t vsyncDisplayId;
+ PhysicalDisplayId vsyncDisplayId;
uint32_t vsyncCount;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
@@ -101,10 +101,11 @@
// Drain all pending events, keep the last vsync.
nsecs_t vsyncTimestamp;
- int32_t vsyncDisplayId;
+ PhysicalDisplayId vsyncDisplayId;
uint32_t vsyncCount;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
- ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", id=%d, count=%d",
+ ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%"
+ ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d",
this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount);
mWaitingForVsync = false;
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
@@ -114,7 +115,7 @@
}
bool DisplayEventDispatcher::processPendingEvents(
- nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) {
+ nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount) {
bool gotVsync = false;
DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
ssize_t n;
@@ -128,11 +129,11 @@
// ones. That's fine, we only care about the most recent.
gotVsync = true;
*outTimestamp = ev.header.timestamp;
- *outId = ev.header.id;
+ *outDisplayId = ev.header.displayId;
*outCount = ev.vsync.count;
break;
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
- dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
+ dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
break;
default:
ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
diff --git a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
index bf35aa3..d2addba 100644
--- a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
+++ b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
@@ -37,10 +37,12 @@
DisplayEventReceiver mReceiver;
bool mWaitingForVsync;
- virtual void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) = 0;
- virtual void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected) = 0;
+ virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0;
+ virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
+ bool connected) = 0;
virtual int handleEvent(int receiveFd, int events, void* data);
- bool processPendingEvents(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
+ bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
+ uint32_t* outCount);
};
}
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 4c67513..cf5d7ce 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -55,9 +55,12 @@
return sDummyDisplay;
}
+ const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
+ LOG_ALWAYS_FATAL_IF(token == nullptr,
+ "Failed to get display info because internal display is disconnected");
+
DisplayInfo displayInfo;
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &displayInfo);
+ status_t status = SurfaceComposerClient::getDisplayInfo(token, &displayInfo);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display info, error %d", status);
return displayInfo;
}
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index 92b6cbd..0a54aca 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -37,11 +37,13 @@
0, // presentationDeadline
};
-DisplayInfo getBuiltInDisplay() {
+DisplayInfo getInternalDisplay() {
#if !HWUI_NULL_GPU
DisplayInfo display;
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &display);
+ const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
+ LOG_ALWAYS_FATAL_IF(token == nullptr,
+ "Failed to get display info because internal display is disconnected\n");
+ status_t status = SurfaceComposerClient::getDisplayInfo(token, &display);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
return display;
#else
diff --git a/libs/hwui/tests/common/TestContext.h b/libs/hwui/tests/common/TestContext.h
index 0996f4d..116d4de 100644
--- a/libs/hwui/tests/common/TestContext.h
+++ b/libs/hwui/tests/common/TestContext.h
@@ -36,7 +36,7 @@
extern DisplayInfo gDisplay;
#define dp(x) ((x)*android::uirenderer::test::gDisplay.density)
-DisplayInfo getBuiltInDisplay();
+DisplayInfo getInternalDisplay();
class TestContext {
public:
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 5fa008b..0e61899e 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -109,7 +109,7 @@
void run(const TestScene::Info& info, const TestScene::Options& opts,
benchmark::BenchmarkReporter* reporter) {
// Switch to the real display
- gDisplay = getBuiltInDisplay();
+ gDisplay = getInternalDisplay();
Properties::forceDrawFrame = true;
TestContext testContext;
diff --git a/native/android/choreographer.cpp b/native/android/choreographer.cpp
index c3629da..2db575b 100644
--- a/native/android/choreographer.cpp
+++ b/native/android/choreographer.cpp
@@ -24,6 +24,7 @@
#include <android/choreographer.h>
#include <androidfw/DisplayEventDispatcher.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
#include <utils/Looper.h>
#include <utils/Mutex.h>
#include <utils/Timers.h>
@@ -67,8 +68,8 @@
explicit Choreographer(const sp<Looper>& looper);
Choreographer(const Choreographer&) = delete;
- virtual void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
- virtual void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
+ void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override;
+ void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
void scheduleCallbacks();
@@ -139,13 +140,10 @@
}
}
-
-void Choreographer::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t) {
- if (id != ISurfaceComposer::eDisplayIdMain) {
- ALOGV("choreographer %p ~ ignoring vsync signal for non-main display (id=%d)", this, id);
- scheduleVsync();
- return;
- }
+// TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the
+// internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for
+// the internal display implicitly.
+void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t) {
std::vector<FrameCallback> callbacks{};
{
AutoMutex _l{mLock};
@@ -160,9 +158,10 @@
}
}
-void Choreographer::dispatchHotplug(nsecs_t, int32_t id, bool connected) {
- ALOGV("choreographer %p ~ received hotplug event (id=%" PRId32 ", connected=%s), ignoring.",
- this, id, toString(connected));
+void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool connected) {
+ ALOGV("choreographer %p ~ received hotplug event (displayId=%"
+ ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", connected=%s), ignoring.",
+ this, displayId, toString(connected));
}
void Choreographer::handleMessage(const Message& message) {
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 416ef42..7d2934b 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -46,7 +46,13 @@
static bool getWideColorSupport(const sp<SurfaceControl>& surfaceControl) {
sp<SurfaceComposerClient> client = surfaceControl->getClient();
- sp<IBinder> display(client->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+
+ const sp<IBinder> display = client->getInternalDisplayToken();
+ if (display == nullptr) {
+ ALOGE("unable to get wide color support for disconnected internal display");
+ return false;
+ }
+
bool isWideColorDisplay = false;
status_t err = client->isWideColorDisplay(display, &isWideColorDisplay);
if (err) {
@@ -58,7 +64,12 @@
static bool getHdrSupport(const sp<SurfaceControl>& surfaceControl) {
sp<SurfaceComposerClient> client = surfaceControl->getClient();
- sp<IBinder> display(client->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+
+ const sp<IBinder> display = client->getInternalDisplayToken();
+ if (display == nullptr) {
+ ALOGE("unable to get hdr capabilities for disconnected internal display");
+ return false;
+ }
HdrCapabilities hdrCapabilities;
status_t err = client->getHdrCapabilities(display, &hdrCapabilities);
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index b3a1a06..0d0ce55 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -323,8 +323,7 @@
}
private ColorSpace.Rgb getDisplayColorSpaceFromSurfaceControl() {
- IBinder displayToken = SurfaceControl.getBuiltInDisplay(
- SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
if (displayToken == null) {
return null;
}
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index f2c539c..2f277e4 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -27,6 +27,7 @@
import android.opengl.EGLSurface;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
+import android.os.IBinder;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -474,8 +475,14 @@
final SurfaceTexture st = new SurfaceTexture(mTexNames[0]);
final Surface s = new Surface(st);
try {
- SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
- SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), s);
+ final IBinder token = SurfaceControl.getInternalDisplayToken();
+ if (token == null) {
+ Slog.e(TAG,
+ "Failed to take screenshot because internal display is disconnected");
+ return false;
+ }
+
+ SurfaceControl.screenshot(token, s);
st.updateTexImage();
st.getTransformMatrix(mTexMatrix);
} finally {
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 16d82df..28f21f63 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -17,12 +17,8 @@
package com.android.server.display;
import android.app.ActivityThread;
-import android.content.res.Resources;
-import com.android.server.LocalServices;
-import com.android.server.lights.Light;
-import com.android.server.lights.LightsManager;
-
import android.content.Context;
+import android.content.res.Resources;
import android.hardware.sidekick.SidekickInternal;
import android.os.Build;
import android.os.Handler;
@@ -31,6 +27,7 @@
import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.Trace;
+import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -38,6 +35,11 @@
import android.view.DisplayEventReceiver;
import android.view.Surface;
import android.view.SurfaceControl;
+
+import com.android.server.LocalServices;
+import com.android.server.lights.Light;
+import com.android.server.lights.LightsManager;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -58,13 +60,9 @@
private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
- private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
- SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
- SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
- };
+ private final LongSparseArray<LocalDisplayDevice> mDevices =
+ new LongSparseArray<LocalDisplayDevice>();
- private final SparseArray<LocalDisplayDevice> mDevices =
- new SparseArray<LocalDisplayDevice>();
@SuppressWarnings("unused") // Becomes active at instantiation time.
private HotplugDisplayEventReceiver mHotplugReceiver;
@@ -80,28 +78,26 @@
mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
- for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
- tryConnectDisplayLocked(builtInDisplayId);
+ for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
+ tryConnectDisplayLocked(physicalDisplayId);
}
}
- private void tryConnectDisplayLocked(int builtInDisplayId) {
- IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
+ private void tryConnectDisplayLocked(long physicalDisplayId) {
+ final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
if (displayToken != null) {
SurfaceControl.PhysicalDisplayInfo[] configs =
SurfaceControl.getDisplayConfigs(displayToken);
if (configs == null) {
// There are no valid configs for this device, so we can't use it
- Slog.w(TAG, "No valid configs found for display device " +
- builtInDisplayId);
+ Slog.w(TAG, "No valid configs found for display device " + physicalDisplayId);
return;
}
int activeConfig = SurfaceControl.getActiveConfig(displayToken);
if (activeConfig < 0) {
// There is no active config, and for now we don't have the
// policy to set one.
- Slog.w(TAG, "No active config found for display device " +
- builtInDisplayId);
+ Slog.w(TAG, "No active config found for display device " + physicalDisplayId);
return;
}
int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
@@ -110,16 +106,17 @@
// configuration pass we'll go ahead and set it to whatever it was set to last (or
// COLOR_MODE_NATIVE if this is the first configuration).
Slog.w(TAG, "Unable to get active color mode for display device " +
- builtInDisplayId);
+ physicalDisplayId);
activeColorMode = Display.COLOR_MODE_INVALID;
}
int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
- LocalDisplayDevice device = mDevices.get(builtInDisplayId);
+ LocalDisplayDevice device = mDevices.get(physicalDisplayId);
if (device == null) {
// Display was added.
- device = new LocalDisplayDevice(displayToken, builtInDisplayId,
- configs, activeConfig, colorModes, activeColorMode);
- mDevices.put(builtInDisplayId, device);
+ final boolean isInternal = mDevices.size() == 0;
+ device = new LocalDisplayDevice(displayToken, physicalDisplayId,
+ configs, activeConfig, colorModes, activeColorMode, isInternal);
+ mDevices.put(physicalDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
} else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
colorModes, activeColorMode)) {
@@ -133,11 +130,11 @@
}
}
- private void tryDisconnectDisplayLocked(int builtInDisplayId) {
- LocalDisplayDevice device = mDevices.get(builtInDisplayId);
+ private void tryDisconnectDisplayLocked(long physicalDisplayId) {
+ LocalDisplayDevice device = mDevices.get(physicalDisplayId);
if (device != null) {
// Display was removed.
- mDevices.remove(builtInDisplayId);
+ mDevices.remove(physicalDisplayId);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
}
}
@@ -158,10 +155,11 @@
}
private final class LocalDisplayDevice extends DisplayDevice {
- private final int mBuiltInDisplayId;
+ private final long mPhysicalDisplayId;
private final Light mBacklight;
private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
+ private final boolean mIsInternal;
private DisplayDeviceInfo mInfo;
private boolean mHavePendingChanges;
@@ -179,16 +177,17 @@
private SurfaceControl.PhysicalDisplayInfo mDisplayInfos[];
- public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
+ LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
- int[] colorModes, int activeColorMode) {
- super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
- mBuiltInDisplayId = builtInDisplayId;
+ int[] colorModes, int activeColorMode, boolean isInternal) {
+ super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
+ mPhysicalDisplayId = physicalDisplayId;
+ mIsInternal = isInternal;
updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
colorModes, activeColorMode);
updateColorModesLocked(colorModes, activeColorMode);
mSidekickInternal = LocalServices.getService(SidekickInternal.class);
- if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
+ if (mIsInternal) {
LightsManager lights = LocalServices.getService(LightsManager.class);
mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
} else {
@@ -392,7 +391,7 @@
}
final Resources res = getOverlayContext().getResources();
- if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
+ if (mIsInternal) {
mInfo.name = res.getString(
com.android.internal.R.string.display_manager_built_in_display_name);
mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
@@ -455,7 +454,7 @@
final boolean stateChanged = (mState != state);
final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
if (stateChanged || brightnessChanged) {
- final int displayId = mBuiltInDisplayId;
+ final long physicalDisplayId = mPhysicalDisplayId;
final IBinder token = getDisplayTokenLocked();
final int oldState = mState;
@@ -519,7 +518,7 @@
private void setVrMode(boolean isVrEnabled) {
if (DEBUG) {
Slog.d(TAG, "setVrMode("
- + "id=" + displayId
+ + "id=" + physicalDisplayId
+ ", state=" + Display.stateToString(state) + ")");
}
mBacklight.setVrMode(isVrEnabled);
@@ -528,7 +527,7 @@
private void setDisplayState(int state) {
if (DEBUG) {
Slog.d(TAG, "setDisplayState("
- + "id=" + displayId
+ + "id=" + physicalDisplayId
+ ", state=" + Display.stateToString(state) + ")");
}
@@ -546,7 +545,7 @@
}
final int mode = getPowerModeForState(state);
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
- + "id=" + displayId
+ + "id=" + physicalDisplayId
+ ", state=" + Display.stateToString(state) + ")");
try {
SurfaceControl.setDisplayPowerMode(token, mode);
@@ -571,11 +570,12 @@
private void setDisplayBrightness(int brightness) {
if (DEBUG) {
Slog.d(TAG, "setDisplayBrightness("
- + "id=" + displayId + ", brightness=" + brightness + ")");
+ + "id=" + physicalDisplayId
+ + ", brightness=" + brightness + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
- + "id=" + displayId + ", brightness=" + brightness + ")");
+ + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
try {
mBacklight.setBrightness(brightness);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
@@ -646,7 +646,7 @@
@Override
public void dumpLocked(PrintWriter pw) {
super.dumpLocked(pw);
- pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
+ pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
pw.println("mActivePhysIndex=" + mActivePhysIndex);
pw.println("mActiveModeId=" + mActiveModeId);
pw.println("mActiveColorMode=" + mActiveColorMode);
@@ -731,12 +731,12 @@
}
@Override
- public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
+ public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
synchronized (getSyncRoot()) {
if (connected) {
- tryConnectDisplayLocked(builtInDisplayId);
+ tryConnectDisplayLocked(physicalDisplayId);
} else {
- tryDisconnectDisplayLocked(builtInDisplayId);
+ tryDisconnectDisplayLocked(physicalDisplayId);
}
}
}