Merge "installd: update per fs-verity kernel uapi change" into pi-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 0701450..21d9ace 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -116,7 +116,8 @@
{ "database", "Database", ATRACE_TAG_DATABASE, { } },
{ "network", "Network", ATRACE_TAG_NETWORK, { } },
{ "adb", "ADB", ATRACE_TAG_ADB, { } },
- { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, {}},
+ { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } },
+ { "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ k_pdxServiceCategory, "PDX services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 3ec0163..cb6d0c6 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -82,6 +82,28 @@
chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/enable
chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/enable
+ # disk
+ chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
+ chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
+ chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
+ chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
+ chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
+ chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
+ chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
+ chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
+
# Tracing disabled by default
write /sys/kernel/debug/tracing/tracing_on 0
write /sys/kernel/tracing/tracing_on 0
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 9d632cc..93a29ba 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -19,25 +19,3 @@
chmod 0666 /sys/kernel/debug/tracing/events/irq/enable
chmod 0666 /sys/kernel/tracing/events/ipi/enable
chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable
-
- # disk
- chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable
- chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
- chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable
- chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
- chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable
- chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
- chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable
- chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
- chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable
- chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
- chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable
- chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
- chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable
- chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
- chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable
- chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
- chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable
- chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
- chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
- chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index fd2fccb..9648ede 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1159,6 +1159,10 @@
static void RunDumpsysProto(const std::string& title, int priority,
std::chrono::milliseconds timeout,
std::chrono::milliseconds service_timeout) {
+ if (!ds.IsZipping()) {
+ MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
+ return;
+ }
sp<android::IServiceManager> sm = defaultServiceManager();
Dumpsys dumpsys(sm.get());
Vector<String16> args;
@@ -1630,20 +1634,8 @@
ShowUsageAndExit();
}
-static void sig_handler(int) {
- _exit(EXIT_FAILURE);
-}
-
static void register_sig_handler() {
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = sig_handler;
- sigaction(SIGPIPE, &sa, NULL); // broken pipe
- sigaction(SIGSEGV, &sa, NULL); // segment fault
- sigaction(SIGINT, &sa, NULL); // ctrl-c
- sigaction(SIGTERM, &sa, NULL); // killed
- sigaction(SIGQUIT, &sa, NULL); // quit
+ signal(SIGPIPE, SIG_IGN);
}
bool Dumpstate::FinishZipFile() {
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 39fddc5..8e393c0 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -378,8 +378,7 @@
}
if (findAndBumpVersion(hal, version)) {
if (&table != &mImplementationsTable) {
- hal->interfaces[interfaceName].name = interfaceName;
- hal->interfaces[interfaceName].instances.insert(instanceName);
+ hal->insertLegacyInstance(interfaceName, instanceName);
}
hal->transportArch.arch |= arch;
done = true;
@@ -389,17 +388,16 @@
if (done) {
continue; // to next TableEntry
}
- decltype(vintf::ManifestHal::interfaces) interfaces;
- if (&table != &mImplementationsTable) {
- interfaces[interfaceName].name = interfaceName;
- interfaces[interfaceName].instances.insert(instanceName);
- }
- if (!manifest.add(vintf::ManifestHal{
+ vintf::ManifestHal manifestHal{
vintf::HalFormat::HIDL,
std::string{fqName.package()},
{version},
{transport, arch},
- std::move(interfaces)})) {
+ {}};
+ if (&table != &mImplementationsTable) {
+ manifestHal.insertLegacyInstance(interfaceName, instanceName);
+ }
+ if (!manifest.add(std::move(manifestHal))) {
err() << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
}
}
@@ -408,7 +406,7 @@
<< " This is a skeleton " << manifest.type() << " manifest. Notes: " << std::endl
<< INIT_VINTF_NOTES
<< "-->" << std::endl;
- out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_ONLY);
+ out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_NO_FQNAME);
}
std::string ListCommand::INIT_VINTF_NOTES{
diff --git a/libs/arect/include/android/rect.h b/libs/arect/include/android/rect.h
index 80741c0..b36728e 100644
--- a/libs/arect/include/android/rect.h
+++ b/libs/arect/include/android/rect.h
@@ -33,23 +33,26 @@
#endif
/**
- * {@link ARect} is a struct that represents a rectangular window area.
+ * Rectangular window area.
*
- * It is used with {@link
- * ANativeActivityCallbacks::onContentRectChanged} event callback and
- * ANativeWindow_lock() function.
+ * This is the NDK equivalent of the android.graphics.Rect class in Java. It is
+ * used with {@link ANativeActivityCallbacks::onContentRectChanged} event
+ * callback and the ANativeWindow_lock() function.
+ *
+ * In a valid ARect, left <= right and top <= bottom. ARect with left=0, top=10,
+ * right=1, bottom=11 contains only one pixel at x=0, y=10.
*/
typedef struct ARect {
#ifdef __cplusplus
typedef int32_t value_type;
#endif
- /** left position */
+ /// Minimum X coordinate of the rectangle.
int32_t left;
- /** top position */
+ /// Minimum Y coordinate of the rectangle.
int32_t top;
- /** left position */
+ /// Maximum X coordinate of the rectangle.
int32_t right;
- /** bottom position */
+ /// Maximum Y coordinate of the rectangle.
int32_t bottom;
} ARect;
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 9adac26..2728f35 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -80,6 +80,15 @@
}
}
+bool ActivityManager::isUidActive(const uid_t uid, const String16& callingPackage)
+{
+ sp<IActivityManager> service = getService();
+ if (service != NULL) {
+ return service->isUidActive(uid, callingPackage);
+ }
+ return false;
+}
+
status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) {
sp<IActivityManager> service = getService();
if (service != NULL) {
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index b7a5fd9..428db4d 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -78,6 +78,18 @@
data.writeStrongBinder(IInterface::asBinder(observer));
remote()->transact(UNREGISTER_UID_OBSERVER_TRANSACTION, data, &reply);
}
+
+ virtual bool isUidActive(const uid_t uid, const String16& callingPackage)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ data.writeString16(callingPackage);
+ remote()->transact(IS_UID_ACTIVE_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) return false;
+ return reply.readInt32() == 1;
+ }
};
// ------------------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 397382f..3090cae 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -50,6 +50,7 @@
const int32_t cutpoint,
const String16& callingPackage);
void unregisterUidObserver(const sp<IUidObserver>& observer);
+ bool isUidActive(const uid_t uid, const String16& callingPackage);
status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index bac2a99..6607c0e 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -35,11 +35,13 @@
const int32_t cutpoint,
const String16& callingPackage) = 0;
virtual void unregisterUidObserver(const sp<IUidObserver>& observer) = 0;
+ virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0;
enum {
OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
REGISTER_UID_OBSERVER_TRANSACTION,
- UNREGISTER_UID_OBSERVER_TRANSACTION
+ UNREGISTER_UID_OBSERVER_TRANSACTION,
+ IS_UID_ACTIVE_TRANSACTION
};
};
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 0244bb5..e22bc70 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -43,6 +43,8 @@
namespace android {
+using ui::ColorMode;
+
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
public:
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 679f44b..a6890ee 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -47,8 +47,8 @@
~BpSurfaceComposerClient() override;
status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,
- uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
- uint32_t ownerUid, sp<IBinder>* handle,
+ uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
+ int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) override {
return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
name, width, height,
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 2e1c24b..6a1aebd 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -44,6 +44,8 @@
namespace android {
+using ui::ColorMode;
+
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
: mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 38f0eb7..bbf681e 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -43,6 +43,8 @@
#include <private/gui/ComposerService.h>
namespace android {
+
+using ui::ColorMode;
// ---------------------------------------------------------------------------
ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);
@@ -609,8 +611,8 @@
PixelFormat format,
uint32_t flags,
SurfaceControl* parent,
- uint32_t windowType,
- uint32_t ownerUid)
+ int32_t windowType,
+ int32_t ownerUid)
{
sp<SurfaceControl> s;
createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid);
@@ -625,11 +627,11 @@
sp<SurfaceControl>* outSurface,
uint32_t flags,
SurfaceControl* parent,
- uint32_t windowType,
- uint32_t ownerUid)
+ int32_t windowType,
+ int32_t ownerUid)
{
sp<SurfaceControl> sur;
- status_t err = NO_ERROR;
+ status_t err = mStatus;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index afe9358..3591090 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -30,7 +30,7 @@
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h>
#include <ui/GraphicBuffer.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#include <vector>
@@ -161,10 +161,10 @@
virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<ColorMode>* outColorModes) = 0;
- virtual ColorMode getActiveColorMode(const sp<IBinder>& display) = 0;
+ Vector<ui::ColorMode>* outColorModes) = 0;
+ virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display) = 0;
virtual status_t setActiveColorMode(const sp<IBinder>& display,
- ColorMode colorMode) = 0;
+ ui::ColorMode colorMode) = 0;
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index d5bbef2..8dfc99a 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -49,8 +49,8 @@
* Requires ACCESS_SURFACE_FLINGER permission
*/
virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
- uint32_t ownerUid, sp<IBinder>* handle,
+ uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
+ int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) = 0;
/*
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 5ce20ad..ffc22f6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -29,7 +29,7 @@
#include <utils/threads.h>
#include <ui/FrameStats.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
#include <gui/CpuConsumer.h>
@@ -89,13 +89,14 @@
// Gets the list of supported color modes for the given display
static status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<ColorMode>* outColorModes);
+ Vector<ui::ColorMode>* outColorModes);
// Gets the active color mode for the given display
- static ColorMode getActiveColorMode(const sp<IBinder>& display);
+ static ui::ColorMode getActiveColorMode(const sp<IBinder>& display);
// Sets the active color mode for the given display
- static status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode);
+ static status_t setActiveColorMode(const sp<IBinder>& display,
+ ui::ColorMode colorMode);
/* Triggers screen on/off or low power mode and waits for it to complete */
static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
@@ -111,8 +112,8 @@
PixelFormat format, // pixel-format desired
uint32_t flags = 0, // usage flags
SurfaceControl* parent = nullptr, // parent
- uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
- uint32_t ownerUid = 0 // UID of the task
+ int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
+ int32_t ownerUid = -1 // UID of the task
);
status_t createSurfaceChecked(
@@ -123,8 +124,8 @@
sp<SurfaceControl>* outSurface,
uint32_t flags = 0, // usage flags
SurfaceControl* parent = nullptr, // parent
- uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
- uint32_t ownerUid = 0 // UID of the task
+ int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
+ int32_t ownerUid = -1 // UID of the task
);
//! Create a virtual display
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 66d5595..2c02ba6 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -42,6 +42,7 @@
// retrieve wide-color and hdr settings from configstore
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+using ui::ColorMode;
using Transaction = SurfaceComposerClient::Transaction;
@@ -58,7 +59,6 @@
class SurfaceTest : public ::testing::Test {
protected:
-
SurfaceTest() {
ProcessState::self()->startThreadPool();
}
@@ -93,6 +93,16 @@
sp<SurfaceControl> mSurfaceControl;
};
+TEST_F(SurfaceTest, CreateSurfaceReturnsErrorBadClient) {
+ mComposerClient->dispose();
+ ASSERT_EQ(NO_INIT, mComposerClient->initCheck());
+
+ sp<SurfaceControl> sc;
+ status_t err = mComposerClient->createSurfaceChecked(
+ String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, &sc, 0);
+ ASSERT_EQ(NO_INIT, err);
+}
+
TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenVisible) {
sp<ANativeWindow> anw(mSurface);
int result = -123;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index a477bf2..cc67aca 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -41,9 +41,11 @@
AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
/**
+ * 32 bits per pixel, 8 bits per channel format where alpha values are
+ * ignored (always opaque).
* Corresponding formats:
* Vulkan: VK_FORMAT_R8G8B8A8_UNORM
- * OpenGL ES: GL_RGBA8
+ * OpenGL ES: GL_RGB8
*/
AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2,
@@ -124,40 +126,49 @@
AHARDWAREBUFFER_FORMAT_S8_UINT = 0x35,
};
+/**
+ * Buffer usage flags, specifying how the buffer will be accessed.
+ */
enum {
- /* The buffer will never be read by the CPU */
+ /// The buffer will never be read by the CPU.
AHARDWAREBUFFER_USAGE_CPU_READ_NEVER = 0UL,
- /* The buffer will sometimes be read by the CPU */
+ /// The buffer will sometimes be read by the CPU.
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY = 2UL,
- /* The buffer will often be read by the CPU */
+ /// The buffer will often be read by the CPU.
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN = 3UL,
- /* CPU read value mask */
+ /// CPU read value mask.
AHARDWAREBUFFER_USAGE_CPU_READ_MASK = 0xFUL,
- /* The buffer will never be written by the CPU */
+ /// The buffer will never be written by the CPU.
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER = 0UL << 4,
- /* The buffer will sometimes be written to by the CPU */
+ /// The buffer will sometimes be written to by the CPU.
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY = 2UL << 4,
- /* The buffer will often be written to by the CPU */
+ /// The buffer will often be written to by the CPU.
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN = 3UL << 4,
- /* CPU write value mask */
+ /// CPU write value mask.
AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK = 0xFUL << 4,
- /* The buffer will be read from by the GPU */
+ /// The buffer will be read from by the GPU as a texture.
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE = 1UL << 8,
- /* The buffer will be written to by the GPU */
+ /**
+ * The buffer will be written to by the GPU as a framebuffer attachment.
+ * Note that the name of this flag is somewhat misleading: it does not imply
+ * that the buffer contains a color format. A buffer with depth or stencil
+ * format that will be used as a framebuffer attachment should also have
+ * this flag.
+ */
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = 1UL << 9,
- /* The buffer must not be used outside of a protected hardware path */
+ /// The buffer must not be used outside of a protected hardware path.
AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14,
- /* The buffer will be read by a hardware video encoder */
+ /// The buffer will be read by a hardware video encoder.
AHARDWAREBUFFER_USAGE_VIDEO_ENCODE = 1UL << 16,
- /* The buffer will be used for sensor direct data */
+ /// The buffer will be used for direct writes from sensors.
AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA = 1UL << 23,
- /* The buffer will be used as a shader storage or uniform buffer object */
+ /// The buffer will be used as a shader storage or uniform buffer object.
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24,
- /* The buffer will be used as a cube map texture */
+ /// The buffer will be used as a cube map texture.
AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP = 1UL << 25,
- /* The buffer contains a complete mipmap hierarchy */
+ /// The buffer contains a complete mipmap hierarchy.
AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE = 1UL << 26,
AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28,
@@ -182,15 +193,19 @@
AHARDWAREBUFFER_USAGE_VENDOR_19 = 1ULL << 63,
};
+/**
+ * Buffer description. Used for allocating new buffers and querying parameters
+ * of existing ones.
+ */
typedef struct AHardwareBuffer_Desc {
- uint32_t width; // width in pixels
- uint32_t height; // height in pixels
- uint32_t layers; // number of images
- uint32_t format; // One of AHARDWAREBUFFER_FORMAT_*
- uint64_t usage; // Combination of AHARDWAREBUFFER_USAGE_*
- uint32_t stride; // Stride in pixels, ignored for AHardwareBuffer_allocate()
- uint32_t rfu0; // Initialize to zero, reserved for future use
- uint64_t rfu1; // Initialize to zero, reserved for future use
+ uint32_t width; ///< Width in pixels.
+ uint32_t height; ///< Height in pixels.
+ uint32_t layers; ///< Number of images in an image array.
+ uint32_t format; ///< One of AHARDWAREBUFFER_FORMAT_*
+ uint64_t usage; ///< Combination of AHARDWAREBUFFER_USAGE_*
+ uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate()
+ uint32_t rfu0; ///< Initialize to zero, reserved for future use.
+ uint64_t rfu1; ///< Initialize to zero, reserved for future use.
} AHardwareBuffer_Desc;
typedef struct AHardwareBuffer AHardwareBuffer;
@@ -199,8 +214,8 @@
* Allocates a buffer that backs an AHardwareBuffer using the passed
* AHardwareBuffer_Desc.
*
- * Returns NO_ERROR on success, or an error number of the allocation fails for
- * any reason.
+ * \return NO_ERROR on success, or an error number of the allocation fails for
+ * any reason. The returned buffer has a reference count of 1.
*/
int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
AHardwareBuffer** outBuffer);
@@ -223,7 +238,7 @@
void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
AHardwareBuffer_Desc* outDesc);
-/*
+/**
* Lock the AHardwareBuffer for reading or writing, depending on the usage flags
* passed. This call may block if the hardware needs to finish rendering or if
* CPU caches need to be synchronized, or possibly for other implementation-
@@ -231,16 +246,16 @@
* descriptor that will be signaled when the buffer is locked, otherwise the
* caller will block until the buffer is available.
*
- * If rect is not NULL, the caller promises to modify only data in the area
+ * If \a rect is not NULL, the caller promises to modify only data in the area
* specified by rect. If rect is NULL, the caller may modify the contents of the
* entire buffer.
*
* The content of the buffer outside of the specified rect is NOT modified
* by this call.
*
- * The buffer usage may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set, then
- * outVirtualAddress is filled with the address of the buffer in virtual memory,
- * otherwise this function will fail.
+ * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set,
+ * then outVirtualAddress is filled with the address of the buffer in virtual
+ * memory.
*
* THREADING CONSIDERATIONS:
*
@@ -252,38 +267,38 @@
* may return an error or leave the buffer's content into an indeterminate
* state.
*
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL or if the usage
+ * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL or if the usage
* flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error
* number of the lock fails for any reason.
*/
int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
int32_t fence, const ARect* rect, void** outVirtualAddress);
-/*
+/**
* Unlock the AHardwareBuffer; must be called after all changes to the buffer
* are completed by the caller. If fence is not NULL then it will be set to a
* file descriptor that is signaled when all pending work on the buffer is
* completed. The caller is responsible for closing the fence when it is no
* longer needed.
*
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL, or an error
- * number of the lock fails for any reason.
+ * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL, or an error
+ * number if the unlock fails for any reason.
*/
int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence);
-/*
+/**
* Send the AHardwareBuffer to an AF_UNIX socket.
*
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL, or an error
- * number of the lock fails for any reason.
+ * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL, or an error
+ * number if the operation fails for any reason.
*/
int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd);
-/*
+/**
* Receive the AHardwareBuffer from an AF_UNIX socket.
*
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL, or an error
- * number of the lock fails for any reason.
+ * \return NO_ERROR on success, BAD_VALUE if \a outBuffer is NULL, or an error
+ * number if the operation fails for any reason.
*/
int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer);
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index f2d6f7a..d5e5e9d 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -85,23 +85,23 @@
* A pointer can be obtained using {@link ANativeWindow_lock()}.
*/
typedef struct ANativeWindow_Buffer {
- // The number of pixels that are show horizontally.
+ /// The number of pixels that are shown horizontally.
int32_t width;
- // The number of pixels that are shown vertically.
+ /// The number of pixels that are shown vertically.
int32_t height;
- // The number of *pixels* that a line in the buffer takes in
- // memory. This may be >= width.
+ /// The number of *pixels* that a line in the buffer takes in
+ /// memory. This may be >= width.
int32_t stride;
- // The format of the buffer. One of AHARDWAREBUFFER_FORMAT_*
+ /// The format of the buffer. One of AHARDWAREBUFFER_FORMAT_*
int32_t format;
- // The actual bits.
+ /// The actual bits.
void* bits;
- // Do not touch.
+ /// Do not touch.
uint32_t reserved[6];
} ANativeWindow_Buffer;
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index d7e191d..d7d8618 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -22,7 +22,7 @@
#include <string>
using android::base::StringPrintf;
-using android::ColorMode;
+using android::ui::ColorMode;
std::string decodeStandard(android_dataspace dataspace) {
const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h
index 3370107..6350d0c 100644
--- a/libs/ui/include/ui/DebugUtils.h
+++ b/libs/ui/include/ui/DebugUtils.h
@@ -16,7 +16,7 @@
#pragma once
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
#include <string>
@@ -29,6 +29,6 @@
std::string decodeTransfer(android_dataspace dataspace);
std::string decodeRange(android_dataspace dataspace);
std::string dataspaceDetails(android_dataspace dataspace);
-std::string decodeColorMode(android::ColorMode colormode);
+std::string decodeColorMode(android::ui::ColorMode colormode);
std::string decodePixelFormat(android::PixelFormat format);
std::string to_string(const android::Rect& rect);
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/libs/ui/include/ui/GraphicTypes.h
similarity index 85%
rename from libs/ui/include/ui/GraphicsTypes.h
rename to libs/ui/include/ui/GraphicTypes.h
index fa9a812..39893b2 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/libs/ui/include/ui/GraphicTypes.h
@@ -19,8 +19,12 @@
#include <android/hardware/graphics/common/1.1/types.h>
#include <system/graphics.h>
+// android::ui::* in this header file will alias different types as
+// the HIDL interface is updated.
namespace android {
+namespace ui {
using android::hardware::graphics::common::V1_0::ColorMode;
+} // namespace ui
} // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 3ce5c9f..660a200 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -769,9 +769,14 @@
auto s3 = p->CreateConsumer();
EXPECT_FALSE(s3);
+ // Note that here the expected error code is EOPNOTSUPP as the socket towards
+ // ProducerChannel has been teared down.
EXPECT_EQ(s3.error(), EOPNOTSUPP);
s3 = c->CreateConsumer();
EXPECT_FALSE(s3);
- EXPECT_EQ(s3.error(), EOPNOTSUPP);
+ // Note that here the expected error code is EPIPE returned from
+ // ConsumerChannel::HandleMessage as the socket is still open but the producer
+ // is gone.
+ EXPECT_EQ(s3.error(), EPIPE);
}
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index c3f4f58..9a449fa 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -105,6 +105,36 @@
return value ? "true" : "false";
}
+static std::string motionActionToString(int32_t action) {
+ // Convert MotionEvent action to string
+ switch(action & AMOTION_EVENT_ACTION_MASK) {
+ case AMOTION_EVENT_ACTION_DOWN:
+ return "DOWN";
+ case AMOTION_EVENT_ACTION_MOVE:
+ return "MOVE";
+ case AMOTION_EVENT_ACTION_UP:
+ return "UP";
+ case AMOTION_EVENT_ACTION_POINTER_DOWN:
+ return "POINTER_DOWN";
+ case AMOTION_EVENT_ACTION_POINTER_UP:
+ return "POINTER_UP";
+ }
+ return StringPrintf("%" PRId32, action);
+}
+
+static std::string keyActionToString(int32_t action) {
+ // Convert KeyEvent action to string
+ switch(action) {
+ case AKEY_EVENT_ACTION_DOWN:
+ return "DOWN";
+ case AKEY_EVENT_ACTION_UP:
+ return "UP";
+ case AKEY_EVENT_ACTION_MULTIPLE:
+ return "MULTIPLE";
+ }
+ return StringPrintf("%" PRId32, action);
+}
+
static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
>> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
@@ -3976,11 +4006,11 @@
}
void InputDispatcher::KeyEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, action=%d, "
+ msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, action=%s, "
"flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
"repeatCount=%d), policyFlags=0x%08x",
- deviceId, source, action, flags, keyCode, scanCode, metaState,
- repeatCount, policyFlags);
+ deviceId, source, keyActionToString(action).c_str(), flags, keyCode,
+ scanCode, metaState, repeatCount, policyFlags);
}
void InputDispatcher::KeyEntry::recycle() {
@@ -4021,11 +4051,11 @@
}
void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, action=%d, actionButton=0x%08x, "
+ msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, action=%s, actionButton=0x%08x, "
"flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
"edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[",
- deviceId, source, action, actionButton, flags, metaState, buttonState, edgeFlags,
- xPrecision, yPrecision, displayId);
+ deviceId, source, motionActionToString(action).c_str(), actionButton, flags, metaState,
+ buttonState, edgeFlags, xPrecision, yPrecision, displayId);
for (uint32_t i = 0; i < pointerCount; i++) {
if (i) {
msg += ", ";
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d22c021..9200207 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -690,9 +690,9 @@
// Add this buffer from our internal queue tracker
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
- mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
- item.mGraphicBuffer->getHeight(),
- item.mFrameNumber);
+ mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+ item.mGraphicBuffer->getHeight(),
+ item.mFrameNumber);
// Reset the frame number tracker when we receive the first buffer after
// a frame number reset
if (item.mFrameNumber == 1) {
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0c9f0e2..c90024b 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -143,7 +143,7 @@
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- const sp<IBinder>& parentHandle, uint32_t windowType, uint32_t ownerUid,
+ const sp<IBinder>& parentHandle, int32_t windowType, int32_t ownerUid,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
{
@@ -180,13 +180,13 @@
PixelFormat format;
uint32_t flags;
sp<Layer>* parent;
- uint32_t windowType;
- uint32_t ownerUid;
+ int32_t windowType;
+ int32_t ownerUid;
public:
MessageCreateLayer(SurfaceFlinger* flinger,
const String8& name, Client* client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- sp<IBinder>* handle, uint32_t windowType, uint32_t ownerUid,
+ sp<IBinder>* handle, int32_t windowType, int32_t ownerUid,
sp<IGraphicBufferProducer>* gbp,
sp<Layer>* parent)
: flinger(flinger), client(client),
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 2aab28f..c7df9f7 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -58,7 +58,7 @@
virtual status_t createSurface(
const String8& name,
uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,
- const sp<IBinder>& parent, uint32_t windowType, uint32_t ownerUid,
+ const sp<IBinder>& parent, int32_t windowType, int32_t ownerUid,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 92d5e21..93cb849 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -49,16 +49,12 @@
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <configstore/Utils.h>
-// ----------------------------------------------------------------------------
-using namespace android;
-// ----------------------------------------------------------------------------
+namespace android {
// retrieve triple buffer setting from configstore
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
-
-static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) >= 3;
+using android::ui::ColorMode;
/*
* Initialize the display to the specified values.
@@ -74,72 +70,43 @@
int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
+ const sp<ANativeWindow>& nativeWindow,
const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
+ std::unique_ptr<RE::Surface> renderSurface,
+ int displayWidth,
+ int displayHeight,
bool supportWideColor,
- bool supportHdr)
+ bool supportHdr,
+ int initialPowerMode)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
+ mNativeWindow(nativeWindow),
mDisplaySurface(displaySurface),
- mSurface{flinger->getRenderEngine().createSurface()},
- mDisplayWidth(),
- mDisplayHeight(),
- mPageFlipCount(),
+ mSurface{std::move(renderSurface)},
+ mDisplayWidth(displayWidth),
+ mDisplayHeight(displayHeight),
+ mPageFlipCount(0),
mIsSecure(isSecure),
mLayerStack(NO_LAYER_STACK),
mOrientation(),
- mPowerMode(HWC_POWER_MODE_OFF),
- mActiveConfig(0)
+ mViewport(Rect::INVALID_RECT),
+ mFrame(Rect::INVALID_RECT),
+ mPowerMode(initialPowerMode),
+ mActiveConfig(0),
+ mActiveColorMode(ColorMode::NATIVE),
+ mDisplayHasWideColor(supportWideColor),
+ mDisplayHasHdr(supportHdr)
{
// clang-format on
- Surface* surface;
- mNativeWindow = surface = new Surface(producer, false);
- ANativeWindow* const window = mNativeWindow.get();
-
- mActiveColorMode = ColorMode::NATIVE;
- mDisplayHasWideColor = supportWideColor;
- mDisplayHasHdr = supportHdr;
-
- /*
- * Create our display's surface
- */
- mSurface->setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
- mSurface->setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
- mSurface->setNativeWindow(window);
- mDisplayWidth = mSurface->queryWidth();
- mDisplayHeight = mSurface->queryHeight();
-
- // Make sure that composition can never be stalled by a virtual display
- // consumer that isn't processing buffers fast enough. We have to do this
- // in two places:
- // * Here, in case the display is composed entirely by HWC.
- // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
- // window's swap interval in eglMakeCurrent, so they'll override the
- // interval we set here.
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
- window->setSwapInterval(window, 0);
-
- mPageFlipCount = 0;
- mViewport.makeInvalid();
- mFrame.makeInvalid();
-
- // virtual displays are always considered enabled
- mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
- HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
-
- if (useTripleFramebuffer) {
- surface->allocateBuffers();
- }
}
-DisplayDevice::~DisplayDevice() {
-}
+DisplayDevice::~DisplayDevice() = default;
void DisplayDevice::disconnect(HWComposer& hwc) {
if (mHwcDisplayId >= 0) {
@@ -486,7 +453,11 @@
tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
auto const surface = static_cast<Surface*>(window);
android_dataspace dataspace = surface->getBuffersDataSpace();
- result.appendFormat(" dataspace: %s (%d)\n", dataspaceDetails(dataspace).c_str(), dataspace);
+ result.appendFormat(" wideColor=%d, hdr=%d, colorMode=%s, dataspace: %s (%d)\n",
+ mDisplayHasWideColor, mDisplayHasHdr,
+ decodeColorMode(mActiveColorMode).c_str(),
+ dataspaceDetails(dataspace).c_str(), dataspace);
+
String8 surfaceDump;
mDisplaySurface->dumpAsString(surfaceDump);
@@ -506,3 +477,5 @@
viewport.makeInvalid();
frame.makeInvalid();
}
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 737971f..df729f5 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -31,7 +31,7 @@
#include <gui/ISurfaceComposer.h>
#include <hardware/hwcomposer_defs.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#include "RenderArea.h"
#include "RenderEngine/Surface.h"
@@ -77,9 +77,14 @@
int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
+ const sp<ANativeWindow>& nativeWindow,
const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
- bool supportWideColor, bool supportHdr);
+ std::unique_ptr<RE::Surface> renderSurface,
+ int displayWidth,
+ int displayHeight,
+ bool supportWideColor,
+ bool supportHdr,
+ int initialPowerMode);
// clang-format on
~DisplayDevice();
@@ -156,8 +161,8 @@
void setPowerMode(int mode);
bool isDisplayOn() const;
- ColorMode getActiveColorMode() const;
- void setActiveColorMode(ColorMode mode);
+ ui::ColorMode getActiveColorMode() const;
+ void setActiveColorMode(ui::ColorMode mode);
void setCompositionDataSpace(android_dataspace dataspace);
/* ------------------------------------------------------------------------
@@ -231,7 +236,7 @@
// Current active config
int mActiveConfig;
// current active color mode
- ColorMode mActiveColorMode;
+ ui::ColorMode mActiveColorMode;
// Need to know if display is wide-color capable or not.
// Initialized by SurfaceFlinger when the DisplayDevice is created.
@@ -280,7 +285,7 @@
bool needsFiltering() const override { return mDevice->needsFiltering(); }
Rect getSourceCrop() const override { return mSourceCrop; }
bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
- ColorMode getActiveColorMode() const override {
+ ui::ColorMode getActiveColorMode() const override {
return mDevice->getActiveColorMode();
}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 4faba3b..9398bde 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -177,9 +177,9 @@
void FramebufferSurface::dumpAsString(String8& result) const {
Mutex::Autolock lock(mMutex);
- result.appendFormat("FramebufferSurface: dataspace: %s(%d)\n",
+ result.appendFormat(" FramebufferSurface: dataspace: %s(%d)\n",
dataspaceDetails(mDataSpace).c_str(), mDataSpace);
- ConsumerBase::dumpLocked(result, "");
+ ConsumerBase::dumpLocked(result, " ");
}
void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index b7bf964..98daec3 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -129,6 +129,7 @@
auto display = std::make_unique<Display>(
*mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
+ display->setConnected(true);
*outDisplay = display.get();
*format = static_cast<android_pixel_format_t>(intFormat);
mDisplays.emplace(displayId, std::move(display));
@@ -144,31 +145,32 @@
void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
if (connection == Connection::Connected) {
- auto display = getDisplayById(displayId);
- if (display) {
- if (display->isConnected()) {
- ALOGW("Attempt to hotplug connect display %" PRIu64
- " , which is already connected.", displayId);
- } else {
- display->setConnected(true);
- }
- } else {
- DisplayType displayType;
- auto intError = mComposer->getDisplayType(displayId,
- reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
- &displayType));
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
- "Aborting hotplug attempt.",
- displayId, to_string(error).c_str(), intError);
- return;
- }
-
- auto newDisplay = std::make_unique<Display>(
- *mComposer.get(), mCapabilities, displayId, displayType);
- mDisplays.emplace(displayId, std::move(newDisplay));
+ // If we get a hotplug connected event for a display we already have,
+ // destroy the display and recreate it. This will force us to requery
+ // the display params and recreate all layers on that display.
+ auto oldDisplay = getDisplayById(displayId);
+ if (oldDisplay != nullptr && oldDisplay->isConnected()) {
+ ALOGI("Hotplug connecting an already connected display."
+ " Clearing old display state.");
}
+ mDisplays.erase(displayId);
+
+ DisplayType displayType;
+ auto intError = mComposer->getDisplayType(displayId,
+ reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
+ &displayType));
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
+ "Aborting hotplug attempt.",
+ displayId, to_string(error).c_str(), intError);
+ return;
+ }
+
+ auto newDisplay = std::make_unique<Display>(
+ *mComposer.get(), mCapabilities, displayId, displayType);
+ newDisplay->setConnected(true);
+ mDisplays.emplace(displayId, std::move(newDisplay));
} else if (connection == Connection::Disconnected) {
// The display will later be destroyed by a call to
// destroyDisplay(). For now we just mark it disconnected.
@@ -209,16 +211,14 @@
// Display methods
Display::Display(android::Hwc2::Composer& composer,
- const std::unordered_set<Capability>& capabilities,
- hwc2_display_t id, DisplayType type)
- : mComposer(composer),
- mCapabilities(capabilities),
- mId(id),
- mIsConnected(false),
- mType(type)
-{
+ const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
+ DisplayType type)
+ : mComposer(composer),
+ mCapabilities(capabilities),
+ mId(id),
+ mIsConnected(false),
+ mType(type) {
ALOGV("Created display %" PRIu64, id);
- setConnected(true);
}
Display::~Display() {
@@ -362,20 +362,10 @@
return Error::None;
}
-Error Display::getColorModes(std::vector<android::ColorMode>* outModes) const
+Error Display::getColorModes(std::vector<android::ui::ColorMode>* outModes) const
{
- std::vector<android::ColorMode> modes;
- auto intError = mComposer.getColorModes(mId, &modes);
- uint32_t numModes = modes.size();
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- outModes->resize(numModes);
- for (size_t i = 0; i < numModes; i++) {
- (*outModes)[i] = modes[i];
- }
+ auto intError = mComposer.getColorModes(mId, outModes);
+ return static_cast<Error>(intError);
return Error::None;
}
@@ -537,7 +527,7 @@
return static_cast<Error>(intError);
}
-Error Display::setColorMode(android::ColorMode mode)
+Error Display::setColorMode(android::ui::ColorMode mode)
{
auto intError = mComposer.setColorMode(mId, mode);
return static_cast<Error>(intError);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 0fc37ec..71c094a 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -25,7 +25,7 @@
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
#include <utils/Log.h>
@@ -48,6 +48,8 @@
namespace Hwc2 {
class Composer;
}
+
+ class TestableSurfaceFlinger;
}
namespace HWC2 {
@@ -126,8 +128,7 @@
class Display
{
public:
- Display(android::Hwc2::Composer& composer,
- const std::unordered_set<Capability>& capabilities,
+ Display(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
hwc2_display_t id, DisplayType type);
~Display();
@@ -210,7 +211,7 @@
[[clang::warn_unused_result]] Error getChangedCompositionTypes(
std::unordered_map<Layer*, Composition>* outTypes);
[[clang::warn_unused_result]] Error getColorModes(
- std::vector<android::ColorMode>* outModes) const;
+ std::vector<android::ui::ColorMode>* outModes) const;
// Doesn't call into the HWC2 device, so no errors are possible
std::vector<std::shared_ptr<const Config>> getConfigs() const;
@@ -234,7 +235,8 @@
uint32_t slot, const android::sp<android::GraphicBuffer>& target,
const android::sp<android::Fence>& acquireFence,
android_dataspace_t dataspace);
- [[clang::warn_unused_result]] Error setColorMode(android::ColorMode mode);
+ [[clang::warn_unused_result]] Error setColorMode(
+ android::ui::ColorMode mode);
[[clang::warn_unused_result]] Error setColorTransform(
const android::mat4& matrix, android_color_transform_t hint);
[[clang::warn_unused_result]] Error setOutputBuffer(
@@ -245,8 +247,8 @@
[[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes,
uint32_t* outNumRequests);
[[clang::warn_unused_result]] Error presentOrValidate(uint32_t* outNumTypes,
- uint32_t* outNumRequests,
- android::sp<android::Fence>* outPresentFence, uint32_t* state);
+ uint32_t* outNumRequests,
+ android::sp<android::Fence>* outPresentFence, uint32_t* state);
// Other Display methods
@@ -263,6 +265,8 @@
// on this display
Layer* getLayerById(hwc2_layer_t id) const;
+ friend android::TestableSurfaceFlinger;
+
// Member variables
// These are references to data owned by HWC2::Device, which will outlive
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 6d5917d..6bf2ee9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -311,8 +311,8 @@
return config;
}
-std::vector<ColorMode> HWComposer::getColorModes(int32_t displayId) const {
- std::vector<ColorMode> modes;
+std::vector<ui::ColorMode> HWComposer::getColorModes(int32_t displayId) const {
+ std::vector<ui::ColorMode> modes;
if (!isValidDisplay(displayId)) {
ALOGE("getColorModes: Attempted to access invalid display %d",
@@ -324,13 +324,13 @@
if (error != HWC2::Error::None) {
ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
- return std::vector<ColorMode>();
+ return std::vector<ui::ColorMode>();
}
return modes;
}
-status_t HWComposer::setActiveColorMode(int32_t displayId, ColorMode mode) {
+status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode) {
if (!isValidDisplay(displayId)) {
ALOGE("setActiveColorMode: Display %d is not valid", displayId);
return BAD_INDEX;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index c442b2f..0366a0d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -23,7 +23,7 @@
#include <sys/types.h>
#include <ui/Fence.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#include <utils/BitSet.h>
#include <utils/Condition.h>
@@ -159,9 +159,9 @@
std::shared_ptr<const HWC2::Display::Config>
getActiveConfig(int32_t displayId) const;
- std::vector<ColorMode> getColorModes(int32_t displayId) const;
+ std::vector<ui::ColorMode> getColorModes(int32_t displayId) const;
- status_t setActiveColorMode(int32_t displayId, ColorMode mode);
+ status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode);
bool isUsingVrComposer() const;
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index ac54059..fb6cff5 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -26,6 +26,10 @@
namespace android {
+EventControlThread::~EventControlThread() = default;
+
+namespace impl {
+
EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function)
: mSetVSyncEnabled(function) {
pthread_setname_np(mThread.native_handle(), "EventControlThread");
@@ -67,4 +71,5 @@
}
}
+} // namespace impl
} // namespace android
diff --git a/services/surfaceflinger/EventControlThread.h b/services/surfaceflinger/EventControlThread.h
index 321fb79..9be4e7c 100644
--- a/services/surfaceflinger/EventControlThread.h
+++ b/services/surfaceflinger/EventControlThread.h
@@ -16,8 +16,8 @@
#pragma once
-#include <cstddef>
#include <condition_variable>
+#include <cstddef>
#include <functional>
#include <mutex>
#include <thread>
@@ -30,12 +30,22 @@
class EventControlThread {
public:
+ virtual ~EventControlThread();
+
+ virtual void setVsyncEnabled(bool enabled) = 0;
+};
+
+namespace impl {
+
+class EventControlThread final : public android::EventControlThread {
+public:
using SetVSyncEnabledFunction = std::function<void(bool)>;
explicit EventControlThread(SetVSyncEnabledFunction function);
~EventControlThread();
- void setVsyncEnabled(bool enabled);
+ // EventControlThread implementation
+ void setVsyncEnabled(bool enabled) override;
private:
void threadMain();
@@ -51,4 +61,5 @@
std::thread mThread{&EventControlThread::threadMain, this};
};
+} // namespace impl
} // namespace android
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 1f4f5a5..bb9c070 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -217,7 +217,7 @@
if (timestamp) {
// we have a vsync event to dispatch
if (mInterceptVSyncs) {
- mFlinger.mInterceptor.saveVSyncEvent(timestamp);
+ mFlinger.mInterceptor->saveVSyncEvent(timestamp);
}
*event = mVSyncEvent[i];
mVSyncEvent[i].header.timestamp = 0;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 44e60ed..166ac22 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -587,8 +587,10 @@
sp<Layer> parent = mDrawingParent.promote();
if (parent.get()) {
auto& parentState = parent->getDrawingState();
- type = parentState.type;
- appId = parentState.appId;
+ if (parentState.type >= 0 || parentState.appId >= 0) {
+ type = parentState.type;
+ appId = parentState.appId;
+ }
}
error = hwcLayer->setInfo(type, appId);
@@ -626,15 +628,9 @@
transform = Transform(invTransform) * tr * bufferOrientation;
}
- // STOPSHIP (b/72106793): If we have less than 25% scaling, HWC usually needs to use the rotator
- // to handle it. However, there is one guaranteed frame of jank when we switch to using the
- // rotator. In the meantime, we force GL composition instead until we have a better fix for the
- // HWC issue.
- bool extremeScaling = abs(t[0][0]) <= 0.25 || abs(t[1][1]) <= 0.25;
-
// this gives us only the "orientation" component of the transform
const uint32_t orientation = transform.getOrientation();
- if (orientation & Transform::ROT_INVALID || extremeScaling) {
+ if (orientation & Transform::ROT_INVALID) {
// we can only handle simple transformation
hwcInfo.forceClientComposition = true;
} else {
@@ -1313,7 +1309,7 @@
return true;
}
-void Layer::setInfo(uint32_t type, uint32_t appId) {
+void Layer::setInfo(int32_t type, int32_t appId) {
mCurrentState.appId = appId;
mCurrentState.type = type;
mCurrentState.modified = true;
@@ -1492,7 +1488,11 @@
const Layer::State& layerState(getDrawingState());
const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId);
- result.appendFormat(" %10d | ", layerState.z);
+ if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
+ result.appendFormat(" rel %6d | ", layerState.z);
+ } else {
+ result.appendFormat(" %10d | ", layerState.z);
+ }
result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str());
const Rect& frame = hwcInfo.displayFrame;
result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
@@ -1594,7 +1594,7 @@
return true;
}
-void Layer::reparentChildrenForDrawing(const sp<Layer>& newParent) {
+void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) {
for (const sp<Layer>& child : mDrawingChildren) {
child->mDrawingParent = newParent;
}
@@ -1919,6 +1919,8 @@
layerInfo->set_queued_frames(getQueuedFrameCount());
layerInfo->set_refresh_pending(isBufferLatched());
+ layerInfo->set_window_type(state.type);
+ layerInfo->set_app_id(state.appId);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 996d686..9a9b5e6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -66,6 +66,10 @@
class LayerDebugInfo;
class LayerBE;
+namespace impl {
+class SurfaceInterceptor;
+}
+
// ---------------------------------------------------------------------------
struct CompositionInfo {
@@ -203,8 +207,8 @@
Region requestedTransparentRegion;
android_dataspace dataSpace;
- uint32_t appId;
- uint32_t type;
+ int32_t appId;
+ int32_t type;
// If non-null, a Surface this Surface's Z-order is interpreted relative to.
wp<Layer> zOrderRelativeOf;
@@ -285,9 +289,9 @@
void deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber);
void deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber);
bool setOverrideScalingMode(int32_t overrideScalingMode);
- void setInfo(uint32_t type, uint32_t appId);
+ void setInfo(int32_t type, int32_t appId);
bool reparentChildren(const sp<IBinder>& layer);
- void reparentChildrenForDrawing(const sp<Layer>& layer);
+ void setChildrenDrawingParent(const sp<Layer>& layer);
bool reparent(const sp<IBinder>& newParentHandle);
bool detachChildren();
@@ -593,7 +597,7 @@
virtual void onFirstRef();
- friend class SurfaceInterceptor;
+ friend class impl::SurfaceInterceptor;
void commitTransaction(const State& stateToCommit);
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 5a6ff4d..056d381 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -24,6 +24,7 @@
#include <utils/Timers.h>
#include <utils/threads.h>
+#include <gui/DisplayEventReceiver.h>
#include <gui/IDisplayEventConnection.h>
#include "EventThread.h"
@@ -45,6 +46,12 @@
// ---------------------------------------------------------------------------
+MessageQueue::~MessageQueue() = default;
+
+// ---------------------------------------------------------------------------
+
+namespace impl {
+
void MessageQueue::Handler::dispatchRefresh() {
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
@@ -72,17 +79,13 @@
// ---------------------------------------------------------------------------
-MessageQueue::MessageQueue() {}
-
-MessageQueue::~MessageQueue() {}
-
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
-void MessageQueue::setEventThread(EventThread* eventThread) {
+void MessageQueue::setEventThread(android::EventThread* eventThread) {
if (mEventThread == eventThread) {
return;
}
@@ -159,4 +162,5 @@
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace impl
+} // namespace android
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index dcfc716..90d1c72 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -25,7 +25,7 @@
#include <utils/Timers.h>
#include <utils/threads.h>
-#include <gui/DisplayEventReceiver.h>
+#include <gui/IDisplayEventConnection.h>
#include <private/gui/BitTube.h>
#include "Barrier.h"
@@ -34,7 +34,6 @@
namespace android {
-class IDisplayEventConnection;
class EventThread;
class SurfaceFlinger;
@@ -77,6 +76,27 @@
// ---------------------------------------------------------------------------
class MessageQueue {
+public:
+ enum {
+ INVALIDATE = 0,
+ REFRESH = 1,
+ };
+
+ virtual ~MessageQueue();
+
+ virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
+ virtual void setEventThread(EventThread* events) = 0;
+ virtual void waitMessage() = 0;
+ virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
+ virtual void invalidate() = 0;
+ virtual void refresh() = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+namespace impl {
+
+class MessageQueue final : public android::MessageQueue {
class Handler : public MessageHandler {
enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
MessageQueue& mQueue;
@@ -93,7 +113,7 @@
sp<SurfaceFlinger> mFlinger;
sp<Looper> mLooper;
- EventThread* mEventThread;
+ android::EventThread* mEventThread;
sp<IDisplayEventConnection> mEvents;
gui::BitTube mEventTube;
sp<Handler> mHandler;
@@ -102,27 +122,22 @@
int eventReceiver(int fd, int events);
public:
- enum {
- INVALIDATE = 0,
- REFRESH = 1,
- };
+ ~MessageQueue() override = default;
+ void init(const sp<SurfaceFlinger>& flinger) override;
+ void setEventThread(android::EventThread* events) override;
- MessageQueue();
- ~MessageQueue();
- void init(const sp<SurfaceFlinger>& flinger);
- void setEventThread(EventThread* events);
-
- void waitMessage();
- status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0);
+ void waitMessage() override;
+ status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) override;
// sends INVALIDATE message at next VSYNC
- void invalidate();
+ void invalidate() override;
// sends REFRESH message at next VSYNC
- void refresh();
+ void refresh() override;
};
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace impl
+} // namespace android
#endif /* ANDROID_MESSAGE_QUEUE_H */
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index b9c4909..bf0707f 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -1,6 +1,6 @@
#pragma once
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#include "Transform.h"
@@ -32,7 +32,7 @@
int getReqWidth() const { return mReqWidth; };
Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
virtual bool getWideColorSupport() const = 0;
- virtual ColorMode getActiveColorMode() const = 0;
+ virtual ui::ColorMode getActiveColorMode() const = 0;
status_t updateDimensions();
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 7a43ea9..6a34981 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -305,15 +305,24 @@
if (needs.hasToneMapping()) {
fs << R"__SHADER__(
- float ToneMapChannel(const float color) {
+ float CalculateY(const vec3 color) {
+ // BT2020 standard uses the unadjusted KR = 0.2627,
+ // KB = 0.0593 luminance interpretation for RGB conversion.
+ return color.r * 0.262700 + color.g * 0.677998 +
+ color.b * 0.059302;
+ }
+ vec3 ToneMap(const vec3 color) {
const float maxLumi = 10000.0;
const float maxMasteringLumi = 1000.0;
const float maxContentLumi = 1000.0;
const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
const float maxOutLumi = 500.0;
+ // Calculate Y value in XYZ color space.
+ float colorY = CalculateY(color);
+
// convert to nits first
- float nits = color * maxLumi;
+ float nits = colorY * maxLumi;
// clamp to max input luminance
nits = clamp(nits, 0.0, maxInLumi);
@@ -360,12 +369,8 @@
}
// convert back to [0.0, 1.0]
- return nits / maxOutLumi;
- }
-
- vec3 ToneMap(const vec3 color) {
- return vec3(ToneMapChannel(color.r), ToneMapChannel(color.g),
- ToneMapChannel(color.b));
+ float targetY = nits / maxOutLumi;
+ return color * (targetY / max(1e-6, colorY));
}
)__SHADER__";
} else {
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
index 3c29e4b..0d20f1f 100644
--- a/services/surfaceflinger/RenderEngine/Surface.cpp
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -66,7 +66,7 @@
EGLint Surface::queryConfig(EGLint attrib) const {
EGLint value;
- if (!eglGetConfigAttrib(mEGLConfig, mEGLConfig, attrib, &value)) {
+ if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
value = 0;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 11658e8..f180a3b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -104,6 +104,7 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+using ui::ColorMode;
namespace {
class ConditionalLock {
@@ -154,6 +155,32 @@
return std::string(value) == "true";
}
+NativeWindowSurface::~NativeWindowSurface() = default;
+
+namespace impl {
+
+class NativeWindowSurface final : public android::NativeWindowSurface {
+public:
+ static std::unique_ptr<android::NativeWindowSurface> create(
+ const sp<IGraphicBufferProducer>& producer) {
+ return std::make_unique<NativeWindowSurface>(producer);
+ }
+
+ explicit NativeWindowSurface(const sp<IGraphicBufferProducer>& producer)
+ : surface(new Surface(producer, false)) {}
+
+ ~NativeWindowSurface() override = default;
+
+private:
+ sp<ANativeWindow> getNativeWindow() const override { return surface; }
+
+ void preallocateBuffers() override { surface->allocateBuffers(); }
+
+ sp<Surface> surface;
+};
+
+} // namespace impl
+
SurfaceFlingerBE::SurfaceFlingerBE()
: mHwcServiceName(getHwcServiceName()),
mRenderEngine(nullptr),
@@ -163,7 +190,7 @@
mComposerSequenceId(0) {
}
-SurfaceFlinger::SurfaceFlinger()
+SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag)
: BnSurfaceComposer(),
mTransactionFlags(0),
mTransactionPending(false),
@@ -186,7 +213,6 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
- mInterceptor(this),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
@@ -195,7 +221,10 @@
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
mMainThreadId(std::this_thread::get_id()),
- mCreateBufferQueue(&BufferQueue::createBufferQueue) {
+ mCreateBufferQueue(&BufferQueue::createBufferQueue),
+ mCreateNativeWindowSurface(&impl::NativeWindowSurface::create) {}
+
+SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
@@ -282,7 +311,7 @@
void SurfaceFlinger::onFirstRef()
{
- mEventQueue.init(this);
+ mEventQueue->init(this);
}
SurfaceFlinger::~SurfaceFlinger()
@@ -348,7 +377,7 @@
DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
info.displayName = displayName;
mCurrentState.displays.add(token, info);
- mInterceptor.saveDisplayCreation(info);
+ mInterceptor->saveDisplayCreation(info);
return token;
}
@@ -366,7 +395,7 @@
ALOGE("destroyDisplay called for non-virtual display");
return;
}
- mInterceptor.saveDisplayDeletion(info.displayId);
+ mInterceptor->saveDisplayDeletion(info.displayId);
mCurrentState.displays.removeItemsAt(idx);
setTransactionFlags(eDisplayTransactionNeeded);
}
@@ -588,9 +617,10 @@
mSfEventThreadSource =
std::make_unique<DispSyncSource>(&mPrimaryDispSync,
SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+
mSFEventThread = std::make_unique<impl::EventThread>(mSfEventThreadSource.get(), *this, true,
"sfEventThread");
- mEventQueue.setEventThread(mSFEventThread.get());
+ mEventQueue->setEventThread(mSFEventThread.get());
// Get a RenderEngine for the given display / config (can't fail)
getBE().mRenderEngine =
@@ -637,9 +667,8 @@
}
}
- mEventControlThread = std::make_unique<EventControlThread>([this](bool enabled) {
- setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled);
- });
+ mEventControlThread = std::make_unique<impl::EventControlThread>(
+ [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); });
// initialize our drawing state
mDrawingState = mCurrentState;
@@ -1079,10 +1108,10 @@
std::make_unique<impl::EventThread>(mVSyncInjector.get(), *this, false,
"injEventThread");
}
- mEventQueue.setEventThread(mInjectorEventThread.get());
+ mEventQueue->setEventThread(mInjectorEventThread.get());
} else {
ALOGV("VSync Injections disabled");
- mEventQueue.setEventThread(mSFEventThread.get());
+ mEventQueue->setEventThread(mSFEventThread.get());
}
mInjectVSyncs = enable;
@@ -1147,30 +1176,30 @@
// ----------------------------------------------------------------------------
void SurfaceFlinger::waitForEvent() {
- mEventQueue.waitMessage();
+ mEventQueue->waitMessage();
}
void SurfaceFlinger::signalTransaction() {
- mEventQueue.invalidate();
+ mEventQueue->invalidate();
}
void SurfaceFlinger::signalLayerUpdate() {
- mEventQueue.invalidate();
+ mEventQueue->invalidate();
}
void SurfaceFlinger::signalRefresh() {
mRefreshPending = true;
- mEventQueue.refresh();
+ mEventQueue->refresh();
}
status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
nsecs_t reltime, uint32_t /* flags */) {
- return mEventQueue.postMessage(msg, reltime);
+ return mEventQueue->postMessage(msg, reltime);
}
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
nsecs_t reltime, uint32_t /* flags */) {
- status_t res = mEventQueue.postMessage(msg, reltime);
+ status_t res = mEventQueue->postMessage(msg, reltime);
if (res == NO_ERROR) {
msg->wait();
}
@@ -2079,7 +2108,7 @@
}
DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display,
- HWC2::Connection connection) const {
+ HWC2::Connection connection) const {
// Figure out whether the event is for the primary display or an
// external display by matching the Hwc display id against one for a
// connected display. If we did not find a match, we then check what
@@ -2120,23 +2149,23 @@
getBE().mHwc->onHotplug(event.display, displayType, event.connection);
if (event.connection == HWC2::Connection::Connected) {
- ALOGV("Creating built in display %d", displayType);
- ALOGW_IF(mBuiltinDisplays[displayType],
- "Overwriting display token for display type %d", displayType);
- mBuiltinDisplays[displayType] = new BBinder();
- // All non-virtual displays are currently considered secure.
- DisplayDeviceState info(displayType, true);
- info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ?
- "Built-in Screen" : "External Screen";
- mCurrentState.displays.add(mBuiltinDisplays[displayType], info);
- mInterceptor.saveDisplayCreation(info);
+ if (!mBuiltinDisplays[displayType].get()) {
+ ALOGV("Creating built in display %d", displayType);
+ mBuiltinDisplays[displayType] = new BBinder();
+ // All non-virtual displays are currently considered secure.
+ DisplayDeviceState info(displayType, true);
+ info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ?
+ "Built-in Screen" : "External Screen";
+ mCurrentState.displays.add(mBuiltinDisplays[displayType], info);
+ mInterceptor->saveDisplayCreation(info);
+ }
} else {
ALOGV("Removing built in display %d", displayType);
ssize_t idx = mCurrentState.displays.indexOfKey(mBuiltinDisplays[displayType]);
if (idx >= 0) {
const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx));
- mInterceptor.saveDisplayDeletion(info.displayId);
+ mInterceptor->saveDisplayDeletion(info.displayId);
mCurrentState.displays.removeItemsAt(idx);
}
mBuiltinDisplays[displayType].clear();
@@ -2148,6 +2177,84 @@
mPendingHotplugEvents.clear();
}
+sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
+ const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
+ const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
+ bool hasWideColorSupport = false;
+ if (hasWideColorDisplay) {
+ std::vector<ColorMode> modes = getHwComposer().getColorModes(state.type);
+ for (ColorMode colorMode : modes) {
+ switch (colorMode) {
+ case ColorMode::DISPLAY_P3:
+ case ColorMode::ADOBE_RGB:
+ case ColorMode::DCI_P3:
+ hasWideColorSupport = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ bool hasHdrSupport = false;
+ std::unique_ptr<HdrCapabilities> hdrCapabilities =
+ getHwComposer().getHdrCapabilities(state.type);
+ if (hdrCapabilities) {
+ const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
+ auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
+ hasHdrSupport = iter != types.cend();
+ }
+
+ auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
+ auto nativeWindow = nativeWindowSurface->getNativeWindow();
+
+ /*
+ * Create our display's surface
+ */
+ std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface();
+ renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
+ renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL);
+ renderSurface->setNativeWindow(nativeWindow.get());
+ const int displayWidth = renderSurface->queryWidth();
+ const int displayHeight = renderSurface->queryHeight();
+
+ // Make sure that composition can never be stalled by a virtual display
+ // consumer that isn't processing buffers fast enough. We have to do this
+ // in two places:
+ // * Here, in case the display is composed entirely by HWC.
+ // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
+ // window's swap interval in eglMakeCurrent, so they'll override the
+ // interval we set here.
+ if (state.type >= DisplayDevice::DISPLAY_VIRTUAL) {
+ nativeWindow->setSwapInterval(nativeWindow.get(), 0);
+ }
+
+ // virtual displays are always considered enabled
+ auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL
+ : HWC_POWER_MODE_OFF;
+
+ sp<DisplayDevice> hw =
+ new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
+ dispSurface, std::move(renderSurface), displayWidth, displayHeight,
+ hasWideColorSupport, hasHdrSupport, initialPowerMode);
+
+ if (maxFrameBufferAcquiredBuffers >= 3) {
+ nativeWindowSurface->preallocateBuffers();
+ }
+
+ ColorMode defaultColorMode = ColorMode::NATIVE;
+ if (hasWideColorSupport) {
+ defaultColorMode = ColorMode::SRGB;
+ }
+ setActiveColorModeInternal(hw, defaultColorMode);
+ hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
+ hw->setLayerStack(state.layerStack);
+ hw->setProjection(state.orientation, state.viewport, state.frame);
+ hw->setDisplayName(state.displayName);
+
+ return hw;
+}
+
void SurfaceFlinger::processDisplayChangesLocked() {
// here we take advantage of Vector's copy-on-write semantics to
// improve performance by skipping the transaction entirely when
@@ -2270,50 +2377,10 @@
}
const wp<IBinder>& display(curr.keyAt(i));
-
if (dispSurface != nullptr) {
- bool hasWideColorSupport = false;
- if (hasWideColorDisplay) {
- std::vector<ColorMode> modes =
- getHwComposer().getColorModes(state.type);
- for (ColorMode colorMode : modes) {
- switch (colorMode) {
- case ColorMode::DISPLAY_P3:
- case ColorMode::ADOBE_RGB:
- case ColorMode::DCI_P3:
- hasWideColorSupport = true;
- break;
- default:
- break;
- }
- }
- }
-
- bool hasHdrSupport = false;
- std::unique_ptr<HdrCapabilities> hdrCapabilities =
- getHwComposer().getHdrCapabilities(state.type);
- if (hdrCapabilities) {
- const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
- auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
- hasHdrSupport = iter != types.cend();
- }
-
- sp<DisplayDevice> hw =
- new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
- dispSurface, producer, hasWideColorSupport,
- hasHdrSupport);
-
- ColorMode defaultColorMode = ColorMode::NATIVE;
- if (hasWideColorSupport) {
- defaultColorMode = ColorMode::SRGB;
- }
- setActiveColorModeInternal(hw, defaultColorMode);
- hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
- hw->setLayerStack(state.layerStack);
- hw->setProjection(state.orientation, state.viewport, state.frame);
- hw->setDisplayName(state.displayName);
-
- mDisplays.add(display, hw);
+ mDisplays.add(display,
+ setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface,
+ producer));
if (!state.isVirtualDisplay()) {
mEventThread->onHotplugReceived(state.type, true);
}
@@ -3063,8 +3130,8 @@
}
if (transactionFlags) {
- if (mInterceptor.isEnabled()) {
- mInterceptor.saveTransaction(states, mCurrentState.displays, displays, flags);
+ if (mInterceptor->isEnabled()) {
+ mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags);
}
// this triggers the transaction
@@ -3318,7 +3385,7 @@
const String8& name,
const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
+ int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
{
if (int32_t(w|h) < 0) {
@@ -3367,7 +3434,7 @@
if (result != NO_ERROR) {
return result;
}
- mInterceptor.saveSurfaceCreation(layer);
+ mInterceptor->saveSurfaceCreation(layer);
setTransactionFlags(eTransactionNeeded);
return result;
@@ -3439,7 +3506,7 @@
status_t err = NO_ERROR;
sp<Layer> l(client->getLayerUser(handle));
if (l != nullptr) {
- mInterceptor.saveSurfaceDeletion(l);
+ mInterceptor->saveSurfaceDeletion(l);
err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -3521,14 +3588,14 @@
return;
}
- if (mInterceptor.isEnabled()) {
+ if (mInterceptor->isEnabled()) {
ConditionalLock lock(mStateLock, !stateLockHeld);
ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
if (idx < 0) {
ALOGW("Surface Interceptor SavePowerMode: invalid display token");
return;
}
- mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
+ mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
}
if (currentMode == HWC_POWER_MODE_OFF) {
@@ -3590,6 +3657,7 @@
ALOGE("Attempting to set unknown power mode: %d\n", mode);
getHwComposer().setPowerMode(type, mode);
}
+ ALOGD("Finished set power mode=%d, type=%d", mode, hw->getDisplayType());
}
void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
@@ -3980,7 +4048,8 @@
LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- result.append(LayerProtoParser::layersToString(layerTree).c_str());
+ result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str());
+ result.append("\n");
/*
* Dump Display state
@@ -3993,6 +4062,7 @@
const sp<const DisplayDevice>& hw(mDisplays[dpy]);
hw->dump(result);
}
+ result.append("\n");
/*
* Dump SurfaceFlinger global state
@@ -4332,11 +4402,11 @@
n = data.readInt32();
if (n) {
ALOGV("Interceptor enabled");
- mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
+ mInterceptor->enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
}
else{
ALOGV("Interceptor disabled");
- mInterceptor.disable();
+ mInterceptor->disable();
}
return NO_ERROR;
}
@@ -4460,9 +4530,9 @@
ReparentForDrawing(const sp<Layer>& oldParent, const sp<Layer>& newParent)
: oldParent(oldParent), newParent(newParent) {
- oldParent->reparentChildrenForDrawing(newParent);
+ oldParent->setChildrenDrawingParent(newParent);
}
- ~ReparentForDrawing() { newParent->reparentChildrenForDrawing(oldParent); }
+ ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); }
};
void render(std::function<void()> drawLayers) override {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 51001e5..448509b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -118,6 +118,19 @@
eTransactionMask = 0x07
};
+// A thin interface to abstract creating instances of Surface (gui/Surface.h) to
+// use as a NativeWindow.
+class NativeWindowSurface {
+public:
+ virtual ~NativeWindowSurface();
+
+ // Gets the NativeWindow to use for the surface.
+ virtual sp<ANativeWindow> getNativeWindow() const = 0;
+
+ // Indicates that the surface should allocate its buffers now.
+ virtual void preallocateBuffers() = 0;
+};
+
class SurfaceFlingerBE
{
public:
@@ -265,6 +278,9 @@
return "SurfaceFlinger";
}
+ struct SkipInitializationTag {};
+ static constexpr SkipInitializationTag SkipInitialization;
+ explicit SurfaceFlinger(SkipInitializationTag) ANDROID_API;
SurfaceFlinger() ANDROID_API;
// must be called before clients can connect
@@ -394,9 +410,9 @@
Vector<DisplayInfo>* configs);
virtual int getActiveConfig(const sp<IBinder>& display);
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<ColorMode>* configs);
- virtual ColorMode getActiveColorMode(const sp<IBinder>& display);
- virtual status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode);
+ Vector<ui::ColorMode>* configs);
+ virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display);
+ virtual status_t setActiveColorMode(const sp<IBinder>& display, ui::ColorMode colorMode);
virtual void setPowerMode(const sp<IBinder>& display, int mode);
virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
virtual status_t clearAnimationFrameStats();
@@ -446,7 +462,7 @@
bool stateLockHeld);
// Called on the main thread in response to setActiveColorMode()
- void setActiveColorModeInternal(const sp<DisplayDevice>& hw, ColorMode colorMode);
+ void setActiveColorModeInternal(const sp<DisplayDevice>& hw, ui::ColorMode colorMode);
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
@@ -485,7 +501,7 @@
*/
status_t createLayer(const String8& name, const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
+ int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
status_t createBufferLayer(const sp<Client>& client, const String8& name,
@@ -619,7 +635,7 @@
// Given a dataSpace, returns the appropriate color_mode to use
// to display that dataSpace.
- ColorMode pickColorMode(android_dataspace dataSpace) const;
+ ui::ColorMode pickColorMode(android_dataspace dataSpace) const;
android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b,
bool hasHdr) const;
@@ -643,6 +659,10 @@
*/
DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display,
HWC2::Connection connection) const;
+ sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId,
+ const DisplayDeviceState& state,
+ const sp<DisplaySurface>& dispSurface,
+ const sp<IGraphicBufferProducer>& producer);
void processDisplayChangesLocked();
void processDisplayHotplugEventsLocked();
@@ -774,7 +794,8 @@
bool mBootFinished;
bool mForceFullDamage;
bool mPropagateBackpressure = true;
- SurfaceInterceptor mInterceptor;
+ std::unique_ptr<SurfaceInterceptor> mInterceptor =
+ std::make_unique<impl::SurfaceInterceptor>(this);
SurfaceTracing mTracing;
bool mUseHwcVirtualDisplays = false;
@@ -782,7 +803,7 @@
bool mLayerTripleBufferingDisabled = false;
// these are thread safe
- mutable MessageQueue mEventQueue;
+ mutable std::unique_ptr<MessageQueue> mEventQueue{std::make_unique<impl::MessageQueue>()};
FrameTracker mAnimFrameTracker;
DispSync mPrimaryDispSync;
@@ -833,6 +854,10 @@
bool /* consumerIsSurfaceFlinger */)>;
CreateBufferQueueFunction mCreateBufferQueue;
+ using CreateNativeWindowSurfaceFunction =
+ std::function<std::unique_ptr<NativeWindowSurface>(const sp<IGraphicBufferProducer>&)>;
+ CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
+
SurfaceFlingerBE mBE;
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index eeb4929..4596a21 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -31,6 +31,10 @@
// ----------------------------------------------------------------------------
+SurfaceInterceptor::~SurfaceInterceptor() = default;
+
+namespace impl {
+
SurfaceInterceptor::SurfaceInterceptor(SurfaceFlinger* flinger)
: mFlinger(flinger)
{
@@ -593,5 +597,5 @@
addPowerModeUpdateLocked(createTraceIncrementLocked(), displayId, mode);
}
-
+} // namespace impl
} // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 30ebcc6..96defcc 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -21,48 +21,89 @@
#include <mutex>
+#include <gui/LayerState.h>
+
+#include <utils/KeyedVector.h>
#include <utils/SortedVector.h>
+#include <utils/StrongPointer.h>
#include <utils/Vector.h>
+#include "DisplayDevice.h"
+
namespace android {
class BufferItem;
class Layer;
class SurfaceFlinger;
+struct ComposerState;
+struct DisplayDeviceState;
struct DisplayState;
struct layer_state_t;
constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat";
+class SurfaceInterceptor {
+public:
+ virtual ~SurfaceInterceptor();
+
+ // Both vectors are used to capture the current state of SF as the initial snapshot in the trace
+ virtual void enable(const SortedVector<sp<Layer>>& layers,
+ const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>& displays) = 0;
+ virtual void disable() = 0;
+ virtual bool isEnabled() = 0;
+
+ // Intercept display and surface transactions
+ virtual void saveTransaction(
+ const Vector<ComposerState>& stateUpdates,
+ const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>& displays,
+ const Vector<DisplayState>& changedDisplays, uint32_t flags) = 0;
+
+ // Intercept surface data
+ virtual void saveSurfaceCreation(const sp<const Layer>& layer) = 0;
+ virtual void saveSurfaceDeletion(const sp<const Layer>& layer) = 0;
+ virtual void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
+ uint64_t frameNumber) = 0;
+
+ // Intercept display data
+ virtual void saveDisplayCreation(const DisplayDeviceState& info) = 0;
+ virtual void saveDisplayDeletion(int32_t displayId) = 0;
+ virtual void savePowerModeUpdate(int32_t displayId, int32_t mode) = 0;
+ virtual void saveVSyncEvent(nsecs_t timestamp) = 0;
+};
+
+namespace impl {
+
/*
* SurfaceInterceptor intercepts and stores incoming streams of window
* properties on SurfaceFlinger.
*/
-class SurfaceInterceptor {
+class SurfaceInterceptor final : public android::SurfaceInterceptor {
public:
- SurfaceInterceptor(SurfaceFlinger* const flinger);
+ explicit SurfaceInterceptor(SurfaceFlinger* const flinger);
+ ~SurfaceInterceptor() override = default;
+
// Both vectors are used to capture the current state of SF as the initial snapshot in the trace
void enable(const SortedVector<sp<Layer>>& layers,
- const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays);
- void disable();
- bool isEnabled();
+ const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>& displays) override;
+ void disable() override;
+ bool isEnabled() override;
// Intercept display and surface transactions
void saveTransaction(const Vector<ComposerState>& stateUpdates,
- const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
- const Vector<DisplayState>& changedDisplays, uint32_t flags);
+ const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>& displays,
+ const Vector<DisplayState>& changedDisplays, uint32_t flags) override;
// Intercept surface data
- void saveSurfaceCreation(const sp<const Layer>& layer);
- void saveSurfaceDeletion(const sp<const Layer>& layer);
+ void saveSurfaceCreation(const sp<const Layer>& layer) override;
+ void saveSurfaceDeletion(const sp<const Layer>& layer) override;
void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
- uint64_t frameNumber);
+ uint64_t frameNumber) override;
// Intercept display data
- void saveDisplayCreation(const DisplayDeviceState& info);
- void saveDisplayDeletion(int32_t displayId);
- void savePowerModeUpdate(int32_t displayId, int32_t mode);
- void saveVSyncEvent(nsecs_t timestamp);
+ void saveDisplayCreation(const DisplayDeviceState& info) override;
+ void saveDisplayDeletion(int32_t displayId) override;
+ void savePowerModeUpdate(int32_t displayId, int32_t mode) override;
+ void saveVSyncEvent(nsecs_t timestamp) override;
private:
// The creation increments of Surfaces and Displays do not contain enough information to capture
@@ -134,6 +175,7 @@
SurfaceFlinger* const mFlinger;
};
-}
+} // namespace impl
+} // namespace android
#endif // ANDROID_SURFACEINTERCEPTOR_H
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index bf37e1e..1383d28 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include <android-base/stringprintf.h>
#include <layerproto/LayerProtoParser.h>
#include <ui/DebugUtils.h>
@@ -24,7 +23,7 @@
namespace android {
namespace surfaceflinger {
-bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
+bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
uint32_t ls = lhs->layerStack;
uint32_t rs = rhs->layerStack;
if (ls != rs) return ls < rs;
@@ -38,20 +37,25 @@
return lhs->id < rhs->id;
}
-std::vector<const LayerProtoParser::Layer*> LayerProtoParser::generateLayerTree(
+bool sortLayerUniquePtrs(const std::unique_ptr<LayerProtoParser::Layer>& lhs,
+ const std::unique_ptr<LayerProtoParser::Layer>& rhs) {
+ return sortLayers(lhs.get(), rhs.get());
+}
+
+std::vector<std::unique_ptr<LayerProtoParser::Layer>> LayerProtoParser::generateLayerTree(
const LayersProto& layersProto) {
- auto layerMap = generateMap(layersProto);
+ std::unordered_map<int32_t, LayerProtoParser::Layer*> layerMap = generateMap(layersProto);
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers;
- std::vector<const Layer*> layers;
- std::for_each(layerMap.begin(), layerMap.end(),
- [&](const std::pair<const int32_t, Layer*>& ref) {
- if (ref.second->parent == nullptr) {
- // only save top level layers
- layers.push_back(ref.second);
- }
- });
+ for (std::pair<int32_t, Layer*> kv : layerMap) {
+ if (kv.second->parent == nullptr) {
+ // Make unique_ptr for top level layers since they are not children. This ensures there
+ // will only be one unique_ptr made for each layer.
+ layers.push_back(std::unique_ptr<Layer>(kv.second));
+ }
+ }
- std::sort(layers.begin(), layers.end(), sortLayers);
+ std::sort(layers.begin(), layers.end(), sortLayerUniquePtrs);
return layers;
}
@@ -102,6 +106,8 @@
layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer());
layer->queuedFrames = layerProto.queued_frames();
layer->refreshPending = layerProto.refresh_pending();
+ layer->windowType = layerProto.window_type();
+ layer->appId = layerProto.app_id();
return layer;
}
@@ -155,63 +161,61 @@
for (int i = 0; i < layerProto.children_size(); i++) {
if (layerMap.count(layerProto.children(i)) > 0) {
- auto childLayer = layerMap[layerProto.children(i)];
- currLayer->children.push_back(childLayer);
+ // Only make unique_ptrs for children since they are guaranteed to be unique, only one
+ // parent per child. This ensures there will only be one unique_ptr made for each layer.
+ currLayer->children.push_back(std::unique_ptr<Layer>(layerMap[layerProto.children(i)]));
}
}
for (int i = 0; i < layerProto.relatives_size(); i++) {
if (layerMap.count(layerProto.relatives(i)) > 0) {
- auto relativeLayer = layerMap[layerProto.relatives(i)];
- currLayer->relatives.push_back(relativeLayer);
+ currLayer->relatives.push_back(layerMap[layerProto.relatives(i)]);
}
}
if (layerProto.has_parent()) {
if (layerMap.count(layerProto.parent()) > 0) {
- auto parentLayer = layerMap[layerProto.parent()];
- currLayer->parent = parentLayer;
+ currLayer->parent = layerMap[layerProto.parent()];
}
}
if (layerProto.has_z_order_relative_of()) {
if (layerMap.count(layerProto.z_order_relative_of()) > 0) {
- auto relativeLayer = layerMap[layerProto.z_order_relative_of()];
- currLayer->zOrderRelativeOf = relativeLayer;
+ currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()];
}
}
}
std::string LayerProtoParser::layersToString(
- const std::vector<const LayerProtoParser::Layer*> layers) {
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers) {
std::string result;
- for (const LayerProtoParser::Layer* layer : layers) {
+ for (std::unique_ptr<LayerProtoParser::Layer>& layer : layers) {
if (layer->zOrderRelativeOf != nullptr) {
continue;
}
- result.append(layerToString(layer).c_str());
+ result.append(layerToString(layer.get()).c_str());
}
return result;
}
-std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) {
+std::string LayerProtoParser::layerToString(LayerProtoParser::Layer* layer) {
std::string result;
- std::vector<const Layer*> traverse(layer->relatives);
- for (const LayerProtoParser::Layer* child : layer->children) {
+ std::vector<Layer*> traverse(layer->relatives);
+ for (std::unique_ptr<LayerProtoParser::Layer>& child : layer->children) {
if (child->zOrderRelativeOf != nullptr) {
continue;
}
- traverse.push_back(child);
+ traverse.push_back(child.get());
}
std::sort(traverse.begin(), traverse.end(), sortLayers);
size_t i = 0;
for (; i < traverse.size(); i++) {
- const auto& relative = traverse[i];
+ auto& relative = traverse[i];
if (relative->z >= 0) {
break;
}
@@ -220,7 +224,7 @@
result.append(layer->to_string().c_str());
result.append("\n");
for (; i < traverse.size(); i++) {
- const auto& relative = traverse[i];
+ auto& relative = traverse[i];
result.append(layerToString(relative).c_str());
}
@@ -269,7 +273,7 @@
finalCrop.to_string().c_str());
StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
- StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str());
+ StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str());
StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
static_cast<double>(color.r), static_cast<double>(color.g),
static_cast<double>(color.b), static_cast<double>(color.a), flags);
@@ -279,7 +283,8 @@
StringAppendF(&result, " zOrderRelativeOf=%s\n",
zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str());
- StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, refreshPending);
+ StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending);
+ StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId);
return result;
}
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 78c6cd1..b56a6fb 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -18,6 +18,7 @@
#include <math/vec4.h>
+#include <memory>
#include <unordered_map>
#include <vector>
@@ -68,8 +69,8 @@
public:
int32_t id;
std::string name;
- std::vector<const Layer*> children;
- std::vector<const Layer*> relatives;
+ std::vector<std::unique_ptr<Layer>> children;
+ std::vector<Layer*> relatives;
std::string type;
LayerProtoParser::Region transparentRegion;
LayerProtoParser::Region visibleRegion;
@@ -95,12 +96,14 @@
LayerProtoParser::ActiveBuffer activeBuffer;
int32_t queuedFrames;
bool refreshPending;
+ int32_t windowType;
+ int32_t appId;
std::string to_string() const;
};
- static std::vector<const Layer*> generateLayerTree(const LayersProto& layersProto);
- static std::string layersToString(const std::vector<const LayerProtoParser::Layer*> layers);
+ static std::vector<std::unique_ptr<Layer>> generateLayerTree(const LayersProto& layersProto);
+ static std::string layersToString(std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers);
private:
static std::unordered_map<int32_t, Layer*> generateMap(const LayersProto& layersProto);
@@ -113,7 +116,7 @@
static void updateChildrenAndRelative(const LayerProto& layerProto,
std::unordered_map<int32_t, Layer*>& layerMap);
- static std::string layerToString(const LayerProtoParser::Layer* layer);
+ static std::string layerToString(LayerProtoParser::Layer* layer);
};
} // namespace surfaceflinger
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index d27dc9b..f18386b 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -64,6 +64,8 @@
// The number of frames available.
optional int32 queued_frames = 28;
optional bool refresh_pending = 29;
+ optional int32 window_type = 30;
+ optional int32 app_id = 31;
}
message PositionProto {
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 7d3da32..7523399 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -33,6 +33,7 @@
"libEGL",
"libGLESv2",
"libgui",
+ "liblayers_proto",
"liblog",
"libprotobuf-cpp-full",
"libui",
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
index 33dd2f5..4577153 100644
--- a/services/surfaceflinger/tests/Stress_test.cpp
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -22,7 +22,7 @@
#include <thread>
#include <functional>
-
+#include <layerproto/LayerProtoParser.h>
namespace android {
@@ -47,4 +47,66 @@
}
}
+surfaceflinger::LayersProto generateLayerProto() {
+ surfaceflinger::LayersProto layersProto;
+ std::array<surfaceflinger::LayerProto*, 10> layers = {};
+ for (size_t i = 0; i < layers.size(); ++i) {
+ layers[i] = layersProto.add_layers();
+ layers[i]->set_id(i);
+ }
+
+ layers[0]->add_children(1);
+ layers[1]->set_parent(0);
+ layers[0]->add_children(2);
+ layers[2]->set_parent(0);
+ layers[0]->add_children(3);
+ layers[3]->set_parent(0);
+ layers[2]->add_children(4);
+ layers[4]->set_parent(2);
+ layers[3]->add_children(5);
+ layers[5]->set_parent(3);
+ layers[5]->add_children(6);
+ layers[6]->set_parent(5);
+ layers[5]->add_children(7);
+ layers[7]->set_parent(5);
+ layers[6]->add_children(8);
+ layers[8]->set_parent(6);
+
+ layers[4]->set_z_order_relative_of(3);
+ layers[3]->add_relatives(4);
+ layers[8]->set_z_order_relative_of(9);
+ layers[9]->add_relatives(8);
+ layers[3]->set_z_order_relative_of(1);
+ layers[1]->add_relatives(3);
+
+/* ----------------------------
+ * - 0 - - 9 -
+ * / | \
+ * 1 2 3(1)
+ * | |
+ * 4(3) 5
+ * / \
+ * 6 7
+ * |
+ * 8(9)
+ * -------------------------- */
+
+ return layersProto;
+}
+
+TEST(LayerProtoStress, mem_info) {
+ std::string cmd = "dumpsys meminfo ";
+ cmd += std::to_string(getpid());
+ system(cmd.c_str());
+ for (int i = 0; i < 100000; i++) {
+ surfaceflinger::LayersProto layersProto = generateLayerProto();
+ auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto);
+ // Allow some layerTrees to just fall out of scope (instead of std::move)
+ if (i % 2) {
+ surfaceflinger::LayerProtoParser::layersToString(std::move(layerTree));
+ }
+ }
+ system(cmd.c_str());
+}
+
}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index fd21991..4e9db72 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2384,6 +2384,17 @@
verify();
}
+TEST_F(ScreenCaptureChildOnlyTest, RegressionTest76099859) {
+ SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true);
+
+ // Even though the parent is hidden we should still capture the child.
+ verify();
+
+ // Verify everything was properly hidden when rendering the full-screen.
+ screenshot()->expectBGColor(0,0);
+}
+
+
TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
auto fgHandle = mFGSurfaceControl->getHandle();
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index 86e2e1e..b3f1b69 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -22,7 +22,7 @@
#include <android-base/unique_fd.h>
#include <hardware/hardware.h>
#include <sync/sync.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
@@ -35,7 +35,7 @@
#include "Hwc2TestClientTarget.h"
#include "Hwc2TestVirtualDisplay.h"
-using android::ColorMode;
+using android::ui::ColorMode;
void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
hwc2_display_t display, int32_t connected);
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 353b245..8ffc5ad 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -21,10 +21,16 @@
":libsurfaceflinger_sources",
"DisplayTransactionTest.cpp",
"MockComposer.cpp",
+ "MockDisplaySurface.cpp",
+ "MockEventControlThread.cpp",
"MockEventThread.cpp",
"MockGraphicBufferConsumer.cpp",
"MockGraphicBufferProducer.cpp",
+ "MockMessageQueue.cpp",
+ "MockNativeWindow.cpp",
+ "MockNativeWindowSurface.cpp",
"MockRenderEngine.cpp",
+ "MockSurfaceInterceptor.cpp",
],
static_libs: [
"libgmock",
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 21590df..c048c58 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -21,12 +21,19 @@
#include <gtest/gtest.h>
#include <log/log.h>
+#include "system/window.h"
#include "MockComposer.h"
+#include "MockDisplaySurface.h"
+#include "MockEventControlThread.h"
#include "MockEventThread.h"
#include "MockGraphicBufferConsumer.h"
#include "MockGraphicBufferProducer.h"
+#include "MockMessageQueue.h"
+#include "MockNativeWindow.h"
+#include "MockNativeWindowSurface.h"
#include "MockRenderEngine.h"
+#include "MockSurfaceInterceptor.h"
#include "TestableSurfaceFlinger.h"
namespace android {
@@ -39,36 +46,119 @@
using testing::Return;
using testing::SetArgPointee;
+using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::Hdr;
using android::Hwc2::Error;
using android::Hwc2::IComposer;
using android::Hwc2::IComposerClient;
+using HWC2Display = TestableSurfaceFlinger::HWC2Display;
+using HotplugEvent = TestableSurfaceFlinger::HotplugEvent;
+
constexpr int32_t DEFAULT_REFRESH_RATE = 1666666666;
constexpr int32_t DEFAULT_DPI = 320;
+constexpr int DEFAULT_CONFIG_ID = 0;
+
class DisplayTransactionTest : public testing::Test {
protected:
DisplayTransactionTest();
~DisplayTransactionTest() override;
- void setupComposer(int virtualDisplayCount);
- void setupPrimaryDisplay(int width, int height);
+ // --------------------------------------------------------------------
+ // Precondition helpers
- void expectFramebufferQueuePairCreation(int width, int height);
+ void setupComposer(int virtualDisplayCount);
+ void setupFakeHwcDisplay(hwc2_display_t displayId, DisplayDevice::DisplayType type, int width,
+ int height);
+
+ struct FakeDisplayDeviceFactory {
+ public:
+ FakeDisplayDeviceFactory(TestableSurfaceFlinger& flinger, sp<BBinder>& displayToken,
+ DisplayDevice::DisplayType type, int hwcId)
+ : mFlinger(flinger), mDisplayToken(displayToken), mType(type), mHwcId(hwcId) {}
+
+ sp<DisplayDevice> build() {
+ return new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, false, mDisplayToken,
+ mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
+ 0, false, false, HWC_POWER_MODE_NORMAL);
+ }
+
+ FakeDisplayDeviceFactory& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
+ mNativeWindow = nativeWindow;
+ return *this;
+ }
+
+ FakeDisplayDeviceFactory& setDisplaySurface(const sp<DisplaySurface>& displaySurface) {
+ mDisplaySurface = displaySurface;
+ return *this;
+ }
+
+ FakeDisplayDeviceFactory& setRenderSurface(std::unique_ptr<RE::Surface> renderSurface) {
+ mRenderSurface = std::move(renderSurface);
+ return *this;
+ }
+
+ TestableSurfaceFlinger& mFlinger;
+ sp<BBinder>& mDisplayToken;
+ DisplayDevice::DisplayType mType;
+ int mHwcId;
+ sp<ANativeWindow> mNativeWindow;
+ sp<DisplaySurface> mDisplaySurface;
+ std::unique_ptr<RE::Surface> mRenderSurface;
+ };
+
+ sp<BBinder> setupFakeExistingPhysicalDisplay(hwc2_display_t displayId,
+ DisplayDevice::DisplayType type);
+
+ void setupFakeBufferQueueFactory();
+ void setupFakeNativeWindowSurfaceFactory(int displayWidth, int displayHeight, bool critical,
+ bool async);
+ void expectFramebufferUsageSet(int width, int height, int grallocUsage);
+ void expectHwcHotplugCalls(hwc2_display_t displayId, int displayWidth, int displayHeight);
+
+ // --------------------------------------------------------------------
+ // Call expectation helpers
+
+ void expectRESurfaceCreationCalls();
+ void expectPhysicalDisplayDeviceCreationCalls(hwc2_display_t displayId, int displayWidth,
+ int displayHeight, bool critical, bool async);
+
+ // --------------------------------------------------------------------
+ // Postcondition helpers
+
+ bool hasTransactionFlagSet(int flag);
+ bool hasDisplayDevice(sp<IBinder> displayToken);
+ sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken);
+ bool hasCurrentDisplayState(sp<IBinder> displayToken);
+ const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken);
+ bool hasDrawingDisplayState(sp<IBinder> displayToken);
+ const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken);
+
+ // --------------------------------------------------------------------
+ // Test instances
+
+ std::unordered_set<HWC2::Capability> mCapabilities;
TestableSurfaceFlinger mFlinger;
mock::EventThread* mEventThread = new mock::EventThread();
+ mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
// These mocks are created by the test, but are destroyed by SurfaceFlinger
// by virtue of being stored into a std::unique_ptr. However we still need
// to keep a reference to them for use in setting up call expectations.
RE::mock::RenderEngine* mRenderEngine = new RE::mock::RenderEngine();
Hwc2::mock::Composer* mComposer = new Hwc2::mock::Composer();
+ mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
+ mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();
// These mocks are created only when expected to be created via a factory.
sp<mock::GraphicBufferConsumer> mConsumer;
sp<mock::GraphicBufferProducer> mProducer;
+ mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
+ sp<mock::NativeWindow> mNativeWindow;
+ RE::mock::Surface* mRenderSurface = nullptr;
+ std::vector<std::unique_ptr<HWC2Display>> mFakeHwcDisplays;
};
DisplayTransactionTest::DisplayTransactionTest() {
@@ -80,8 +170,16 @@
ADD_FAILURE() << "Unexpected request to create a buffer queue.";
});
+ mFlinger.setCreateNativeWindowSurface([](auto) {
+ ADD_FAILURE() << "Unexpected request to create a native window surface.";
+ return nullptr;
+ });
+
+ mFlinger.mutableEventControlThread().reset(mEventControlThread);
mFlinger.mutableEventThread().reset(mEventThread);
+ mFlinger.mutableEventQueue().reset(mMessageQueue);
mFlinger.setupRenderEngine(std::unique_ptr<RE::RenderEngine>(mRenderEngine));
+ mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);
setupComposer(0);
}
@@ -101,40 +199,49 @@
Mock::VerifyAndClear(mComposer);
}
-void DisplayTransactionTest::setupPrimaryDisplay(int width, int height) {
- EXPECT_CALL(*mComposer, getDisplayType(DisplayDevice::DISPLAY_PRIMARY, _))
- .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
- Return(Error::NONE)));
- EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
- EXPECT_CALL(*mComposer, getDisplayConfigs(_, _))
- .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{0}), Return(Error::NONE)));
- EXPECT_CALL(*mComposer,
- getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
- IComposerClient::Attribute::WIDTH, _))
- .WillOnce(DoAll(SetArgPointee<3>(width), Return(Error::NONE)));
- EXPECT_CALL(*mComposer,
- getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
- IComposerClient::Attribute::HEIGHT, _))
- .WillOnce(DoAll(SetArgPointee<3>(height), Return(Error::NONE)));
- EXPECT_CALL(*mComposer,
- getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
- IComposerClient::Attribute::VSYNC_PERIOD, _))
- .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
- EXPECT_CALL(*mComposer,
- getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
- IComposerClient::Attribute::DPI_X, _))
- .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
- EXPECT_CALL(*mComposer,
- getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
- IComposerClient::Attribute::DPI_Y, _))
- .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+void DisplayTransactionTest::setupFakeHwcDisplay(hwc2_display_t displayId,
+ DisplayDevice::DisplayType type, int width,
+ int height) {
+ auto display = std::make_unique<HWC2Display>(*mComposer, mCapabilities, displayId,
+ HWC2::DisplayType::Physical);
+ display->mutableIsConnected() = true;
+ display->mutableConfigs().emplace(DEFAULT_CONFIG_ID,
+ HWC2::Display::Config::Builder(*display, DEFAULT_CONFIG_ID)
+ .setWidth(width)
+ .setHeight(height)
+ .setVsyncPeriod(DEFAULT_REFRESH_RATE)
+ .setDpiX(DEFAULT_DPI)
+ .setDpiY(DEFAULT_DPI)
+ .build());
- mFlinger.setupPrimaryDisplay();
+ mFlinger.mutableHwcDisplayData()[type].reset();
+ mFlinger.mutableHwcDisplayData()[type].hwcDisplay = display.get();
+ mFlinger.mutableHwcDisplaySlots().emplace(displayId, type);
- Mock::VerifyAndClear(mComposer);
+ mFakeHwcDisplays.push_back(std::move(display));
}
-void DisplayTransactionTest::expectFramebufferQueuePairCreation(int width, int height) {
+sp<BBinder> DisplayTransactionTest::setupFakeExistingPhysicalDisplay(
+ hwc2_display_t displayId, DisplayDevice::DisplayType type) {
+ setupFakeHwcDisplay(displayId, type, 0, 0);
+
+ sp<BBinder> displayToken = new BBinder();
+ mFlinger.mutableBuiltinDisplays()[type] = displayToken;
+ mFlinger.mutableDisplays()
+ .add(displayToken,
+ FakeDisplayDeviceFactory(mFlinger, displayToken, type, type).build());
+
+ DisplayDeviceState state(type, true);
+ mFlinger.mutableCurrentState().displays.add(displayToken, state);
+ mFlinger.mutableDrawingState().displays.add(displayToken, state);
+
+ return displayToken;
+}
+
+void DisplayTransactionTest::setupFakeBufferQueueFactory() {
+ // This setup is only expected once per test.
+ ASSERT_TRUE(mConsumer == nullptr && mProducer == nullptr);
+
mConsumer = new mock::GraphicBufferConsumer();
mProducer = new mock::GraphicBufferProducer();
@@ -142,64 +249,187 @@
*outProducer = mProducer;
*outConsumer = mConsumer;
});
+}
+void DisplayTransactionTest::setupFakeNativeWindowSurfaceFactory(int displayWidth,
+ int displayHeight, bool critical,
+ bool async) {
+ // This setup is only expected once per test.
+ ASSERT_TRUE(mNativeWindowSurface == nullptr);
+
+ mNativeWindowSurface = new mock::NativeWindowSurface();
+ mNativeWindow = new mock::NativeWindow();
+
+ mFlinger.setCreateNativeWindowSurface(
+ [this](auto) { return std::unique_ptr<NativeWindowSurface>(mNativeWindowSurface); });
+
+ EXPECT_CALL(*mNativeWindowSurface, getNativeWindow()).WillOnce(Return(mNativeWindow));
+
+ EXPECT_CALL(*mNativeWindow, perform(19)).Times(1);
+
+ EXPECT_CALL(*mRenderSurface, setAsync(async)).Times(1);
+ EXPECT_CALL(*mRenderSurface, setCritical(critical)).Times(1);
+ EXPECT_CALL(*mRenderSurface, setNativeWindow(mNativeWindow.get())).Times(1);
+ EXPECT_CALL(*mRenderSurface, queryWidth()).WillOnce(Return(displayWidth));
+ EXPECT_CALL(*mRenderSurface, queryHeight()).WillOnce(Return(displayHeight));
+}
+
+void DisplayTransactionTest::expectFramebufferUsageSet(int width, int height, int grallocUsage) {
EXPECT_CALL(*mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
- EXPECT_CALL(*mConsumer,
- setConsumerUsageBits(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER |
- GRALLOC_USAGE_HW_FB))
- .WillRepeatedly(Return(NO_ERROR));
+ EXPECT_CALL(*mConsumer, setConsumerUsageBits(grallocUsage)).WillRepeatedly(Return(NO_ERROR));
EXPECT_CALL(*mConsumer, setDefaultBufferSize(width, height)).WillRepeatedly(Return(NO_ERROR));
EXPECT_CALL(*mConsumer, setMaxAcquiredBufferCount(_)).WillRepeatedly(Return(NO_ERROR));
EXPECT_CALL(*mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
}
-TEST_F(DisplayTransactionTest, processDisplayChangesLockedProcessesPrimaryDisplayConnected) {
- using android::hardware::graphics::common::V1_0::ColorMode;
+void DisplayTransactionTest::expectHwcHotplugCalls(hwc2_display_t displayId, int displayWidth,
+ int displayHeight) {
+ EXPECT_CALL(*mComposer, getDisplayType(displayId, _))
+ .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
+ Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
+ EXPECT_CALL(*mComposer, getDisplayConfigs(_, _))
+ .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{0}), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::WIDTH, _))
+ .WillOnce(DoAll(SetArgPointee<3>(displayWidth), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer,
+ getDisplayAttribute(displayId, 0, IComposerClient::Attribute::HEIGHT, _))
+ .WillOnce(DoAll(SetArgPointee<3>(displayHeight), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer,
+ getDisplayAttribute(displayId, 0, IComposerClient::Attribute::VSYNC_PERIOD, _))
+ .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::DPI_X, _))
+ .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::DPI_Y, _))
+ .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+}
- setupPrimaryDisplay(1920, 1080);
+void DisplayTransactionTest::expectRESurfaceCreationCalls() {
+ // This setup is only expected once per test.
+ ASSERT_TRUE(mRenderSurface == nullptr);
- sp<BBinder> token = new BBinder();
- mFlinger.mutableCurrentState().displays.add(token, {DisplayDevice::DISPLAY_PRIMARY, true});
+ mRenderSurface = new RE::mock::Surface();
+ EXPECT_CALL(*mRenderEngine, createSurface())
+ .WillOnce(Return(ByMove(std::unique_ptr<RE::Surface>(mRenderSurface))));
+}
- EXPECT_CALL(*mComposer, getActiveConfig(DisplayDevice::DISPLAY_PRIMARY, _))
- .WillOnce(DoAll(SetArgPointee<1>(0), Return(Error::NONE)));
- EXPECT_CALL(*mComposer, getColorModes(DisplayDevice::DISPLAY_PRIMARY, _)).Times(0);
- EXPECT_CALL(*mComposer, getHdrCapabilities(DisplayDevice::DISPLAY_PRIMARY, _, _, _, _))
+void DisplayTransactionTest::expectPhysicalDisplayDeviceCreationCalls(hwc2_display_t displayId,
+ int displayWidth,
+ int displayHeight,
+ bool critical, bool async) {
+ EXPECT_CALL(*mComposer, getActiveConfig(displayId, _))
+ .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getColorModes(displayId, _)).Times(0);
+ EXPECT_CALL(*mComposer, getHdrCapabilities(displayId, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
- expectFramebufferQueuePairCreation(1920, 1080);
+ setupFakeBufferQueueFactory();
+ expectFramebufferUsageSet(displayWidth, displayHeight,
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_HW_FB);
- auto reSurface = new RE::mock::Surface();
- EXPECT_CALL(*mRenderEngine, createSurface())
- .WillOnce(Return(ByMove(std::unique_ptr<RE::Surface>(reSurface))));
- EXPECT_CALL(*reSurface, setAsync(false)).Times(1);
- EXPECT_CALL(*reSurface, setCritical(true)).Times(1);
- EXPECT_CALL(*reSurface, setNativeWindow(_)).Times(1);
- EXPECT_CALL(*reSurface, queryWidth()).WillOnce(Return(1920));
- EXPECT_CALL(*reSurface, queryHeight()).WillOnce(Return(1080));
+ setupFakeNativeWindowSurfaceFactory(displayWidth, displayHeight, critical, async);
+}
+
+bool DisplayTransactionTest::hasTransactionFlagSet(int flag) {
+ return mFlinger.mutableTransactionFlags() & flag;
+}
+
+bool DisplayTransactionTest::hasDisplayDevice(sp<IBinder> displayToken) {
+ return mFlinger.mutableDisplays().indexOfKey(displayToken) >= 0;
+}
+
+sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) {
+ return mFlinger.mutableDisplays().valueFor(displayToken);
+}
+
+bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableCurrentState().displays.indexOfKey(displayToken) >= 0;
+}
+
+const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableCurrentState().displays.valueFor(displayToken);
+}
+
+bool DisplayTransactionTest::hasDrawingDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableDrawingState().displays.indexOfKey(displayToken) >= 0;
+}
+
+const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableDrawingState().displays.valueFor(displayToken);
+}
+
+/* ------------------------------------------------------------------------
+ * SurfaceFlinger::handleTransactionLocked(eDisplayTransactionNeeded)
+ */
+
+TEST_F(DisplayTransactionTest, handleTransactionLockedProcessesHotplugConnectPrimary) {
+ constexpr hwc2_display_t externalDisplayId = 102;
+ constexpr hwc2_display_t displayId = 123;
+ constexpr int displayWidth = 1920;
+ constexpr int displayHeight = 1080;
+
+ // --------------------------------------------------------------------
+ // Preconditions
+
+ // An external display may already be set up
+ setupFakeHwcDisplay(externalDisplayId, DisplayDevice::DISPLAY_EXTERNAL, 3840, 2160);
+
+ // A hotplug connect comes in for a new display
+ mFlinger.mutablePendingHotplugEvents().emplace_back(
+ HotplugEvent{displayId, HWC2::Connection::Connected});
+
+ // --------------------------------------------------------------------
+ // Call Expectations
+
+ EXPECT_CALL(*mComposer, isUsingVrComposer()).WillOnce(Return(false));
+ expectHwcHotplugCalls(displayId, displayWidth, displayHeight);
+ expectRESurfaceCreationCalls();
+ expectPhysicalDisplayDeviceCreationCalls(displayId, displayWidth, displayHeight, true, false);
+
+ EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
EXPECT_CALL(*mEventThread, onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true)).Times(1);
- mFlinger.processDisplayChangesLocked();
+ // --------------------------------------------------------------------
+ // Invocation
- ASSERT_TRUE(mFlinger.mutableDisplays().indexOfKey(token) >= 0);
+ mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
- const auto& device = mFlinger.mutableDisplays().valueFor(token);
- ASSERT_TRUE(device.get());
+ // --------------------------------------------------------------------
+ // Postconditions
+
+ // HWComposer should have an entry for the display
+ EXPECT_TRUE(mFlinger.mutableHwcDisplaySlots().count(displayId) == 1);
+
+ // The display should have set up as a primary built-in display.
+ auto displayToken = mFlinger.mutableBuiltinDisplays()[DisplayDevice::DISPLAY_PRIMARY];
+ ASSERT_TRUE(displayToken != nullptr);
+
+ // The display device should have been set up in the list of displays.
+ ASSERT_TRUE(hasDisplayDevice(displayToken));
+ const auto& device = getDisplayDevice(displayToken);
EXPECT_TRUE(device->isSecure());
EXPECT_TRUE(device->isPrimary());
- ssize_t i = mFlinger.mutableDrawingState().displays.indexOfKey(token);
- ASSERT_GE(0, i);
- const auto& draw = mFlinger.mutableDrawingState().displays[i];
+ // The display should have been set up in the current display state
+ ASSERT_TRUE(hasCurrentDisplayState(displayToken));
+ const auto& current = getCurrentDisplayState(displayToken);
+ EXPECT_EQ(DisplayDevice::DISPLAY_PRIMARY, current.type);
+
+ // The display should have been set up in the drawing display state
+ ASSERT_TRUE(hasDrawingDisplayState(displayToken));
+ const auto& draw = getDrawingDisplayState(displayToken);
EXPECT_EQ(DisplayDevice::DISPLAY_PRIMARY, draw.type);
- EXPECT_CALL(*mComposer, setVsyncEnabled(0, IComposerClient::Vsync::DISABLE))
- .WillOnce(Return(Error::NONE));
+ // --------------------------------------------------------------------
+ // Cleanup conditions
- EXPECT_CALL(*mConsumer, consumerDisconnect()).Times(1);
+ EXPECT_CALL(*mComposer, setVsyncEnabled(displayId, IComposerClient::Vsync::DISABLE))
+ .WillOnce(Return(Error::NONE));
+ EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
}
} // namespace
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/services/surfaceflinger/tests/unittests/MockDisplaySurface.cpp
similarity index 66%
copy from libs/ui/include/ui/GraphicsTypes.h
copy to services/surfaceflinger/tests/unittests/MockDisplaySurface.cpp
index fa9a812..507626b 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/services/surfaceflinger/tests/unittests/MockDisplaySurface.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#pragma once
-
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <system/graphics.h>
+#include "MockDisplaySurface.h"
namespace android {
+namespace mock {
-using android::hardware::graphics::common::V1_0::ColorMode;
+// Explicit default instantiation is recommended.
+DisplaySurface::DisplaySurface() = default;
+DisplaySurface::~DisplaySurface() = default;
-} // namespace android
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockDisplaySurface.h b/services/surfaceflinger/tests/unittests/MockDisplaySurface.h
new file mode 100644
index 0000000..d6c9aa4
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockDisplaySurface.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include <utils/String8.h>
+
+#include "DisplayHardware/DisplaySurface.h"
+
+namespace android {
+namespace mock {
+
+class DisplaySurface : public android::DisplaySurface {
+public:
+ DisplaySurface();
+ ~DisplaySurface() override;
+
+ MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
+ MOCK_METHOD1(prepareFrame, status_t(CompositionType compositionType));
+ MOCK_METHOD0(advanceFrame, status_t());
+ MOCK_METHOD0(onFrameCommitted, void());
+ MOCK_CONST_METHOD1(dumpAsString, void(String8& result));
+ MOCK_METHOD2(resizeBuffers, void(uint32_t, uint32_t));
+ MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
+};
+
+} // namespace mock
+} // namespace android
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/services/surfaceflinger/tests/unittests/MockEventControlThread.cpp
similarity index 65%
copy from libs/ui/include/ui/GraphicsTypes.h
copy to services/surfaceflinger/tests/unittests/MockEventControlThread.cpp
index fa9a812..398fd42 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/services/surfaceflinger/tests/unittests/MockEventControlThread.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#pragma once
-
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <system/graphics.h>
+#include "MockEventControlThread.h"
namespace android {
+namespace mock {
-using android::hardware::graphics::common::V1_0::ColorMode;
+// Explicit default instantiation is recommended.
+EventControlThread::EventControlThread() = default;
+EventControlThread::~EventControlThread() = default;
-} // namespace android
+} // namespace mock
+} // namespace android
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/services/surfaceflinger/tests/unittests/MockEventControlThread.h
similarity index 62%
copy from libs/ui/include/ui/GraphicsTypes.h
copy to services/surfaceflinger/tests/unittests/MockEventControlThread.h
index fa9a812..8ac09a9 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/services/surfaceflinger/tests/unittests/MockEventControlThread.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,20 @@
#pragma once
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <system/graphics.h>
+#include <gmock/gmock.h>
+
+#include "EventControlThread.h"
namespace android {
+namespace mock {
-using android::hardware::graphics::common::V1_0::ColorMode;
+class EventControlThread : public android::EventControlThread {
+public:
+ EventControlThread();
+ ~EventControlThread() override;
-} // namespace android
+ MOCK_METHOD1(setVsyncEnabled, void(bool));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/services/surfaceflinger/tests/unittests/MockMessageQueue.cpp
similarity index 67%
copy from libs/ui/include/ui/GraphicsTypes.h
copy to services/surfaceflinger/tests/unittests/MockMessageQueue.cpp
index fa9a812..62f45ed 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/services/surfaceflinger/tests/unittests/MockMessageQueue.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#pragma once
-
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <system/graphics.h>
+#include "MockMessageQueue.h"
namespace android {
+namespace mock {
-using android::hardware::graphics::common::V1_0::ColorMode;
+// Explicit default instantiation is recommended.
+MessageQueue::MessageQueue() = default;
+MessageQueue::~MessageQueue() = default;
-} // namespace android
+} // namespace mock
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/MockMessageQueue.h
new file mode 100644
index 0000000..cf07cf7
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockMessageQueue.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "MessageQueue.h"
+
+namespace android {
+namespace mock {
+
+class MessageQueue : public android::MessageQueue {
+public:
+ MessageQueue();
+ ~MessageQueue() override;
+
+ MOCK_METHOD1(init, void(const sp<SurfaceFlinger>&));
+ MOCK_METHOD1(setEventThread, void(android::EventThread*));
+ MOCK_METHOD0(waitMessage, void());
+ MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
+ MOCK_METHOD0(invalidate, void());
+ MOCK_METHOD0(refresh, void());
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockNativeWindow.cpp b/services/surfaceflinger/tests/unittests/MockNativeWindow.cpp
new file mode 100644
index 0000000..61038f4
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockNativeWindow.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockNativeWindow.h"
+
+namespace android {
+namespace mock {
+namespace {
+
+int dispatch_setSwapInterval(struct ANativeWindow* window, int interval) {
+ return static_cast<NativeWindow*>(window)->setSwapInterval(interval);
+}
+
+int dispatch_dequeueBuffer_DEPRECATED(struct ANativeWindow* window,
+ struct ANativeWindowBuffer** buffer) {
+ return static_cast<NativeWindow*>(window)->dequeueBuffer_DEPRECATED(buffer);
+}
+
+int dispatch_lockBuffer_DEPRECATED(struct ANativeWindow* window,
+ struct ANativeWindowBuffer* buffer) {
+ return static_cast<NativeWindow*>(window)->lockBuffer_DEPRECATED(buffer);
+}
+
+int dispatch_queueBuffer_DEPRECATED(struct ANativeWindow* window,
+ struct ANativeWindowBuffer* buffer) {
+ return static_cast<NativeWindow*>(window)->queueBuffer_DEPRECATED(buffer);
+}
+
+int dispatch_query(const struct ANativeWindow* window, int what, int* value) {
+ return static_cast<const NativeWindow*>(window)->query(what, value);
+}
+
+int dispatch_perform(struct ANativeWindow* window, int operation, ...) {
+ // TODO: Handle the various operations and their varargs better.
+ return static_cast<NativeWindow*>(window)->perform(operation);
+}
+
+int dispatch_cancelBuffer_DEPRECATED(struct ANativeWindow* window,
+ struct ANativeWindowBuffer* buffer) {
+ return static_cast<NativeWindow*>(window)->cancelBuffer_DEPRECATED(buffer);
+}
+
+int dispatch_dequeueBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer,
+ int* fenceFd) {
+ return static_cast<NativeWindow*>(window)->dequeueBuffer(buffer, fenceFd);
+}
+
+int dispatch_queueBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer,
+ int fenceFd) {
+ return static_cast<NativeWindow*>(window)->queueBuffer(buffer, fenceFd);
+}
+
+int dispatch_cancelBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer,
+ int fenceFd) {
+ return static_cast<NativeWindow*>(window)->cancelBuffer(buffer, fenceFd);
+}
+
+} // namespace
+
+NativeWindow::NativeWindow() {
+ // ANativeWindow is a structure with function pointers and not a C++ class.
+ // Set all the pointers to dispatch functions, which will invoke the mock
+ // interface functions.
+ ANativeWindow::setSwapInterval = &dispatch_setSwapInterval;
+ ANativeWindow::dequeueBuffer_DEPRECATED = &dispatch_dequeueBuffer_DEPRECATED;
+ ANativeWindow::lockBuffer_DEPRECATED = &dispatch_lockBuffer_DEPRECATED;
+ ANativeWindow::queueBuffer_DEPRECATED = &dispatch_queueBuffer_DEPRECATED;
+ ANativeWindow::query = &dispatch_query;
+ ANativeWindow::perform = &dispatch_perform;
+ ANativeWindow::cancelBuffer_DEPRECATED = &dispatch_cancelBuffer_DEPRECATED;
+ ANativeWindow::dequeueBuffer = &dispatch_dequeueBuffer;
+ ANativeWindow::queueBuffer = &dispatch_queueBuffer;
+ ANativeWindow::cancelBuffer = &dispatch_cancelBuffer;
+}
+
+// Explicit default instantiation is recommended.
+NativeWindow::~NativeWindow() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockNativeWindow.h b/services/surfaceflinger/tests/unittests/MockNativeWindow.h
new file mode 100644
index 0000000..561fd58
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockNativeWindow.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include <system/window.h>
+
+#include <ui/ANativeObjectBase.h>
+
+namespace android {
+namespace mock {
+
+class NativeWindow : public ANativeObjectBase<ANativeWindow, NativeWindow, RefBase> {
+public:
+ NativeWindow();
+ ~NativeWindow();
+
+ MOCK_METHOD1(setSwapInterval, int(int interval));
+ MOCK_METHOD1(dequeueBuffer_DEPRECATED, int(struct ANativeWindowBuffer**));
+ MOCK_METHOD1(lockBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
+ MOCK_METHOD1(queueBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
+ MOCK_CONST_METHOD2(query, int(int, int*));
+ MOCK_METHOD1(perform, int(int));
+ MOCK_METHOD1(cancelBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
+ MOCK_METHOD2(dequeueBuffer, int(struct ANativeWindowBuffer**, int*));
+ MOCK_METHOD2(queueBuffer, int(struct ANativeWindowBuffer*, int));
+ MOCK_METHOD2(cancelBuffer, int(struct ANativeWindowBuffer*, int));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.cpp
similarity index 64%
copy from libs/ui/include/ui/GraphicsTypes.h
copy to services/surfaceflinger/tests/unittests/MockNativeWindowSurface.cpp
index fa9a812..0314568 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#pragma once
-
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <system/graphics.h>
+#include "MockNativeWindowSurface.h"
namespace android {
+namespace mock {
-using android::hardware::graphics::common::V1_0::ColorMode;
+// Explicit default instantiation is recommended.
+NativeWindowSurface::NativeWindowSurface() = default;
+NativeWindowSurface::~NativeWindowSurface() = default;
-} // namespace android
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.h b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.h
new file mode 100644
index 0000000..88d1a9f
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include <system/window.h> // for ANativeWindow
+
+#include "SurfaceFlinger.h" // for base NativeWindowSurface
+
+namespace android {
+namespace mock {
+
+class NativeWindowSurface : public android::NativeWindowSurface {
+public:
+ NativeWindowSurface();
+ ~NativeWindowSurface();
+
+ MOCK_CONST_METHOD0(getNativeWindow, sp<ANativeWindow>());
+ MOCK_METHOD0(preallocateBuffers, void());
+};
+
+} // namespace mock
+} // namespace android
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/services/surfaceflinger/tests/unittests/MockSurfaceInterceptor.cpp
similarity index 65%
copy from libs/ui/include/ui/GraphicsTypes.h
copy to services/surfaceflinger/tests/unittests/MockSurfaceInterceptor.cpp
index fa9a812..b2ec721 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/services/surfaceflinger/tests/unittests/MockSurfaceInterceptor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#pragma once
-
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <system/graphics.h>
+#include "MockSurfaceInterceptor.h"
namespace android {
+namespace mock {
-using android::hardware::graphics::common::V1_0::ColorMode;
+// Explicit default instantiation is recommended.
+SurfaceInterceptor::SurfaceInterceptor() = default;
+SurfaceInterceptor::~SurfaceInterceptor() = default;
-} // namespace android
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockSurfaceInterceptor.h b/services/surfaceflinger/tests/unittests/MockSurfaceInterceptor.h
new file mode 100644
index 0000000..458b2f3
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockSurfaceInterceptor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "SurfaceInterceptor.h"
+
+namespace android {
+namespace mock {
+
+class SurfaceInterceptor : public android::SurfaceInterceptor {
+public:
+ SurfaceInterceptor();
+ ~SurfaceInterceptor() override;
+
+ MOCK_METHOD2(enable,
+ void(const SortedVector<sp<Layer>>&,
+ const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>&));
+ MOCK_METHOD0(disable, void());
+ MOCK_METHOD0(isEnabled, bool());
+ MOCK_METHOD4(saveTransaction,
+ void(const Vector<ComposerState>&,
+ const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>&,
+ const Vector<DisplayState>&, uint32_t));
+ MOCK_METHOD1(saveSurfaceCreation, void(const sp<const Layer>&));
+ MOCK_METHOD1(saveSurfaceDeletion, void(const sp<const Layer>&));
+ MOCK_METHOD4(saveBufferUpdate, void(const sp<const Layer>&, uint32_t, uint32_t, uint64_t));
+ MOCK_METHOD1(saveDisplayCreation, void(const DisplayDeviceState&));
+ MOCK_METHOD1(saveDisplayDeletion, void(int32_t));
+ MOCK_METHOD2(savePowerModeUpdate, void(int32_t, int32_t));
+ MOCK_METHOD1(saveVSyncEvent, void(nsecs_t));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4895e16..2dd8e5f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -44,33 +44,44 @@
mFlinger->getBE().mHwc.reset(new HWComposer(std::move(composer)));
}
- void setupPrimaryDisplay() {
- mFlinger->getBE().mHwc->mHwcDevice->onHotplug(0, HWC2::Connection::Connected);
- mFlinger->getBE().mHwc->onHotplug(0, DisplayDevice::DISPLAY_PRIMARY,
- HWC2::Connection::Connected);
- }
-
using CreateBufferQueueFunction = SurfaceFlinger::CreateBufferQueueFunction;
-
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
mFlinger->mCreateBufferQueue = f;
}
+ using CreateNativeWindowSurfaceFunction = SurfaceFlinger::CreateNativeWindowSurfaceFunction;
+ void setCreateNativeWindowSurface(CreateNativeWindowSurfaceFunction f) {
+ mFlinger->mCreateNativeWindowSurface = f;
+ }
+
+ using HotplugEvent = SurfaceFlinger::HotplugEvent;
+
/* ------------------------------------------------------------------------
* Forwarding for functions being tested
*/
- auto processDisplayChangesLocked() { return mFlinger->processDisplayChangesLocked(); }
+
+ auto handleTransactionLocked(uint32_t transactionFlags) {
+ return mFlinger->handleTransactionLocked(transactionFlags);
+ }
/* ------------------------------------------------------------------------
* Read-write access to private data to set up preconditions and assert
* post-conditions.
*/
+
auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; }
- auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableCurrentState() { return mFlinger->mCurrentState; }
+ auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableDrawingState() { return mFlinger->mDrawingState; }
- auto& mutableEventThread() { return mFlinger->mEventThread; }
+ auto& mutableEventControlThread() { return mFlinger->mEventControlThread; }
auto& mutableEventQueue() { return mFlinger->mEventQueue; }
+ auto& mutableEventThread() { return mFlinger->mEventThread; }
+ auto& mutableInterceptor() { return mFlinger->mInterceptor; }
+ auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
+ auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }
+
+ auto& mutableHwcDisplayData() { return mFlinger->getBE().mHwc->mDisplayData; }
+ auto& mutableHwcDisplaySlots() { return mFlinger->getBE().mHwc->mHwcDisplaySlots; }
~TestableSurfaceFlinger() {
// All these pointer and container clears help ensure that GMock does
@@ -78,12 +89,33 @@
// still be referenced by something despite our best efforts to destroy
// it after each test is done.
mutableDisplays().clear();
+ mutableEventControlThread().reset();
+ mutableEventQueue().reset();
mutableEventThread().reset();
+ mutableInterceptor().reset();
mFlinger->getBE().mHwc.reset();
mFlinger->getBE().mRenderEngine.reset();
}
- sp<SurfaceFlinger> mFlinger = new SurfaceFlinger();
+ /* ------------------------------------------------------------------------
+ * Wrapper classes for Read-write access to private data to set up
+ * preconditions and assert post-conditions.
+ */
+ struct HWC2Display : public HWC2::Display {
+ HWC2Display(Hwc2::Composer& composer,
+ const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id,
+ HWC2::DisplayType type)
+ : HWC2::Display(composer, capabilities, id, type) {}
+ ~HWC2Display() {
+ // Prevents a call to disable vsyncs.
+ mType = HWC2::DisplayType::Invalid;
+ }
+
+ auto& mutableIsConnected() { return this->mIsConnected; }
+ auto& mutableConfigs() { return this->mConfigs; }
+ };
+
+ sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(SurfaceFlinger::SkipInitialization);
};
} // namespace android
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index e141b91..c38c12b 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -134,7 +134,6 @@
channel_id(), buffer_id(), buffer_state_->load());
for (auto consumer : consumer_channels_) {
consumer->OnProducerClosed();
- service()->SetChannel(consumer->channel_id(), nullptr);
}
Hangup();
}