diff options
20 files changed, 210 insertions, 167 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 5dcb392b002d..46917e4f6062 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -252,10 +252,12 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) 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 @@ void BootAnimation::handleViewport(nsecs_t timestep) { // 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 04d4f9a6fd06..19616cb790c7 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -171,6 +171,7 @@ private: 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 3d74f8b207af..c4976675dc04 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 @@ static status_t notifyMediaScanner(const char* fileName) { 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 @@ int main(int argc, char** argv) 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 @@ int main(int argc, char** argv) } if (fd == -1) { - usage(pname); + usage(pname, *displayId); return 1; } @@ -192,9 +196,10 @@ int main(int argc, char** argv) 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 7f4d1d0db5a2..7f1021b5d62e 100644 --- a/config/boot-image-profile.txt +++ b/config/boot-image-profile.txt @@ -33456,7 +33456,6 @@ HSPLandroid/view/SurfaceControl;->destroy()V 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 ccd0fc179f0e..03e8a0fc0d39 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -22,7 +22,6 @@ import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER; 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 @@ public final class Choreographer { 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 edd3f1a8de98..3e8002f4634d 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -136,12 +136,11 @@ public abstract class DisplayEventReceiver { * * @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 @@ public abstract class DisplayEventReceiver { * * @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 @@ public abstract class DisplayEventReceiver { // 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 8061cc3bab74..a68cc664da66 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -131,7 +131,8 @@ public final class SurfaceControl implements Parcelable { 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, @@ -329,24 +330,6 @@ public final class SurfaceControl implements Parcelable { */ 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. @@ -1729,9 +1712,28 @@ public final class SurfaceControl implements Parcelable { /** * @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]); } /** @@ -1790,8 +1792,12 @@ public final class SurfaceControl implements Parcelable { 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 c1b5aaec1106..191472d086f6 100644 --- a/core/jni/android_view_DisplayEventReceiver.cpp +++ b/core/jni/android_view_DisplayEventReceiver.cpp @@ -59,8 +59,8 @@ private: 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 @@ void NativeDisplayEventReceiver::dispose() { 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 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) { 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 fad2fe0d3845..68be0054ae45 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -483,8 +483,29 @@ static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong transactionObj, 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 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (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 @@ int register_android_view_SurfaceControl(JNIEnv* env) return err; } -}; +} // namespace android diff --git a/libs/androidfw/DisplayEventDispatcher.cpp b/libs/androidfw/DisplayEventDispatcher.cpp index 7708e4340397..3b9a348047ba 100644 --- a/libs/androidfw/DisplayEventDispatcher.cpp +++ b/libs/androidfw/DisplayEventDispatcher.cpp @@ -68,7 +68,7 @@ status_t DisplayEventDispatcher::scheduleVsync() { // 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 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { // 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 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { } 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 @@ bool DisplayEventDispatcher::processPendingEvents( // 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 bf35aa3c15bb..d2addba61679 100644 --- a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h +++ b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h @@ -37,10 +37,12 @@ private: 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 4c675133a6c1..cf5d7ce3f738 100644 --- a/libs/hwui/DeviceInfo.cpp +++ b/libs/hwui/DeviceInfo.cpp @@ -55,9 +55,12 @@ DisplayInfo QueryDisplayInfo() { 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 92b6cbdfc613..0a54aca4970d 100644 --- a/libs/hwui/tests/common/TestContext.cpp +++ b/libs/hwui/tests/common/TestContext.cpp @@ -37,11 +37,13 @@ static android::DisplayInfo DUMMY_DISPLAY{ 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 0996f4dc706e..116d4de8090a 100644 --- a/libs/hwui/tests/common/TestContext.h +++ b/libs/hwui/tests/common/TestContext.h @@ -36,7 +36,7 @@ namespace test { 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 5fa008b5b4df..0e61899ed58b 100644 --- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp +++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp @@ -109,7 +109,7 @@ void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options 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 c3629da1cb12..2db575bf5a13 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 @@ private: 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::scheduleCallbacks() { } } - -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::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t) { } } -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 3156732ef02b..d68d3499cc1e 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -46,7 +46,13 @@ using Transaction = SurfaceComposerClient::Transaction; 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 getWideColorSupport(const sp<SurfaceControl>& surfaceControl) { 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 591ce8dd2bae..9fad35be9098 100644 --- a/services/core/java/com/android/server/display/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/ColorDisplayService.java @@ -23,6 +23,7 @@ import static android.hardware.display.ColorDisplayManager.COLOR_MODE_AUTOMATIC; import static android.hardware.display.ColorDisplayManager.COLOR_MODE_BOOSTED; import static android.hardware.display.ColorDisplayManager.COLOR_MODE_NATURAL; import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED; + import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE; import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION; @@ -65,10 +66,9 @@ import android.provider.Settings.System; import android.util.MathUtils; import android.util.Slog; import android.view.SurfaceControl; +import android.view.SurfaceControl.DisplayPrimaries; import android.view.accessibility.AccessibilityManager; import android.view.animation.AnimationUtils; -import android.view.SurfaceControl; -import android.view.SurfaceControl.DisplayPrimaries; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -79,6 +79,7 @@ import com.android.server.SystemService; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; @@ -315,8 +316,7 @@ public final class ColorDisplayService extends SystemService { } 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 f2c539cb257c..2f277e4f2ff5 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.EGLDisplay; 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 class ColorFade { 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 16d82df4dd5b..28f21f633ac4 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.Looper; 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.DisplayCutout; 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { // 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } - 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { } 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 class LocalDisplayAdapter extends DisplayAdapter { } 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 class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { private void setDisplayState(int state) { if (DEBUG) { Slog.d(TAG, "setDisplayState(" - + "id=" + displayId + + "id=" + physicalDisplayId + ", state=" + Display.stateToString(state) + ")"); } @@ -546,7 +545,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { } 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { @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 @@ final class LocalDisplayAdapter extends DisplayAdapter { } @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); } } } |