Merge "Generalize physical display management"

This commit is contained in:
Dominik Laskowski
2019-02-06 22:46:09 +00:00
committed by Android (Google) Code Review
20 changed files with 207 additions and 165 deletions

View File

@@ -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;

View File

@@ -171,6 +171,7 @@ private:
EGLDisplay mDisplay;
EGLDisplay mContext;
EGLDisplay mSurface;
sp<IBinder> mDisplayToken;
sp<SurfaceControl> mFlingerSurfaceControl;
sp<Surface> mFlingerSurface;
bool mClockEnabled;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -132,7 +132,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,
@@ -330,24 +331,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.
@@ -1730,9 +1713,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]);
}
/**
@@ -1791,8 +1793,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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
};
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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:

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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);

View File

@@ -323,8 +323,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;
}

View File

@@ -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 {

View File

@@ -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);
}
}
}