Merge "SF: Forward declare RefreshRateConfigs in SurfaceFlingerFactory.h"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 86558ef..302d491 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2708,7 +2708,7 @@
}
/* tell activity manager we're done */
- if (options_->do_broadcast) {
+ if (options_->do_broadcast && !CalledByApi()) {
SendBugreportFinishedBroadcast();
// Note that listener_ is notified in Run();
}
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 4811927..9f65425 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -201,7 +201,13 @@
if (i == optind) {
services.add(String16(argv[i]));
} else {
- args.add(String16(argv[i]));
+ const String16 arg(argv[i]);
+ args.add(arg);
+ // For backward compatible, if the proto argument is passed to the service, the
+ // dump request is also considered to use proto.
+ if (!asProto && !arg.compare(String16(PriorityDumper::PROTO_ARG))) {
+ asProto = true;
+ }
}
}
}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index dd51898..4026f29 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -832,7 +832,7 @@
};
LOG(DEBUG) << "Copying " << from << " to " << to;
- return android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
+ return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
}
binder::Status InstalldNativeService::snapshotAppData(
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 6fba0ac..01cf2f8 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -64,6 +64,20 @@
ANDROID_BITMAP_FORMAT_RGBA_F16 = 9,
};
+/** Bitmap alpha format */
+enum {
+ /** Pixel components are premultiplied by alpha. */
+ ANDROID_BITMAP_FLAGS_ALPHA_PREMUL = 0,
+ /** Pixels are opaque. */
+ ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE = 1,
+ /** Pixel components are independent of alpha. */
+ ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL = 2,
+ /** Bit mask for AndroidBitmapFormat.flags to isolate the alpha. */
+ ANDROID_BITMAP_FLAGS_ALPHA_MASK = 0x3,
+ /** Shift for AndroidBitmapFormat.flags to isolate the alpha. */
+ ANDROID_BITMAP_FLAGS_ALPHA_SHIFT = 0,
+};
+
/** Bitmap info, see AndroidBitmap_getInfo(). */
typedef struct {
/** The bitmap width in pixels. */
@@ -74,8 +88,9 @@
uint32_t stride;
/** The bitmap pixel format. See {@link AndroidBitmapFormat} */
int32_t format;
- /** Unused. */
- uint32_t flags; // 0 for now
+ /** Two bits are used to encode alpha. Use ANDROID_BITMAP_FLAGS_ALPHA_MASK
+ * and ANDROID_BITMAP_FLAGS_ALPHA_SHIFT to retrieve them. */
+ uint32_t flags;
} AndroidBitmapInfo;
/**
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 28b8d80..c056c97 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -35,7 +35,6 @@
#include <binder/IBinder.h>
#include <input/Input.h>
-#include <input/LatencyStatistics.h>
#include <utils/BitSet.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -289,12 +288,8 @@
status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);
private:
- static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min;
sp<InputChannel> mChannel;
- LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD};
-
- void reportTouchEventForStatistics(nsecs_t evdevTime);
};
/*
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 49a9414..5e4c98f 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -114,4 +114,4 @@
return INVALID_OPERATION;
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index f3d4b7e..296e3f6 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -51,7 +51,7 @@
"IpPrefix.cpp",
]
-cc_library_shared {
+cc_library {
name: "libbinder",
// for vndbinder
@@ -101,6 +101,11 @@
target: {
android: {
srcs: libbinder_device_interface_sources,
+
+ // NOT static to keep the wire protocol unfrozen
+ static: {
+ enabled: false,
+ },
},
vendor: {
exclude_srcs: libbinder_device_interface_sources,
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 711fed9..9da9c13 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -223,4 +223,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 693045e..2f6e9c3 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -99,6 +99,32 @@
return reply.readNullableStrongBinder(out);
}
+status_t IBinder::getDebugPid(pid_t* out) {
+ BBinder* local = this->localBinder();
+ if (local != nullptr) {
+ *out = local->getDebugPid();
+ return OK;
+ }
+
+ BpBinder* proxy = this->remoteBinder();
+ LOG_ALWAYS_FATAL_IF(proxy == nullptr);
+
+ Parcel data;
+ Parcel reply;
+ status_t status = transact(DEBUG_PID_TRANSACTION, data, &reply);
+ if (status != OK) return status;
+
+ int32_t pid;
+ status = reply.readInt32(&pid);
+ if (status != OK) return status;
+
+ if (pid < 0 || pid > std::numeric_limits<pid_t>::max()) {
+ return BAD_VALUE;
+ }
+ *out = pid;
+ return OK;
+}
+
// ---------------------------------------------------------------------------
class BBinder::Extras
@@ -152,6 +178,9 @@
case EXTENSION_TRANSACTION:
err = reply->writeStrongBinder(getExtension());
break;
+ case DEBUG_PID_TRANSACTION:
+ err = reply->writeInt32(getDebugPid());
+ break;
default:
err = onTransact(code, data, reply, flags);
break;
@@ -250,6 +279,10 @@
return e->mExtension;
}
+pid_t BBinder::getDebugPid() {
+ return getpid();
+}
+
void BBinder::setExtension(const sp<IBinder>& extension) {
Extras* e = getOrCreateExtras();
e->mExtension = extension;
@@ -386,4 +419,4 @@
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index c5aa007..50c7053 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -491,4 +491,4 @@
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index a7d5240..fb424fd 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -280,4 +280,4 @@
return mGlobalState;
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index a1c2a8b..64c1ff6 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -308,5 +308,5 @@
return proc->getKernelReferences(count, buf);
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 377f604..1eb5363 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -110,4 +110,4 @@
IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager");
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index 4c151e7..0ce1dd5 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -66,4 +66,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index c58ea02..6c16c2d 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -309,4 +309,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index cc0022a..a47dbac 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -240,4 +240,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index 59d51ed..b19004d 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -46,4 +46,4 @@
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
index 77e3d23..4198e49 100644
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -59,4 +59,4 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index a7662e9..c2bb811 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -512,4 +512,4 @@
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 7c45c77..4981d7a 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -597,9 +597,8 @@
result = getAndExecuteCommand();
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
- ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
+ LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
- abort();
}
// Let this thread exit the thread pool if it is no longer
@@ -1326,4 +1325,4 @@
state->mOut.writePointer((uintptr_t)data);
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index bf2f20a..d9bf3cc 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -172,4 +172,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index 96e1a8c..a38a27a 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -88,4 +88,4 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index 1e11941..556288c 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -65,4 +65,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index f3e8f45..ee637e2 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -285,4 +285,4 @@
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index 88cc603..a3e2b67 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -85,4 +85,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp
index 82f9047..038e6bf 100644
--- a/libs/binder/IUidObserver.cpp
+++ b/libs/binder/IUidObserver.cpp
@@ -112,4 +112,4 @@
}
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
index 033066b..32300df 100644
--- a/libs/binder/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -43,4 +43,4 @@
}
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index eacad3b..ebf91f9 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -481,4 +481,4 @@
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 4c300b4..e4ea60f 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -181,4 +181,4 @@
}
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2a75619..d0f20fe 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -68,7 +68,7 @@
static size_t pad_size(size_t s) {
if (s > (std::numeric_limits<size_t>::max() - 3)) {
- abort();
+ LOG_ALWAYS_FATAL("pad size too big %zu", s);
}
return PAD_SIZE_UNSAFE(s);
}
@@ -295,7 +295,7 @@
{
size_t result = dataSize() - dataPosition();
if (result > INT32_MAX) {
- abort();
+ LOG_ALWAYS_FATAL("result too big: %zu", result);
}
return result;
}
@@ -332,7 +332,7 @@
if (pos > INT32_MAX) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
- abort();
+ LOG_ALWAYS_FATAL("pos too big: %zu", pos);
}
mDataPos = pos;
@@ -2793,4 +2793,4 @@
mMutable = false;
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index a4c28ad..75a6d22 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -110,4 +110,4 @@
}
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp
index 34b2ca5..0c89245 100644
--- a/libs/binder/PermissionController.cpp
+++ b/libs/binder/PermissionController.cpp
@@ -85,4 +85,4 @@
return service != nullptr ? service->getPackageUid(package, flags) : -1;
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
index 5cb2033..00d6eef 100644
--- a/libs/binder/ProcessInfoService.cpp
+++ b/libs/binder/ProcessInfoService.cpp
@@ -101,4 +101,4 @@
ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService);
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index eb828c3..0336d3e 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -387,4 +387,4 @@
mDriverFD = -1;
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index 101eba3..684a7dc 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -69,4 +69,4 @@
return to;
}
-}; // namespace android
+} // namespace android
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
new file mode 100644
index 0000000..f3e4229
--- /dev/null
+++ b/libs/binder/fuzzer/Android.bp
@@ -0,0 +1,31 @@
+cc_fuzz {
+ name: "binder_parcel_fuzzer",
+ host_supported: true,
+ srcs: [
+ "binder.cpp",
+ "hwbinder.cpp",
+ "main.cpp",
+ "util.cpp",
+ ],
+ static_libs: [
+ "libbase",
+ "libbinderthreadstate",
+ "libcgrouprc",
+ "libcgrouprc_format",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libprocessgroup",
+ "libjsoncpp",
+ "libutils",
+ ],
+
+ target: {
+ android: {
+ shared_libs: ["libbinder"],
+ },
+ host: {
+ static_libs: ["libbinder"],
+ },
+ },
+}
diff --git a/libs/binder/fuzzer/binder.cpp b/libs/binder/fuzzer/binder.cpp
new file mode 100644
index 0000000..ce21178
--- /dev/null
+++ b/libs/binder/fuzzer/binder.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "binder"
+
+#include "binder.h"
+#include "util.h"
+
+using ::android::status_t;
+
+#define PARCEL_READ_WITH_STATUS(T, FUN) \
+ [] (const ::android::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\
+ T t{};\
+ status_t status = p.FUN(&t);\
+ FUZZ_LOG() << #T " status: " << status /* << " value: " << t*/;\
+ }
+
+#define PARCEL_READ_NO_STATUS(T, FUN) \
+ [] (const ::android::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
+ T t = p.FUN();\
+ (void) t;\
+ FUZZ_LOG() << #T " done " /* << " value: " << t*/;\
+ }
+
+#define PARCEL_READ_OPT_STATUS(T, FUN) \
+ PARCEL_READ_WITH_STATUS(T, FUN), \
+ PARCEL_READ_NO_STATUS(T, FUN)
+
+std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
+ PARCEL_READ_NO_STATUS(size_t, dataSize),
+ PARCEL_READ_NO_STATUS(size_t, dataAvail),
+ PARCEL_READ_NO_STATUS(size_t, dataPosition),
+ PARCEL_READ_NO_STATUS(size_t, dataCapacity),
+ [] (const ::android::Parcel& p, uint8_t pos) {
+ FUZZ_LOG() << "about to setDataPosition: " << pos;
+ p.setDataPosition(pos);
+ FUZZ_LOG() << "setDataPosition done";
+ },
+ PARCEL_READ_NO_STATUS(size_t, allowFds),
+ PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors),
+ [] (const ::android::Parcel& p, uint8_t len) {
+#ifdef __ANDROID__
+ std::string interface(len, 'a');
+ FUZZ_LOG() << "about to enforceInterface: " << interface;
+ bool b = p.enforceInterface(::android::String16(interface.c_str()));
+ FUZZ_LOG() << "enforced interface: " << b;
+#else
+ FUZZ_LOG() << "skipping enforceInterface";
+ (void)p;
+ (void)len;
+#endif // __ANDROID__
+ },
+ [] (const ::android::Parcel& p, uint8_t /*len*/) {
+#ifdef __ANDROID__
+ FUZZ_LOG() << "about to checkInterface";
+ bool b = p.checkInterface(new android::BBinder());
+ FUZZ_LOG() << "checked interface: " << b;
+#else
+ FUZZ_LOG() << "skipping checkInterface";
+ (void)p;
+#endif // __ANDROID__
+ },
+ PARCEL_READ_NO_STATUS(size_t, objectsCount),
+ PARCEL_READ_NO_STATUS(status_t, errorCheck),
+ [] (const ::android::Parcel& p, uint8_t len) {
+ FUZZ_LOG() << "about to read void*";
+ std::vector<uint8_t> data(len);
+ status_t status = p.read(data.data(), len);
+ FUZZ_LOG() << "read status: " << status;
+ },
+ [] (const ::android::Parcel& p, uint8_t len) {
+ FUZZ_LOG() << "about to readInplace";
+ const void* r = p.readInplace(len);
+ FUZZ_LOG() << "readInplace done. pointer: " << r;
+ },
+ PARCEL_READ_OPT_STATUS(int32_t, readInt32),
+ PARCEL_READ_OPT_STATUS(uint32_t, readUint32),
+ PARCEL_READ_OPT_STATUS(int64_t, readInt64),
+ PARCEL_READ_OPT_STATUS(uint64_t, readUint64),
+ PARCEL_READ_OPT_STATUS(float, readFloat),
+ PARCEL_READ_OPT_STATUS(double, readDouble),
+ PARCEL_READ_OPT_STATUS(intptr_t, readIntPtr),
+ PARCEL_READ_OPT_STATUS(bool, readBool),
+ PARCEL_READ_OPT_STATUS(char16_t, readChar),
+ PARCEL_READ_OPT_STATUS(int8_t, readByte),
+
+ PARCEL_READ_WITH_STATUS(std::string, readUtf8FromUtf16),
+ PARCEL_READ_WITH_STATUS(std::unique_ptr<std::string>, readUtf8FromUtf16),
+ [] (const ::android::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to read c-str";
+ const char* str = p.readCString();
+ FUZZ_LOG() << "read c-str: " << (str ? str : "<empty string>");
+ },
+ PARCEL_READ_OPT_STATUS(android::String8, readString8),
+ PARCEL_READ_OPT_STATUS(android::String16, readString16),
+ PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16),
+ // TODO: readString16Inplace
+ PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readStrongBinder),
+ PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readNullableStrongBinder),
+
+ // TODO: all templated versions of readParcelableVector, readParcelable
+ // TODO: readParcelable
+ // TODO: templated versions of readStrongBinder, readNullableStrongBinder
+
+ // TODO(b/131868573): can force read of arbitrarily sized vector
+ // PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::IBinder>>, readStrongBinderVector),
+
+ // TODO(b/131868573): can force read of arbitrarily sized vector
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int8_t>>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<int8_t>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int32_t>>, readInt32Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<int32_t>, readInt32Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int64_t>>, readInt64Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<int64_t>, readInt64Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint64_t>>, readUint64Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<uint64_t>, readUint64Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<float>>, readFloatVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<float>, readFloatVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<double>>, readDoubleVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<double>, readDoubleVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<bool>>, readBoolVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<bool>, readBoolVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<char16_t>>, readCharVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<char16_t>, readCharVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<android::String16>>>, readString16Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<android::String16>, readString16Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<std::string>>>, readUtf8VectorFromUtf16Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector),
+
+ // TODO: read(Flattenable<T>)
+ // TODO: read(LightFlattenable<T>)
+ // TODO: resizeOutVector
+
+ PARCEL_READ_NO_STATUS(int32_t, readExceptionCode),
+ // TODO: readNativeHandle
+ PARCEL_READ_NO_STATUS(int, readFileDescriptor),
+ PARCEL_READ_NO_STATUS(int, readParcelFileDescriptor),
+ PARCEL_READ_WITH_STATUS(android::base::unique_fd, readUniqueFileDescriptor),
+
+ // TODO(b/131868573): can force read of arbitrarily sized vector
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<android::base::unique_fd>, readUniqueFileDescriptorVector),
+
+ [] (const android::Parcel& p, uint8_t len) {
+ FUZZ_LOG() << "about to readBlob";
+ ::android::Parcel::ReadableBlob blob;
+ status_t status = p.readBlob(len, &blob);
+ FUZZ_LOG() << "readBlob status: " << status;
+ },
+ // TODO: readObject
+ PARCEL_READ_NO_STATUS(uid_t, readCallingWorkSourceUid),
+ PARCEL_READ_NO_STATUS(size_t, getBlobAshmemSize),
+ PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize),
+};
diff --git a/libs/binder/fuzzer/binder.h b/libs/binder/fuzzer/binder.h
new file mode 100644
index 0000000..32dcc79
--- /dev/null
+++ b/libs/binder/fuzzer/binder.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 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 <binder/Parcel.h>
+#include <vector>
+
+#include "parcel.h"
+
+extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS;
diff --git a/libs/binder/fuzzer/hwbinder.cpp b/libs/binder/fuzzer/hwbinder.cpp
new file mode 100644
index 0000000..b8cce72
--- /dev/null
+++ b/libs/binder/fuzzer/hwbinder.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "hwbinder"
+
+#include "hwbinder.h"
+#include "util.h"
+
+#include <android-base/logging.h>
+#include <hwbinder/Parcel.h>
+
+using ::android::status_t;
+
+// TODO: support scatter-gather types
+
+std::ostream& operator<<(std::ostream& os, const ::android::sp<::android::hardware::IBinder>& binder) {
+ os << binder.get();
+ return os;
+}
+
+#define PARCEL_READ_NO_STATUS(T, FUN) \
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
+ T t = p.FUN();\
+ FUZZ_LOG() << #T " value: " << t;\
+ }
+
+#define PARCEL_READ_WITH_STATUS(T, FUN) \
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\
+ T t;\
+ status_t status = p.FUN(&t);\
+ FUZZ_LOG() << #T " status: " << status << " value: " << t;\
+ }
+
+std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS {
+ PARCEL_READ_NO_STATUS(size_t, dataSize),
+ PARCEL_READ_NO_STATUS(size_t, dataAvail),
+ PARCEL_READ_NO_STATUS(size_t, dataPosition),
+ PARCEL_READ_NO_STATUS(size_t, dataCapacity),
+ [] (const ::android::hardware::Parcel& p, uint8_t pos) {
+ FUZZ_LOG() << "about to setDataPosition: " << pos;
+ p.setDataPosition(pos);
+ FUZZ_LOG() << "setDataPosition done";
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ FUZZ_LOG() << "about to enforceInterface";
+ std::string interfaceName(length, 'a');
+ bool okay = p.enforceInterface(interfaceName.c_str());
+ FUZZ_LOG() << "enforceInterface status: " << okay;
+ },
+ PARCEL_READ_NO_STATUS(size_t, objectsCount),
+ PARCEL_READ_WITH_STATUS(int8_t, readInt8),
+ PARCEL_READ_WITH_STATUS(uint8_t, readUint8),
+ PARCEL_READ_WITH_STATUS(int16_t, readInt16),
+ PARCEL_READ_WITH_STATUS(uint16_t, readUint16),
+ PARCEL_READ_WITH_STATUS(int32_t, readInt32),
+ PARCEL_READ_WITH_STATUS(uint32_t, readUint32),
+ PARCEL_READ_WITH_STATUS(int64_t, readInt64),
+ PARCEL_READ_WITH_STATUS(uint64_t, readUint64),
+ PARCEL_READ_WITH_STATUS(float, readFloat),
+ PARCEL_READ_WITH_STATUS(double, readDouble),
+ PARCEL_READ_WITH_STATUS(bool, readBool),
+ PARCEL_READ_WITH_STATUS(::android::String16, readString16),
+ PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
+ PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
+ [] (const ::android::hardware::Parcel& p, uint8_t amount) {
+ FUZZ_LOG() << "about to readInPlace " << amount;
+ const uint8_t* data = (const uint8_t*)p.readInplace(amount);
+ if (data) {
+ std::vector<uint8_t> vdata(data, data + amount);
+ FUZZ_LOG() << "readInPlace " << amount << " data: " << hexString(vdata);
+ } else {
+ FUZZ_LOG() << "readInPlace " << amount << " no data";
+ }
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readBuffer";
+ size_t handle = 0;
+ const void* data = nullptr;
+ status_t status = p.readBuffer(size, &handle, &data);
+ FUZZ_LOG() << "readBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readNullableBuffer";
+ size_t handle = 0;
+ const void* data = nullptr;
+ status_t status = p.readNullableBuffer(size, &handle, &data);
+ FUZZ_LOG() << "readNullableBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readEmbeddedBuffer";
+ size_t handle = 0;
+ size_t parent_buffer_handle = 0;
+ size_t parent_offset = 3;
+ const void* data = nullptr;
+ status_t status = p.readEmbeddedBuffer(size, &handle, parent_buffer_handle, parent_offset, &data);
+ FUZZ_LOG() << "readEmbeddedBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readNullableEmbeddedBuffer";
+ size_t handle = 0;
+ size_t parent_buffer_handle = 0;
+ size_t parent_offset = 3;
+ const void* data = nullptr;
+ status_t status = p.readNullableEmbeddedBuffer(size, &handle, parent_buffer_handle, parent_offset, &data);
+ FUZZ_LOG() << "readNullableEmbeddedBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readNativeHandleNoDup";
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readNativeHandleNoDup(&handle);
+ FUZZ_LOG() << "readNativeHandleNoDup status: " << status << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ CHECK(status != ::android::OK);
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readNullableNativeHandleNoDup";
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readNullableNativeHandleNoDup(&handle);
+ FUZZ_LOG() << "readNullableNativeHandleNoDup status: " << status << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ },
+};
diff --git a/libs/binder/fuzzer/hwbinder.h b/libs/binder/fuzzer/hwbinder.h
new file mode 100644
index 0000000..03ab510
--- /dev/null
+++ b/libs/binder/fuzzer/hwbinder.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 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 <hwbinder/Parcel.h>
+#include <vector>
+
+#include "parcel.h"
+
+extern std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS;
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp
new file mode 100644
index 0000000..03fde3a
--- /dev/null
+++ b/libs/binder/fuzzer/main.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "main"
+
+#include "binder.h"
+#include "hwbinder.h"
+#include "util.h"
+
+#include <android-base/logging.h>
+
+#include <cstdlib>
+#include <ctime>
+
+template <typename P>
+void doFuzz(
+ const std::vector<ParcelRead<P>>& reads,
+ const std::vector<uint8_t>& input,
+ const std::vector<uint8_t>& instructions) {
+
+ P p;
+ p.setData(input.data(), input.size());
+
+ for (size_t i = 0; i < instructions.size() - 1; i += 2) {
+ uint8_t a = instructions[i];
+ uint8_t b = instructions[i + 1];
+
+ FUZZ_LOG() << "size: " << p.dataSize() << " avail: " << p.dataAvail()
+ << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity();
+
+ reads[a % reads.size()](p, b);
+ }
+}
+
+void fuzz(uint8_t options, const std::vector<uint8_t>& input, const std::vector<uint8_t>& instructions) {
+ (void) options;
+
+ // although they will do completely different things, might as well fuzz both
+ doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input, instructions);
+ doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size <= 1) return 0; // no use
+ uint8_t options = *data;
+ data++;
+ size--;
+
+ // TODO: generate 'objects' data
+
+ // data to fill out parcel
+ size_t inputLen = size / 2;
+ std::vector<uint8_t> input(data, data + inputLen);
+ data += inputLen;
+ size -= inputLen;
+
+ // data to use to determine what to do
+ size_t instructionLen = size;
+ std::vector<uint8_t> instructions(data, data + instructionLen);
+ data += instructionLen;
+ size -= instructionLen;
+
+ CHECK(size == 0) << "size: " << size;
+
+ FUZZ_LOG() << "options: " << (int)options << " inputLen: " << inputLen << " instructionLen: " << instructionLen;
+ FUZZ_LOG() << "input: " << hexString(input);
+ FUZZ_LOG() << "instructions: " << hexString(instructions);
+
+ fuzz(options, input, instructions);
+ return 0;
+}
diff --git a/libs/binder/fuzzer/parcel.h b/libs/binder/fuzzer/parcel.h
new file mode 100644
index 0000000..5f05335
--- /dev/null
+++ b/libs/binder/fuzzer/parcel.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+template <typename P>
+using ParcelRead = std::function<void(const P& p, uint8_t data)>;
+
+
diff --git a/libs/binder/fuzzer/util.cpp b/libs/binder/fuzzer/util.cpp
new file mode 100644
index 0000000..b3a4ee7
--- /dev/null
+++ b/libs/binder/fuzzer/util.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "util"
+#include "util.h"
+
+#include <android-base/logging.h>
+
+#include <iomanip>
+#include <sstream>
+
+std::string hexString(const std::vector<uint8_t>& hash) {
+ std::ostringstream s;
+ s << std::hex << std::setfill('0');
+ for (uint8_t i : hash) {
+ s << std::setw(2) << static_cast<int>(i);
+ }
+ return s.str();
+}
diff --git a/libs/binder/fuzzer/util.h b/libs/binder/fuzzer/util.h
new file mode 100644
index 0000000..07e68a8
--- /dev/null
+++ b/libs/binder/fuzzer/util.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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 <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#ifndef FUZZ_LOG_TAG
+#error "Must define FUZZ_LOG_TAG"
+#endif
+
+#define ENABLE_LOG_FUZZ 1
+#define FUZZ_LOG() FuzzLog(FUZZ_LOG_TAG, ENABLE_LOG_FUZZ).log()
+
+class FuzzLog {
+public:
+ FuzzLog(const std::string& tag, bool log) : mTag(tag), mLog(log) {}
+ ~FuzzLog() {
+ if (mLog) {
+ std::cout << mTag << ": " << mOs.str() << std::endl;
+ }
+ }
+
+ std::stringstream& log() {
+ return mOs;
+ }
+
+private:
+ std::string mTag;
+ bool mLog;
+ std::stringstream mOs;
+};
+
+std::string hexString(const std::vector<uint8_t>& hash);
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 5f324c7..9108e31 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -89,7 +89,7 @@
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index f5a54ce..0ab40b8 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -160,7 +160,7 @@
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 1095c7f..3be61f9 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -68,6 +68,8 @@
// This must be called before the object is sent to another process. Not thread safe.
void setExtension(const sp<IBinder>& extension);
+ pid_t getDebugPid();
+
protected:
virtual ~BBinder();
@@ -112,7 +114,7 @@
std::atomic<int32_t> mState;
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index 9230e89..c17ae6f 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -62,6 +62,6 @@
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BINDER_SERVICE_H
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 28599f4..7dca733 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -144,7 +144,7 @@
static bool sBinderProxyThrottleCreate;
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
index feae93d..1b27bb2 100644
--- a/libs/binder/include/binder/BufferedTextOutput.h
+++ b/libs/binder/include/binder/BufferedTextOutput.h
@@ -62,6 +62,6 @@
};
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_BUFFEREDTEXTOUTPUT_H
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
index 58e2b32..324e5c1 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/include/binder/Debug.h
@@ -44,6 +44,6 @@
__END_DECLS
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_BINDER_DEBUG_H
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index 6abc071..e0248f6 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -51,7 +51,7 @@
// ------------------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/binder/include/binder/IAppOpsCallback.h
index b500219..7664260 100644
--- a/libs/binder/include/binder/IAppOpsCallback.h
+++ b/libs/binder/include/binder/IAppOpsCallback.h
@@ -52,7 +52,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 9784003..8b8a3c2 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -88,6 +88,6 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_IAPP_OPS_SERVICE_H
diff --git a/libs/binder/include/binder/IBatteryStats.h b/libs/binder/include/binder/IBatteryStats.h
index 48da865..b786f89 100644
--- a/libs/binder/include/binder/IBatteryStats.h
+++ b/libs/binder/include/binder/IBatteryStats.h
@@ -77,7 +77,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 027e088..64f3052 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -59,6 +59,7 @@
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
+ DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
FLAG_ONEWAY = 0x00000001
@@ -129,6 +130,11 @@
*/
status_t getExtension(sp<IBinder>* out);
+ /**
+ * Dump PID for a binder, for debugging.
+ */
+ status_t getDebugPid(pid_t* outPid);
+
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t transact( uint32_t code,
const Parcel& data,
@@ -236,7 +242,7 @@
private:
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 0d30560..5793a1c 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -168,6 +168,6 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_IINTERFACE_H
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
index 213ee63..da2b7cf 100644
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ b/libs/binder/include/binder/IMediaResourceMonitor.h
@@ -52,7 +52,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
index 8791741..1a36eb0 100644
--- a/libs/binder/include/binder/IMemory.h
+++ b/libs/binder/include/binder/IMemory.h
@@ -123,6 +123,6 @@
// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_IMEMORY_H
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index b810f7e..ff9244e 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -196,7 +196,7 @@
ProcessState::CallRestriction mCallRestriction;
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index 26a1b23..4b66df8 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -65,7 +65,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IProcessInfoService.h b/libs/binder/include/binder/IProcessInfoService.h
index 033c145..ca30ad3 100644
--- a/libs/binder/include/binder/IProcessInfoService.h
+++ b/libs/binder/include/binder/IProcessInfoService.h
@@ -46,7 +46,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IResultReceiver.h b/libs/binder/include/binder/IResultReceiver.h
index 00b3d89..70e99e7 100644
--- a/libs/binder/include/binder/IResultReceiver.h
+++ b/libs/binder/include/binder/IResultReceiver.h
@@ -50,7 +50,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_IRESULT_RECEIVER_H
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 8ae860d..def1bea 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -104,7 +104,7 @@
int32_t* outPid, int32_t* outUid);
bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
-}; // namespace android
+} // namespace android
#endif // ANDROID_ISERVICE_MANAGER_H
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index 6715678..b7ab6ea 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -51,7 +51,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_ISHELL_CALLBACK_H
diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include/binder/IUidObserver.h
index a1f530d..09e50a9 100644
--- a/libs/binder/include/binder/IUidObserver.h
+++ b/libs/binder/include/binder/IUidObserver.h
@@ -58,7 +58,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/MemoryBase.h b/libs/binder/include/binder/MemoryBase.h
index 463e26d..4dd3638 100644
--- a/libs/binder/include/binder/MemoryBase.h
+++ b/libs/binder/include/binder/MemoryBase.h
@@ -46,6 +46,6 @@
};
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_MEMORY_BASE_H
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index b483be0..6c1c412 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -59,6 +59,6 @@
// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_MEMORY_DEALER_H
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 100d784..3fccddc 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -98,6 +98,6 @@
};
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_MEMORY_HEAP_BASE_H
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 3471e13..8726681 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -921,7 +921,7 @@
return to;
}
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index 95eabff..c258215 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -77,7 +77,7 @@
};
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
index d81f514..4db522a 100644
--- a/libs/binder/include/binder/PermissionController.h
+++ b/libs/binder/include/binder/PermissionController.h
@@ -60,7 +60,7 @@
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/ProcessInfoService.h b/libs/binder/include/binder/ProcessInfoService.h
index a03aae9..6bfd1bc 100644
--- a/libs/binder/include/binder/ProcessInfoService.h
+++ b/libs/binder/include/binder/ProcessInfoService.h
@@ -78,7 +78,7 @@
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 8339976..f7c38f4 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -126,7 +126,7 @@
CallRestriction mCallRestriction;
};
-}; // namespace android
+} // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index 5b5f766..f66406f 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -199,6 +199,6 @@
inline bool HexDump::carrayStyle() const { return mCArrayStyle; }
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_TEXTOUTPUT_H
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 7749e66..8efaf3d 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -57,7 +57,6 @@
"libutils",
"libbinder",
"libui",
- "libstatslog",
],
sanitize: {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 8a2fc2a..366c93c 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -34,7 +34,6 @@
#include <utils/Trace.h>
#include <input/InputTransport.h>
-#include <statslog.h>
using android::base::StringPrintf;
@@ -538,9 +537,6 @@
msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
}
- if (source == AINPUT_SOURCE_TOUCHSCREEN) {
- reportTouchEventForStatistics(eventTime);
- }
return mChannel->sendMessage(&msg);
}
@@ -567,17 +563,6 @@
return OK;
}
-void InputPublisher::reportTouchEventForStatistics(nsecs_t evdevTime) {
- if (mTouchStatistics.shouldReport()) {
- android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(),
- mTouchStatistics.getMax(), mTouchStatistics.getMean(),
- mTouchStatistics.getStDev(), mTouchStatistics.getCount());
- mTouchStatistics.reset();
- }
- nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime);
- mTouchStatistics.addValue(latency);
-}
-
// --- InputConsumer ---
InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
diff --git a/libs/input/LatencyStatistics.cpp b/libs/input/LatencyStatistics.cpp
index e343578..394da22 100644
--- a/libs/input/LatencyStatistics.cpp
+++ b/libs/input/LatencyStatistics.cpp
@@ -84,7 +84,7 @@
bool LatencyStatistics::shouldReport() {
std::chrono::duration timeSinceReport = std::chrono::steady_clock::now() - mLastReportTime;
- return mCount != 0 && timeSinceReport > mReportPeriod;
+ return mCount != 0 && timeSinceReport >= mReportPeriod;
}
} // namespace android
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index dd4c55d..f39f066 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -827,11 +827,14 @@
drawMesh(mesh);
// The middle part of the layer can turn off blending.
- const Rect middleRect(bounds.left, bounds.top + radius, bounds.right, bounds.bottom - radius);
- setScissor(middleRect);
- mState.cornerRadius = 0.0;
- disableBlending();
- drawMesh(mesh);
+ if (topRect.bottom < bottomRect.top) {
+ const Rect middleRect(bounds.left, bounds.top + radius, bounds.right,
+ bounds.bottom - radius);
+ setScissor(middleRect);
+ mState.cornerRadius = 0.0;
+ disableBlending();
+ drawMesh(mesh);
+ }
disableScissor();
}
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 693e48e..48a68af 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -72,15 +72,13 @@
"libarect",
],
header_libs: [
+ "bionic_libc_platform_headers",
"gl_headers",
"libsystem_headers",
"libhardware_headers",
"libnativebase_headers",
],
export_header_lib_headers: ["gl_headers"],
-
- // we need to access the private Bionic header <bionic_tls.h>
- include_dirs: ["bionic/libc/private"],
}
//##############################################################################
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 63a0e14..86fec21 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -46,7 +46,7 @@
#define MAX_NUMBER_OF_GL_EXTENSIONS 256
-#include <bionic_tls.h> /* special private C library header */
+#include <bionic/tls.h> /* special private C library header */
// ----------------------------------------------------------------------------
namespace android {
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index 19c8b37..8bfe517 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -28,9 +28,11 @@
],
include_dirs: [
- "bionic/libc/private",
"frameworks/native/opengl/libs",
"frameworks/native/opengl/libs/EGL",
],
+ header_libs: [
+ "bionic_libc_platform_headers",
+ ],
}
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 11578c3..f6b5935 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -44,6 +44,7 @@
"libhidlbase",
"libinput",
"liblog",
+ "libstatslog",
"libutils",
"libui",
"server_configurable_flags",
diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp
index bc53cf5..0422d83 100644
--- a/services/inputflinger/InputReaderBase.cpp
+++ b/services/inputflinger/InputReaderBase.cpp
@@ -114,8 +114,10 @@
std::optional<DisplayViewport> result = std::nullopt;
for (const DisplayViewport& currentViewport : mDisplays) {
// Return the first match
- if (currentViewport.type == type && !result) {
- result = std::make_optional(currentViewport);
+ if (currentViewport.type == type) {
+ if (!result) {
+ result = std::make_optional(currentViewport);
+ }
count++;
}
}
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index b8c3a80..9185e00 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -34,6 +34,7 @@
"libinputreporter",
"libinputflinger_base",
"liblog",
+ "libstatslog",
"libui",
"libutils",
],
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index a9e22f1..28c2799 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -29,6 +29,9 @@
namespace android::inputdispatcher {
+// Sequence number for synthesized or injected events.
+constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
+
struct EventEntry {
enum { TYPE_CONFIGURATION_CHANGED, TYPE_DEVICE_RESET, TYPE_KEY, TYPE_MOTION };
@@ -41,8 +44,23 @@
bool dispatchInProgress; // initially false, set to true while dispatching
+ /**
+ * Injected keys are events from an external (probably untrusted) application
+ * and are not related to real hardware state. They come in via
+ * InputDispatcher::injectInputEvent, which sets policy flag POLICY_FLAG_INJECTED.
+ */
inline bool isInjected() const { return injectionState != nullptr; }
+ /**
+ * Synthesized events are either injected events, or events that come
+ * from real hardware, but aren't directly attributable to a specific hardware event.
+ * Key repeat is a synthesized event, because it is related to an actual hardware state
+ * (a key is currently pressed), but the repeat itself is generated by the framework.
+ */
+ inline bool isSynthesized() const {
+ return isInjected() || sequenceNum == SYNTHESIZED_EVENT_SEQUENCE_NUM;
+ }
+
void release();
virtual void appendDescription(std::string& msg) const = 0;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index e161e8c..aa51e23 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -50,6 +50,7 @@
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
+#include <statslog.h>
#include <stddef.h>
#include <time.h>
#include <unistd.h>
@@ -2276,6 +2277,7 @@
motionEntry->downTime, motionEntry->eventTime,
motionEntry->pointerCount,
motionEntry->pointerProperties, usingCoords);
+ reportTouchEventForStatistics(*motionEntry);
break;
}
@@ -4481,6 +4483,34 @@
// TODO Write some statistics about how long we spend waiting.
}
+/**
+ * Report the touch event latency to the statsd server.
+ * Input events are reported for statistics if:
+ * - This is a touchscreen event
+ * - InputFilter is not enabled
+ * - Event is not injected or synthesized
+ *
+ * Statistics should be reported before calling addValue, to prevent a fresh new sample
+ * from getting aggregated with the "old" data.
+ */
+void InputDispatcher::reportTouchEventForStatistics(const MotionEntry& motionEntry)
+ REQUIRES(mLock) {
+ const bool reportForStatistics = (motionEntry.source == AINPUT_SOURCE_TOUCHSCREEN) &&
+ !(motionEntry.isSynthesized()) && !mInputFilterEnabled;
+ if (!reportForStatistics) {
+ return;
+ }
+
+ if (mTouchStatistics.shouldReport()) {
+ android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(),
+ mTouchStatistics.getMax(), mTouchStatistics.getMean(),
+ mTouchStatistics.getStDev(), mTouchStatistics.getCount());
+ mTouchStatistics.reset();
+ }
+ const float latencyMicros = nanoseconds_to_microseconds(now() - motionEntry.eventTime);
+ mTouchStatistics.addValue(latencyMicros);
+}
+
void InputDispatcher::traceInboundQueueLengthLocked() {
if (ATRACE_ENABLED()) {
ATRACE_INT("iq", mInboundQueue.size());
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index f2c0402..0d9d6b0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -33,6 +33,7 @@
#include <input/InputApplication.h>
#include <input/InputTransport.h>
#include <input/InputWindow.h>
+#include <input/LatencyStatistics.h>
#include <limits.h>
#include <stddef.h>
#include <ui/Region.h>
@@ -455,6 +456,10 @@
void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
// Statistics gathering.
+ static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min;
+ LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD};
+
+ void reportTouchEventForStatistics(const MotionEntry& entry);
void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
void traceInboundQueueLengthLocked() REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index bccef0f..47e9b36 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -24,9 +24,6 @@
namespace android::inputdispatcher {
-// Sequence number for synthesized or injected events.
-constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
-
/* Tracks dispatched key and motion event state so that cancellation events can be
* synthesized when events are dropped. */
class InputState {
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index c15ecfd..efe3809 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -271,9 +271,8 @@
ALOGI("Video device scanning disabled");
}
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = EPOLLIN;
+ struct epoll_event eventItem = {};
+ eventItem.events = EPOLLIN | EPOLLWAKEUP;
eventItem.data.fd = mINotifyFd;
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index fba235d..d189846 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -58,7 +58,7 @@
BufferLayer::BufferLayer(const LayerCreationArgs& args)
: Layer(args),
- mTextureName(args.flinger->getNewTexture()),
+ mTextureName(args.textureName),
mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
compositionengine::LayerCreationArgs{this})} {
ALOGV("Creating Layer %s", args.name.string());
@@ -70,7 +70,13 @@
}
BufferLayer::~BufferLayer() {
- mFlinger->deleteTextureAsync(mTextureName);
+ if (!isClone()) {
+ // The original layer and the clone layer share the same texture. Therefore, only one of
+ // the layers, in this case the original layer, needs to handle the deletion. The original
+ // layer and the clone should be removed at the same time so there shouldn't be any issue
+ // with the clone layer trying to use the deleted texture.
+ mFlinger->deleteTextureAsync(mTextureName);
+ }
const int32_t layerID = getSequence();
mFlinger->mTimeStats->onDestroy(layerID);
mFlinger->mFrameTracer->onDestroy(layerID);
@@ -722,6 +728,15 @@
mBufferInfo.mTransform, filteringEnabled);
}
+void BufferLayer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
+ Layer::setInitialValuesForClone(clonedFrom);
+
+ sp<BufferLayer> bufferClonedFrom = static_cast<BufferLayer*>(clonedFrom.get());
+ mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha;
+ mPotentialCursor = bufferClonedFrom->mPotentialCursor;
+ mProtectedByApp = bufferClonedFrom->mProtectedByApp;
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index f0a30e3..b2c0618 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -194,6 +194,7 @@
bool mRefreshPending{false};
ui::Dataspace translateDataspace(ui::Dataspace dataspace);
+ void setInitialValuesForClone(const sp<Layer>& clonedFrom);
private:
// Returns true if this layer requires filtering
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index fcabedf..eb13f65 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -461,12 +461,7 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
- {
- // Grab the SF state lock during this since it's the only safe way to access RenderEngine
- Mutex::Autolock lock(mFlinger->mStateLock);
- mConsumer =
- new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
- }
+ mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
@@ -476,7 +471,7 @@
mProducer->setMaxDequeuedBufferCount(2);
}
- if (const auto display = mFlinger->getDefaultDisplayDevice()) {
+ if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) {
updateTransformHint(display);
}
}
@@ -531,4 +526,15 @@
mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
}
+sp<Layer> BufferQueueLayer::createClone() {
+ const String8 name = mName + " (Mirror)";
+ LayerCreationArgs args =
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+ args.textureName = mTextureName;
+ sp<BufferQueueLayer> layer = new BufferQueueLayer(args);
+ layer->setInitialValuesForClone(this);
+
+ return layer;
+}
+
} // namespace android
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 9374741..36dff15 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -31,6 +31,7 @@
*/
class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener {
public:
+ // Only call while mStateLock is held
explicit BufferQueueLayer(const LayerCreationArgs&);
~BufferQueueLayer() override;
@@ -81,6 +82,7 @@
status_t updateFrameNumber(nsecs_t latchTime) override;
void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ sp<Layer> createClone() override;
// -----------------------------------------------------------------------
// Interface implementation for BufferLayerConsumer::ContentsChangedListener
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index ad05bc8..30fdbe1 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -48,10 +48,17 @@
: BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
+ if (const auto display = args.displayDevice) {
+ updateTransformHint(display);
+ }
}
BufferStateLayer::~BufferStateLayer() {
- if (mBufferInfo.mBuffer != nullptr) {
+ // The original layer and the clone layer share the same texture and buffer. Therefore, only
+ // one of the layers, in this case the original layer, needs to handle the deletion. The
+ // original layer and the clone should be removed at the same time so there shouldn't be any
+ // issue with the clone layer trying to use the texture.
+ if (mBufferInfo.mBuffer != nullptr && !isClone()) {
// Ensure that mBuffer is uncached from RenderEngine here, as
// RenderEngine may have been using the buffer as an external texture
// after the client uncached the buffer.
@@ -545,14 +552,6 @@
mFrameNumber++;
}
-void BufferStateLayer::onFirstRef() {
- BufferLayer::onFirstRef();
-
- if (const auto display = mFlinger->getDefaultDisplayDevice()) {
- updateTransformHint(display);
- }
-}
-
void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
std::lock_guard lock(mMutex);
if (!clientCacheId.isValid()) {
@@ -668,4 +667,14 @@
return s.crop;
}
+sp<Layer> BufferStateLayer::createClone() {
+ const String8 name = mName + " (Mirror)";
+ LayerCreationArgs args =
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+ args.textureName = mTextureName;
+ sp<BufferStateLayer> layer = new BufferStateLayer(args);
+ layer->mHwcSlotGenerator = mHwcSlotGenerator;
+ layer->setInitialValuesForClone(this);
+ return layer;
+}
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 52063fc..e951ccf 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -124,13 +124,13 @@
status_t updateFrameNumber(nsecs_t latchTime) override;
void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ sp<Layer> createClone() override;
// Crop that applies to the buffer
Rect computeCrop(const State& s);
private:
friend class SlotGenerationTest;
- void onFirstRef() override;
bool willPresentCurrentTransaction() const;
static const std::array<float, 16> IDENTITY_MATRIX;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 99805d9..5b62054 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -107,6 +107,14 @@
return mDrawingState.dataspace;
}
+sp<Layer> ColorLayer::createClone() {
+ String8 name = mName + " (Mirror)";
+ sp<ColorLayer> layer = new ColorLayer(
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+ layer->setInitialValuesForClone(this);
+ return layer;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 16921df..634a800 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -50,6 +50,8 @@
compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
std::shared_ptr<compositionengine::Layer> mCompositionLayer;
+
+ sp<Layer> createClone() override;
};
} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index fcb94fd..1407ef7 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -3,6 +3,7 @@
defaults: ["surfaceflinger_defaults"],
cflags: [
"-DLOG_TAG=\"CompositionEngine\"",
+ "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
shared_libs: [
"android.frameworks.vr.composer@2.0",
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 4a11303..cb50d9f 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -30,4 +30,11 @@
return false;
}
+sp<Layer> ContainerLayer::createClone() {
+ String8 name = mName + " (Mirror)";
+ sp<ContainerLayer> layer = new ContainerLayer(
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+ layer->setInitialValuesForClone(this);
+ return layer;
+}
} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index c3624f6..b48d471 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -32,6 +32,9 @@
bool isVisible() const override;
bool isCreatedFromMainThread() const override { return true; }
+
+protected:
+ sp<Layer> createClone() override;
};
} // namespace android
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b1fcff2..89123df 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -255,13 +255,17 @@
scissor = displayBounds;
}
+ uint32_t transformOrientation;
+
if (isPrimary()) {
sPrimaryDisplayOrientation = displayStateOrientationToTransformOrientation(orientation);
+ transformOrientation = displayStateOrientationToTransformOrientation(
+ (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1));
+ } else {
+ transformOrientation = displayStateOrientationToTransformOrientation(orientation);
}
- getCompositionDisplay()->setProjection(globalTransform,
- displayStateOrientationToTransformOrientation(
- orientation),
+ getCompositionDisplay()->setProjection(globalTransform, transformOrientation,
frame, viewport, scissor, needsFiltering);
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ba948cf..079bc66 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -899,6 +899,7 @@
}
setZOrderRelativeOf(nullptr);
}
+ mCurrentState.isRelativeOf = false;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -942,6 +943,7 @@
mCurrentState.sequence++;
mCurrentState.modified = true;
mCurrentState.z = relativeZ;
+ mCurrentState.isRelativeOf = true;
auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
if (oldZOrderRelativeOf != nullptr) {
@@ -1540,7 +1542,7 @@
bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const State& state = useDrawing ? mDrawingState : mCurrentState;
- return state.zOrderRelativeOf != nullptr;
+ return state.isRelativeOf;
}
__attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList(
@@ -1565,8 +1567,7 @@
}
for (const sp<Layer>& child : children) {
- const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
- if (childState.zOrderRelativeOf != nullptr) {
+ if (child->usingRelativeZ(stateSet)) {
continue;
}
traverse.add(child);
@@ -2015,6 +2016,15 @@
return outputLayer->getState().visibleRegion;
}
+void Layer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
+ // copy drawing state from cloned layer
+ mDrawingState = clonedFrom->mDrawingState;
+ mClonedFrom = clonedFrom;
+
+ // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple
+ // InputWindows per client token yet.
+ mDrawingState.inputInfo.token = nullptr;
+}
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8771ccd..610df25 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -91,6 +91,8 @@
LayerMetadata metadata;
pid_t callingPid;
uid_t callingUid;
+ sp<const DisplayDevice> displayDevice;
+ uint32_t textureName;
};
class Layer : public compositionengine::LayerFE {
@@ -170,6 +172,7 @@
// If non-null, a Surface this Surface's Z-order is interpreted relative to.
wp<Layer> zOrderRelativeOf;
+ bool isRelativeOf{false};
// A list of surfaces whose Z-order is interpreted relative to ours.
SortedVector<wp<Layer>> zOrderRelatives;
@@ -465,6 +468,13 @@
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
virtual bool needsFiltering(const sp<const DisplayDevice>&) const { return false; }
+protected:
+ virtual sp<Layer> createClone() = 0;
+ sp<Layer> getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; }
+
+ bool isClone() { return getClonedFrom() != nullptr; }
+ virtual void setInitialValuesForClone(const sp<Layer>& clonedFrom);
+
public:
/*
* compositionengine::LayerFE overrides
@@ -912,6 +922,12 @@
// to help debugging.
pid_t mCallingPid;
uid_t mCallingUid;
+
+ // The current layer is a clone of mClonedFrom. This means that this layer will update it's
+ // properties based on mClonedFrom. When mClonedFrom latches a new buffer for BufferLayers,
+ // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children,
+ // and relatives, this layer will update as well.
+ wp<Layer> mClonedFrom;
};
} // namespace android
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 8494524..8271fd9 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -64,7 +64,7 @@
const auto& layer = (*this)[i];
auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
: layer->getDrawingState();
- if (state.zOrderRelativeOf != nullptr) {
+ if (state.isRelativeOf) {
continue;
}
layer->traverseInZOrder(stateSet, visitor);
@@ -76,7 +76,7 @@
const auto& layer = (*this)[i];
auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
: layer->getDrawingState();
- if (state.zOrderRelativeOf != nullptr) {
+ if (state.isRelativeOf) {
continue;
}
layer->traverseInReverseZOrder(stateSet, visitor);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7928219..a065c6c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3531,8 +3531,18 @@
break;
}
- sp<BufferQueueLayer> layer = getFactory().createBufferQueueLayer(
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+ sp<BufferQueueLayer> layer;
+ LayerCreationArgs args =
+ LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+ args.textureName = getNewTexture();
+ {
+ // Grab the SF state lock during this since it's the only safe way to access
+ // RenderEngine when creating a BufferLayerConsumer
+ // TODO: Check if this lock is still needed here
+ Mutex::Autolock lock(mStateLock);
+ layer = getFactory().createBufferQueueLayer(args);
+ }
+
status_t err = layer->setDefaultBufferProperties(w, h, format);
if (err == NO_ERROR) {
*handle = layer->getHandle();
@@ -3548,8 +3558,11 @@
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
sp<Layer>* outLayer) {
- sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+ LayerCreationArgs args =
+ LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+ args.displayDevice = getDefaultDisplayDevice();
+ args.textureName = getNewTexture();
+ sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
*handle = layer->getHandle();
*outLayer = layer;
@@ -4093,6 +4106,7 @@
const int32_t offscreenRootLayerId = INT32_MAX - 2;
rootProto->set_id(offscreenRootLayerId);
rootProto->set_name("Offscreen Root");
+ rootProto->set_parent(-1);
for (Layer* offscreenLayer : mOffscreenLayers) {
// Add layer as child of the fake root
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 7f960f3..d6b9b60 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -19,10 +19,19 @@
srcs: [
"BufferGenerator.cpp",
"Credentials_test.cpp",
- "InvalidHandles_test.cpp",
- "Stress_test.cpp",
+ "DereferenceSurfaceControl_test.cpp",
+ "DisplayActiveConfig_test.cpp",
+ "InvalidHandles_test.cpp",
+ "LayerCallback_test.cpp",
+ "LayerRenderTypeTransaction_test.cpp",
+ "LayerTransaction_test.cpp",
+ "LayerTypeAndRenderTypeTransaction_test.cpp",
+ "LayerTypeTransaction_test.cpp",
+ "LayerUpdate_test.cpp",
+ "MultiDisplayLayerBounds_test.cpp",
+ "RelativeZ_test.cpp",
+ "Stress_test.cpp",
"SurfaceInterceptor_test.cpp",
- "Transaction_test.cpp",
"VirtualDisplay_test.cpp",
],
data: ["SurfaceFlinger_test.filter"],
diff --git a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp
new file mode 100644
index 0000000..0cef0d1
--- /dev/null
+++ b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 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 "LayerTransactionTest.h"
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+class DereferenceSurfaceControlTest : public LayerTransactionTest {
+protected:
+ void SetUp() override {
+ LayerTransactionTest::SetUp();
+ bgLayer = createLayer("BG layer", 20, 20);
+ fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20);
+ fgLayer = createLayer("FG layer", 20, 20);
+ fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20);
+ Transaction().setLayer(fgLayer, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("before anything");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE);
+ }
+ }
+ void TearDown() override {
+ LayerTransactionTest::TearDown();
+ bgLayer = 0;
+ fgLayer = 0;
+ }
+
+ sp<SurfaceControl> bgLayer;
+ sp<SurfaceControl> fgLayer;
+};
+
+TEST_F(DereferenceSurfaceControlTest, LayerNotInTransaction) {
+ fgLayer = nullptr;
+ {
+ SCOPED_TRACE("after setting null");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 20, 20), Color::RED);
+ }
+}
+
+TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) {
+ auto transaction = Transaction().show(fgLayer);
+ fgLayer = nullptr;
+ {
+ SCOPED_TRACE("after setting null");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE);
+ }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/DisplayActiveConfig_test.cpp b/services/surfaceflinger/tests/DisplayActiveConfig_test.cpp
new file mode 100644
index 0000000..2e3b760
--- /dev/null
+++ b/services/surfaceflinger/tests/DisplayActiveConfig_test.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 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 <thread>
+#include "LayerTransactionTest.h"
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+class DisplayActiveConfigTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
+ SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &mDisplayconfigs);
+ EXPECT_GT(mDisplayconfigs.size(), 0);
+
+ // set display power to on to make sure config can be changed
+ SurfaceComposerClient::setDisplayPowerMode(mDisplayToken, HWC_POWER_MODE_NORMAL);
+ }
+
+ sp<IBinder> mDisplayToken;
+ Vector<DisplayInfo> mDisplayconfigs;
+};
+
+TEST_F(DisplayActiveConfigTest, allConfigsAllowed) {
+ std::vector<int32_t> allowedConfigs;
+
+ // Add all configs to the allowed configs
+ for (int i = 0; i < mDisplayconfigs.size(); i++) {
+ allowedConfigs.push_back(i);
+ }
+
+ status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs);
+ EXPECT_EQ(res, NO_ERROR);
+
+ std::vector<int32_t> outConfigs;
+ res = SurfaceComposerClient::getAllowedDisplayConfigs(mDisplayToken, &outConfigs);
+ EXPECT_EQ(res, NO_ERROR);
+ EXPECT_EQ(allowedConfigs, outConfigs);
+}
+
+TEST_F(DisplayActiveConfigTest, changeAllowedConfig) {
+ // we need at least 2 configs available for this test
+ if (mDisplayconfigs.size() <= 1) return;
+
+ int activeConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken);
+
+ // We want to set the allowed config to everything but the active config
+ std::vector<int32_t> allowedConfigs;
+ for (int i = 0; i < mDisplayconfigs.size(); i++) {
+ if (i != activeConfig) {
+ allowedConfigs.push_back(i);
+ }
+ }
+
+ status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs);
+ EXPECT_EQ(res, NO_ERROR);
+
+ // Allow some time for the config change
+ std::this_thread::sleep_for(200ms);
+
+ int newActiveConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken);
+ EXPECT_NE(activeConfig, newActiveConfig);
+
+ // Make sure the new config is part of allowed config
+ EXPECT_TRUE(std::find(allowedConfigs.begin(), allowedConfigs.end(), newActiveConfig) !=
+ allowedConfigs.end());
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
new file mode 100644
index 0000000..7a5ed48
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -0,0 +1,872 @@
+/*
+ * Copyright (C) 2019 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 "LayerTransactionTest.h"
+#include "utils/CallbackUtils.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+class LayerCallbackTest : public LayerTransactionTest {
+public:
+ virtual sp<SurfaceControl> createBufferStateLayer() {
+ return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
+ }
+
+ static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
+ const sp<SurfaceControl>& layer = nullptr, bool setBuffer = true,
+ bool setBackgroundColor = false) {
+ if (layer) {
+ sp<GraphicBuffer> buffer;
+ sp<Fence> fence;
+ if (setBuffer) {
+ int err = getBuffer(&buffer, &fence);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ transaction.setBuffer(layer, buffer);
+ transaction.setAcquireFence(layer, fence);
+ }
+
+ if (setBackgroundColor) {
+ transaction.setBackgroundColor(layer, /*color*/ half3(1.0f, 0, 0), /*alpha*/ 1.0f,
+ ui::Dataspace::UNKNOWN);
+ }
+ }
+
+ transaction.addTransactionCompletedCallback(callbackHelper->function,
+ callbackHelper->getContext());
+ return NO_ERROR;
+ }
+
+ static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
+ bool finalState = false) {
+ CallbackData callbackData;
+ ASSERT_NO_FATAL_FAILURE(helper.getCallbackData(&callbackData));
+ EXPECT_NO_FATAL_FAILURE(expectedResult.verifyCallbackData(callbackData));
+
+ if (finalState) {
+ ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
+ }
+ }
+
+ static void waitForCallbacks(CallbackHelper& helper,
+ const std::vector<ExpectedResult>& expectedResults,
+ bool finalState = false) {
+ for (const auto& expectedResult : expectedResults) {
+ waitForCallback(helper, expectedResult);
+ }
+ if (finalState) {
+ ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
+ }
+ }
+};
+
+TEST_F(LayerCallbackTest, BufferColor) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer, true, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, NoBufferNoColor) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer, false, false);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, BufferNoColor) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer, true, false);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, NoBufferColor) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, NoStateChange) {
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+
+ ExpectedResult expected;
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, OffScreen) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, MergeBufferNoColor) {
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+
+TEST_F(LayerCallbackTest, MergeNoBufferColor) {
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ int err = fillTransaction(transaction1, &callback1, layer1, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+
+TEST_F(LayerCallbackTest, MergeOneBufferOneColor) {
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1);
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer2,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+TEST_F(LayerCallbackTest, Merge_SameCallback) {
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction1, &callback, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction2.merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, Merge_SameLayer) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ int err = fillTransaction(transaction1, &callback1, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction2.merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+
+TEST_F(LayerCallbackTest, Merge_DifferentClients) {
+ sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
+ client2(new SurfaceComposerClient);
+
+ ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
+ ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
+
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ for (size_t i = 0; i < 10; i++) {
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::ACQUIRED,
+ (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
+ : ExpectedResult::PreviousBuffer::RELEASED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
+ }
+ ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_NoStateChange) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ for (size_t i = 0; i < 10; i++) {
+ ExpectedResult expected;
+
+ if (i == 0) {
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ } else {
+ int err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ }
+
+ transaction.apply();
+
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
+ }
+ ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ for (size_t i = 0; i < 10; i++) {
+ if (i == 0) {
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ } else {
+ int err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED
+ : ExpectedResult::Transaction::NOT_PRESENTED,
+ layer,
+ (i == 0) ? ExpectedResult::Buffer::ACQUIRED
+ : ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0));
+ }
+ ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_Merge) {
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ for (size_t i = 0; i < 10; i++) {
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
+ ExpectedResult::Buffer::ACQUIRED,
+ (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
+ : ExpectedResult::PreviousBuffer::RELEASED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected));
+ }
+ ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState());
+ ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState());
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) {
+ sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
+ client2(new SurfaceComposerClient);
+ ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
+ ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
+
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ for (size_t i = 0; i < 10; i++) {
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
+ ExpectedResult::Buffer::ACQUIRED,
+ (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
+ : ExpectedResult::PreviousBuffer::RELEASED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected));
+ }
+ ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState());
+ ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState());
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateChange) {
+ sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
+ client2(new SurfaceComposerClient);
+ ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
+ ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
+
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+
+ // Normal call to set up test
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+ expected.reset();
+
+ // Test
+ err = fillTransaction(transaction1, &callback1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction2.merge(std::move(transaction1)).apply();
+
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateChange) {
+ sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
+ client2(new SurfaceComposerClient);
+
+ ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
+ ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
+
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+
+ // Normal call to set up test
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+ expected.reset();
+
+ // Test
+ err = fillTransaction(transaction1, &callback1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ std::vector<ExpectedResult> expectedResults(50);
+ for (auto& expected : expectedResults) {
+ expected.reset();
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::ACQUIRED,
+ ExpectedResult::PreviousBuffer::UNKNOWN);
+
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+ }
+ EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_NoStateChange) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ // Normal call to set up test
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+
+ // Test
+ std::vector<ExpectedResult> expectedResults(50);
+ for (auto& expected : expectedResults) {
+ expected.reset();
+
+ err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+ }
+ EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
+}
+
+TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ // Normal call to set up test
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ ExpectedResult expectedResult;
+ expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expectedResult, true));
+
+ // Test
+ std::vector<ExpectedResult> expectedResults(50);
+ for (auto& expected : expectedResults) {
+ expected.reset();
+ expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+
+ err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+ }
+ EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
+}
+
+TEST_F(LayerCallbackTest, DesiredPresentTime) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ // Try to present 100ms in the future
+ nsecs_t time = systemTime() + (100 * 1e6);
+
+ transaction.setDesiredPresentTime(time);
+ transaction.apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ expected.addExpectedPresentTime(time);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback1;
+ int err = fillTransaction(transaction, &callback1, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ // Try to present 100ms in the future
+ nsecs_t time = systemTime() + (100 * 1e6);
+
+ transaction.setDesiredPresentTime(time);
+ transaction.apply();
+
+ ExpectedResult expected1;
+ expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ expected1.addExpectedPresentTime(time);
+
+ CallbackHelper callback2;
+ err = fillTransaction(transaction, &callback2, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ // Try to present 33ms after the first frame
+ time += (33.3 * 1e6);
+
+ transaction.setDesiredPresentTime(time);
+ transaction.apply();
+
+ ExpectedResult expected2;
+ expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::ACQUIRED,
+ ExpectedResult::PreviousBuffer::RELEASED);
+ expected2.addExpectedPresentTime(time);
+
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true));
+}
+
+TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback1;
+ int err = fillTransaction(transaction, &callback1, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ // Try to present 100ms in the future
+ nsecs_t time = systemTime() + (100 * 1e6);
+
+ transaction.setDesiredPresentTime(time);
+ transaction.apply();
+
+ ExpectedResult expected1;
+ expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ expected1.addExpectedPresentTime(time);
+
+ CallbackHelper callback2;
+ err = fillTransaction(transaction, &callback2, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ // Try to present 33ms before the previous frame
+ time -= (33.3 * 1e6);
+
+ transaction.setDesiredPresentTime(time);
+ transaction.apply();
+
+ ExpectedResult expected2;
+ expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::ACQUIRED,
+ ExpectedResult::PreviousBuffer::RELEASED);
+
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true));
+}
+
+TEST_F(LayerCallbackTest, DesiredPresentTime_Past) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ // Try to present 100ms in the past
+ nsecs_t time = systemTime() - (100 * 1e6);
+
+ transaction.setDesiredPresentTime(time);
+ transaction.apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ expected.addExpectedPresentTime(systemTime());
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
new file mode 100644
index 0000000..a48f553
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -0,0 +1,1834 @@
+/*
+ * Copyright (C) 2019 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 <gui/BufferItemConsumer.h>
+#include <thread>
+#include "TransactionTestHarnesses.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+class LayerRenderTypeTransactionTest : public LayerTransactionTest,
+ public ::testing::WithParamInterface<RenderPath> {
+public:
+ LayerRenderTypeTransactionTest() : mHarness(LayerRenderPathTestHarness(this, GetParam())) {}
+
+ std::unique_ptr<ScreenCapture> getScreenCapture() { return mHarness.getScreenCapture(); }
+ void setRelativeZBasicHelper(uint32_t layerType);
+ void setRelativeZGroupHelper(uint32_t layerType);
+ void setAlphaBasicHelper(uint32_t layerType);
+ void setBackgroundColorHelper(uint32_t layerType, bool priorColor, bool bufferFill, float alpha,
+ Color finalColor);
+
+protected:
+ LayerRenderPathTestHarness mHarness;
+};
+
+INSTANTIATE_TEST_CASE_P(LayerRenderTypeTransactionTests, LayerRenderTypeTransactionTest,
+ ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT));
+
+TEST_P(LayerRenderTypeTransactionTest, SetPositionBasic_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("default position");
+ const Rect rect(0, 0, 32, 32);
+ auto shot = getScreenCapture();
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
+ }
+
+ Transaction().setPosition(layer, 5, 10).apply();
+ {
+ SCOPED_TRACE("new position");
+ const Rect rect(5, 10, 37, 42);
+ auto shot = getScreenCapture();
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetPositionRounding_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // GLES requires only 4 bits of subpixel precision during rasterization
+ // XXX GLES composition does not match HWC composition due to precision
+ // loss (b/69315223)
+ const float epsilon = 1.0f / 16.0f;
+ Transaction().setPosition(layer, 0.5f - epsilon, 0.5f - epsilon).apply();
+ {
+ SCOPED_TRACE("rounding down");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setPosition(layer, 0.5f + epsilon, 0.5f + epsilon).apply();
+ {
+ SCOPED_TRACE("rounding up");
+ getScreenCapture()->expectColor(Rect(1, 1, 33, 33), Color::RED);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetPositionOutOfBounds_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction().setPosition(layer, -32, -32).apply();
+ {
+ SCOPED_TRACE("negative coordinates");
+ getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
+ }
+
+ Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply();
+ {
+ SCOPED_TRACE("positive coordinates");
+ getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetPositionPartiallyOutOfBounds_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // partially out of bounds
+ Transaction().setPosition(layer, -30, -30).apply();
+ {
+ SCOPED_TRACE("negative coordinates");
+ getScreenCapture()->expectColor(Rect(0, 0, 2, 2), Color::RED);
+ }
+
+ Transaction().setPosition(layer, mDisplayWidth - 2, mDisplayHeight - 2).apply();
+ {
+ SCOPED_TRACE("positive coordinates");
+ getScreenCapture()->expectColor(Rect(mDisplayWidth - 2, mDisplayHeight - 2, mDisplayWidth,
+ mDisplayHeight),
+ Color::RED);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetPositionWithResize_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // setPosition is applied immediately by default, with or without resize
+ // pending
+ Transaction().setPosition(layer, 5, 10).setSize(layer, 64, 64).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = getScreenCapture();
+ const Rect rect(5, 10, 37, 42);
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
+ {
+ SCOPED_TRACE("resize applied");
+ getScreenCapture()->expectColor(Rect(5, 10, 69, 74), Color::RED);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction().setSize(layer, 64, 64).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = getScreenCapture();
+ const Rect rect(0, 0, 32, 32);
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
+ {
+ SCOPED_TRACE("resize applied");
+ auto shot = getScreenCapture();
+ const Rect rect(0, 0, 64, 64);
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetSizeWithScaleToWindow_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition
+ Transaction()
+ .setSize(layer, 64, 64)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED);
+}
+
+void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32));
+
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ Transaction()
+ .setPosition(layerG, 16, 16)
+ .setRelativeLayer(layerG, layerR->getHandle(), 1)
+ .apply();
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ Transaction()
+ .setFrame(layerR, Rect(0, 0, 32, 32))
+ .setFrame(layerG, Rect(16, 16, 48, 48))
+ .setRelativeLayer(layerG, layerR->getHandle(), 1)
+ .apply();
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
+ {
+ SCOPED_TRACE("layerG above");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+ shot->expectColor(Rect(16, 16, 48, 48), Color::GREEN);
+ }
+
+ Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).apply();
+ {
+ SCOPED_TRACE("layerG below");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectColor(Rect(32, 32, 48, 48), Color::GREEN);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
+void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ sp<SurfaceControl> layerB;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerB, Color::BLUE, 32, 32));
+
+ // layerR = 0, layerG = layerR + 3, layerB = 2
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ Transaction()
+ .setPosition(layerG, 8, 8)
+ .setRelativeLayer(layerG, layerR->getHandle(), 3)
+ .setPosition(layerB, 16, 16)
+ .setLayer(layerB, mLayerZBase + 2)
+ .apply();
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ Transaction()
+ .setFrame(layerR, Rect(0, 0, 32, 32))
+ .setFrame(layerG, Rect(8, 8, 40, 40))
+ .setRelativeLayer(layerG, layerR->getHandle(), 3)
+ .setFrame(layerB, Rect(16, 16, 48, 48))
+ .setLayer(layerB, mLayerZBase + 2)
+ .apply();
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
+
+ {
+ SCOPED_TRACE("(layerR < layerG) < layerB");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
+ shot->expectColor(Rect(8, 8, 16, 16), Color::GREEN);
+ shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
+ }
+
+ // layerR = 4, layerG = layerR + 3, layerB = 2
+ Transaction().setLayer(layerR, mLayerZBase + 4).apply();
+ {
+ SCOPED_TRACE("layerB < (layerR < layerG)");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
+ shot->expectColor(Rect(8, 8, 40, 40), Color::GREEN);
+ shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
+ }
+
+ // layerR = 4, layerG = layerR - 3, layerB = 2
+ Transaction().setRelativeLayer(layerG, layerR->getHandle(), -3).apply();
+ {
+ SCOPED_TRACE("layerB < (layerG < layerR)");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectColor(Rect(32, 32, 40, 40), Color::GREEN);
+ shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
+ }
+
+ // restore to absolute z
+ // layerR = 4, layerG = 0, layerB = 2
+ Transaction().setLayer(layerG, mLayerZBase).apply();
+ {
+ SCOPED_TRACE("layerG < layerB < layerR");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectColor(Rect(32, 32, 48, 48), Color::BLUE);
+ }
+
+ // layerR should not affect layerG anymore
+ // layerR = 1, layerG = 0, layerB = 2
+ Transaction().setLayer(layerR, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("layerG < layerR < layerB");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+ shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferQueue) {
+ const Rect top(0, 0, 32, 16);
+ const Rect bottom(0, 16, 32, 32);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+
+ ANativeWindow_Buffer buffer;
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::RED));
+ // setTransparentRegionHint always applies to the following buffer
+ Transaction().setTransparentRegionHint(layer, Region(top)).apply();
+ ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
+ {
+ SCOPED_TRACE("top transparent");
+ auto shot = getScreenCapture();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::RED);
+ }
+
+ Transaction().setTransparentRegionHint(layer, Region(bottom)).apply();
+ {
+ SCOPED_TRACE("transparent region hint pending");
+ auto shot = getScreenCapture();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
+ {
+ SCOPED_TRACE("bottom transparent");
+ auto shot = getScreenCapture();
+ shot->expectColor(top, Color::RED);
+ shot->expectColor(bottom, Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState) {
+ const Rect top(0, 0, 32, 16);
+ const Rect bottom(0, 16, 32, 32);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillGraphicBufferColor(buffer, top, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::RED));
+ Transaction()
+ .setTransparentRegionHint(layer, Region(top))
+ .setBuffer(layer, buffer)
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .apply();
+ {
+ SCOPED_TRACE("top transparent");
+ auto shot = getScreenCapture();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::RED);
+ }
+
+ Transaction().setTransparentRegionHint(layer, Region(bottom)).apply();
+ {
+ SCOPED_TRACE("transparent region hint intermediate");
+ auto shot = getScreenCapture();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::BLACK);
+ }
+
+ buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+
+ ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, top, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT));
+ Transaction().setBuffer(layer, buffer).apply();
+ {
+ SCOPED_TRACE("bottom transparent");
+ auto shot = getScreenCapture();
+ shot->expectColor(top, Color::RED);
+ shot->expectColor(bottom, Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferQueue) {
+ sp<SurfaceControl> layerTransparent;
+ sp<SurfaceControl> layerR;
+ ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+
+ // check that transparent region hint is bound by the layer size
+ Transaction()
+ .setTransparentRegionHint(layerTransparent, Region(mDisplayRect))
+ .setPosition(layerR, 16, 16)
+ .setLayer(layerR, mLayerZBase + 1)
+ .apply();
+ ASSERT_NO_FATAL_FAILURE(
+ fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layerR, Color::RED, 32, 32));
+ getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferState) {
+ sp<SurfaceControl> layerTransparent;
+ sp<SurfaceControl> layerR;
+ ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ layerR = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ // check that transparent region hint is bound by the layer size
+ Transaction()
+ .setTransparentRegionHint(layerTransparent, Region(mDisplayRect))
+ .setFrame(layerR, Rect(16, 16, 48, 48))
+ .setLayer(layerR, mLayerZBase + 1)
+ .apply();
+ ASSERT_NO_FATAL_FAILURE(
+ fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layerR, Color::RED, 32, 32));
+ getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED);
+}
+
+void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) {
+ sp<SurfaceControl> layer1;
+ sp<SurfaceControl> layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer1, {64, 0, 0, 255}, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer2, {0, 64, 0, 255}, 32, 32));
+
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ Transaction()
+ .setAlpha(layer1, 0.25f)
+ .setAlpha(layer2, 0.75f)
+ .setPosition(layer2, 16, 0)
+ .setLayer(layer2, mLayerZBase + 1)
+ .apply();
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ Transaction()
+ .setAlpha(layer1, 0.25f)
+ .setAlpha(layer2, 0.75f)
+ .setFrame(layer1, Rect(0, 0, 32, 32))
+ .setFrame(layer2, Rect(16, 0, 48, 32))
+ .setLayer(layer2, mLayerZBase + 1)
+ .apply();
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
+ {
+ auto shot = getScreenCapture();
+ uint8_t r = 16; // 64 * 0.25f
+ uint8_t g = 48; // 64 * 0.75f
+ shot->expectColor(Rect(0, 0, 16, 32), {r, 0, 0, 255});
+ shot->expectColor(Rect(32, 0, 48, 32), {0, g, 0, 255});
+
+ r /= 4; // r * (1.0f - 0.75f)
+ shot->expectColor(Rect(16, 0, 32, 32), {r, g, 0, 255});
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorBasic) {
+ sp<SurfaceControl> bufferLayer;
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(colorLayer =
+ createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor));
+
+ Transaction()
+ .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+ .setLayer(colorLayer, mLayerZBase + 1)
+ .apply();
+
+ {
+ SCOPED_TRACE("default color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
+ const Color expected = {15, 51, 85, 255};
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+ Transaction().setColor(colorLayer, color).apply();
+ {
+ SCOPED_TRACE("new color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expected, tolerance);
+ }
+}
+
+// RED: Color layer base color and BufferQueueLayer/BufferStateLayer fill
+// BLUE: prior background color
+// GREEN: final background color
+// BLACK: no color or fill
+void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType, bool priorColor,
+ bool bufferFill, float alpha,
+ Color finalColor) {
+ sp<SurfaceControl> layer;
+ int32_t width = 500;
+ int32_t height = 500;
+
+ Color fillColor = Color::RED;
+ Color priorBgColor = Color::BLUE;
+ Color expectedColor = Color::BLACK;
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceColor:
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 0, 0, layerType));
+ Transaction()
+ .setCrop_legacy(layer, Rect(0, 0, width, height))
+ .setColor(layer, half3(1.0f, 0, 0))
+ .apply();
+ expectedColor = fillColor;
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height));
+ if (bufferFill) {
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, fillColor, width, height));
+ expectedColor = fillColor;
+ }
+ Transaction().setCrop_legacy(layer, Rect(0, 0, width, height)).apply();
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, layerType));
+ if (bufferFill) {
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height));
+ expectedColor = fillColor;
+ }
+ Transaction().setFrame(layer, Rect(0, 0, width, height)).apply();
+ break;
+ default:
+ GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper";
+ return;
+ }
+
+ if (priorColor && layerType != ISurfaceComposerClient::eFXSurfaceColor) {
+ Transaction()
+ .setBackgroundColor(layer, half3(0, 0, 1.0f), 1.0f, ui::Dataspace::UNKNOWN)
+ .apply();
+ if (!bufferFill) {
+ expectedColor = priorBgColor;
+ }
+ }
+
+ {
+ SCOPED_TRACE("default before setting background color layer");
+ screenshot()->expectColor(Rect(0, 0, width, height), expectedColor);
+ }
+ Transaction()
+ .setBackgroundColor(layer, half3(0, 1.0f, 0), alpha, ui::Dataspace::UNKNOWN)
+ .apply();
+
+ {
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, width, height), finalColor);
+ shot->expectBorder(Rect(0, 0, width, height), Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_Color_NoEffect) {
+ bool priorColor = false;
+ bool bufferFill = false;
+ float alpha = 1.0f;
+ Color finalColor = Color::RED;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceColor,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferQueue_BufferFill_NoPriorColor_Basic) {
+ bool priorColor = false;
+ bool bufferFill = true;
+ float alpha = 1.0f;
+ Color finalColor = Color::RED;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferQueue_NoBufferFill_NoPriorColor_Basic) {
+ bool priorColor = false;
+ bool bufferFill = false;
+ float alpha = 1.0f;
+ Color finalColor = Color::GREEN;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferQueue_BufferFill_PriorColor_Basic) {
+ bool priorColor = true;
+ bool bufferFill = true;
+ float alpha = 1.0f;
+ Color finalColor = Color::RED;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferQueue_NoBufferFill_PriorColor_Basic) {
+ bool priorColor = true;
+ bool bufferFill = false;
+ float alpha = 1.0f;
+ Color finalColor = Color::GREEN;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+ priorColor, bufferFill, alpha, finalColor));
+}
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferQueue_NoPriorColor_ZeroAlpha_NoEffect) {
+ bool priorColor = false;
+ bool bufferFill = false;
+ float alpha = 0;
+ Color finalColor = Color::BLACK;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferQueue_PriorColor_ZeroAlpha_DeleteBackground) {
+ bool priorColor = true;
+ bool bufferFill = false;
+ float alpha = 0;
+ Color finalColor = Color::BLACK;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferState_BufferFill_NoPriorColor_Basic) {
+ bool priorColor = false;
+ bool bufferFill = true;
+ float alpha = 1.0f;
+ Color finalColor = Color::RED;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferState_NoBufferFill_NoPriorColor_Basic) {
+ bool priorColor = false;
+ bool bufferFill = false;
+ float alpha = 1.0f;
+ Color finalColor = Color::GREEN;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferState_NoBufferFill_PriorColor_Basic) {
+ bool priorColor = true;
+ bool bufferFill = false;
+ float alpha = 1.0f;
+ Color finalColor = Color::GREEN;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferState_NoPriorColor_ZeroAlpha_NoEffect) {
+ bool priorColor = false;
+ bool bufferFill = false;
+ float alpha = 0;
+ Color finalColor = Color::BLACK;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+ SetBackgroundColor_BufferState_PriorColor_ZeroAlpha_DeleteBackground) {
+ bool priorColor = true;
+ bool bufferFill = false;
+ float alpha = 0;
+ Color finalColor = Color::BLACK;
+ ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
+ priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorClamped) {
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(colorLayer =
+ createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor));
+ Transaction()
+ .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+ .setColor(colorLayer, half3(2.0f, -1.0f, 0.0f))
+ .apply();
+
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorWithAlpha) {
+ sp<SurfaceControl> bufferLayer;
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(colorLayer =
+ createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor));
+ Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply();
+
+ const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
+ const float alpha = 0.25f;
+ const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f);
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+ Transaction()
+ .setColor(colorLayer, color)
+ .setAlpha(colorLayer, alpha)
+ .setLayer(colorLayer, mLayerZBase + 1)
+ .apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255},
+ tolerance);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorWithParentAlpha_Bug74220420) {
+ sp<SurfaceControl> bufferLayer;
+ sp<SurfaceControl> parentLayer;
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer("childWithColor", 0 /* buffer width */,
+ 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor));
+ Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply();
+ const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
+ const float alpha = 0.25f;
+ const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f);
+ // this is handwavy, but the precision loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+ Transaction()
+ .reparent(colorLayer, parentLayer->getHandle())
+ .setColor(colorLayer, color)
+ .setAlpha(parentLayer, alpha)
+ .setLayer(parentLayer, mLayerZBase + 1)
+ .apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255},
+ tolerance);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply();
+ {
+ SCOPED_TRACE("IDENTITY");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 32, 0).apply();
+ {
+ SCOPED_TRACE("FLIP_H");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED,
+ Color::WHITE, Color::BLUE);
+ }
+
+ Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).setPosition(layer, 0, 32).apply();
+ {
+ SCOPED_TRACE("FLIP_V");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE,
+ Color::RED, Color::GREEN);
+ }
+
+ Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).setPosition(layer, 32, 0).apply();
+ {
+ SCOPED_TRACE("ROT_90");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED,
+ Color::WHITE, Color::GREEN);
+ }
+
+ Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setPosition(layer, 0, 0).apply();
+ {
+ SCOPED_TRACE("SCALE");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 64), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE, true /* filtered */);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction()
+ .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f)
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .apply();
+ {
+ SCOPED_TRACE("IDENTITY");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply();
+ {
+ SCOPED_TRACE("FLIP_H");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply();
+ {
+ SCOPED_TRACE("FLIP_V");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply();
+ {
+ SCOPED_TRACE("ROT_90");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply();
+ {
+ SCOPED_TRACE("SCALE");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetMatrixRot45_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ const float rot = M_SQRT1_2; // 45 degrees
+ const float trans = M_SQRT2 * 16.0f;
+ Transaction().setMatrix(layer, rot, rot, -rot, rot).setPosition(layer, trans, 0).apply();
+
+ auto shot = getScreenCapture();
+ // check a 8x8 region inside each color
+ auto get8x8Rect = [](int32_t centerX, int32_t centerY) {
+ const int32_t halfL = 4;
+ return Rect(centerX - halfL, centerY - halfL, centerX + halfL, centerY + halfL);
+ };
+ const int32_t unit = int32_t(trans / 2);
+ shot->expectColor(get8x8Rect(2 * unit, 1 * unit), Color::RED);
+ shot->expectColor(get8x8Rect(3 * unit, 2 * unit), Color::GREEN);
+ shot->expectColor(get8x8Rect(1 * unit, 2 * unit), Color::BLUE);
+ shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithResize_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // setMatrix is applied after any pending resize, unlike setPosition
+ Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = getScreenCapture();
+ const Rect rect(0, 0, 32, 32);
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
+ {
+ SCOPED_TRACE("resize applied");
+ const Rect rect(0, 0, 128, 128);
+ getScreenCapture()->expectColor(rect, Color::RED);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithScaleToWindow_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition
+ Transaction()
+ .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+ .setSize(layer, 64, 64)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 128, 128), Color::RED);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetOverrideScalingModeBasic_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ // XXX SCALE_CROP is not respected; calling setSize and
+ // setOverrideScalingMode in separate transactions does not work
+ // (b/69315456)
+ Transaction()
+ .setSize(layer, 64, 16)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .apply();
+ {
+ SCOPED_TRACE("SCALE_TO_WINDOW");
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 16), Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE, true /* filtered */);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+ const Rect crop(8, 8, 24, 24);
+
+ Transaction().setCrop_legacy(layer, crop).apply();
+ auto shot = getScreenCapture();
+ shot->expectColor(crop, Color::RED);
+ shot->expectBorder(crop, Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ const Rect crop(8, 8, 24, 24);
+
+ Transaction().setCrop(layer, crop).apply();
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("empty rect");
+ Transaction().setCrop_legacy(layer, Rect(8, 8, 8, 8)).apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ {
+ SCOPED_TRACE("negative rect");
+ Transaction().setCrop_legacy(layer, Rect(8, 8, 0, 0)).apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("empty rect");
+ Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply();
+ getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ }
+
+ {
+ SCOPED_TRACE("negative rect");
+ Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply();
+ getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply();
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 64, ISurfaceComposerClient::eFXSurfaceBufferState));
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 64, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE);
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED);
+
+ Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply();
+
+ Transaction().setBuffer(layer, buffer).apply();
+
+ // Partially out of bounds in the negative (upper left) direction
+ Transaction().setCrop(layer, Rect(-128, -128, 32, 16)).apply();
+ {
+ SCOPED_TRACE("out of bounds, negative (upper left) direction");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+ }
+
+ // Partially out of bounds in the positive (lower right) direction
+ Transaction().setCrop(layer, Rect(0, 16, 128, 128)).apply();
+ {
+ SCOPED_TRACE("out of bounds, positive (lower right) direction");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
+ shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+ }
+
+ // Fully out of buffer space bounds
+ Transaction().setCrop(layer, Rect(-128, -128, -1, -1)).apply();
+ {
+ SCOPED_TRACE("Fully out of bounds");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE);
+ shot->expectColor(Rect(0, 16, 64, 64), Color::RED);
+ shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ const Point position(32, 32);
+ const Rect crop(8, 8, 24, 24);
+ Transaction().setPosition(layer, position.x, position.y).setCrop_legacy(layer, crop).apply();
+ auto shot = getScreenCapture();
+ shot->expectColor(crop + position, Color::RED);
+ shot->expectBorder(crop + position, Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ const Rect frame(32, 32, 64, 64);
+ const Rect crop(8, 8, 24, 24);
+ Transaction().setFrame(layer, frame).setCrop(layer, crop).apply();
+ auto shot = getScreenCapture();
+ shot->expectColor(frame, Color::RED);
+ shot->expectBorder(frame, Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // crop_legacy is affected by matrix
+ Transaction()
+ .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+ .setCrop_legacy(layer, Rect(8, 8, 24, 24))
+ .apply();
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
+ shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetCropWithResize_BufferQueue) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ // setCrop_legacy is applied immediately by default, with or without resize pending
+ Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
+ shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
+ {
+ SCOPED_TRACE("resize applied");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
+ shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ const Rect frame(8, 8, 24, 24);
+
+ Transaction().setFrame(layer, frame).apply();
+ auto shot = getScreenCapture();
+ shot->expectColor(frame, Color::RED);
+ shot->expectBorder(frame, Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("empty rect");
+ Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ {
+ SCOPED_TRACE("negative rect");
+ Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10));
+
+ // A parentless layer will default to a frame with the same size as the buffer
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) {
+ sp<SurfaceControl> parent, child;
+ ASSERT_NO_FATAL_FAILURE(
+ parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
+ Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
+
+ ASSERT_NO_FATAL_FAILURE(
+ child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+
+ Transaction().reparent(child, parent->getHandle()).apply();
+
+ // A layer will default to the frame of its parent
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) {
+ sp<SurfaceControl> parent, child;
+ ASSERT_NO_FATAL_FAILURE(parent = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32));
+
+ ASSERT_NO_FATAL_FAILURE(
+ child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+
+ Transaction().reparent(child, parent->getHandle()).apply();
+
+ // A layer will default to the frame of its parent
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ std::this_thread::sleep_for(500ms);
+
+ Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply();
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
+ shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) {
+ sp<SurfaceControl> parent, child;
+ ASSERT_NO_FATAL_FAILURE(
+ parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(
+ child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ Transaction().reparent(child, parent->getHandle()).apply();
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
+ Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+ Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply();
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 16), Color::RED);
+ shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("set buffer 1");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
+
+ {
+ SCOPED_TRACE("set buffer 2");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("set buffer 3");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) {
+ sp<SurfaceControl> layer1;
+ ASSERT_NO_FATAL_FAILURE(
+ layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<SurfaceControl> layer2;
+ ASSERT_NO_FATAL_FAILURE(
+ layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64));
+
+ Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply();
+ {
+ SCOPED_TRACE("set layer 1 buffer red");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32));
+
+ Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply();
+ {
+ SCOPED_TRACE("set layer 2 buffer blue");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectColor(Rect(0, 32, 64, 64), Color::RED);
+ shot->expectColor(Rect(0, 32, 32, 64), Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64));
+ {
+ SCOPED_TRACE("set layer 1 buffer green");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN);
+ shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32));
+
+ {
+ SCOPED_TRACE("set layer 2 buffer white");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE);
+ shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN);
+ shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
+
+ std::array<sp<GraphicBuffer>, 10> buffers;
+
+ size_t idx = 0;
+ for (auto& buffer : buffers) {
+ buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ Color color = colors[idx % colors.size()];
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+ idx++;
+ }
+
+ // Set each buffer twice. The first time adds it to the cache, the second time tests that the
+ // cache is working.
+ idx = 0;
+ for (auto& buffer : buffers) {
+ for (int i = 0; i < 2; i++) {
+ Transaction().setBuffer(layer, buffer).apply();
+
+ Color color = colors[idx % colors.size()];
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+ idx++;
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
+
+ std::array<sp<GraphicBuffer>, 70> buffers;
+
+ size_t idx = 0;
+ for (auto& buffer : buffers) {
+ buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ Color color = colors[idx % colors.size()];
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+ idx++;
+ }
+
+ // Set each buffer twice. The first time adds it to the cache, the second time tests that the
+ // cache is working.
+ idx = 0;
+ for (auto& buffer : buffers) {
+ for (int i = 0; i < 2; i++) {
+ Transaction().setBuffer(layer, buffer).apply();
+
+ Color color = colors[idx % colors.size()];
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+ idx++;
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
+
+ std::array<sp<GraphicBuffer>, 65> buffers;
+
+ size_t idx = 0;
+ for (auto& buffer : buffers) {
+ buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ Color color = colors[idx % colors.size()];
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+ idx++;
+ }
+
+ // Set each buffer twice. The first time adds it to the cache, the second time tests that the
+ // cache is working.
+ idx = 0;
+ for (auto& buffer : buffers) {
+ for (int i = 0; i < 2; i++) {
+ Transaction().setBuffer(layer, buffer).apply();
+
+ Color color = colors[idx % colors.size()];
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+ if (idx == 0) {
+ buffers[0].clear();
+ }
+ idx++;
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90)
+ .apply();
+
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE,
+ Color::GREEN, true /* filtered */);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H)
+ .apply();
+
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE,
+ Color::BLUE, true /* filtered */);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V)
+ .apply();
+
+ getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED,
+ Color::GREEN, true /* filtered */);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFenceBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ Transaction transaction;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ sp<Fence> fence;
+ if (getBuffer(nullptr, &fence) != NO_ERROR) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+
+ status_t status = fence->wait(1000);
+ ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status);
+ std::this_thread::sleep_for(200ms);
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ sp<Fence> fence = Fence::NO_FENCE;
+
+ Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply();
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ HdrMetadata hdrMetadata;
+ hdrMetadata.validTypes = 0;
+ Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply();
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ Region region;
+ region.set(32, 32);
+ Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply();
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply();
+
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+ shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) {
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(colorLayer =
+ createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor));
+ Transaction()
+ .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+ .setLayer(colorLayer, mLayerZBase + 1)
+ .apply();
+ {
+ SCOPED_TRACE("default color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
+ half3 expected = color;
+ mat3 matrix;
+ matrix[0][0] = 0.3;
+ matrix[1][0] = 0.59;
+ matrix[2][0] = 0.11;
+ matrix[0][1] = 0.3;
+ matrix[1][1] = 0.59;
+ matrix[2][1] = 0.11;
+ matrix[0][2] = 0.3;
+ matrix[1][2] = 0.59;
+ matrix[2][2] = 0.11;
+
+ // degamma before applying the matrix
+ if (mColorManagementUsed) {
+ ColorTransformHelper::DegammaColor(expected);
+ }
+
+ ColorTransformHelper::applyMatrix(expected, matrix);
+
+ if (mColorManagementUsed) {
+ ColorTransformHelper::GammaColor(expected);
+ }
+
+ const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255),
+ uint8_t(expected.b * 255), 255};
+
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+
+ Transaction().setColor(colorLayer, color).setColorTransform(colorLayer, matrix, vec3()).apply();
+ {
+ SCOPED_TRACE("new color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnParent) {
+ sp<SurfaceControl> parentLayer;
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */,
+ 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceContainer));
+ ASSERT_NO_FATAL_FAILURE(
+ colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get()));
+
+ Transaction()
+ .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100))
+ .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+ .setLayer(parentLayer, mLayerZBase + 1)
+ .apply();
+ {
+ SCOPED_TRACE("default color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
+ half3 expected = color;
+ mat3 matrix;
+ matrix[0][0] = 0.3;
+ matrix[1][0] = 0.59;
+ matrix[2][0] = 0.11;
+ matrix[0][1] = 0.3;
+ matrix[1][1] = 0.59;
+ matrix[2][1] = 0.11;
+ matrix[0][2] = 0.3;
+ matrix[1][2] = 0.59;
+ matrix[2][2] = 0.11;
+
+ // degamma before applying the matrix
+ if (mColorManagementUsed) {
+ ColorTransformHelper::DegammaColor(expected);
+ }
+
+ ColorTransformHelper::applyMatrix(expected, matrix);
+
+ if (mColorManagementUsed) {
+ ColorTransformHelper::GammaColor(expected);
+ }
+
+ const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255),
+ uint8_t(expected.b * 255), 255};
+
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+
+ Transaction()
+ .setColor(colorLayer, color)
+ .setColorTransform(parentLayer, matrix, vec3())
+ .apply();
+ {
+ SCOPED_TRACE("new color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnChildAndParent) {
+ sp<SurfaceControl> parentLayer;
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */,
+ 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceContainer));
+ ASSERT_NO_FATAL_FAILURE(
+ colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get()));
+
+ Transaction()
+ .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100))
+ .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
+ .setLayer(parentLayer, mLayerZBase + 1)
+ .apply();
+ {
+ SCOPED_TRACE("default color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
+ half3 expected = color;
+ mat3 matrixChild;
+ matrixChild[0][0] = 0.3;
+ matrixChild[1][0] = 0.59;
+ matrixChild[2][0] = 0.11;
+ matrixChild[0][1] = 0.3;
+ matrixChild[1][1] = 0.59;
+ matrixChild[2][1] = 0.11;
+ matrixChild[0][2] = 0.3;
+ matrixChild[1][2] = 0.59;
+ matrixChild[2][2] = 0.11;
+ mat3 matrixParent;
+ matrixParent[0][0] = 0.2;
+ matrixParent[1][0] = 0.4;
+ matrixParent[2][0] = 0.10;
+ matrixParent[0][1] = 0.2;
+ matrixParent[1][1] = 0.4;
+ matrixParent[2][1] = 0.10;
+ matrixParent[0][2] = 0.2;
+ matrixParent[1][2] = 0.4;
+ matrixParent[2][2] = 0.10;
+
+ // degamma before applying the matrix
+ if (mColorManagementUsed) {
+ ColorTransformHelper::DegammaColor(expected);
+ }
+
+ ColorTransformHelper::applyMatrix(expected, matrixChild);
+ ColorTransformHelper::applyMatrix(expected, matrixParent);
+
+ if (mColorManagementUsed) {
+ ColorTransformHelper::GammaColor(expected);
+ }
+
+ const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255),
+ uint8_t(expected.b * 255), 255};
+
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+
+ Transaction()
+ .setColor(colorLayer, color)
+ .setColorTransform(parentLayer, matrixParent, vec3())
+ .setColorTransform(colorLayer, matrixChild, vec3())
+ .apply();
+ {
+ SCOPED_TRACE("new color");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
+ }
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
new file mode 100644
index 0000000..7edddb6
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#ifndef ANDROID_LAYER_TRANSACTION_TEST_H
+#define ANDROID_LAYER_TRANSACTION_TEST_H
+
+#include <gtest/gtest.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <hardware/hwcomposer_defs.h>
+#include <private/gui/ComposerService.h>
+
+#include <ui/DisplayInfo.h>
+
+#include "BufferGenerator.h"
+#include "utils/ScreenshotUtils.h"
+#include "utils/TransactionUtils.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+class LayerTransactionTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mClient = new SurfaceComposerClient;
+ ASSERT_EQ(NO_ERROR, mClient->initCheck()) << "failed to create SurfaceComposerClient";
+
+ ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
+
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed));
+ }
+
+ virtual void TearDown() {
+ mBlackBgSurface = 0;
+ mClient->dispose();
+ mClient = 0;
+ }
+
+ virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client,
+ const char* name, uint32_t width, uint32_t height,
+ uint32_t flags = 0, SurfaceControl* parent = nullptr) {
+ auto layer =
+ createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags, parent);
+
+ Transaction t;
+ t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase);
+
+ status_t error = t.apply();
+ if (error != NO_ERROR) {
+ ADD_FAILURE() << "failed to initialize SurfaceControl";
+ layer.clear();
+ }
+
+ return layer;
+ }
+
+ virtual sp<SurfaceControl> createSurface(const sp<SurfaceComposerClient>& client,
+ const char* name, uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t flags,
+ SurfaceControl* parent = nullptr) {
+ auto layer = client->createSurface(String8(name), width, height, format, flags, parent);
+ EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
+ return layer;
+ }
+
+ virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
+ uint32_t flags = 0, SurfaceControl* parent = nullptr) {
+ return createLayer(mClient, name, width, height, flags, parent);
+ }
+
+ sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
+ SurfaceControl* parent = nullptr) {
+ auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */,
+ PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, parent);
+ asTransaction([&](Transaction& t) {
+ t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f});
+ t.setAlpha(colorLayer, color.a / 255.0f);
+ });
+ return colorLayer;
+ }
+
+ ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
+ // wait for previous transactions (such as setSize) to complete
+ Transaction().apply(true);
+
+ ANativeWindow_Buffer buffer = {};
+ EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr));
+
+ return buffer;
+ }
+
+ void postBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
+ ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
+
+ // wait for the newly posted buffer to be latched
+ waitForLayerBuffers();
+ }
+
+ virtual void fillBufferQueueLayerColor(const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
+ ANativeWindow_Buffer buffer;
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ TransactionUtils::fillANativeWindowBufferColor(buffer,
+ Rect(0, 0, bufferWidth, bufferHeight),
+ color);
+ postBufferQueueLayerBuffer(layer);
+ }
+
+ virtual void fillBufferStateLayerColor(const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight),
+ color);
+ Transaction().setBuffer(layer, buffer).apply();
+ }
+
+ void fillLayerColor(uint32_t mLayerType, const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
+ switch (mLayerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight);
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight);
+ break;
+ default:
+ ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType;
+ }
+ }
+
+ void fillLayerQuadrant(uint32_t mLayerType, const sp<SurfaceControl>& layer,
+ int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft,
+ const Color& topRight, const Color& bottomLeft,
+ const Color& bottomRight) {
+ switch (mLayerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight,
+ bottomLeft, bottomRight);
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight,
+ bottomLeft, bottomRight);
+ break;
+ default:
+ ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType;
+ }
+ }
+
+ virtual void fillBufferQueueLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
+ int32_t bufferHeight, const Color& topLeft,
+ const Color& topRight, const Color& bottomLeft,
+ const Color& bottomRight) {
+ ANativeWindow_Buffer buffer;
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0);
+
+ const int32_t halfW = bufferWidth / 2;
+ const int32_t halfH = bufferHeight / 2;
+ TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+ TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH),
+ topRight);
+ TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight),
+ bottomLeft);
+ TransactionUtils::fillANativeWindowBufferColor(buffer,
+ Rect(halfW, halfH, bufferWidth,
+ bufferHeight),
+ bottomRight);
+
+ postBufferQueueLayerBuffer(layer);
+ }
+
+ virtual void fillBufferStateLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
+ int32_t bufferHeight, const Color& topLeft,
+ const Color& topRight, const Color& bottomLeft,
+ const Color& bottomRight) {
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+
+ ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0);
+
+ const int32_t halfW = bufferWidth / 2;
+ const int32_t halfH = bufferHeight / 2;
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH),
+ topRight);
+ TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight),
+ bottomLeft);
+ TransactionUtils::fillGraphicBufferColor(buffer,
+ Rect(halfW, halfH, bufferWidth, bufferHeight),
+ bottomRight);
+
+ Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply();
+ }
+
+ std::unique_ptr<ScreenCapture> screenshot() {
+ std::unique_ptr<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot);
+ return screenshot;
+ }
+
+ void asTransaction(const std::function<void(Transaction&)>& exec) {
+ Transaction t;
+ exec(t);
+ t.apply(true);
+ }
+
+ static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+ static BufferGenerator bufferGenerator;
+ return bufferGenerator.get(outBuffer, outFence);
+ }
+
+ sp<SurfaceComposerClient> mClient;
+
+ sp<IBinder> mDisplay;
+ uint32_t mDisplayWidth;
+ uint32_t mDisplayHeight;
+ uint32_t mDisplayLayerStack;
+ Rect mDisplayRect = Rect::INVALID_RECT;
+
+ // leave room for ~256 layers
+ const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256;
+
+ sp<SurfaceControl> mBlackBgSurface;
+ bool mColorManagementUsed;
+
+private:
+ void SetUpDisplay() {
+ mDisplay = mClient->getInternalDisplayToken();
+ ASSERT_FALSE(mDisplay == nullptr) << "failed to get display";
+
+ // get display width/height
+ DisplayInfo info;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
+ mDisplayWidth = info.w;
+ mDisplayHeight = info.h;
+ mDisplayRect =
+ Rect(static_cast<int32_t>(mDisplayWidth), static_cast<int32_t>(mDisplayHeight));
+
+ // After a new buffer is queued, SurfaceFlinger is notified and will
+ // latch the new buffer on next vsync. Let's heuristically wait for 3
+ // vsyncs.
+ mBufferPostDelay = int32_t(1e6 / info.fps) * 3;
+
+ mDisplayLayerStack = 0;
+
+ mBlackBgSurface =
+ createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */,
+ PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor);
+
+ // set layer stack (b/68888219)
+ Transaction t;
+ t.setDisplayLayerStack(mDisplay, mDisplayLayerStack);
+ t.setCrop_legacy(mBlackBgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight));
+ t.setLayerStack(mBlackBgSurface, mDisplayLayerStack);
+ t.setColor(mBlackBgSurface, half3{0, 0, 0});
+ t.setLayer(mBlackBgSurface, mLayerZBase);
+ t.apply();
+ }
+
+ void waitForLayerBuffers() {
+ // Request an empty transaction to get applied synchronously to ensure the buffer is
+ // latched.
+ Transaction().apply(true);
+ usleep(mBufferPostDelay);
+ }
+
+ int32_t mBufferPostDelay;
+
+ friend class LayerRenderPathTestHarness;
+};
+} // namespace android
+
+#endif
diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp
new file mode 100644
index 0000000..35c51e1
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2019 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 <private/android_filesystem_config.h>
+#include <thread>
+#include "LayerTransactionTest.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+TEST_F(LayerTransactionTest, SetFlagsSecureEUidSystem) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<GraphicBuffer> outBuffer;
+ Transaction()
+ .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
+ .apply(true);
+ ASSERT_EQ(PERMISSION_DENIED,
+ composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+
+ UIDFaker f(AID_SYSTEM);
+
+ // By default the system can capture screenshots with secure layers but they
+ // will be blacked out
+ ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+
+ {
+ SCOPED_TRACE("as system");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able
+ // to receive them...we are expected to take care with the results.
+ bool outCapturedSecureLayers;
+ ASSERT_EQ(NO_ERROR,
+ composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers,
+ ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0,
+ 0, false, ISurfaceComposer::eRotateNone, true));
+ ASSERT_EQ(true, outCapturedSecureLayers);
+ ScreenCapture sc(outBuffer);
+ sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ Transaction().setTransformToDisplayInverse(layer, false).apply();
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32));
+
+ Transaction().setTransformToDisplayInverse(layer, true).apply();
+}
+
+TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ // verify this doesn't cause a crash
+ Transaction().setSidebandStream(layer, nullptr).apply();
+}
+
+TEST_F(LayerTransactionTest, ReparentToSelf) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+ Transaction().reparent(layer, layer->getHandle()).apply();
+
+ {
+ // We expect the transaction to be silently dropped, but for SurfaceFlinger
+ // to still be functioning.
+ SCOPED_TRACE("after reparent to self");
+ const Rect rect(0, 0, 32, 32);
+ auto shot = screenshot();
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
+ }
+}
+
+// This test ensures that when we drop an app buffer in SurfaceFlinger, we merge
+// the dropped buffer's damage region into the next buffer's damage region. If
+// we don't do this, we'll report an incorrect damage region to hardware
+// composer, resulting in broken rendering. This test checks the BufferQueue
+// case.
+//
+// Unfortunately, we don't currently have a way to inspect the damage region
+// SurfaceFlinger sends to hardware composer from a test, so this test requires
+// the dev to manually watch the device's screen during the test to spot broken
+// rendering. Because the results can't be automatically verified, this test is
+// marked disabled.
+TEST_F(LayerTransactionTest, DISABLED_BufferQueueLayerMergeDamageRegionWhenDroppingBuffers) {
+ const int width = mDisplayWidth;
+ const int height = mDisplayHeight;
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height));
+ const auto producer = layer->getIGraphicBufferProducer();
+ const sp<IProducerListener> dummyListener(new DummyProducerListener);
+ IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
+ ASSERT_EQ(OK,
+ producer->connect(dummyListener, NATIVE_WINDOW_API_CPU, true, &queueBufferOutput));
+
+ std::map<int, sp<GraphicBuffer>> slotMap;
+ auto slotToBuffer = [&](int slot, sp<GraphicBuffer>* buf) {
+ ASSERT_NE(nullptr, buf);
+ const auto iter = slotMap.find(slot);
+ ASSERT_NE(slotMap.end(), iter);
+ *buf = iter->second;
+ };
+
+ auto dequeue = [&](int* outSlot) {
+ ASSERT_NE(nullptr, outSlot);
+ *outSlot = -1;
+ int slot;
+ sp<Fence> fence;
+ uint64_t age;
+ FrameEventHistoryDelta timestamps;
+ const status_t dequeueResult =
+ producer->dequeueBuffer(&slot, &fence, width, height, PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ &age, ×tamps);
+ if (dequeueResult == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
+ sp<GraphicBuffer> newBuf;
+ ASSERT_EQ(OK, producer->requestBuffer(slot, &newBuf));
+ ASSERT_NE(nullptr, newBuf.get());
+ slotMap[slot] = newBuf;
+ } else {
+ ASSERT_EQ(OK, dequeueResult);
+ }
+ *outSlot = slot;
+ };
+
+ auto queue = [&](int slot, const Region& damage, nsecs_t displayTime) {
+ IGraphicBufferProducer::QueueBufferInput input(
+ /*timestamp=*/displayTime, /*isAutoTimestamp=*/false, HAL_DATASPACE_UNKNOWN,
+ /*crop=*/Rect::EMPTY_RECT, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
+ /*transform=*/0, Fence::NO_FENCE);
+ input.setSurfaceDamage(damage);
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_EQ(OK, producer->queueBuffer(slot, input, &output));
+ };
+
+ auto fillAndPostBuffers = [&](const Color& color) {
+ int slot1;
+ ASSERT_NO_FATAL_FAILURE(dequeue(&slot1));
+ int slot2;
+ ASSERT_NO_FATAL_FAILURE(dequeue(&slot2));
+
+ sp<GraphicBuffer> buf1;
+ ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot1, &buf1));
+ sp<GraphicBuffer> buf2;
+ ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot2, &buf2));
+ TransactionUtils::fillGraphicBufferColor(buf1, Rect(width, height), color);
+ TransactionUtils::fillGraphicBufferColor(buf2, Rect(width, height), color);
+
+ const auto displayTime = systemTime() + milliseconds_to_nanoseconds(100);
+ ASSERT_NO_FATAL_FAILURE(queue(slot1, Region::INVALID_REGION, displayTime));
+ ASSERT_NO_FATAL_FAILURE(
+ queue(slot2, Region(Rect(width / 3, height / 3, 2 * width / 3, 2 * height / 3)),
+ displayTime));
+ };
+
+ const auto startTime = systemTime();
+ const std::array<Color, 3> colors = {Color::RED, Color::GREEN, Color::BLUE};
+ int colorIndex = 0;
+ while (nanoseconds_to_seconds(systemTime() - startTime) < 10) {
+ ASSERT_NO_FATAL_FAILURE(fillAndPostBuffers(colors[colorIndex++ % colors.size()]));
+ std::this_thread::sleep_for(1s);
+ }
+
+ ASSERT_EQ(OK, producer->disconnect(NATIVE_WINDOW_API_CPU));
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
new file mode 100644
index 0000000..daeff17
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2019 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 <gui/BufferItemConsumer.h>
+#include "TransactionTestHarnesses.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+class LayerTypeAndRenderTypeTransactionTest
+ : public LayerTypeTransactionHarness,
+ public ::testing::WithParamInterface<std::tuple<uint32_t, RenderPath>> {
+public:
+ LayerTypeAndRenderTypeTransactionTest()
+ : LayerTypeTransactionHarness(std::get<0>(GetParam())),
+ mRenderPathHarness(LayerRenderPathTestHarness(this, std::get<1>(GetParam()))) {}
+
+ std::unique_ptr<ScreenCapture> getScreenCapture() {
+ return mRenderPathHarness.getScreenCapture();
+ }
+
+protected:
+ LayerRenderPathTestHarness mRenderPathHarness;
+};
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+INSTANTIATE_TEST_CASE_P(
+ LayerTypeAndRenderTypeTransactionTests, LayerTypeAndRenderTypeTransactionTest,
+ ::testing::Combine(
+ ::testing::Values(
+ static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue),
+ static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)),
+ ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT)));
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetSizeInvalid) {
+ // cannot test robustness against invalid sizes (zero or really huge)
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZBasic) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
+
+ Transaction().setLayer(layerR, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("layerR");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setLayer(layerG, mLayerZBase + 2).apply();
+ {
+ SCOPED_TRACE("layerG");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+ }
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetRelativeZBug64572777) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
+
+ Transaction()
+ .setPosition(layerG, 16, 16)
+ .setRelativeLayer(layerG, layerR->getHandle(), 1)
+ .apply();
+
+ layerG.clear();
+ // layerG should have been removed
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsHidden) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply();
+ {
+ SCOPED_TRACE("layer hidden");
+ getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
+ }
+
+ Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply();
+ {
+ SCOPED_TRACE("layer shown");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsOpaque) {
+ const Color translucentRed = {100, 0, 0, 100};
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
+
+ Transaction()
+ .setLayer(layerR, mLayerZBase + 1)
+ .setFlags(layerR, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque)
+ .apply();
+ {
+ SCOPED_TRACE("layerR opaque");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, 0, 0, 255});
+ }
+
+ Transaction().setFlags(layerR, 0, layer_state_t::eLayerOpaque).apply();
+ {
+ SCOPED_TRACE("layerR translucent");
+ const uint8_t g = uint8_t(255 - translucentRed.a);
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, g, 0, 255});
+ }
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZNegative) {
+ sp<SurfaceControl> parent =
+ LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceContainer);
+ Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply();
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
+
+ Transaction()
+ .reparent(layerR, parent->getHandle())
+ .reparent(layerG, parent->getHandle())
+ .apply();
+ Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply();
+ {
+ SCOPED_TRACE("layerR");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setLayer(layerR, -3).apply();
+ {
+ SCOPED_TRACE("layerG");
+ auto shot = getScreenCapture();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+ }
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetAlphaClamped) {
+ const Color color = {64, 0, 0, 255};
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32));
+
+ Transaction().setAlpha(layer, 2.0f).apply();
+ {
+ SCOPED_TRACE("clamped to 1.0f");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), color);
+ }
+
+ Transaction().setAlpha(layer, -1.0f).apply();
+ {
+ SCOPED_TRACE("clamped to 0.0f");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) {
+ sp<SurfaceControl> layer;
+ const uint8_t size = 64;
+ const uint8_t testArea = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
+
+ Transaction()
+ .setCornerRadius(layer, cornerRadius)
+ .setCrop_legacy(layer, Rect(0, 0, size, size))
+ .apply();
+ {
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
+ auto shot = getScreenCapture();
+ // Transparent corners
+ shot->expectColor(Rect(0, 0, testArea, testArea), Color::BLACK);
+ shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::BLACK);
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
+ shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::BLACK);
+ }
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) {
+ sp<SurfaceControl> parent;
+ sp<SurfaceControl> child;
+ const uint8_t size = 64;
+ const uint8_t testArea = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, size, size));
+ ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2));
+
+ Transaction()
+ .setCornerRadius(parent, cornerRadius)
+ .setCrop_legacy(parent, Rect(0, 0, size, size))
+ .reparent(child, parent->getHandle())
+ .setPosition(child, 0, size / 2)
+ .apply();
+ {
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
+ auto shot = getScreenCapture();
+ // Top edge of child should not have rounded corners because it's translated in the parent
+ shot->expectColor(Rect(0, size / 2, right, static_cast<int>(bottom - cornerRadius)),
+ Color::GREEN);
+ // But bottom edges should have been clipped according to parent bounds
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
+ shot->expectColor(Rect(right - testArea, bottom - testArea, right, bottom), Color::BLACK);
+ }
+}
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetColorWithBuffer) {
+ sp<SurfaceControl> bufferLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32));
+
+ // color is ignored
+ Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply();
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetLayerStackBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply();
+ {
+ SCOPED_TRACE("non-existing layer stack");
+ getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
+ }
+
+ Transaction().setLayerStack(layer, mDisplayLayerStack).apply();
+ {
+ SCOPED_TRACE("original layer stack");
+ getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
new file mode 100644
index 0000000..42ec34a
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2019 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 <gui/BufferItemConsumer.h>
+#include "TransactionTestHarnesses.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+class LayerTypeTransactionTest : public LayerTypeTransactionHarness,
+ public ::testing::WithParamInterface<uint32_t> {
+public:
+ LayerTypeTransactionTest() : LayerTypeTransactionHarness(GetParam()) {}
+};
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+INSTANTIATE_TEST_CASE_P(
+ LayerTypeTransactionTests, LayerTypeTransactionTest,
+ ::testing::Values(static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue),
+ static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)));
+
+TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) {
+ sp<SurfaceControl> parent =
+ LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceContainer);
+ Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply();
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ sp<SurfaceControl> layerB;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32));
+
+ Transaction().reparent(layerB, parent->getHandle()).apply();
+
+ // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2
+ Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply();
+
+ std::unique_ptr<ScreenCapture> screenshot;
+ // only layerB is in this range
+ sp<IBinder> parentHandle = parent->getHandle();
+ ScreenCapture::captureLayers(&screenshot, parentHandle, Rect(0, 0, 32, 32));
+ screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+}
+
+TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) {
+ sp<SurfaceControl> parent =
+ LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor);
+
+ sp<SurfaceControl> childLayer;
+ ASSERT_NO_FATAL_FAILURE(
+ childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */,
+ 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor,
+ parent.get()));
+ Transaction()
+ .setColor(childLayer, half3{1.0f, 0.0f, 0.0f})
+ .setColor(parent, half3{0.0f, 0.0f, 0.0f})
+ .show(childLayer)
+ .show(parent)
+ .setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight))
+ .setCrop_legacy(childLayer, Rect(0, 0, 20, 30))
+ .apply();
+
+ Transaction()
+ .setRelativeLayer(childLayer, parent->getHandle(), -1)
+ .setLayer(childLayer, 1)
+ .apply();
+
+ {
+ SCOPED_TRACE("setLayer above");
+ // Set layer should get applied and place the child above.
+ std::unique_ptr<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot);
+ screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED);
+ }
+
+ Transaction()
+ .setLayer(childLayer, 1)
+ .setRelativeLayer(childLayer, parent->getHandle(), -1)
+ .apply();
+
+ {
+ SCOPED_TRACE("setRelative below");
+ // Set relative layer should get applied and place the child below.
+ std::unique_ptr<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot);
+ screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK);
+ }
+}
+
+TEST_P(LayerTypeTransactionTest, HideRelativeParentHidesLayer) {
+ sp<SurfaceControl> parent =
+ LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor);
+ sp<SurfaceControl> relativeParent =
+ LayerTransactionTest::createLayer("RelativeParent", 0 /* buffer width */,
+ 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor);
+
+ sp<SurfaceControl> childLayer;
+ ASSERT_NO_FATAL_FAILURE(
+ childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */,
+ 0 /* buffer height */,
+ ISurfaceComposerClient::eFXSurfaceColor,
+ parent.get()));
+ Transaction()
+ .setColor(childLayer, half3{1.0f, 0.0f, 0.0f})
+ .setColor(parent, half3{0.0f, 0.0f, 0.0f})
+ .setColor(relativeParent, half3{0.0f, 1.0f, 0.0f})
+ .show(childLayer)
+ .show(parent)
+ .show(relativeParent)
+ .setLayer(parent, mLayerZBase - 1)
+ .setLayer(relativeParent, mLayerZBase)
+ .apply();
+
+ Transaction().setRelativeLayer(childLayer, relativeParent->getHandle(), 1).apply();
+
+ {
+ SCOPED_TRACE("setLayer above");
+ // Set layer should get applied and place the child above.
+ std::unique_ptr<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot);
+ screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED);
+ }
+
+ Transaction().hide(relativeParent).apply();
+
+ {
+ SCOPED_TRACE("hide relative parent");
+ // The relative should no longer be visible.
+ std::unique_ptr<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot);
+ screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK);
+ }
+}
+
+TEST_P(LayerTypeTransactionTest, SetFlagsSecure) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+
+ sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<GraphicBuffer> outBuffer;
+ Transaction()
+ .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
+ .apply(true);
+ ASSERT_EQ(PERMISSION_DENIED,
+ composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+
+ Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
+ ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+}
+TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+
+ sp<IBinder> handle = layer->getHandle();
+ ASSERT_TRUE(handle != nullptr);
+
+ FrameStats frameStats;
+ mClient->getLayerFrameStats(handle, &frameStats);
+
+ ASSERT_GT(frameStats.refreshPeriodNano, static_cast<nsecs_t>(0));
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp
new file mode 100644
index 0000000..73f563d
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp
@@ -0,0 +1,1655 @@
+/*
+ * Copyright (C) 2019 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 "LayerTransactionTest.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+class LayerUpdateTest : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+ ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+ const auto display = SurfaceComposerClient::getInternalDisplayToken();
+ ASSERT_FALSE(display == nullptr);
+
+ DisplayInfo info;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
+
+ ssize_t displayWidth = info.w;
+ ssize_t displayHeight = info.h;
+
+ // Background surface
+ mBGSurfaceControl = createLayer(String8("BG Test Surface"), displayWidth, displayHeight, 0);
+ ASSERT_TRUE(mBGSurfaceControl != nullptr);
+ ASSERT_TRUE(mBGSurfaceControl->isValid());
+ TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
+
+ // Foreground surface
+ mFGSurfaceControl = createLayer(String8("FG Test Surface"), 64, 64, 0);
+
+ ASSERT_TRUE(mFGSurfaceControl != nullptr);
+ ASSERT_TRUE(mFGSurfaceControl->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+
+ // Synchronization surface
+ mSyncSurfaceControl = createLayer(String8("Sync Test Surface"), 1, 1, 0);
+ ASSERT_TRUE(mSyncSurfaceControl != nullptr);
+ ASSERT_TRUE(mSyncSurfaceControl->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+
+ asTransaction([&](Transaction& t) {
+ t.setDisplayLayerStack(display, 0);
+
+ t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl);
+
+ t.setLayer(mFGSurfaceControl, INT32_MAX - 1)
+ .setPosition(mFGSurfaceControl, 64, 64)
+ .show(mFGSurfaceControl);
+
+ t.setLayer(mSyncSurfaceControl, INT32_MAX - 1)
+ .setPosition(mSyncSurfaceControl, displayWidth - 2, displayHeight - 2)
+ .show(mSyncSurfaceControl);
+ });
+ }
+
+ virtual void TearDown() {
+ LayerTransactionTest::TearDown();
+ mBGSurfaceControl = 0;
+ mFGSurfaceControl = 0;
+ mSyncSurfaceControl = 0;
+ }
+
+ void waitForPostedBuffers() {
+ // Since the sync surface is in synchronous mode (i.e. double buffered)
+ // posting three buffers to it should ensure that at least two
+ // SurfaceFlinger::handlePageFlip calls have been made, which should
+ // guaranteed that a buffer posted to another Surface has been retired.
+ TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ }
+
+ sp<SurfaceControl> mBGSurfaceControl;
+ sp<SurfaceControl> mFGSurfaceControl;
+
+ // This surface is used to ensure that the buffers posted to
+ // mFGSurfaceControl have been picked up by SurfaceFlinger.
+ sp<SurfaceControl> mSyncSurfaceControl;
+};
+
+TEST_F(LayerUpdateTest, RelativesAreNotDetached) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ sp<SurfaceControl> relative = createLayer(String8("relativeTestSurface"), 10, 10, 0);
+ TransactionUtils::fillSurfaceRGBA8(relative, 10, 10, 10);
+ waitForPostedBuffers();
+
+ Transaction{}
+ .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1)
+ .setPosition(relative, 64, 64)
+ .apply();
+
+ {
+ // The relative should be on top of the FG control.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(64, 64, 10, 10, 10);
+ }
+ Transaction{}.detachChildren(mFGSurfaceControl).apply();
+
+ {
+ // Nothing should change at this point.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(64, 64, 10, 10, 10);
+ }
+
+ Transaction{}.hide(relative).apply();
+
+ {
+ // Ensure that the relative was actually hidden, rather than
+ // being left in the detached but visible state.
+ ScreenCapture::captureScreen(&sc);
+ sc->expectFGColor(64, 64);
+ }
+}
+
+class GeometryLatchingTest : public LayerUpdateTest {
+protected:
+ void EXPECT_INITIAL_STATE(const char* trace) {
+ SCOPED_TRACE(trace);
+ ScreenCapture::captureScreen(&sc);
+ // We find the leading edge of the FG surface.
+ sc->expectFGColor(127, 127);
+ sc->expectBGColor(128, 128);
+ }
+
+ void lockAndFillFGBuffer() {
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
+ }
+
+ void unlockFGBuffer() {
+ sp<Surface> s = mFGSurfaceControl->getSurface();
+ ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ waitForPostedBuffers();
+ }
+
+ void completeFGResize() {
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+ waitForPostedBuffers();
+ }
+ void restoreInitialState() {
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 64, 64);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64));
+ });
+
+ EXPECT_INITIAL_STATE("After restoring initial state");
+ }
+ std::unique_ptr<ScreenCapture> sc;
+};
+
+class CropLatchingTest : public GeometryLatchingTest {
+protected:
+ void EXPECT_CROPPED_STATE(const char* trace) {
+ SCOPED_TRACE(trace);
+ ScreenCapture::captureScreen(&sc);
+ // The edge should be moved back one pixel by our crop.
+ sc->expectFGColor(126, 126);
+ sc->expectBGColor(127, 127);
+ sc->expectBGColor(128, 128);
+ }
+
+ void EXPECT_RESIZE_STATE(const char* trace) {
+ SCOPED_TRACE(trace);
+ ScreenCapture::captureScreen(&sc);
+ // The FG is now resized too 128,128 at 64,64
+ sc->expectFGColor(64, 64);
+ sc->expectFGColor(191, 191);
+ sc->expectBGColor(192, 192);
+ }
+};
+
+TEST_F(LayerUpdateTest, DeferredTransactionTest) {
+ std::unique_ptr<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before anything");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(32, 32);
+ sc->expectFGColor(96, 96);
+ sc->expectBGColor(160, 160);
+ }
+
+ // set up two deferred transactions on different frames
+ asTransaction([&](Transaction& t) {
+ t.setAlpha(mFGSurfaceControl, 0.75);
+ t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber());
+ });
+
+ asTransaction([&](Transaction& t) {
+ t.setPosition(mFGSurfaceControl, 128, 128);
+ t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+ });
+
+ {
+ SCOPED_TRACE("before any trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(32, 32);
+ sc->expectFGColor(96, 96);
+ sc->expectBGColor(160, 160);
+ }
+
+ // should trigger the first deferred transaction, but not the second one
+ TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ {
+ SCOPED_TRACE("after first trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(32, 32);
+ sc->checkPixel(96, 96, 162, 63, 96);
+ sc->expectBGColor(160, 160);
+ }
+
+ // should show up immediately since it's not deferred
+ asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); });
+
+ // trigger the second deferred transaction
+ TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ {
+ SCOPED_TRACE("after second trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(32, 32);
+ sc->expectBGColor(96, 96);
+ sc->expectFGColor(160, 160);
+ }
+}
+
+TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ sp<SurfaceControl> childNoBuffer =
+ createSurface(mClient, "Bufferless child", 0 /* buffer width */, 0 /* buffer height */,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ sp<SurfaceControl> childBuffer = createSurface(mClient, "Buffered child", 20, 20,
+ PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
+ TransactionUtils::fillSurfaceRGBA8(childBuffer, 200, 200, 200);
+ SurfaceComposerClient::Transaction{}
+ .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10))
+ .show(childNoBuffer)
+ .show(childBuffer)
+ .apply(true);
+ {
+ ScreenCapture::captureScreen(&sc);
+ sc->expectChildColor(73, 73);
+ sc->expectFGColor(74, 74);
+ }
+ SurfaceComposerClient::Transaction{}
+ .setCrop_legacy(childNoBuffer, Rect(0, 0, 20, 20))
+ .apply(true);
+ {
+ ScreenCapture::captureScreen(&sc);
+ sc->expectChildColor(73, 73);
+ sc->expectChildColor(74, 74);
+ }
+}
+
+TEST_F(LayerUpdateTest, MergingTransactions) {
+ std::unique_ptr<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before move");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(0, 12);
+ sc->expectFGColor(75, 75);
+ sc->expectBGColor(145, 145);
+ }
+
+ Transaction t1, t2;
+ t1.setPosition(mFGSurfaceControl, 128, 128);
+ t2.setPosition(mFGSurfaceControl, 0, 0);
+ // We expect that the position update from t2 now
+ // overwrites the position update from t1.
+ t1.merge(std::move(t2));
+ t1.apply();
+
+ {
+ ScreenCapture::captureScreen(&sc);
+ sc->expectFGColor(1, 1);
+ }
+}
+
+TEST_F(LayerUpdateTest, MergingTransactionFlags) {
+ Transaction().hide(mFGSurfaceControl).apply();
+ std::unique_ptr<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before merge");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(0, 12);
+ sc->expectBGColor(75, 75);
+ sc->expectBGColor(145, 145);
+ }
+
+ Transaction t1, t2;
+ t1.show(mFGSurfaceControl);
+ t2.setFlags(mFGSurfaceControl, 0 /* flags */, layer_state_t::eLayerSecure /* mask */);
+ t1.merge(std::move(t2));
+ t1.apply();
+
+ {
+ SCOPED_TRACE("after merge");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectFGColor(75, 75);
+ }
+}
+
+class ChildLayerTest : public LayerUpdateTest {
+protected:
+ void SetUp() override {
+ LayerUpdateTest::SetUp();
+ mChild = createSurface(mClient, "Child surface", 10, 15, PIXEL_FORMAT_RGBA_8888, 0,
+ mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
+
+ {
+ SCOPED_TRACE("before anything");
+ mCapture = screenshot();
+ mCapture->expectChildColor(64, 64);
+ }
+ }
+ void TearDown() override {
+ LayerUpdateTest::TearDown();
+ mChild = 0;
+ }
+
+ sp<SurfaceControl> mChild;
+ std::unique_ptr<ScreenCapture> mCapture;
+};
+
+TEST_F(ChildLayerTest, ChildLayerPositioning) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground should now be at 0, 0
+ mCapture->expectFGColor(0, 0);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(10, 10);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(20, 20);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildLayerCropping) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5));
+ });
+
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(4, 4);
+ mCapture->expectBGColor(5, 5);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildLayerConstraints) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setPosition(mChild, 63, 63);
+ });
+
+ {
+ mCapture = screenshot();
+ mCapture->expectFGColor(0, 0);
+ // Last pixel in foreground should now be the child.
+ mCapture->expectChildColor(63, 63);
+ // But the child should be constrained and the next pixel
+ // must be the background
+ mCapture->expectBGColor(64, 64);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildLayerScaling) {
+ asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); });
+
+ // Find the boundary between the parent and child
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(9, 9);
+ mCapture->expectFGColor(10, 10);
+ }
+
+ asTransaction([&](Transaction& t) { t.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0); });
+
+ // The boundary should be twice as far from the origin now.
+ // The pixels from the last test should all be child now
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(9, 9);
+ mCapture->expectChildColor(10, 10);
+ mCapture->expectChildColor(19, 19);
+ mCapture->expectFGColor(20, 20);
+ }
+}
+
+// A child with a scale transform should be cropped by its parent bounds.
+TEST_F(ChildLayerTest, ChildLayerScalingCroppedByParent) {
+ asTransaction([&](Transaction& t) {
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setPosition(mChild, 0, 0);
+ });
+
+ // Find the boundary between the parent and child.
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 9);
+ mCapture->expectFGColor(10, 10);
+ }
+
+ asTransaction([&](Transaction& t) { t.setMatrix(mChild, 10.0, 0, 0, 10.0); });
+
+ // The child should fill its parent bounds and be cropped by it.
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(63, 63);
+ mCapture->expectBGColor(64, 64);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildLayerAlpha) {
+ TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254);
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0);
+ TransactionUtils::fillSurfaceRGBA8(mChild, 0, 254, 0);
+ waitForPostedBuffers();
+
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
+
+ {
+ mCapture = screenshot();
+ // Unblended child color
+ mCapture->checkPixel(0, 0, 0, 254, 0);
+ }
+
+ asTransaction([&](Transaction& t) { t.setAlpha(mChild, 0.5); });
+
+ {
+ mCapture = screenshot();
+ // Child and BG blended.
+ mCapture->checkPixel(0, 0, 127, 127, 0);
+ }
+
+ asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.5); });
+
+ {
+ mCapture = screenshot();
+ // Child and BG blended.
+ mCapture->checkPixel(0, 0, 95, 64, 95);
+ }
+}
+
+TEST_F(ChildLayerTest, ReparentChildren) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle());
+ });
+
+ {
+ mCapture = screenshot();
+ mCapture->expectFGColor(64, 64);
+ // In reparenting we should have exposed the entire foreground surface.
+ mCapture->expectFGColor(74, 74);
+ // And the child layer should now begin at 10, 10 (since the BG
+ // layer is at (0, 0)).
+ mCapture->expectBGColor(9, 9);
+ mCapture->expectChildColor(10, 10);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
+ sp<SurfaceControl> mGrandChild =
+ createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+ TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
+
+ {
+ SCOPED_TRACE("Grandchild visible");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 111, 111, 111);
+ }
+
+ mChild.clear();
+
+ {
+ SCOPED_TRACE("After destroying child");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->expectFGColor(64, 64);
+ }
+
+ asTransaction([&](Transaction& t) { t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); });
+
+ {
+ SCOPED_TRACE("After reparenting grandchild");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 111, 111, 111);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) {
+ sp<SurfaceControl> mGrandChild =
+ createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+ TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
+
+ // draw grand child behind the foreground surface
+ asTransaction([&](Transaction& t) {
+ t.setRelativeLayer(mGrandChild, mFGSurfaceControl->getHandle(), -1);
+ });
+
+ {
+ SCOPED_TRACE("Child visible");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 200, 200, 200);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.reparent(mChild, nullptr);
+ t.reparentChildren(mChild, mFGSurfaceControl->getHandle());
+ });
+
+ {
+ SCOPED_TRACE("foreground visible reparenting grandchild");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 195, 63, 63);
+ }
+}
+
+TEST_F(ChildLayerTest, DetachChildrenSameClient) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
+
+ asTransaction([&](Transaction& t) { t.hide(mChild); });
+
+ // Since the child has the same client as the parent, it will not get
+ // detached and will be hidden.
+ {
+ mCapture = screenshot();
+ mCapture->expectFGColor(64, 64);
+ mCapture->expectFGColor(74, 74);
+ mCapture->expectFGColor(84, 84);
+ }
+}
+
+TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
+ sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> mChildNewClient =
+ createSurface(mNewComposerClient, "New Child Test Surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+ ASSERT_TRUE(mChildNewClient->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
+
+ asTransaction([&](Transaction& t) {
+ t.hide(mChild);
+ t.show(mChildNewClient);
+ t.setPosition(mChildNewClient, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
+
+ asTransaction([&](Transaction& t) { t.hide(mChildNewClient); });
+
+ // Nothing should have changed.
+ {
+ mCapture = screenshot();
+ mCapture->expectFGColor(64, 64);
+ mCapture->expectChildColor(74, 74);
+ mCapture->expectFGColor(84, 84);
+ }
+}
+
+TEST_F(ChildLayerTest, DetachChildrenThenAttach) {
+ sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> childNewClient =
+ newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+ ASSERT_TRUE(childNewClient != nullptr);
+ ASSERT_TRUE(childNewClient->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+
+ Transaction()
+ .hide(mChild)
+ .show(childNewClient)
+ .setPosition(childNewClient, 10, 10)
+ .setPosition(mFGSurfaceControl, 64, 64)
+ .apply();
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ Transaction().detachChildren(mFGSurfaceControl).apply();
+ Transaction().hide(childNewClient).apply();
+
+ // Nothing should have changed.
+ {
+ mCapture = screenshot();
+ mCapture->expectFGColor(64, 64);
+ mCapture->expectChildColor(74, 74);
+ mCapture->expectFGColor(84, 84);
+ }
+
+ sp<SurfaceControl> newParentSurface = createLayer(String8("New Parent Surface"), 32, 32, 0);
+ fillLayerColor(ISurfaceComposerClient::eFXSurfaceBufferQueue, newParentSurface, Color::RED, 32,
+ 32);
+ Transaction()
+ .setLayer(newParentSurface, INT32_MAX - 1)
+ .show(newParentSurface)
+ .setPosition(newParentSurface, 20, 20)
+ .reparent(childNewClient, newParentSurface->getHandle())
+ .apply();
+ {
+ mCapture = screenshot();
+ // Child is now hidden.
+ mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
+ }
+}
+TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) {
+ sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> childNewClient =
+ newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+ ASSERT_TRUE(childNewClient != nullptr);
+ ASSERT_TRUE(childNewClient->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+
+ Transaction()
+ .hide(mChild)
+ .show(childNewClient)
+ .setPosition(childNewClient, 10, 10)
+ .setPosition(mFGSurfaceControl, 64, 64)
+ .apply();
+
+ {
+ mCapture = screenshot();
+ Rect rect = Rect(74, 74, 84, 84);
+ mCapture->expectBorder(rect, Color{195, 63, 63, 255});
+ mCapture->expectColor(rect, Color{200, 200, 200, 255});
+ }
+
+ Transaction()
+ .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(),
+ mFGSurfaceControl->getSurface()->getNextFrameNumber())
+ .apply();
+ Transaction().detachChildren(mFGSurfaceControl).apply();
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32));
+
+ // BufferLayer can still dequeue buffers even though there's a detached layer with a
+ // deferred transaction.
+ {
+ SCOPED_TRACE("new buffer");
+ mCapture = screenshot();
+ Rect rect = Rect(74, 74, 84, 84);
+ mCapture->expectBorder(rect, Color::RED);
+ mCapture->expectColor(rect, Color{200, 200, 200, 255});
+ }
+}
+
+TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
+
+ {
+ mCapture = screenshot();
+ // We've positioned the child in the top left.
+ mCapture->expectChildColor(0, 0);
+ // But it's only 10x15.
+ mCapture->expectFGColor(10, 15);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ // We cause scaling by 2.
+ t.setSize(mFGSurfaceControl, 128, 128);
+ });
+
+ {
+ mCapture = screenshot();
+ // We've positioned the child in the top left.
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(10, 10);
+ mCapture->expectChildColor(19, 29);
+ // And now it should be scaled all the way to 20x30
+ mCapture->expectFGColor(20, 30);
+ }
+}
+
+// Regression test for b/37673612
+TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
+
+ {
+ mCapture = screenshot();
+ // We've positioned the child in the top left.
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 14);
+ // But it's only 10x15.
+ mCapture->expectFGColor(10, 15);
+ }
+ // We set things up as in b/37673612 so that there is a mismatch between the buffer size and
+ // the WM specified state size.
+ asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); });
+ sp<Surface> s = mFGSurfaceControl->getSurface();
+ auto anw = static_cast<ANativeWindow*>(s.get());
+ native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
+ native_window_set_buffers_dimensions(anw, 64, 128);
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+ waitForPostedBuffers();
+
+ {
+ // The child should still be in the same place and not have any strange scaling as in
+ // b/37673612.
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectFGColor(10, 10);
+ }
+}
+
+// A child with a buffer transform from its parents should be cropped by its parent bounds.
+TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferTransform) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setSize(mChild, 100, 100);
+ });
+ TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
+
+ {
+ mCapture = screenshot();
+
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(63, 63);
+ mCapture->expectBGColor(64, 64);
+ }
+
+ asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); });
+ sp<Surface> s = mFGSurfaceControl->getSurface();
+ auto anw = static_cast<ANativeWindow*>(s.get());
+ // Apply a 90 transform on the buffer.
+ native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
+ native_window_set_buffers_dimensions(anw, 64, 128);
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+ waitForPostedBuffers();
+
+ // The child should be cropped by the new parent bounds.
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(99, 63);
+ mCapture->expectFGColor(100, 63);
+ mCapture->expectBGColor(128, 64);
+ }
+}
+
+// A child with a scale transform from its parents should be cropped by its parent bounds.
+TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferScale) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setSize(mChild, 200, 200);
+ });
+ TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
+
+ {
+ mCapture = screenshot();
+
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(63, 63);
+ mCapture->expectBGColor(64, 64);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ // Set a scaling by 2.
+ t.setSize(mFGSurfaceControl, 128, 128);
+ });
+
+ // Child should inherit its parents scale but should be cropped by its parent bounds.
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(127, 127);
+ mCapture->expectBGColor(128, 128);
+ }
+}
+
+// Regression test for b/127368943
+// Child should ignore the buffer transform but apply parent scale transform.
+TEST_F(ChildLayerTest, ChildrenWithParentBufferTransformAndScale) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
+
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 14);
+ mCapture->expectFGColor(10, 15);
+ }
+
+ // Change the size of the foreground to 128 * 64 so we can test rotation as well.
+ asTransaction([&](Transaction& t) {
+ t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ t.setSize(mFGSurfaceControl, 128, 64);
+ });
+ sp<Surface> s = mFGSurfaceControl->getSurface();
+ auto anw = static_cast<ANativeWindow*>(s.get());
+ // Apply a 90 transform on the buffer and submit a buffer half the expected size so that we
+ // have an effective scale of 2.0 applied to the buffer along with a rotation transform.
+ native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
+ native_window_set_buffers_dimensions(anw, 32, 64);
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+ waitForPostedBuffers();
+
+ // The child should ignore the buffer transform but apply the 2.0 scale from parent.
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(19, 29);
+ mCapture->expectFGColor(20, 30);
+ }
+}
+
+TEST_F(ChildLayerTest, Bug36858924) {
+ // Destroy the child layer
+ mChild.clear();
+
+ // Now recreate it as hidden
+ mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eHidden, mFGSurfaceControl.get());
+
+ // Show the child layer in a deferred transaction
+ asTransaction([&](Transaction& t) {
+ t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(),
+ mFGSurfaceControl->getSurface()->getNextFrameNumber());
+ t.show(mChild);
+ });
+
+ // Render the foreground surface a few times
+ //
+ // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the third
+ // frame because SurfaceFlinger would never process the deferred transaction and would therefore
+ // never acquire/release the first buffer
+ ALOGI("Filling 1");
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
+ ALOGI("Filling 2");
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255);
+ ALOGI("Filling 3");
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0);
+ ALOGI("Filling 4");
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
+}
+
+TEST_F(ChildLayerTest, Reparent) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl->getHandle()); });
+
+ {
+ mCapture = screenshot();
+ mCapture->expectFGColor(64, 64);
+ // In reparenting we should have exposed the entire foreground surface.
+ mCapture->expectFGColor(74, 74);
+ // And the child layer should now begin at 10, 10 (since the BG
+ // layer is at (0, 0)).
+ mCapture->expectBGColor(9, 9);
+ mCapture->expectChildColor(10, 10);
+ }
+}
+
+TEST_F(ChildLayerTest, ReparentToNoParent) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+ asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); });
+ {
+ mCapture = screenshot();
+ // The surface should now be offscreen.
+ mCapture->expectFGColor(64, 64);
+ mCapture->expectFGColor(74, 74);
+ mCapture->expectFGColor(84, 84);
+ }
+}
+
+TEST_F(ChildLayerTest, ReparentFromNoParent) {
+ sp<SurfaceControl> newSurface = createLayer(String8("New Surface"), 10, 10, 0);
+ ASSERT_TRUE(newSurface != nullptr);
+ ASSERT_TRUE(newSurface->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(newSurface, 63, 195, 63);
+ asTransaction([&](Transaction& t) {
+ t.hide(mChild);
+ t.show(newSurface);
+ t.setPosition(newSurface, 10, 10);
+ t.setLayer(newSurface, INT32_MAX - 2);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ mCapture = screenshot();
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // At 10, 10 we should see the new surface
+ mCapture->checkPixel(10, 10, 63, 195, 63);
+ }
+
+ asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl->getHandle()); });
+
+ {
+ mCapture = screenshot();
+ // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from
+ // mFGSurface, putting it at 74, 74.
+ mCapture->expectFGColor(64, 64);
+ mCapture->checkPixel(74, 74, 63, 195, 63);
+ mCapture->expectFGColor(84, 84);
+ }
+}
+
+TEST_F(ChildLayerTest, NestedChildren) {
+ sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+ TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
+
+ {
+ mCapture = screenshot();
+ // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer
+ // which begins at 64, 64
+ mCapture->checkPixel(64, 64, 50, 50, 50);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildLayerRelativeLayer) {
+ sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 128, 128, 0);
+ TransactionUtils::fillSurfaceRGBA8(relative, 255, 255, 255);
+
+ Transaction t;
+ t.setLayer(relative, INT32_MAX)
+ .setRelativeLayer(mChild, relative->getHandle(), 1)
+ .setPosition(mFGSurfaceControl, 0, 0)
+ .apply(true);
+
+ // We expect that the child should have been elevated above our
+ // INT_MAX layer even though it's not a child of it.
+ {
+ mCapture = screenshot();
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 9);
+ mCapture->checkPixel(10, 10, 255, 255, 255);
+ }
+}
+
+class BoundlessLayerTest : public LayerUpdateTest {
+protected:
+ std::unique_ptr<ScreenCapture> mCapture;
+};
+
+// Verify setting a size on a buffer layer has no effect.
+TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) {
+ sp<SurfaceControl> bufferLayer =
+ createSurface(mClient, "BufferLayer", 45, 45, PIXEL_FORMAT_RGBA_8888, 0,
+ mFGSurfaceControl.get());
+ ASSERT_TRUE(bufferLayer->isValid());
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30));
+ asTransaction([&](Transaction& t) { t.show(bufferLayer); });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 94, 94), Color::BLACK);
+ // Buffer layer should not extend past buffer bounds
+ mCapture->expectFGColor(95, 95);
+ }
+}
+
+// Verify a boundless color layer will fill its parent bounds. The parent has a buffer size
+// which will crop the color layer.
+TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) {
+ sp<SurfaceControl> colorLayer =
+ createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get());
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has
+// a crop which will be used to crop the color layer.
+TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) {
+ sp<SurfaceControl> cropLayer = createSurface(mClient, "CropLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */, mFGSurfaceControl.get());
+ ASSERT_TRUE(cropLayer->isValid());
+ sp<SurfaceControl> colorLayer =
+ createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get());
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10));
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(cropLayer);
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // 5 pixels from the foreground we should see the child surface
+ mCapture->expectColor(Rect(69, 69, 74, 74), Color::BLACK);
+ // 10 pixels from the foreground we should be back to the foreground surface
+ mCapture->expectFGColor(74, 74);
+ }
+}
+
+// Verify for boundless layer with no children, their transforms have no effect.
+TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) {
+ sp<SurfaceControl> colorLayer =
+ createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get());
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setPosition(colorLayer, 320, 320);
+ t.setMatrix(colorLayer, 2, 0, 0, 2);
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify for boundless layer with children, their transforms have an effect.
+TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) {
+ sp<SurfaceControl> boundlessLayerRightShift =
+ createSurface(mClient, "BoundlessLayerRightShift", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */, mFGSurfaceControl.get());
+ ASSERT_TRUE(boundlessLayerRightShift->isValid());
+ sp<SurfaceControl> boundlessLayerDownShift =
+ createSurface(mClient, "BoundlessLayerLeftShift", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */, boundlessLayerRightShift.get());
+ ASSERT_TRUE(boundlessLayerDownShift->isValid());
+ sp<SurfaceControl> colorLayer =
+ createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, boundlessLayerDownShift.get());
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setPosition(boundlessLayerRightShift, 32, 0);
+ t.show(boundlessLayerRightShift);
+ t.setPosition(boundlessLayerDownShift, 0, 32);
+ t.show(boundlessLayerDownShift);
+ t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(96, 96, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify child layers do not get clipped if they temporarily move into the negative
+// coordinate space as the result of an intermediate transformation.
+TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) {
+ sp<SurfaceControl> boundlessLayer =
+ mClient->createSurface(String8("BoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */, mFGSurfaceControl.get());
+ ASSERT_TRUE(boundlessLayer != nullptr);
+ ASSERT_TRUE(boundlessLayer->isValid());
+ sp<SurfaceControl> colorLayer =
+ mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, boundlessLayer.get());
+ ASSERT_TRUE(colorLayer != nullptr);
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ // shift child layer off bounds. If this layer was not boundless, we will
+ // expect the child layer to be cropped.
+ t.setPosition(boundlessLayer, 32, 32);
+ t.show(boundlessLayer);
+ t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
+ // undo shift by parent
+ t.setPosition(colorLayer, -32, -32);
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify for boundless root layers with children, their transforms have an effect.
+TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) {
+ sp<SurfaceControl> rootBoundlessLayer = createSurface(mClient, "RootBoundlessLayer", 0, 0,
+ PIXEL_FORMAT_RGBA_8888, 0 /* flags */);
+ ASSERT_TRUE(rootBoundlessLayer->isValid());
+ sp<SurfaceControl> colorLayer =
+ createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, rootBoundlessLayer.get());
+
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setLayer(rootBoundlessLayer, INT32_MAX - 1);
+ t.setPosition(rootBoundlessLayer, 32, 32);
+ t.show(rootBoundlessLayer);
+ t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ t.hide(mFGSurfaceControl);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Top left of foreground must now be visible
+ mCapture->expectBGColor(31, 31);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(32, 32, 96, 96), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(97, 97);
+ }
+}
+
+class ScreenCaptureTest : public LayerUpdateTest {
+protected:
+ std::unique_ptr<ScreenCapture> mCapture;
+};
+
+TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
+ auto bgHandle = mBGSurfaceControl->getHandle();
+ ScreenCapture::captureLayers(&mCapture, bgHandle);
+ mCapture->expectBGColor(0, 0);
+ // Doesn't capture FG layer which is at 64, 64
+ mCapture->expectBGColor(64, 64);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ // Captures mFGSurfaceControl layer and its child.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ // Captures mFGSurfaceControl's child
+ ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerExclude) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .show(child2)
+ .setLayer(child, 1)
+ .setLayer(child2, 2)
+ .apply(true);
+
+ // Child2 would be visible but its excluded, so we should see child1 color instead.
+ ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->checkPixel(0, 0, 200, 200, 200);
+}
+
+// Like the last test but verifies that children are also exclude.
+TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
+ sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, child2.get());
+ TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .show(child2)
+ .show(child3)
+ .setLayer(child, 1)
+ .setLayer(child2, 2)
+ .apply(true);
+
+ // Child2 would be visible but its excluded, so we should see child1 color instead.
+ ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->checkPixel(0, 0, 200, 200, 200);
+}
+
+TEST_F(ScreenCaptureTest, CaptureTransparent) {
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ auto childHandle = child->getHandle();
+
+ // Captures child
+ ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20});
+ mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
+ // Area outside of child's bounds is transparent.
+ mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0});
+}
+
+TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ ASSERT_NE(nullptr, child.get()) << "failed to create surface";
+ sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0);
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ // Set relative layer above fg layer so should be shown above when computing all layers.
+ .setRelativeLayer(relative, fgHandle, 1)
+ .show(relative)
+ .apply(true);
+
+ // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ // Set relative layer below fg layer but relative to child layer so it should be shown
+ // above child layer.
+ .setLayer(relative, -1)
+ .setRelativeLayer(relative, child->getHandle(), 1)
+ .show(relative)
+ .apply(true);
+
+ // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its
+ // relative value should be taken into account, placing it above child layer.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ // Relative layer is showing on top of child layer
+ mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255});
+}
+
+// In the following tests we verify successful skipping of a parent layer,
+// so we use the same verification logic and only change how we mutate
+// the parent layer to verify that various properties are ignored.
+class ScreenCaptureChildOnlyTest : public LayerUpdateTest {
+public:
+ void SetUp() override {
+ LayerUpdateTest::SetUp();
+
+ mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
+ mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(mChild).apply(true);
+ }
+
+ void verify(std::function<void()> verifyStartingState) {
+ // Verify starting state before a screenshot is taken.
+ verifyStartingState();
+
+ // Verify child layer does not inherit any of the properties of its
+ // parent when its screenshot is captured.
+ auto fgHandle = mFGSurfaceControl->getHandle();
+ ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->expectChildColor(0, 0);
+
+ // Verify all assumptions are still true after the screenshot is taken.
+ verifyStartingState();
+ }
+
+ std::unique_ptr<ScreenCapture> mCapture;
+ sp<SurfaceControl> mChild;
+};
+
+// Regression test b/76099859
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) {
+ SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true);
+
+ // Even though the parent is hidden we should still capture the child.
+
+ // Before and after reparenting, verify child is properly hidden
+ // when rendering full-screen.
+ verify([&] { screenshot()->expectBGColor(64, 64); });
+}
+
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) {
+ SurfaceComposerClient::Transaction()
+ .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1))
+ .apply(true);
+
+ // Even though the parent is cropped out we should still capture the child.
+
+ // Before and after reparenting, verify child is cropped by parent.
+ verify([&] { screenshot()->expectBGColor(65, 65); });
+}
+
+// Regression test b/124372894
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) {
+ SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2).apply(true);
+
+ // We should not inherit the parent scaling.
+
+ // Before and after reparenting, verify child is properly scaled.
+ verify([&] { screenshot()->expectChildColor(80, 80); });
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
+ PIXEL_FORMAT_RGBA_8888, 0, child.get());
+
+ TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .setPosition(grandchild, 5, 5)
+ .show(grandchild)
+ .apply(true);
+
+ // Captures mFGSurfaceControl, its child, and the grandchild.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+ mCapture->checkPixel(5, 5, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureChildOnly) {
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ auto childHandle = child->getHandle();
+
+ SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
+
+ // Captures only the child layer, and not the parent.
+ ScreenCapture::captureLayers(&mCapture, childHandle);
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 9);
+}
+
+TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ auto childHandle = child->getHandle();
+
+ sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
+ PIXEL_FORMAT_RGBA_8888, 0, child.get());
+ TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .setPosition(grandchild, 5, 5)
+ .show(grandchild)
+ .apply(true);
+
+ auto grandchildHandle = grandchild->getHandle();
+
+ // Captures only the grandchild.
+ ScreenCapture::captureLayers(&mCapture, grandchildHandle);
+ mCapture->checkPixel(0, 0, 50, 50, 50);
+ mCapture->checkPixel(4, 4, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureCrop) {
+ sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
+ sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
+ PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
+
+ SurfaceComposerClient::Transaction()
+ .setLayer(redLayer, INT32_MAX - 1)
+ .show(redLayer)
+ .show(blueLayer)
+ .apply(true);
+
+ auto redLayerHandle = redLayer->getHandle();
+
+ // Capturing full screen should have both red and blue are visible.
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+ const Rect crop = Rect(0, 0, 30, 30);
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
+ // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
+ // area visible.
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureSize) {
+ sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
+ sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
+ PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
+
+ SurfaceComposerClient::Transaction()
+ .setLayer(redLayer, INT32_MAX - 1)
+ .show(redLayer)
+ .show(blueLayer)
+ .apply(true);
+
+ auto redLayerHandle = redLayer->getHandle();
+
+ // Capturing full screen should have both red and blue are visible.
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
+ // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
+ mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED);
+ mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
+ sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+
+ auto redLayerHandle = redLayer->getHandle();
+ redLayer.clear();
+ SurfaceComposerClient::Transaction().apply(true);
+
+ sp<GraphicBuffer> outBuffer;
+
+ // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0));
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
new file mode 100644
index 0000000..066c9aa
--- /dev/null
+++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 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 "LayerTransactionTest.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+class MultiDisplayLayerBoundsTest : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+ ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+ mMainDisplay = SurfaceComposerClient::getInternalDisplayToken();
+ SurfaceComposerClient::getDisplayInfo(mMainDisplay, &mMainDisplayInfo);
+
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&mProducer, &consumer);
+ consumer->setConsumerName(String8("Virtual disp consumer"));
+ consumer->setDefaultBufferSize(mMainDisplayInfo.w, mMainDisplayInfo.h);
+ }
+
+ virtual void TearDown() {
+ SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
+ LayerTransactionTest::TearDown();
+ mColorLayer = 0;
+ }
+
+ void createDisplay(const Rect& layerStackRect, uint32_t layerStack) {
+ mVirtualDisplay =
+ SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/);
+ asTransaction([&](Transaction& t) {
+ t.setDisplaySurface(mVirtualDisplay, mProducer);
+ t.setDisplayLayerStack(mVirtualDisplay, layerStack);
+ t.setDisplayProjection(mVirtualDisplay, mMainDisplayInfo.orientation, layerStackRect,
+ Rect(mMainDisplayInfo.w, mMainDisplayInfo.h));
+ });
+ }
+
+ void createColorLayer(uint32_t layerStack) {
+ mColorLayer =
+ createSurface(mClient, "ColorLayer", 0 /* buffer width */, 0 /* buffer height */,
+ PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor);
+ ASSERT_TRUE(mColorLayer != nullptr);
+ ASSERT_TRUE(mColorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setLayerStack(mColorLayer, layerStack);
+ t.setCrop_legacy(mColorLayer, Rect(0, 0, 30, 40));
+ t.setLayer(mColorLayer, INT32_MAX - 2);
+ t.setColor(mColorLayer,
+ half3{mExpectedColor.r / 255.0f, mExpectedColor.g / 255.0f,
+ mExpectedColor.b / 255.0f});
+ t.show(mColorLayer);
+ });
+ }
+
+ DisplayInfo mMainDisplayInfo;
+ sp<IBinder> mMainDisplay;
+ sp<IBinder> mVirtualDisplay;
+ sp<IGraphicBufferProducer> mProducer;
+ sp<SurfaceControl> mColorLayer;
+ Color mExpectedColor = {63, 63, 195, 255};
+};
+
+TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInVirtualDisplay) {
+ createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 1 /* layerStack */);
+ createColorLayer(1 /* layerStack */);
+
+ asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); });
+
+ // Verify color layer does not render on main display.
+ std::unique_ptr<ScreenCapture> sc;
+ ScreenCapture::captureScreen(&sc, mMainDisplay);
+ sc->expectColor(Rect(10, 10, 40, 50), {0, 0, 0, 255});
+ sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
+
+ // Verify color layer renders correctly on virtual display.
+ ScreenCapture::captureScreen(&sc, mVirtualDisplay);
+ sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
+ sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 0});
+}
+
+TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) {
+ // Create a display and set its layer stack to the main display's layer stack so
+ // the contents of the main display are mirrored on to the virtual display.
+
+ // Assumption here is that the new mirrored display has the same viewport as the
+ // primary display that it is mirroring.
+ createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 0 /* layerStack */);
+ createColorLayer(0 /* layerStack */);
+
+ asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); });
+
+ // Verify color layer renders correctly on main display and it is mirrored on the
+ // virtual display.
+ std::unique_ptr<ScreenCapture> sc;
+ ScreenCapture::captureScreen(&sc, mMainDisplay);
+ sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
+ sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
+
+ ScreenCapture::captureScreen(&sc, mVirtualDisplay);
+ sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
+ sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp
new file mode 100644
index 0000000..8549db2
--- /dev/null
+++ b/services/surfaceflinger/tests/RelativeZ_test.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2019 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 "LayerTransactionTest.h"
+
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+::testing::Environment* const binderEnv =
+ ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
+
+class RelativeZTest : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+ ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+ const auto display = SurfaceComposerClient::getInternalDisplayToken();
+ ASSERT_FALSE(display == nullptr);
+
+ // Back layer
+ mBackgroundLayer = createColorLayer("Background layer", Color::RED);
+
+ // Front layer
+ mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
+
+ asTransaction([&](Transaction& t) {
+ t.setDisplayLayerStack(display, 0);
+ t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
+ t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
+ });
+ }
+
+ virtual void TearDown() {
+ LayerTransactionTest::TearDown();
+ mBackgroundLayer = 0;
+ mForegroundLayer = 0;
+ }
+
+ sp<SurfaceControl> mBackgroundLayer;
+ sp<SurfaceControl> mForegroundLayer;
+};
+
+// When a layer is reparented offscreen, remove relative z order if the relative parent
+// is still onscreen so that the layer is not drawn.
+TEST_F(RelativeZTest, LayerRemoved) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ // Background layer (RED)
+ // Child layer (WHITE) (relative to foregroud layer)
+ // Foregroud layer (GREEN)
+ sp<SurfaceControl> childLayer =
+ createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get());
+
+ Transaction{}
+ .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1)
+ .show(childLayer)
+ .apply();
+
+ {
+ // The childLayer should be in front of the FG control.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLayer, nullptr).apply();
+
+ // Background layer (RED)
+ // Child layer (WHITE)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply();
+
+ {
+ // The relative z info for child layer should be reset, leaving FG control on top.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+}
+
+// When a layer is reparented offscreen, preseve relative z order if the relative parent
+// is also offscreen. Regression test b/132613412
+TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // child level 1 (WHITE)
+ // child level 2a (BLUE)
+ // child level 3 (GREEN) (relative to child level 2b)
+ // child level 2b (BLACK)
+ sp<SurfaceControl> childLevel1 =
+ createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get());
+ sp<SurfaceControl> childLevel2a =
+ createColorLayer("child level 2a", Color::BLUE, childLevel1.get());
+ sp<SurfaceControl> childLevel2b =
+ createColorLayer("child level 2b", Color::BLACK, childLevel1.get());
+ sp<SurfaceControl> childLevel3 =
+ createColorLayer("child level 3", Color::GREEN, childLevel2a.get());
+
+ Transaction{}
+ .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1)
+ .show(childLevel2a)
+ .show(childLevel2b)
+ .show(childLevel3)
+ .apply();
+
+ {
+ // The childLevel3 should be in front of childLevel2b.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLevel1, nullptr).apply();
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // child level 1 (WHITE)
+ // child level 2 back (BLUE)
+ // child level 3 (GREEN) (relative to child level 2b)
+ // child level 2 front (BLACK)
+ Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply();
+
+ {
+ // Nothing should change at this point since relative z info was preserved.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
new file mode 100644
index 0000000..8fdcde4
--- /dev/null
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#ifndef ANDROID_TRANSACTION_TEST_HARNESSES
+#define ANDROID_TRANSACTION_TEST_HARNESSES
+
+/*#include <algorithm>
+#include <chrono>
+#include <cinttypes>
+#include <functional>
+#include <limits>
+#include <ostream>
+
+#include <android/native_window.h>
+
+#include <binder/ProcessState.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/IProducerListener.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <hardware/hwcomposer_defs.h>
+#include <private/android_filesystem_config.h>
+#include <private/gui/ComposerService.h>
+
+#include <ui/DisplayInfo.h>
+
+#include <math.h>
+#include <math/vec3.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "BufferGenerator.h"
+*/
+#include "LayerTransactionTest.h"
+/*#include "utils/CallbackUtils.h"
+#include "utils/ColorUtils.h"
+#include "utils/ScreenshotUtils.h"
+#include "utils/TransactionUtils.h"
+*/
+namespace android {
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+class LayerRenderPathTestHarness {
+public:
+ LayerRenderPathTestHarness(LayerTransactionTest* delegate, RenderPath renderPath)
+ : mDelegate(delegate), mRenderPath(renderPath) {}
+
+ std::unique_ptr<ScreenCapture> getScreenCapture() {
+ switch (mRenderPath) {
+ case RenderPath::SCREENSHOT:
+ return mDelegate->screenshot();
+ case RenderPath::VIRTUAL_DISPLAY:
+
+ const auto mainDisplay = SurfaceComposerClient::getInternalDisplayToken();
+ DisplayInfo mainDisplayInfo;
+ SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
+
+ sp<IBinder> vDisplay;
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ sp<BufferItemConsumer> itemConsumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ consumer->setConsumerName(String8("Virtual disp consumer"));
+ consumer->setDefaultBufferSize(mainDisplayInfo.w, mainDisplayInfo.h);
+
+ itemConsumer = new BufferItemConsumer(consumer,
+ // Sample usage bits from screenrecord
+ GRALLOC_USAGE_HW_VIDEO_ENCODER |
+ GRALLOC_USAGE_SW_READ_OFTEN);
+
+ vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"),
+ false /*secure*/);
+
+ SurfaceComposerClient::Transaction t;
+ t.setDisplaySurface(vDisplay, producer);
+ t.setDisplayLayerStack(vDisplay, 0);
+ t.setDisplayProjection(vDisplay, mainDisplayInfo.orientation,
+ Rect(mainDisplayInfo.viewportW, mainDisplayInfo.viewportH),
+ Rect(mainDisplayInfo.w, mainDisplayInfo.h));
+ t.apply();
+ SurfaceComposerClient::Transaction().apply(true);
+ BufferItem item;
+ itemConsumer->acquireBuffer(&item, 0, true);
+ auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
+ itemConsumer->releaseBuffer(item);
+ SurfaceComposerClient::destroyDisplay(vDisplay);
+ return sc;
+ }
+ }
+
+protected:
+ LayerTransactionTest* mDelegate;
+ RenderPath mRenderPath;
+};
+
+class LayerTypeTransactionHarness : public LayerTransactionTest {
+public:
+ LayerTypeTransactionHarness(uint32_t layerType) : mLayerType(layerType) {}
+
+ sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
+ uint32_t flags = 0, SurfaceControl* parent = nullptr) {
+ // if the flags already have a layer type specified, return an error
+ if (flags & ISurfaceComposerClient::eFXSurfaceMask) {
+ return nullptr;
+ }
+ return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType, parent);
+ }
+
+ void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth,
+ int32_t bufferHeight) {
+ ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color,
+ bufferWidth, bufferHeight));
+ }
+
+ void fillLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
+ int32_t bufferHeight, const Color& topLeft, const Color& topRight,
+ const Color& bottomLeft, const Color& bottomRight) {
+ ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer,
+ bufferWidth, bufferHeight,
+ topLeft, topRight,
+ bottomLeft, bottomRight));
+ }
+
+protected:
+ uint32_t mLayerType;
+};
+} // namespace android
+#endif
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
deleted file mode 100644
index d765f68..0000000
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ /dev/null
@@ -1,5593 +0,0 @@
-/*
- * Copyright (C) 2011 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 <algorithm>
-#include <chrono>
-#include <cinttypes>
-#include <functional>
-#include <limits>
-#include <ostream>
-
-#include <gtest/gtest.h>
-
-#include <android/native_window.h>
-
-#include <binder/ProcessState.h>
-#include <gui/BufferItemConsumer.h>
-#include <gui/IProducerListener.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/LayerState.h>
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-#include <hardware/hwcomposer_defs.h>
-#include <private/android_filesystem_config.h>
-#include <private/gui/ComposerService.h>
-
-#include <ui/DisplayInfo.h>
-
-#include <math.h>
-#include <math/vec3.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "BufferGenerator.h"
-#include "utils/CallbackUtils.h"
-#include "utils/ColorUtils.h"
-#include "utils/ScreenshotUtils.h"
-#include "utils/TransactionUtils.h"
-
-namespace android {
-
-using android::hardware::graphics::common::V1_1::BufferUsage;
-
-class LayerTransactionTest : public ::testing::Test {
-protected:
- void SetUp() override {
- mClient = new SurfaceComposerClient;
- ASSERT_EQ(NO_ERROR, mClient->initCheck()) << "failed to create SurfaceComposerClient";
-
- ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
-
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed));
- }
-
- virtual void TearDown() {
- mBlackBgSurface = 0;
- mClient->dispose();
- mClient = 0;
- }
-
- virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client,
- const char* name, uint32_t width, uint32_t height,
- uint32_t flags = 0, SurfaceControl* parent = nullptr) {
- auto layer =
- createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags, parent);
-
- Transaction t;
- t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase);
-
- status_t error = t.apply();
- if (error != NO_ERROR) {
- ADD_FAILURE() << "failed to initialize SurfaceControl";
- layer.clear();
- }
-
- return layer;
- }
-
- virtual sp<SurfaceControl> createSurface(const sp<SurfaceComposerClient>& client,
- const char* name, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t flags,
- SurfaceControl* parent = nullptr) {
- auto layer = client->createSurface(String8(name), width, height, format, flags, parent);
- EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
- return layer;
- }
-
- virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
- uint32_t flags = 0, SurfaceControl* parent = nullptr) {
- return createLayer(mClient, name, width, height, flags, parent);
- }
-
- sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
- SurfaceControl* parent = nullptr) {
- auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */,
- PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceColor, parent);
- asTransaction([&](Transaction& t) {
- t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f});
- t.setAlpha(colorLayer, color.a / 255.0f);
- });
- return colorLayer;
- }
-
- ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
- // wait for previous transactions (such as setSize) to complete
- Transaction().apply(true);
-
- ANativeWindow_Buffer buffer = {};
- EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr));
-
- return buffer;
- }
-
- void postBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
- ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
-
- // wait for the newly posted buffer to be latched
- waitForLayerBuffers();
- }
-
- virtual void fillBufferQueueLayerColor(const sp<SurfaceControl>& layer, const Color& color,
- int32_t bufferWidth, int32_t bufferHeight) {
- ANativeWindow_Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
- TransactionUtils::fillANativeWindowBufferColor(buffer,
- Rect(0, 0, bufferWidth, bufferHeight),
- color);
- postBufferQueueLayerBuffer(layer);
- }
-
- virtual void fillBufferStateLayerColor(const sp<SurfaceControl>& layer, const Color& color,
- int32_t bufferWidth, int32_t bufferHeight) {
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight),
- color);
- Transaction().setBuffer(layer, buffer).apply();
- }
-
- void fillLayerColor(uint32_t mLayerType, const sp<SurfaceControl>& layer, const Color& color,
- int32_t bufferWidth, int32_t bufferHeight) {
- switch (mLayerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight);
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight);
- break;
- default:
- ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType;
- }
- }
-
- void fillLayerQuadrant(uint32_t mLayerType, const sp<SurfaceControl>& layer,
- int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft,
- const Color& topRight, const Color& bottomLeft,
- const Color& bottomRight) {
- switch (mLayerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight,
- bottomLeft, bottomRight);
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight,
- bottomLeft, bottomRight);
- break;
- default:
- ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType;
- }
- }
-
- virtual void fillBufferQueueLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
- int32_t bufferHeight, const Color& topLeft,
- const Color& topRight, const Color& bottomLeft,
- const Color& bottomRight) {
- ANativeWindow_Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
- ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0);
-
- const int32_t halfW = bufferWidth / 2;
- const int32_t halfH = bufferHeight / 2;
- TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
- TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH),
- topRight);
- TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight),
- bottomLeft);
- TransactionUtils::fillANativeWindowBufferColor(buffer,
- Rect(halfW, halfH, bufferWidth,
- bufferHeight),
- bottomRight);
-
- postBufferQueueLayerBuffer(layer);
- }
-
- virtual void fillBufferStateLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
- int32_t bufferHeight, const Color& topLeft,
- const Color& topRight, const Color& bottomLeft,
- const Color& bottomRight) {
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
-
- ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0);
-
- const int32_t halfW = bufferWidth / 2;
- const int32_t halfH = bufferHeight / 2;
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH),
- topRight);
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight),
- bottomLeft);
- TransactionUtils::fillGraphicBufferColor(buffer,
- Rect(halfW, halfH, bufferWidth, bufferHeight),
- bottomRight);
-
- Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply();
- }
-
- std::unique_ptr<ScreenCapture> screenshot() {
- std::unique_ptr<ScreenCapture> screenshot;
- ScreenCapture::captureScreen(&screenshot);
- return screenshot;
- }
-
- void asTransaction(const std::function<void(Transaction&)>& exec) {
- Transaction t;
- exec(t);
- t.apply(true);
- }
-
- static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
- static BufferGenerator bufferGenerator;
- return bufferGenerator.get(outBuffer, outFence);
- }
-
- sp<SurfaceComposerClient> mClient;
-
- sp<IBinder> mDisplay;
- uint32_t mDisplayWidth;
- uint32_t mDisplayHeight;
- uint32_t mDisplayLayerStack;
- Rect mDisplayRect = Rect::INVALID_RECT;
-
- // leave room for ~256 layers
- const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256;
-
- sp<SurfaceControl> mBlackBgSurface;
- bool mColorManagementUsed;
-
-private:
- void SetUpDisplay() {
- mDisplay = mClient->getInternalDisplayToken();
- ASSERT_FALSE(mDisplay == nullptr) << "failed to get display";
-
- // get display width/height
- DisplayInfo info;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
- mDisplayWidth = info.w;
- mDisplayHeight = info.h;
- mDisplayRect =
- Rect(static_cast<int32_t>(mDisplayWidth), static_cast<int32_t>(mDisplayHeight));
-
- // After a new buffer is queued, SurfaceFlinger is notified and will
- // latch the new buffer on next vsync. Let's heuristically wait for 3
- // vsyncs.
- mBufferPostDelay = int32_t(1e6 / info.fps) * 3;
-
- mDisplayLayerStack = 0;
-
- mBlackBgSurface =
- createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */,
- PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor);
-
- // set layer stack (b/68888219)
- Transaction t;
- t.setDisplayLayerStack(mDisplay, mDisplayLayerStack);
- t.setCrop_legacy(mBlackBgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight));
- t.setLayerStack(mBlackBgSurface, mDisplayLayerStack);
- t.setColor(mBlackBgSurface, half3{0, 0, 0});
- t.setLayer(mBlackBgSurface, mLayerZBase);
- t.apply();
- }
-
- void waitForLayerBuffers() {
- // Request an empty transaction to get applied synchronously to ensure the buffer is
- // latched.
- Transaction().apply(true);
- usleep(mBufferPostDelay);
- }
-
- int32_t mBufferPostDelay;
-
- friend class LayerRenderPathTestHarness;
-};
-
-class LayerRenderPathTestHarness {
-public:
- LayerRenderPathTestHarness(LayerTransactionTest* delegate, RenderPath renderPath)
- : mDelegate(delegate), mRenderPath(renderPath) {}
-
- std::unique_ptr<ScreenCapture> getScreenCapture() {
- switch (mRenderPath) {
- case RenderPath::SCREENSHOT:
- return mDelegate->screenshot();
- case RenderPath::VIRTUAL_DISPLAY:
-
- const auto mainDisplay = SurfaceComposerClient::getInternalDisplayToken();
- DisplayInfo mainDisplayInfo;
- SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
-
- sp<IBinder> vDisplay;
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- sp<BufferItemConsumer> itemConsumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
-
- consumer->setConsumerName(String8("Virtual disp consumer"));
- consumer->setDefaultBufferSize(mainDisplayInfo.w, mainDisplayInfo.h);
-
- itemConsumer = new BufferItemConsumer(consumer,
- // Sample usage bits from screenrecord
- GRALLOC_USAGE_HW_VIDEO_ENCODER |
- GRALLOC_USAGE_SW_READ_OFTEN);
-
- vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"),
- false /*secure*/);
-
- SurfaceComposerClient::Transaction t;
- t.setDisplaySurface(vDisplay, producer);
- t.setDisplayLayerStack(vDisplay, 0);
- t.setDisplayProjection(vDisplay, mainDisplayInfo.orientation,
- Rect(mainDisplayInfo.viewportW, mainDisplayInfo.viewportH),
- Rect(mainDisplayInfo.w, mainDisplayInfo.h));
- t.apply();
- SurfaceComposerClient::Transaction().apply(true);
- BufferItem item;
- itemConsumer->acquireBuffer(&item, 0, true);
- auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
- itemConsumer->releaseBuffer(item);
- SurfaceComposerClient::destroyDisplay(vDisplay);
- return sc;
- }
- }
-
-protected:
- LayerTransactionTest* mDelegate;
- RenderPath mRenderPath;
-};
-
-class LayerTypeTransactionHarness : public LayerTransactionTest {
-public:
- LayerTypeTransactionHarness(uint32_t layerType) : mLayerType(layerType) {}
-
- sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
- uint32_t flags = 0, SurfaceControl* parent = nullptr) {
- // if the flags already have a layer type specified, return an error
- if (flags & ISurfaceComposerClient::eFXSurfaceMask) {
- return nullptr;
- }
- return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType, parent);
- }
-
- void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth,
- int32_t bufferHeight) {
- ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color,
- bufferWidth, bufferHeight));
- }
-
- void fillLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
- int32_t bufferHeight, const Color& topLeft, const Color& topRight,
- const Color& bottomLeft, const Color& bottomRight) {
- ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer,
- bufferWidth, bufferHeight,
- topLeft, topRight,
- bottomLeft, bottomRight));
- }
-
-protected:
- uint32_t mLayerType;
-};
-
-class LayerTypeTransactionTest : public LayerTypeTransactionHarness,
- public ::testing::WithParamInterface<uint32_t> {
-public:
- LayerTypeTransactionTest() : LayerTypeTransactionHarness(GetParam()) {}
-};
-
-class LayerTypeAndRenderTypeTransactionTest
- : public LayerTypeTransactionHarness,
- public ::testing::WithParamInterface<std::tuple<uint32_t, RenderPath>> {
-public:
- LayerTypeAndRenderTypeTransactionTest()
- : LayerTypeTransactionHarness(std::get<0>(GetParam())),
- mRenderPathHarness(LayerRenderPathTestHarness(this, std::get<1>(GetParam()))) {}
-
- std::unique_ptr<ScreenCapture> getScreenCapture() {
- return mRenderPathHarness.getScreenCapture();
- }
-
-protected:
- LayerRenderPathTestHarness mRenderPathHarness;
-};
-
-::testing::Environment* const binderEnv =
- ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
-
-class LayerRenderTypeTransactionTest : public LayerTransactionTest,
- public ::testing::WithParamInterface<RenderPath> {
-public:
- LayerRenderTypeTransactionTest() : mHarness(LayerRenderPathTestHarness(this, GetParam())) {}
-
- std::unique_ptr<ScreenCapture> getScreenCapture() { return mHarness.getScreenCapture(); }
- void setRelativeZBasicHelper(uint32_t layerType);
- void setRelativeZGroupHelper(uint32_t layerType);
- void setAlphaBasicHelper(uint32_t layerType);
- void setBackgroundColorHelper(uint32_t layerType, bool priorColor, bool bufferFill, float alpha,
- Color finalColor);
-
-protected:
- LayerRenderPathTestHarness mHarness;
-};
-
-INSTANTIATE_TEST_CASE_P(
- LayerTypeAndRenderTypeTransactionTests, LayerTypeAndRenderTypeTransactionTest,
- ::testing::Combine(
- ::testing::Values(
- static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue),
- static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)),
- ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT)));
-
-INSTANTIATE_TEST_CASE_P(LayerRenderTypeTransactionTests, LayerRenderTypeTransactionTest,
- ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT));
-
-INSTANTIATE_TEST_CASE_P(
- LayerTypeTransactionTests, LayerTypeTransactionTest,
- ::testing::Values(static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue),
- static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)));
-
-TEST_P(LayerRenderTypeTransactionTest, SetPositionBasic_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- {
- SCOPED_TRACE("default position");
- const Rect rect(0, 0, 32, 32);
- auto shot = getScreenCapture();
- shot->expectColor(rect, Color::RED);
- shot->expectBorder(rect, Color::BLACK);
- }
-
- Transaction().setPosition(layer, 5, 10).apply();
- {
- SCOPED_TRACE("new position");
- const Rect rect(5, 10, 37, 42);
- auto shot = getScreenCapture();
- shot->expectColor(rect, Color::RED);
- shot->expectBorder(rect, Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetPositionRounding_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // GLES requires only 4 bits of subpixel precision during rasterization
- // XXX GLES composition does not match HWC composition due to precision
- // loss (b/69315223)
- const float epsilon = 1.0f / 16.0f;
- Transaction().setPosition(layer, 0.5f - epsilon, 0.5f - epsilon).apply();
- {
- SCOPED_TRACE("rounding down");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
- }
-
- Transaction().setPosition(layer, 0.5f + epsilon, 0.5f + epsilon).apply();
- {
- SCOPED_TRACE("rounding up");
- getScreenCapture()->expectColor(Rect(1, 1, 33, 33), Color::RED);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetPositionOutOfBounds_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- Transaction().setPosition(layer, -32, -32).apply();
- {
- SCOPED_TRACE("negative coordinates");
- getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
- }
-
- Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply();
- {
- SCOPED_TRACE("positive coordinates");
- getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetPositionPartiallyOutOfBounds_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // partially out of bounds
- Transaction().setPosition(layer, -30, -30).apply();
- {
- SCOPED_TRACE("negative coordinates");
- getScreenCapture()->expectColor(Rect(0, 0, 2, 2), Color::RED);
- }
-
- Transaction().setPosition(layer, mDisplayWidth - 2, mDisplayHeight - 2).apply();
- {
- SCOPED_TRACE("positive coordinates");
- getScreenCapture()->expectColor(Rect(mDisplayWidth - 2, mDisplayHeight - 2, mDisplayWidth,
- mDisplayHeight),
- Color::RED);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetPositionWithResize_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // setPosition is applied immediately by default, with or without resize
- // pending
- Transaction().setPosition(layer, 5, 10).setSize(layer, 64, 64).apply();
- {
- SCOPED_TRACE("resize pending");
- auto shot = getScreenCapture();
- const Rect rect(5, 10, 37, 42);
- shot->expectColor(rect, Color::RED);
- shot->expectBorder(rect, Color::BLACK);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
- {
- SCOPED_TRACE("resize applied");
- getScreenCapture()->expectColor(Rect(5, 10, 69, 74), Color::RED);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- Transaction().setSize(layer, 64, 64).apply();
- {
- SCOPED_TRACE("resize pending");
- auto shot = getScreenCapture();
- const Rect rect(0, 0, 32, 32);
- shot->expectColor(rect, Color::RED);
- shot->expectBorder(rect, Color::BLACK);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
- {
- SCOPED_TRACE("resize applied");
- auto shot = getScreenCapture();
- const Rect rect(0, 0, 64, 64);
- shot->expectColor(rect, Color::RED);
- shot->expectBorder(rect, Color::BLACK);
- }
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetSizeInvalid) {
- // cannot test robustness against invalid sizes (zero or really huge)
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetSizeWithScaleToWindow_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition
- Transaction()
- .setSize(layer, 64, 64)
- .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
- .apply();
- getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED);
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZBasic) {
- sp<SurfaceControl> layerR;
- sp<SurfaceControl> layerG;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
-
- Transaction().setLayer(layerR, mLayerZBase + 1).apply();
- {
- SCOPED_TRACE("layerR");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
- }
-
- Transaction().setLayer(layerG, mLayerZBase + 2).apply();
- {
- SCOPED_TRACE("layerG");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
- }
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZNegative) {
- sp<SurfaceControl> parent =
- LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceContainer);
- Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply();
- sp<SurfaceControl> layerR;
- sp<SurfaceControl> layerG;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
-
- Transaction()
- .reparent(layerR, parent->getHandle())
- .reparent(layerG, parent->getHandle())
- .apply();
- Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply();
- {
- SCOPED_TRACE("layerR");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- }
-
- Transaction().setLayer(layerR, -3).apply();
- {
- SCOPED_TRACE("layerG");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
- }
-}
-
-void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) {
- sp<SurfaceControl> layerR;
- sp<SurfaceControl> layerG;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32));
-
- switch (layerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- Transaction()
- .setPosition(layerG, 16, 16)
- .setRelativeLayer(layerG, layerR->getHandle(), 1)
- .apply();
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- Transaction()
- .setFrame(layerR, Rect(0, 0, 32, 32))
- .setFrame(layerG, Rect(16, 16, 48, 48))
- .setRelativeLayer(layerG, layerR->getHandle(), 1)
- .apply();
- break;
- default:
- ASSERT_FALSE(true) << "Unsupported layer type";
- }
- {
- SCOPED_TRACE("layerG above");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
- shot->expectColor(Rect(16, 16, 48, 48), Color::GREEN);
- }
-
- Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).apply();
- {
- SCOPED_TRACE("layerG below");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectColor(Rect(32, 32, 48, 48), Color::GREEN);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferQueue) {
- ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferState) {
- ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
-}
-
-TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) {
- sp<SurfaceControl> parent =
- LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceContainer);
- Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply();
- sp<SurfaceControl> layerR;
- sp<SurfaceControl> layerG;
- sp<SurfaceControl> layerB;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32));
-
- Transaction()
- .reparent(layerB, parent->getHandle())
- .apply();
-
- // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2
- Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply();
-
- std::unique_ptr<ScreenCapture> screenshot;
- // only layerB is in this range
- sp<IBinder> parentHandle = parent->getHandle();
- ScreenCapture::captureLayers(&screenshot, parentHandle, Rect(0, 0, 32, 32));
- screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
-}
-
-TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) {
- sp<SurfaceControl> parent =
- LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor);
-
- sp<SurfaceControl> childLayer;
- ASSERT_NO_FATAL_FAILURE(
- childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */,
- 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor,
- parent.get()));
- Transaction()
- .setColor(childLayer, half3{1.0f, 0.0f, 0.0f})
- .setColor(parent, half3{0.0f, 0.0f, 0.0f})
- .show(childLayer)
- .show(parent)
- .setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight))
- .setCrop_legacy(childLayer, Rect(0, 0, 20, 30))
- .apply();
-
- Transaction()
- .setRelativeLayer(childLayer, parent->getHandle(), -1)
- .setLayer(childLayer, 1)
- .apply();
-
- {
- SCOPED_TRACE("setLayer above");
- // Set layer should get applied and place the child above.
- std::unique_ptr<ScreenCapture> screenshot;
- ScreenCapture::captureScreen(&screenshot);
- screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED);
- }
-
- Transaction()
- .setLayer(childLayer, 1)
- .setRelativeLayer(childLayer, parent->getHandle(), -1)
- .apply();
-
- {
- SCOPED_TRACE("setRelative below");
- // Set relative layer should get applied and place the child below.
- std::unique_ptr<ScreenCapture> screenshot;
- ScreenCapture::captureScreen(&screenshot);
- screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK);
- }
-}
-
-TEST_P(LayerTypeTransactionTest, HideRelativeParentHidesLayer) {
- sp<SurfaceControl> parent =
- LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor);
- sp<SurfaceControl> relativeParent =
- LayerTransactionTest::createLayer("RelativeParent", 0 /* buffer width */,
- 0 /* buffer height */, ISurfaceComposerClient::eFXSurfaceColor);
-
- sp<SurfaceControl> childLayer;
- ASSERT_NO_FATAL_FAILURE(
- childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */,
- 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor,
- parent.get()));
- Transaction()
- .setColor(childLayer, half3{1.0f, 0.0f, 0.0f})
- .setColor(parent, half3{0.0f, 0.0f, 0.0f})
- .setColor(relativeParent, half3{0.0f, 1.0f, 0.0f})
- .show(childLayer)
- .show(parent)
- .show(relativeParent)
- .setLayer(parent, mLayerZBase - 1)
- .setLayer(relativeParent, mLayerZBase)
- .apply();
-
- Transaction()
- .setRelativeLayer(childLayer, relativeParent->getHandle(), 1)
- .apply();
-
- {
- SCOPED_TRACE("setLayer above");
- // Set layer should get applied and place the child above.
- std::unique_ptr<ScreenCapture> screenshot;
- ScreenCapture::captureScreen(&screenshot);
- screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED);
- }
-
- Transaction()
- .hide(relativeParent)
- .apply();
-
- {
- SCOPED_TRACE("hide relative parent");
- // The relative should no longer be visible.
- std::unique_ptr<ScreenCapture> screenshot;
- ScreenCapture::captureScreen(&screenshot);
- screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK);
- }
-}
-
-void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) {
- sp<SurfaceControl> layerR;
- sp<SurfaceControl> layerG;
- sp<SurfaceControl> layerB;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerB, Color::BLUE, 32, 32));
-
- // layerR = 0, layerG = layerR + 3, layerB = 2
- switch (layerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- Transaction()
- .setPosition(layerG, 8, 8)
- .setRelativeLayer(layerG, layerR->getHandle(), 3)
- .setPosition(layerB, 16, 16)
- .setLayer(layerB, mLayerZBase + 2)
- .apply();
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- Transaction()
- .setFrame(layerR, Rect(0, 0, 32, 32))
- .setFrame(layerG, Rect(8, 8, 40, 40))
- .setRelativeLayer(layerG, layerR->getHandle(), 3)
- .setFrame(layerB, Rect(16, 16, 48, 48))
- .setLayer(layerB, mLayerZBase + 2)
- .apply();
- break;
- default:
- ASSERT_FALSE(true) << "Unsupported layer type";
- }
-
- {
- SCOPED_TRACE("(layerR < layerG) < layerB");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
- shot->expectColor(Rect(8, 8, 16, 16), Color::GREEN);
- shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
- }
-
- // layerR = 4, layerG = layerR + 3, layerB = 2
- Transaction().setLayer(layerR, mLayerZBase + 4).apply();
- {
- SCOPED_TRACE("layerB < (layerR < layerG)");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
- shot->expectColor(Rect(8, 8, 40, 40), Color::GREEN);
- shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
- }
-
- // layerR = 4, layerG = layerR - 3, layerB = 2
- Transaction().setRelativeLayer(layerG, layerR->getHandle(), -3).apply();
- {
- SCOPED_TRACE("layerB < (layerG < layerR)");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectColor(Rect(32, 32, 40, 40), Color::GREEN);
- shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
- }
-
- // restore to absolute z
- // layerR = 4, layerG = 0, layerB = 2
- Transaction().setLayer(layerG, mLayerZBase).apply();
- {
- SCOPED_TRACE("layerG < layerB < layerR");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectColor(Rect(32, 32, 48, 48), Color::BLUE);
- }
-
- // layerR should not affect layerG anymore
- // layerR = 1, layerG = 0, layerB = 2
- Transaction().setLayer(layerR, mLayerZBase + 1).apply();
- {
- SCOPED_TRACE("layerG < layerR < layerB");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
- shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferQueue) {
- ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferState) {
- ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetRelativeZBug64572777) {
- sp<SurfaceControl> layerR;
- sp<SurfaceControl> layerG;
-
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
-
- Transaction()
- .setPosition(layerG, 16, 16)
- .setRelativeLayer(layerG, layerR->getHandle(), 1)
- .apply();
-
- layerG.clear();
- // layerG should have been removed
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsHidden) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
-
- Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply();
- {
- SCOPED_TRACE("layer hidden");
- getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
- }
-
- Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply();
- {
- SCOPED_TRACE("layer shown");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
- }
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsOpaque) {
- const Color translucentRed = {100, 0, 0, 100};
- sp<SurfaceControl> layerR;
- sp<SurfaceControl> layerG;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
-
- Transaction()
- .setLayer(layerR, mLayerZBase + 1)
- .setFlags(layerR, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque)
- .apply();
- {
- SCOPED_TRACE("layerR opaque");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, 0, 0, 255});
- }
-
- Transaction().setFlags(layerR, 0, layer_state_t::eLayerOpaque).apply();
- {
- SCOPED_TRACE("layerR translucent");
- const uint8_t g = uint8_t(255 - translucentRed.a);
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, g, 0, 255});
- }
-}
-
-TEST_P(LayerTypeTransactionTest, SetFlagsSecure) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
-
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
- sp<GraphicBuffer> outBuffer;
- Transaction()
- .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
- .apply(true);
- ASSERT_EQ(PERMISSION_DENIED,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
-
- Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
- ASSERT_EQ(NO_ERROR,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
-}
-
-TEST_F(LayerTransactionTest, SetFlagsSecureEUidSystem) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
- sp<GraphicBuffer> outBuffer;
- Transaction()
- .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
- .apply(true);
- ASSERT_EQ(PERMISSION_DENIED,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
-
- UIDFaker f(AID_SYSTEM);
-
- // By default the system can capture screenshots with secure layers but they
- // will be blacked out
- ASSERT_EQ(NO_ERROR,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
-
- {
- SCOPED_TRACE("as system");
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-
- // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able
- // to receive them...we are expected to take care with the results.
- bool outCapturedSecureLayers;
- ASSERT_EQ(NO_ERROR,
- composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers,
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0,
- 0, false, ISurfaceComposer::eRotateNone, true));
- ASSERT_EQ(true, outCapturedSecureLayers);
- ScreenCapture sc(outBuffer);
- sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferQueue) {
- const Rect top(0, 0, 32, 16);
- const Rect bottom(0, 16, 32, 32);
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-
- ANativeWindow_Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
- ASSERT_NO_FATAL_FAILURE(
- TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT));
- ASSERT_NO_FATAL_FAILURE(
- TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::RED));
- // setTransparentRegionHint always applies to the following buffer
- Transaction().setTransparentRegionHint(layer, Region(top)).apply();
- ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
- {
- SCOPED_TRACE("top transparent");
- auto shot = getScreenCapture();
- shot->expectColor(top, Color::BLACK);
- shot->expectColor(bottom, Color::RED);
- }
-
- Transaction().setTransparentRegionHint(layer, Region(bottom)).apply();
- {
- SCOPED_TRACE("transparent region hint pending");
- auto shot = getScreenCapture();
- shot->expectColor(top, Color::BLACK);
- shot->expectColor(bottom, Color::RED);
- }
-
- ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
- ASSERT_NO_FATAL_FAILURE(
- TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::RED));
- ASSERT_NO_FATAL_FAILURE(
- TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT));
- ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
- {
- SCOPED_TRACE("bottom transparent");
- auto shot = getScreenCapture();
- shot->expectColor(top, Color::RED);
- shot->expectColor(bottom, Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState) {
- const Rect top(0, 0, 32, 16);
- const Rect bottom(0, 16, 32, 32);
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
-
- ASSERT_NO_FATAL_FAILURE(
- TransactionUtils::fillGraphicBufferColor(buffer, top, Color::TRANSPARENT));
- ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::RED));
- Transaction()
- .setTransparentRegionHint(layer, Region(top))
- .setBuffer(layer, buffer)
- .setFrame(layer, Rect(0, 0, 32, 32))
- .apply();
- {
- SCOPED_TRACE("top transparent");
- auto shot = getScreenCapture();
- shot->expectColor(top, Color::BLACK);
- shot->expectColor(bottom, Color::RED);
- }
-
- Transaction().setTransparentRegionHint(layer, Region(bottom)).apply();
- {
- SCOPED_TRACE("transparent region hint intermediate");
- auto shot = getScreenCapture();
- shot->expectColor(top, Color::BLACK);
- shot->expectColor(bottom, Color::BLACK);
- }
-
- buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
-
- ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, top, Color::RED));
- ASSERT_NO_FATAL_FAILURE(
- TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT));
- Transaction().setBuffer(layer, buffer).apply();
- {
- SCOPED_TRACE("bottom transparent");
- auto shot = getScreenCapture();
- shot->expectColor(top, Color::RED);
- shot->expectColor(bottom, Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferQueue) {
- sp<SurfaceControl> layerTransparent;
- sp<SurfaceControl> layerR;
- ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
-
- // check that transparent region hint is bound by the layer size
- Transaction()
- .setTransparentRegionHint(layerTransparent, Region(mDisplayRect))
- .setPosition(layerR, 16, 16)
- .setLayer(layerR, mLayerZBase + 1)
- .apply();
- ASSERT_NO_FATAL_FAILURE(
- fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layerR, Color::RED, 32, 32));
- getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferState) {
- sp<SurfaceControl> layerTransparent;
- sp<SurfaceControl> layerR;
- ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
- ASSERT_NO_FATAL_FAILURE(
- layerR = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- // check that transparent region hint is bound by the layer size
- Transaction()
- .setTransparentRegionHint(layerTransparent, Region(mDisplayRect))
- .setFrame(layerR, Rect(16, 16, 48, 48))
- .setLayer(layerR, mLayerZBase + 1)
- .apply();
- ASSERT_NO_FATAL_FAILURE(
- fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layerR, Color::RED, 32, 32));
- getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED);
-}
-
-void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) {
- sp<SurfaceControl> layer1;
- sp<SurfaceControl> layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer1, {64, 0, 0, 255}, 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer2, {0, 64, 0, 255}, 32, 32));
-
- switch (layerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- Transaction()
- .setAlpha(layer1, 0.25f)
- .setAlpha(layer2, 0.75f)
- .setPosition(layer2, 16, 0)
- .setLayer(layer2, mLayerZBase + 1)
- .apply();
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- Transaction()
- .setAlpha(layer1, 0.25f)
- .setAlpha(layer2, 0.75f)
- .setFrame(layer1, Rect(0, 0, 32, 32))
- .setFrame(layer2, Rect(16, 0, 48, 32))
- .setLayer(layer2, mLayerZBase + 1)
- .apply();
- break;
- default:
- ASSERT_FALSE(true) << "Unsupported layer type";
- }
- {
- auto shot = getScreenCapture();
- uint8_t r = 16; // 64 * 0.25f
- uint8_t g = 48; // 64 * 0.75f
- shot->expectColor(Rect(0, 0, 16, 32), {r, 0, 0, 255});
- shot->expectColor(Rect(32, 0, 48, 32), {0, g, 0, 255});
-
- r /= 4; // r * (1.0f - 0.75f)
- shot->expectColor(Rect(16, 0, 32, 32), {r, g, 0, 255});
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferQueue) {
- ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferState) {
- ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetAlphaClamped) {
- const Color color = {64, 0, 0, 255};
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32));
-
- Transaction().setAlpha(layer, 2.0f).apply();
- {
- SCOPED_TRACE("clamped to 1.0f");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), color);
- }
-
- Transaction().setAlpha(layer, -1.0f).apply();
- {
- SCOPED_TRACE("clamped to 0.0f");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) {
- sp<SurfaceControl> layer;
- const uint8_t size = 64;
- const uint8_t testArea = 4;
- const float cornerRadius = 20.0f;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
-
- Transaction()
- .setCornerRadius(layer, cornerRadius)
- .setCrop_legacy(layer, Rect(0, 0, size, size))
- .apply();
- {
- const uint8_t bottom = size - 1;
- const uint8_t right = size - 1;
- auto shot = getScreenCapture();
- // Transparent corners
- shot->expectColor(Rect(0, 0, testArea, testArea), Color::BLACK);
- shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::BLACK);
- shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
- shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::BLACK);
- }
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) {
- sp<SurfaceControl> parent;
- sp<SurfaceControl> child;
- const uint8_t size = 64;
- const uint8_t testArea = 4;
- const float cornerRadius = 20.0f;
- ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", size, size));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, size, size));
- ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2));
-
- Transaction()
- .setCornerRadius(parent, cornerRadius)
- .setCrop_legacy(parent, Rect(0, 0, size, size))
- .reparent(child, parent->getHandle())
- .setPosition(child, 0, size / 2)
- .apply();
- {
- const uint8_t bottom = size - 1;
- const uint8_t right = size - 1;
- auto shot = getScreenCapture();
- // Top edge of child should not have rounded corners because it's translated in the parent
- shot->expectColor(Rect(0, size / 2, right, static_cast<int>(bottom - cornerRadius)),
- Color::GREEN);
- // But bottom edges should have been clipped according to parent bounds
- shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
- shot->expectColor(Rect(right - testArea, bottom - testArea, right, bottom), Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorBasic) {
- sp<SurfaceControl> bufferLayer;
- sp<SurfaceControl> colorLayer;
- ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(colorLayer =
- createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor));
-
- Transaction()
- .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
- .setLayer(colorLayer, mLayerZBase + 1)
- .apply();
-
- {
- SCOPED_TRACE("default color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-
- const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
- const Color expected = {15, 51, 85, 255};
- // this is handwavy, but the precison loss scaled by 255 (8-bit per
- // channel) should be less than one
- const uint8_t tolerance = 1;
- Transaction().setColor(colorLayer, color).apply();
- {
- SCOPED_TRACE("new color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expected, tolerance);
- }
-}
-
-// RED: Color layer base color and BufferQueueLayer/BufferStateLayer fill
-// BLUE: prior background color
-// GREEN: final background color
-// BLACK: no color or fill
-void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType, bool priorColor,
- bool bufferFill, float alpha,
- Color finalColor) {
- sp<SurfaceControl> layer;
- int32_t width = 500;
- int32_t height = 500;
-
- Color fillColor = Color::RED;
- Color priorBgColor = Color::BLUE;
- Color expectedColor = Color::BLACK;
- switch (layerType) {
- case ISurfaceComposerClient::eFXSurfaceColor:
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 0, 0, layerType));
- Transaction()
- .setCrop_legacy(layer, Rect(0, 0, width, height))
- .setColor(layer, half3(1.0f, 0, 0))
- .apply();
- expectedColor = fillColor;
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height));
- if (bufferFill) {
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, fillColor, width, height));
- expectedColor = fillColor;
- }
- Transaction().setCrop_legacy(layer, Rect(0, 0, width, height)).apply();
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, layerType));
- if (bufferFill) {
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height));
- expectedColor = fillColor;
- }
- Transaction().setFrame(layer, Rect(0, 0, width, height)).apply();
- break;
- default:
- GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper";
- return;
- }
-
- if (priorColor && layerType != ISurfaceComposerClient::eFXSurfaceColor) {
- Transaction()
- .setBackgroundColor(layer, half3(0, 0, 1.0f), 1.0f, ui::Dataspace::UNKNOWN)
- .apply();
- if (!bufferFill) {
- expectedColor = priorBgColor;
- }
- }
-
- {
- SCOPED_TRACE("default before setting background color layer");
- screenshot()->expectColor(Rect(0, 0, width, height), expectedColor);
- }
- Transaction()
- .setBackgroundColor(layer, half3(0, 1.0f, 0), alpha, ui::Dataspace::UNKNOWN)
- .apply();
-
- {
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, width, height), finalColor);
- shot->expectBorder(Rect(0, 0, width, height), Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_Color_NoEffect) {
- bool priorColor = false;
- bool bufferFill = false;
- float alpha = 1.0f;
- Color finalColor = Color::RED;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceColor,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferQueue_BufferFill_NoPriorColor_Basic) {
- bool priorColor = false;
- bool bufferFill = true;
- float alpha = 1.0f;
- Color finalColor = Color::RED;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferQueue_NoBufferFill_NoPriorColor_Basic) {
- bool priorColor = false;
- bool bufferFill = false;
- float alpha = 1.0f;
- Color finalColor = Color::GREEN;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferQueue_BufferFill_PriorColor_Basic) {
- bool priorColor = true;
- bool bufferFill = true;
- float alpha = 1.0f;
- Color finalColor = Color::RED;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferQueue_NoBufferFill_PriorColor_Basic) {
- bool priorColor = true;
- bool bufferFill = false;
- float alpha = 1.0f;
- Color finalColor = Color::GREEN;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
- priorColor, bufferFill, alpha, finalColor));
-}
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferQueue_NoPriorColor_ZeroAlpha_NoEffect) {
- bool priorColor = false;
- bool bufferFill = false;
- float alpha = 0;
- Color finalColor = Color::BLACK;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferQueue_PriorColor_ZeroAlpha_DeleteBackground) {
- bool priorColor = true;
- bool bufferFill = false;
- float alpha = 0;
- Color finalColor = Color::BLACK;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferState_BufferFill_NoPriorColor_Basic) {
- bool priorColor = false;
- bool bufferFill = true;
- float alpha = 1.0f;
- Color finalColor = Color::RED;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferState_NoBufferFill_NoPriorColor_Basic) {
- bool priorColor = false;
- bool bufferFill = false;
- float alpha = 1.0f;
- Color finalColor = Color::GREEN;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferState_NoBufferFill_PriorColor_Basic) {
- bool priorColor = true;
- bool bufferFill = false;
- float alpha = 1.0f;
- Color finalColor = Color::GREEN;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferState_NoPriorColor_ZeroAlpha_NoEffect) {
- bool priorColor = false;
- bool bufferFill = false;
- float alpha = 0;
- Color finalColor = Color::BLACK;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest,
- SetBackgroundColor_BufferState_PriorColor_ZeroAlpha_DeleteBackground) {
- bool priorColor = true;
- bool bufferFill = false;
- float alpha = 0;
- Color finalColor = Color::BLACK;
- ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState,
- priorColor, bufferFill, alpha, finalColor));
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorClamped) {
- sp<SurfaceControl> colorLayer;
- ASSERT_NO_FATAL_FAILURE(colorLayer =
- createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor));
- Transaction()
- .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
- .setColor(colorLayer, half3(2.0f, -1.0f, 0.0f))
- .apply();
-
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorWithAlpha) {
- sp<SurfaceControl> bufferLayer;
- sp<SurfaceControl> colorLayer;
- ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(colorLayer =
- createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor));
- Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply();
-
- const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
- const float alpha = 0.25f;
- const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f);
- // this is handwavy, but the precison loss scaled by 255 (8-bit per
- // channel) should be less than one
- const uint8_t tolerance = 1;
- Transaction()
- .setColor(colorLayer, color)
- .setAlpha(colorLayer, alpha)
- .setLayer(colorLayer, mLayerZBase + 1)
- .apply();
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255},
- tolerance);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorWithParentAlpha_Bug74220420) {
- sp<SurfaceControl> bufferLayer;
- sp<SurfaceControl> parentLayer;
- sp<SurfaceControl> colorLayer;
- ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
- ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer("childWithColor", 0 /* buffer width */,
- 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor));
- Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply();
- const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
- const float alpha = 0.25f;
- const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f);
- // this is handwavy, but the precision loss scaled by 255 (8-bit per
- // channel) should be less than one
- const uint8_t tolerance = 1;
- Transaction()
- .reparent(colorLayer, parentLayer->getHandle())
- .setColor(colorLayer, color)
- .setAlpha(parentLayer, alpha)
- .setLayer(parentLayer, mLayerZBase + 1)
- .apply();
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255},
- tolerance);
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetColorWithBuffer) {
- sp<SurfaceControl> bufferLayer;
- ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32));
-
- // color is ignored
- Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply();
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetLayerStackBasic) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
-
- Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply();
- {
- SCOPED_TRACE("non-existing layer stack");
- getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
- }
-
- Transaction().setLayerStack(layer, mDisplayLayerStack).apply();
- {
- SCOPED_TRACE("original layer stack");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE));
-
- Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply();
- {
- SCOPED_TRACE("IDENTITY");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE);
- }
-
- Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 32, 0).apply();
- {
- SCOPED_TRACE("FLIP_H");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED,
- Color::WHITE, Color::BLUE);
- }
-
- Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).setPosition(layer, 0, 32).apply();
- {
- SCOPED_TRACE("FLIP_V");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE,
- Color::RED, Color::GREEN);
- }
-
- Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).setPosition(layer, 32, 0).apply();
- {
- SCOPED_TRACE("ROT_90");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED,
- Color::WHITE, Color::GREEN);
- }
-
- Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setPosition(layer, 0, 0).apply();
- {
- SCOPED_TRACE("SCALE");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 64), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE, true /* filtered */);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE));
-
- Transaction()
- .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f)
- .setFrame(layer, Rect(0, 0, 32, 32))
- .apply();
- {
- SCOPED_TRACE("IDENTITY");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE);
- }
-
- Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply();
- {
- SCOPED_TRACE("FLIP_H");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE);
- }
-
- Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply();
- {
- SCOPED_TRACE("FLIP_V");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE);
- }
-
- Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply();
- {
- SCOPED_TRACE("ROT_90");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE);
- }
-
- Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply();
- {
- SCOPED_TRACE("SCALE");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetMatrixRot45_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE));
-
- const float rot = M_SQRT1_2; // 45 degrees
- const float trans = M_SQRT2 * 16.0f;
- Transaction().setMatrix(layer, rot, rot, -rot, rot).setPosition(layer, trans, 0).apply();
-
- auto shot = getScreenCapture();
- // check a 8x8 region inside each color
- auto get8x8Rect = [](int32_t centerX, int32_t centerY) {
- const int32_t halfL = 4;
- return Rect(centerX - halfL, centerY - halfL, centerX + halfL, centerY + halfL);
- };
- const int32_t unit = int32_t(trans / 2);
- shot->expectColor(get8x8Rect(2 * unit, 1 * unit), Color::RED);
- shot->expectColor(get8x8Rect(3 * unit, 2 * unit), Color::GREEN);
- shot->expectColor(get8x8Rect(1 * unit, 2 * unit), Color::BLUE);
- shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithResize_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // setMatrix is applied after any pending resize, unlike setPosition
- Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply();
- {
- SCOPED_TRACE("resize pending");
- auto shot = getScreenCapture();
- const Rect rect(0, 0, 32, 32);
- shot->expectColor(rect, Color::RED);
- shot->expectBorder(rect, Color::BLACK);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
- {
- SCOPED_TRACE("resize applied");
- const Rect rect(0, 0, 128, 128);
- getScreenCapture()->expectColor(rect, Color::RED);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithScaleToWindow_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition
- Transaction()
- .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
- .setSize(layer, 64, 64)
- .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
- .apply();
- getScreenCapture()->expectColor(Rect(0, 0, 128, 128), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetOverrideScalingModeBasic_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE));
-
- // XXX SCALE_CROP is not respected; calling setSize and
- // setOverrideScalingMode in separate transactions does not work
- // (b/69315456)
- Transaction()
- .setSize(layer, 64, 16)
- .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
- .apply();
- {
- SCOPED_TRACE("SCALE_TO_WINDOW");
- getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 16), Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE, true /* filtered */);
- }
-}
-
-TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-
- sp<IBinder> handle = layer->getHandle();
- ASSERT_TRUE(handle != nullptr);
-
- FrameStats frameStats;
- mClient->getLayerFrameStats(handle, &frameStats);
-
- ASSERT_GT(frameStats.refreshPeriodNano, static_cast<nsecs_t>(0));
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
- const Rect crop(8, 8, 24, 24);
-
- Transaction().setCrop_legacy(layer, crop).apply();
- auto shot = getScreenCapture();
- shot->expectColor(crop, Color::RED);
- shot->expectBorder(crop, Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
- const Rect crop(8, 8, 24, 24);
-
- Transaction().setCrop(layer, crop).apply();
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- {
- SCOPED_TRACE("empty rect");
- Transaction().setCrop_legacy(layer, Rect(8, 8, 8, 8)).apply();
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
- }
-
- {
- SCOPED_TRACE("negative rect");
- Transaction().setCrop_legacy(layer, Rect(8, 8, 0, 0)).apply();
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- {
- SCOPED_TRACE("empty rect");
- Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply();
- getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- }
-
- {
- SCOPED_TRACE("negative rect");
- Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply();
- getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply();
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 64, ISurfaceComposerClient::eFXSurfaceBufferState));
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 64, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE);
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED);
-
- Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply();
-
- Transaction().setBuffer(layer, buffer).apply();
-
- // Partially out of bounds in the negative (upper left) direction
- Transaction().setCrop(layer, Rect(-128, -128, 32, 16)).apply();
- {
- SCOPED_TRACE("out of bounds, negative (upper left) direction");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE);
- shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
- }
-
- // Partially out of bounds in the positive (lower right) direction
- Transaction().setCrop(layer, Rect(0, 16, 128, 128)).apply();
- {
- SCOPED_TRACE("out of bounds, positive (lower right) direction");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
- shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
- }
-
- // Fully out of buffer space bounds
- Transaction().setCrop(layer, Rect(-128, -128, -1, -1)).apply();
- {
- SCOPED_TRACE("Fully out of bounds");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE);
- shot->expectColor(Rect(0, 16, 64, 64), Color::RED);
- shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- const Point position(32, 32);
- const Rect crop(8, 8, 24, 24);
- Transaction().setPosition(layer, position.x, position.y).setCrop_legacy(layer, crop).apply();
- auto shot = getScreenCapture();
- shot->expectColor(crop + position, Color::RED);
- shot->expectBorder(crop + position, Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- const Rect frame(32, 32, 64, 64);
- const Rect crop(8, 8, 24, 24);
- Transaction().setFrame(layer, frame).setCrop(layer, crop).apply();
- auto shot = getScreenCapture();
- shot->expectColor(frame, Color::RED);
- shot->expectBorder(frame, Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // crop_legacy is affected by matrix
- Transaction()
- .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
- .setCrop_legacy(layer, Rect(8, 8, 24, 24))
- .apply();
- auto shot = getScreenCapture();
- shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
- shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropWithResize_BufferQueue) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
- // setCrop_legacy is applied immediately by default, with or without resize pending
- Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
- {
- SCOPED_TRACE("resize pending");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
- shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
- {
- SCOPED_TRACE("resize applied");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
- shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
- const Rect frame(8, 8, 24, 24);
-
- Transaction().setFrame(layer, frame).apply();
- auto shot = getScreenCapture();
- shot->expectColor(frame, Color::RED);
- shot->expectBorder(frame, Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- {
- SCOPED_TRACE("empty rect");
- Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply();
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-
- {
- SCOPED_TRACE("negative rect");
- Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply();
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10));
-
- // A parentless layer will default to a frame with the same size as the buffer
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) {
- sp<SurfaceControl> parent, child;
- ASSERT_NO_FATAL_FAILURE(
- parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
- Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
-
- ASSERT_NO_FATAL_FAILURE(
- child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
-
- Transaction().reparent(child, parent->getHandle()).apply();
-
- // A layer will default to the frame of its parent
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) {
- sp<SurfaceControl> parent, child;
- ASSERT_NO_FATAL_FAILURE(parent = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32));
-
- ASSERT_NO_FATAL_FAILURE(
- child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
-
- Transaction().reparent(child, parent->getHandle()).apply();
-
- // A layer will default to the frame of its parent
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
- Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
- std::this_thread::sleep_for(500ms);
-
- Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply();
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
- shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) {
- sp<SurfaceControl> parent, child;
- ASSERT_NO_FATAL_FAILURE(
- parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(
- child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- Transaction().reparent(child, parent->getHandle()).apply();
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
- Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
- Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply();
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 16), Color::RED);
- shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- {
- SCOPED_TRACE("set buffer 1");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
-
- {
- SCOPED_TRACE("set buffer 2");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- {
- SCOPED_TRACE("set buffer 3");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) {
- sp<SurfaceControl> layer1;
- ASSERT_NO_FATAL_FAILURE(
- layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<SurfaceControl> layer2;
- ASSERT_NO_FATAL_FAILURE(
- layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64));
-
- Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply();
- {
- SCOPED_TRACE("set layer 1 buffer red");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32));
-
- Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply();
- {
- SCOPED_TRACE("set layer 2 buffer blue");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
- shot->expectColor(Rect(0, 32, 64, 64), Color::RED);
- shot->expectColor(Rect(0, 32, 32, 64), Color::RED);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64));
- {
- SCOPED_TRACE("set layer 1 buffer green");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
- shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN);
- shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32));
-
- {
- SCOPED_TRACE("set layer 2 buffer white");
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE);
- shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN);
- shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
-
- std::array<sp<GraphicBuffer>, 10> buffers;
-
- size_t idx = 0;
- for (auto& buffer : buffers) {
- buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- Color color = colors[idx % colors.size()];
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
- idx++;
- }
-
- // Set each buffer twice. The first time adds it to the cache, the second time tests that the
- // cache is working.
- idx = 0;
- for (auto& buffer : buffers) {
- for (int i = 0; i < 2; i++) {
- Transaction().setBuffer(layer, buffer).apply();
-
- Color color = colors[idx % colors.size()];
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
- }
- idx++;
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
-
- std::array<sp<GraphicBuffer>, 70> buffers;
-
- size_t idx = 0;
- for (auto& buffer : buffers) {
- buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- Color color = colors[idx % colors.size()];
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
- idx++;
- }
-
- // Set each buffer twice. The first time adds it to the cache, the second time tests that the
- // cache is working.
- idx = 0;
- for (auto& buffer : buffers) {
- for (int i = 0; i < 2; i++) {
- Transaction().setBuffer(layer, buffer).apply();
-
- Color color = colors[idx % colors.size()];
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
- }
- idx++;
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN};
-
- std::array<sp<GraphicBuffer>, 65> buffers;
-
- size_t idx = 0;
- for (auto& buffer : buffers) {
- buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- Color color = colors[idx % colors.size()];
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
- idx++;
- }
-
- // Set each buffer twice. The first time adds it to the cache, the second time tests that the
- // cache is working.
- idx = 0;
- for (auto& buffer : buffers) {
- for (int i = 0; i < 2; i++) {
- Transaction().setBuffer(layer, buffer).apply();
-
- Color color = colors[idx % colors.size()];
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
- }
- if (idx == 0) {
- buffers[0].clear();
- }
- idx++;
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE));
-
- Transaction()
- .setFrame(layer, Rect(0, 0, 32, 32))
- .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90)
- .apply();
-
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE,
- Color::GREEN, true /* filtered */);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE));
-
- Transaction()
- .setFrame(layer, Rect(0, 0, 32, 32))
- .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H)
- .apply();
-
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE,
- Color::BLUE, true /* filtered */);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
- Color::BLUE, Color::WHITE));
-
- Transaction()
- .setFrame(layer, Rect(0, 0, 32, 32))
- .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V)
- .apply();
-
- getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED,
- Color::GREEN, true /* filtered */);
-}
-
-TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- Transaction().setTransformToDisplayInverse(layer, false).apply();
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32));
-
- Transaction().setTransformToDisplayInverse(layer, true).apply();
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFenceBasic_BufferState) {
- sp<SurfaceControl> layer;
- Transaction transaction;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
- sp<Fence> fence;
- if (getBuffer(nullptr, &fence) != NO_ERROR) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
-
- status_t status = fence->wait(1000);
- ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status);
- std::this_thread::sleep_for(200ms);
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
- sp<Fence> fence = Fence::NO_FENCE;
-
- Transaction()
- .setBuffer(layer, buffer)
- .setAcquireFence(layer, fence)
- .apply();
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
- Transaction()
- .setBuffer(layer, buffer)
- .setDataspace(layer, ui::Dataspace::UNKNOWN)
- .apply();
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
- HdrMetadata hdrMetadata;
- hdrMetadata.validTypes = 0;
- Transaction()
- .setBuffer(layer, buffer)
- .setHdrMetadata(layer, hdrMetadata)
- .apply();
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
- Region region;
- region.set(32, 32);
- Transaction()
- .setBuffer(layer, buffer)
- .setSurfaceDamageRegion(layer, region)
- .apply();
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY,
- "test");
- TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
- Transaction()
- .setBuffer(layer, buffer)
- .setApi(layer, NATIVE_WINDOW_API_CPU)
- .apply();
-
- auto shot = getScreenCapture();
- shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
- shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
-}
-
-TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
- // verify this doesn't cause a crash
- Transaction().setSidebandStream(layer, nullptr).apply();
-}
-
-TEST_F(LayerTransactionTest, ReparentToSelf) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
- Transaction().reparent(layer, layer->getHandle()).apply();
-
- {
- // We expect the transaction to be silently dropped, but for SurfaceFlinger
- // to still be functioning.
- SCOPED_TRACE("after reparent to self");
- const Rect rect(0, 0, 32, 32);
- auto shot = screenshot();
- shot->expectColor(rect, Color::RED);
- shot->expectBorder(rect, Color::BLACK);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) {
- sp<SurfaceControl> colorLayer;
- ASSERT_NO_FATAL_FAILURE(colorLayer =
- createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor));
- Transaction()
- .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
- .setLayer(colorLayer, mLayerZBase + 1)
- .apply();
- {
- SCOPED_TRACE("default color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-
- const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
- half3 expected = color;
- mat3 matrix;
- matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11;
- matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11;
- matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11;
-
- // degamma before applying the matrix
- if (mColorManagementUsed) {
- ColorTransformHelper::DegammaColor(expected);
- }
-
- ColorTransformHelper::applyMatrix(expected, matrix);
-
- if (mColorManagementUsed) {
- ColorTransformHelper::GammaColor(expected);
- }
-
- const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255),
- uint8_t(expected.b * 255), 255};
-
- // this is handwavy, but the precison loss scaled by 255 (8-bit per
- // channel) should be less than one
- const uint8_t tolerance = 1;
-
- Transaction().setColor(colorLayer, color)
- .setColorTransform(colorLayer, matrix, vec3()).apply();
- {
- SCOPED_TRACE("new color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnParent) {
- sp<SurfaceControl> parentLayer;
- sp<SurfaceControl> colorLayer;
- ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */,
- 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceContainer));
- ASSERT_NO_FATAL_FAILURE(
- colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get()));
-
- Transaction()
- .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100))
- .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
- .setLayer(parentLayer, mLayerZBase + 1)
- .apply();
- {
- SCOPED_TRACE("default color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-
- const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
- half3 expected = color;
- mat3 matrix;
- matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11;
- matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11;
- matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11;
-
- // degamma before applying the matrix
- if (mColorManagementUsed) {
- ColorTransformHelper::DegammaColor(expected);
- }
-
- ColorTransformHelper::applyMatrix(expected, matrix);
-
- if (mColorManagementUsed) {
- ColorTransformHelper::GammaColor(expected);
- }
-
- const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255),
- uint8_t(expected.b * 255), 255};
-
- // this is handwavy, but the precison loss scaled by 255 (8-bit per
- // channel) should be less than one
- const uint8_t tolerance = 1;
-
- Transaction()
- .setColor(colorLayer, color)
- .setColorTransform(parentLayer, matrix, vec3())
- .apply();
- {
- SCOPED_TRACE("new color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
- }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnChildAndParent) {
- sp<SurfaceControl> parentLayer;
- sp<SurfaceControl> colorLayer;
- ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */,
- 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceContainer));
- ASSERT_NO_FATAL_FAILURE(
- colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */,
- ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get()));
-
- Transaction()
- .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100))
- .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32))
- .setLayer(parentLayer, mLayerZBase + 1)
- .apply();
- {
- SCOPED_TRACE("default color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
- }
-
- const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
- half3 expected = color;
- mat3 matrixChild;
- matrixChild[0][0] = 0.3; matrixChild[1][0] = 0.59; matrixChild[2][0] = 0.11;
- matrixChild[0][1] = 0.3; matrixChild[1][1] = 0.59; matrixChild[2][1] = 0.11;
- matrixChild[0][2] = 0.3; matrixChild[1][2] = 0.59; matrixChild[2][2] = 0.11;
- mat3 matrixParent;
- matrixParent[0][0] = 0.2; matrixParent[1][0] = 0.4; matrixParent[2][0] = 0.10;
- matrixParent[0][1] = 0.2; matrixParent[1][1] = 0.4; matrixParent[2][1] = 0.10;
- matrixParent[0][2] = 0.2; matrixParent[1][2] = 0.4; matrixParent[2][2] = 0.10;
-
- // degamma before applying the matrix
- if (mColorManagementUsed) {
- ColorTransformHelper::DegammaColor(expected);
- }
-
- ColorTransformHelper::applyMatrix(expected, matrixChild);
- ColorTransformHelper::applyMatrix(expected, matrixParent);
-
- if (mColorManagementUsed) {
- ColorTransformHelper::GammaColor(expected);
- }
-
- const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255),
- uint8_t(expected.b * 255), 255};
-
- // this is handwavy, but the precison loss scaled by 255 (8-bit per
- // channel) should be less than one
- const uint8_t tolerance = 1;
-
- Transaction()
- .setColor(colorLayer, color)
- .setColorTransform(parentLayer, matrixParent, vec3())
- .setColorTransform(colorLayer, matrixChild, vec3())
- .apply();
- {
- SCOPED_TRACE("new color");
- getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
- }
-}
-
-class LayerCallbackTest : public LayerTransactionTest {
-public:
- virtual sp<SurfaceControl> createBufferStateLayer() {
- return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
- }
-
- static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
- const sp<SurfaceControl>& layer = nullptr, bool setBuffer = true,
- bool setBackgroundColor = false) {
- if (layer) {
- sp<GraphicBuffer> buffer;
- sp<Fence> fence;
- if (setBuffer) {
- int err = getBuffer(&buffer, &fence);
- if (err != NO_ERROR) {
- return err;
- }
-
- transaction.setBuffer(layer, buffer);
- transaction.setAcquireFence(layer, fence);
- }
-
- if (setBackgroundColor) {
- transaction.setBackgroundColor(layer, /*color*/ half3(1.0f, 0, 0), /*alpha*/ 1.0f,
- ui::Dataspace::UNKNOWN);
- }
- }
-
- transaction.addTransactionCompletedCallback(callbackHelper->function,
- callbackHelper->getContext());
- return NO_ERROR;
- }
-
- static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
- bool finalState = false) {
- CallbackData callbackData;
- ASSERT_NO_FATAL_FAILURE(helper.getCallbackData(&callbackData));
- EXPECT_NO_FATAL_FAILURE(expectedResult.verifyCallbackData(callbackData));
-
- if (finalState) {
- ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
- }
- }
-
- static void waitForCallbacks(CallbackHelper& helper,
- const std::vector<ExpectedResult>& expectedResults,
- bool finalState = false) {
- for (const auto& expectedResult : expectedResults) {
- waitForCallback(helper, expectedResult);
- }
- if (finalState) {
- ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
- }
- }
-};
-
-TEST_F(LayerCallbackTest, BufferColor) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer, true, true);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, NoBufferNoColor) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer, false, false);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
- ExpectedResult::Buffer::NOT_ACQUIRED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, BufferNoColor) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer, true, false);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, NoBufferColor) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer, false, true);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
- ExpectedResult::Buffer::NOT_ACQUIRED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, NoStateChange) {
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.apply();
-
- ExpectedResult expected;
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, OffScreen) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, MergeBufferNoColor) {
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- int err = fillTransaction(transaction1, &callback1, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
-TEST_F(LayerCallbackTest, MergeNoBufferColor) {
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- int err = fillTransaction(transaction1, &callback1, layer1, false, true);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2, false, true);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
- ExpectedResult::Buffer::NOT_ACQUIRED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
-TEST_F(LayerCallbackTest, MergeOneBufferOneColor) {
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- int err = fillTransaction(transaction1, &callback1, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2, false, true);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1);
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer2,
- ExpectedResult::Buffer::NOT_ACQUIRED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-TEST_F(LayerCallbackTest, Merge_SameCallback) {
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
- Transaction transaction1, transaction2;
- CallbackHelper callback;
- int err = fillTransaction(transaction1, &callback, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback, layer2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction2.merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, Merge_SameLayer) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- int err = fillTransaction(transaction1, &callback1, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction2.merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
-TEST_F(LayerCallbackTest, Merge_DifferentClients) {
- sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
- client2(new SurfaceComposerClient);
-
- ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
- ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
-
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- int err = fillTransaction(transaction1, &callback1, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- for (size_t i = 0; i < 10; i++) {
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
- ExpectedResult::Buffer::ACQUIRED,
- (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
- : ExpectedResult::PreviousBuffer::RELEASED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
- }
- ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_NoStateChange) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- for (size_t i = 0; i < 10; i++) {
- ExpectedResult expected;
-
- if (i == 0) {
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- } else {
- int err = fillTransaction(transaction, &callback);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- }
-
- transaction.apply();
-
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
- }
- ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- for (size_t i = 0; i < 10; i++) {
- if (i == 0) {
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- } else {
- int err = fillTransaction(transaction, &callback);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- }
-
- transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
- ExpectedResult expected;
- expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED
- : ExpectedResult::Transaction::NOT_PRESENTED,
- layer,
- (i == 0) ? ExpectedResult::Buffer::ACQUIRED
- : ExpectedResult::Buffer::NOT_ACQUIRED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0));
- }
- ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_Merge) {
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- for (size_t i = 0; i < 10; i++) {
- int err = fillTransaction(transaction1, &callback1, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
- ExpectedResult::Buffer::ACQUIRED,
- (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
- : ExpectedResult::PreviousBuffer::RELEASED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected));
- }
- ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState());
- ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState());
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) {
- sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
- client2(new SurfaceComposerClient);
- ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
- ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
-
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- for (size_t i = 0; i < 10; i++) {
- int err = fillTransaction(transaction1, &callback1, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
- ExpectedResult::Buffer::ACQUIRED,
- (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
- : ExpectedResult::PreviousBuffer::RELEASED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected));
- }
- ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState());
- ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState());
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateChange) {
- sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
- client2(new SurfaceComposerClient);
- ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
- ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
-
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
-
- // Normal call to set up test
- int err = fillTransaction(transaction1, &callback1, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
- expected.reset();
-
- // Test
- err = fillTransaction(transaction1, &callback1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction2.merge(std::move(transaction1)).apply();
-
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateChange) {
- sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
- client2(new SurfaceComposerClient);
-
- ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient";
- ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
-
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
- ISurfaceComposerClient::eFXSurfaceBufferState));
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
-
- // Normal call to set up test
- int err = fillTransaction(transaction1, &callback1, layer1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2, layer2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
- expected.reset();
-
- // Test
- err = fillTransaction(transaction1, &callback1);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
- err = fillTransaction(transaction2, &callback2);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2,
- ExpectedResult::Buffer::NOT_ACQUIRED);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- std::vector<ExpectedResult> expectedResults(50);
- for (auto& expected : expectedResults) {
- expected.reset();
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
- ExpectedResult::Buffer::ACQUIRED,
- ExpectedResult::PreviousBuffer::UNKNOWN);
-
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.apply();
- }
- EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_NoStateChange) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- // Normal call to set up test
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-
- // Test
- std::vector<ExpectedResult> expectedResults(50);
- for (auto& expected : expectedResults) {
- expected.reset();
-
- err = fillTransaction(transaction, &callback);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.apply();
- }
- EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
-}
-
-TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- // Normal call to set up test
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
- ExpectedResult expectedResult;
- expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expectedResult, true));
-
- // Test
- std::vector<ExpectedResult> expectedResults(50);
- for (auto& expected : expectedResults) {
- expected.reset();
- expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
- ExpectedResult::Buffer::NOT_ACQUIRED);
-
- err = fillTransaction(transaction, &callback);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
- }
- EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
-}
-
-TEST_F(LayerCallbackTest, DesiredPresentTime) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- // Try to present 100ms in the future
- nsecs_t time = systemTime() + (100 * 1e6);
-
- transaction.setDesiredPresentTime(time);
- transaction.apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- expected.addExpectedPresentTime(time);
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback1;
- int err = fillTransaction(transaction, &callback1, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- // Try to present 100ms in the future
- nsecs_t time = systemTime() + (100 * 1e6);
-
- transaction.setDesiredPresentTime(time);
- transaction.apply();
-
- ExpectedResult expected1;
- expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- expected1.addExpectedPresentTime(time);
-
- CallbackHelper callback2;
- err = fillTransaction(transaction, &callback2, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- // Try to present 33ms after the first frame
- time += (33.3 * 1e6);
-
- transaction.setDesiredPresentTime(time);
- transaction.apply();
-
- ExpectedResult expected2;
- expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
- ExpectedResult::Buffer::ACQUIRED,
- ExpectedResult::PreviousBuffer::RELEASED);
- expected2.addExpectedPresentTime(time);
-
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true));
-}
-
-TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback1;
- int err = fillTransaction(transaction, &callback1, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- // Try to present 100ms in the future
- nsecs_t time = systemTime() + (100 * 1e6);
-
- transaction.setDesiredPresentTime(time);
- transaction.apply();
-
- ExpectedResult expected1;
- expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- expected1.addExpectedPresentTime(time);
-
- CallbackHelper callback2;
- err = fillTransaction(transaction, &callback2, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- // Try to present 33ms before the previous frame
- time -= (33.3 * 1e6);
-
- transaction.setDesiredPresentTime(time);
- transaction.apply();
-
- ExpectedResult expected2;
- expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
- ExpectedResult::Buffer::ACQUIRED,
- ExpectedResult::PreviousBuffer::RELEASED);
-
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true));
-}
-
-TEST_F(LayerCallbackTest, DesiredPresentTime_Past) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
-
- Transaction transaction;
- CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer);
- if (err) {
- GTEST_SUCCEED() << "test not supported";
- return;
- }
-
- // Try to present 100ms in the past
- nsecs_t time = systemTime() - (100 * 1e6);
-
- transaction.setDesiredPresentTime(time);
- transaction.apply();
-
- ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- expected.addExpectedPresentTime(systemTime());
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
-}
-
-class LayerUpdateTest : public LayerTransactionTest {
-protected:
- virtual void SetUp() {
- LayerTransactionTest::SetUp();
- ASSERT_EQ(NO_ERROR, mClient->initCheck());
-
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- ASSERT_FALSE(display == nullptr);
-
- DisplayInfo info;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
-
- ssize_t displayWidth = info.w;
- ssize_t displayHeight = info.h;
-
- // Background surface
- mBGSurfaceControl = createLayer(String8("BG Test Surface"), displayWidth,
- displayHeight, 0);
- ASSERT_TRUE(mBGSurfaceControl != nullptr);
- ASSERT_TRUE(mBGSurfaceControl->isValid());
- TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
-
- // Foreground surface
- mFGSurfaceControl = createLayer(String8("FG Test Surface"), 64, 64, 0);
-
- ASSERT_TRUE(mFGSurfaceControl != nullptr);
- ASSERT_TRUE(mFGSurfaceControl->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
-
- // Synchronization surface
- mSyncSurfaceControl = createLayer(String8("Sync Test Surface"), 1, 1, 0);
- ASSERT_TRUE(mSyncSurfaceControl != nullptr);
- ASSERT_TRUE(mSyncSurfaceControl->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
-
- asTransaction([&](Transaction& t) {
- t.setDisplayLayerStack(display, 0);
-
- t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl);
-
- t.setLayer(mFGSurfaceControl, INT32_MAX - 1)
- .setPosition(mFGSurfaceControl, 64, 64)
- .show(mFGSurfaceControl);
-
- t.setLayer(mSyncSurfaceControl, INT32_MAX - 1)
- .setPosition(mSyncSurfaceControl, displayWidth - 2, displayHeight - 2)
- .show(mSyncSurfaceControl);
- });
- }
-
- virtual void TearDown() {
- LayerTransactionTest::TearDown();
- mBGSurfaceControl = 0;
- mFGSurfaceControl = 0;
- mSyncSurfaceControl = 0;
- }
-
- void waitForPostedBuffers() {
- // Since the sync surface is in synchronous mode (i.e. double buffered)
- // posting three buffers to it should ensure that at least two
- // SurfaceFlinger::handlePageFlip calls have been made, which should
- // guaranteed that a buffer posted to another Surface has been retired.
- TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
- TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
- TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
- }
-
-
- sp<SurfaceControl> mBGSurfaceControl;
- sp<SurfaceControl> mFGSurfaceControl;
-
- // This surface is used to ensure that the buffers posted to
- // mFGSurfaceControl have been picked up by SurfaceFlinger.
- sp<SurfaceControl> mSyncSurfaceControl;
-};
-
-TEST_F(LayerUpdateTest, RelativesAreNotDetached) {
-
- std::unique_ptr<ScreenCapture> sc;
-
- sp<SurfaceControl> relative = createLayer(String8("relativeTestSurface"), 10, 10, 0);
- TransactionUtils::fillSurfaceRGBA8(relative, 10, 10, 10);
- waitForPostedBuffers();
-
- Transaction{}
- .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1)
- .setPosition(relative, 64, 64)
- .apply();
-
- {
- // The relative should be on top of the FG control.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(64, 64, 10, 10, 10);
- }
- Transaction{}.detachChildren(mFGSurfaceControl).apply();
-
- {
- // Nothing should change at this point.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(64, 64, 10, 10, 10);
- }
-
- Transaction{}.hide(relative).apply();
-
- {
- // Ensure that the relative was actually hidden, rather than
- // being left in the detached but visible state.
- ScreenCapture::captureScreen(&sc);
- sc->expectFGColor(64, 64);
- }
-}
-
-class GeometryLatchingTest : public LayerUpdateTest {
-protected:
- void EXPECT_INITIAL_STATE(const char* trace) {
- SCOPED_TRACE(trace);
- ScreenCapture::captureScreen(&sc);
- // We find the leading edge of the FG surface.
- sc->expectFGColor(127, 127);
- sc->expectBGColor(128, 128);
- }
-
- void lockAndFillFGBuffer() {
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
- }
-
- void unlockFGBuffer() {
- sp<Surface> s = mFGSurfaceControl->getSurface();
- ASSERT_EQ(NO_ERROR, s->unlockAndPost());
- waitForPostedBuffers();
- }
-
- void completeFGResize() {
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
- waitForPostedBuffers();
- }
- void restoreInitialState() {
- asTransaction([&](Transaction& t) {
- t.setSize(mFGSurfaceControl, 64, 64);
- t.setPosition(mFGSurfaceControl, 64, 64);
- t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64));
- });
-
- EXPECT_INITIAL_STATE("After restoring initial state");
- }
- std::unique_ptr<ScreenCapture> sc;
-};
-
-class CropLatchingTest : public GeometryLatchingTest {
-protected:
- void EXPECT_CROPPED_STATE(const char* trace) {
- SCOPED_TRACE(trace);
- ScreenCapture::captureScreen(&sc);
- // The edge should be moved back one pixel by our crop.
- sc->expectFGColor(126, 126);
- sc->expectBGColor(127, 127);
- sc->expectBGColor(128, 128);
- }
-
- void EXPECT_RESIZE_STATE(const char* trace) {
- SCOPED_TRACE(trace);
- ScreenCapture::captureScreen(&sc);
- // The FG is now resized too 128,128 at 64,64
- sc->expectFGColor(64, 64);
- sc->expectFGColor(191, 191);
- sc->expectBGColor(192, 192);
- }
-};
-
-TEST_F(LayerUpdateTest, DeferredTransactionTest) {
- std::unique_ptr<ScreenCapture> sc;
- {
- SCOPED_TRACE("before anything");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(32, 32);
- sc->expectFGColor(96, 96);
- sc->expectBGColor(160, 160);
- }
-
- // set up two deferred transactions on different frames
- asTransaction([&](Transaction& t) {
- t.setAlpha(mFGSurfaceControl, 0.75);
- t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
- mSyncSurfaceControl->getSurface()->getNextFrameNumber());
- });
-
- asTransaction([&](Transaction& t) {
- t.setPosition(mFGSurfaceControl, 128, 128);
- t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
- mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
- });
-
- {
- SCOPED_TRACE("before any trigger");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(32, 32);
- sc->expectFGColor(96, 96);
- sc->expectBGColor(160, 160);
- }
-
- // should trigger the first deferred transaction, but not the second one
- TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
- {
- SCOPED_TRACE("after first trigger");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(32, 32);
- sc->checkPixel(96, 96, 162, 63, 96);
- sc->expectBGColor(160, 160);
- }
-
- // should show up immediately since it's not deferred
- asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); });
-
- // trigger the second deferred transaction
- TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
- {
- SCOPED_TRACE("after second trigger");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(32, 32);
- sc->expectBGColor(96, 96);
- sc->expectFGColor(160, 160);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) {
- std::unique_ptr<ScreenCapture> sc;
-
- sp<SurfaceControl> childNoBuffer =
- createSurface(mClient, "Bufferless child", 0 /* buffer width */, 0 /* buffer height */,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- sp<SurfaceControl> childBuffer = createSurface(mClient, "Buffered child", 20, 20,
- PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
- TransactionUtils::fillSurfaceRGBA8(childBuffer, 200, 200, 200);
- SurfaceComposerClient::Transaction{}
- .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10))
- .show(childNoBuffer)
- .show(childBuffer)
- .apply(true);
- {
- ScreenCapture::captureScreen(&sc);
- sc->expectChildColor(73, 73);
- sc->expectFGColor(74, 74);
- }
- SurfaceComposerClient::Transaction{}
- .setCrop_legacy(childNoBuffer, Rect(0, 0, 20, 20))
- .apply(true);
- {
- ScreenCapture::captureScreen(&sc);
- sc->expectChildColor(73, 73);
- sc->expectChildColor(74, 74);
- }
-}
-
-TEST_F(LayerUpdateTest, MergingTransactions) {
- std::unique_ptr<ScreenCapture> sc;
- {
- SCOPED_TRACE("before move");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(0, 12);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- Transaction t1, t2;
- t1.setPosition(mFGSurfaceControl, 128, 128);
- t2.setPosition(mFGSurfaceControl, 0, 0);
- // We expect that the position update from t2 now
- // overwrites the position update from t1.
- t1.merge(std::move(t2));
- t1.apply();
-
- {
- ScreenCapture::captureScreen(&sc);
- sc->expectFGColor(1, 1);
- }
-}
-
-TEST_F(LayerUpdateTest, MergingTransactionFlags) {
- Transaction().hide(mFGSurfaceControl).apply();
- std::unique_ptr<ScreenCapture> sc;
- {
- SCOPED_TRACE("before merge");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(0, 12);
- sc->expectBGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- Transaction t1, t2;
- t1.show(mFGSurfaceControl);
- t2.setFlags(mFGSurfaceControl, 0 /* flags */, layer_state_t::eLayerSecure /* mask */);
- t1.merge(std::move(t2));
- t1.apply();
-
- {
- SCOPED_TRACE("after merge");
- ScreenCapture::captureScreen(&sc);
- sc->expectFGColor(75, 75);
- }
-}
-
-class ChildLayerTest : public LayerUpdateTest {
-protected:
- void SetUp() override {
- LayerUpdateTest::SetUp();
- mChild = createSurface(mClient, "Child surface", 10, 15, PIXEL_FORMAT_RGBA_8888, 0,
- mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
-
- {
- SCOPED_TRACE("before anything");
- mCapture = screenshot();
- mCapture->expectChildColor(64, 64);
- }
- }
- void TearDown() override {
- LayerUpdateTest::TearDown();
- mChild = 0;
- }
-
- sp<SurfaceControl> mChild;
- std::unique_ptr<ScreenCapture> mCapture;
-};
-
-TEST_F(ChildLayerTest, ChildLayerPositioning) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); });
-
- {
- mCapture = screenshot();
- // Top left of foreground should now be at 0, 0
- mCapture->expectFGColor(0, 0);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(10, 10);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(20, 20);
- }
-}
-
-TEST_F(ChildLayerTest, ChildLayerCropping) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 0, 0);
- t.setPosition(mFGSurfaceControl, 0, 0);
- t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5));
- });
-
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(4, 4);
- mCapture->expectBGColor(5, 5);
- }
-}
-
-TEST_F(ChildLayerTest, ChildLayerConstraints) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mFGSurfaceControl, 0, 0);
- t.setPosition(mChild, 63, 63);
- });
-
- {
- mCapture = screenshot();
- mCapture->expectFGColor(0, 0);
- // Last pixel in foreground should now be the child.
- mCapture->expectChildColor(63, 63);
- // But the child should be constrained and the next pixel
- // must be the background
- mCapture->expectBGColor(64, 64);
- }
-}
-
-TEST_F(ChildLayerTest, ChildLayerScaling) {
- asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); });
-
- // Find the boundary between the parent and child
- {
- mCapture = screenshot();
- mCapture->expectChildColor(9, 9);
- mCapture->expectFGColor(10, 10);
- }
-
- asTransaction([&](Transaction& t) { t.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0); });
-
- // The boundary should be twice as far from the origin now.
- // The pixels from the last test should all be child now
- {
- mCapture = screenshot();
- mCapture->expectChildColor(9, 9);
- mCapture->expectChildColor(10, 10);
- mCapture->expectChildColor(19, 19);
- mCapture->expectFGColor(20, 20);
- }
-}
-
-// A child with a scale transform should be cropped by its parent bounds.
-TEST_F(ChildLayerTest, ChildLayerScalingCroppedByParent) {
- asTransaction([&](Transaction& t) {
- t.setPosition(mFGSurfaceControl, 0, 0);
- t.setPosition(mChild, 0, 0);
- });
-
- // Find the boundary between the parent and child.
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(9, 9);
- mCapture->expectFGColor(10, 10);
- }
-
- asTransaction([&](Transaction& t) { t.setMatrix(mChild, 10.0, 0, 0, 10.0); });
-
- // The child should fill its parent bounds and be cropped by it.
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(63, 63);
- mCapture->expectBGColor(64, 64);
- }
-}
-
-TEST_F(ChildLayerTest, ChildLayerAlpha) {
- TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254);
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0);
- TransactionUtils::fillSurfaceRGBA8(mChild, 0, 254, 0);
- waitForPostedBuffers();
-
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 0, 0);
- t.setPosition(mFGSurfaceControl, 0, 0);
- });
-
- {
- mCapture = screenshot();
- // Unblended child color
- mCapture->checkPixel(0, 0, 0, 254, 0);
- }
-
- asTransaction([&](Transaction& t) { t.setAlpha(mChild, 0.5); });
-
- {
- mCapture = screenshot();
- // Child and BG blended.
- mCapture->checkPixel(0, 0, 127, 127, 0);
- }
-
- asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.5); });
-
- {
- mCapture = screenshot();
- // Child and BG blended.
- mCapture->checkPixel(0, 0, 95, 64, 95);
- }
-}
-
-TEST_F(ChildLayerTest, ReparentChildren) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- asTransaction([&](Transaction& t) {
- t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle());
- });
-
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- // In reparenting we should have exposed the entire foreground surface.
- mCapture->expectFGColor(74, 74);
- // And the child layer should now begin at 10, 10 (since the BG
- // layer is at (0, 0)).
- mCapture->expectBGColor(9, 9);
- mCapture->expectChildColor(10, 10);
- }
-}
-
-TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
- sp<SurfaceControl> mGrandChild =
- createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
- TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
-
- {
- SCOPED_TRACE("Grandchild visible");
- ScreenCapture::captureScreen(&mCapture);
- mCapture->checkPixel(64, 64, 111, 111, 111);
- }
-
- mChild.clear();
-
- {
- SCOPED_TRACE("After destroying child");
- ScreenCapture::captureScreen(&mCapture);
- mCapture->expectFGColor(64, 64);
- }
-
- asTransaction([&](Transaction& t) {
- t.reparent(mGrandChild, mFGSurfaceControl->getHandle());
- });
-
- {
- SCOPED_TRACE("After reparenting grandchild");
- ScreenCapture::captureScreen(&mCapture);
- mCapture->checkPixel(64, 64, 111, 111, 111);
- }
-}
-
-TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) {
- sp<SurfaceControl> mGrandChild =
- createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
- TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
-
- // draw grand child behind the foreground surface
- asTransaction([&](Transaction& t) {
- t.setRelativeLayer(mGrandChild, mFGSurfaceControl->getHandle(), -1);
- });
-
- {
- SCOPED_TRACE("Child visible");
- ScreenCapture::captureScreen(&mCapture);
- mCapture->checkPixel(64, 64, 200, 200, 200);
- }
-
- asTransaction([&](Transaction& t) {
- t.reparent(mChild, nullptr);
- t.reparentChildren(mChild, mFGSurfaceControl->getHandle());
- });
-
- {
- SCOPED_TRACE("foreground visible reparenting grandchild");
- ScreenCapture::captureScreen(&mCapture);
- mCapture->checkPixel(64, 64, 195, 63, 63);
- }
-}
-
-TEST_F(ChildLayerTest, DetachChildrenSameClient) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
-
- asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
-
- asTransaction([&](Transaction& t) { t.hide(mChild); });
-
- // Since the child has the same client as the parent, it will not get
- // detached and will be hidden.
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- mCapture->expectFGColor(74, 74);
- mCapture->expectFGColor(84, 84);
- }
-}
-
-TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
- sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> mChildNewClient =
- createSurface(mNewComposerClient, "New Child Test Surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- ASSERT_TRUE(mChildNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
-
- asTransaction([&](Transaction& t) {
- t.hide(mChild);
- t.show(mChildNewClient);
- t.setPosition(mChildNewClient, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
-
- asTransaction([&](Transaction& t) { t.hide(mChildNewClient); });
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- mCapture->expectChildColor(74, 74);
- mCapture->expectFGColor(84, 84);
- }
-}
-
-TEST_F(ChildLayerTest, DetachChildrenThenAttach) {
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- ASSERT_TRUE(childNewClient != nullptr);
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
-
- Transaction()
- .hide(mChild)
- .show(childNewClient)
- .setPosition(childNewClient, 10, 10)
- .setPosition(mFGSurfaceControl, 64, 64)
- .apply();
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- Transaction().detachChildren(mFGSurfaceControl).apply();
- Transaction().hide(childNewClient).apply();
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- mCapture->expectChildColor(74, 74);
- mCapture->expectFGColor(84, 84);
- }
-
- sp<SurfaceControl> newParentSurface = createLayer(String8("New Parent Surface"), 32, 32, 0);
- fillLayerColor(ISurfaceComposerClient::eFXSurfaceBufferQueue, newParentSurface, Color::RED, 32,
- 32);
- Transaction()
- .setLayer(newParentSurface, INT32_MAX - 1)
- .show(newParentSurface)
- .setPosition(newParentSurface, 20, 20)
- .reparent(childNewClient, newParentSurface->getHandle())
- .apply();
- {
- mCapture = screenshot();
- // Child is now hidden.
- mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
- }
-}
-TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) {
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- ASSERT_TRUE(childNewClient != nullptr);
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
-
- Transaction()
- .hide(mChild)
- .show(childNewClient)
- .setPosition(childNewClient, 10, 10)
- .setPosition(mFGSurfaceControl, 64, 64)
- .apply();
-
- {
- mCapture = screenshot();
- Rect rect = Rect(74, 74, 84, 84);
- mCapture->expectBorder(rect, Color{195, 63, 63, 255});
- mCapture->expectColor(rect, Color{200, 200, 200, 255});
- }
-
- Transaction()
- .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(),
- mFGSurfaceControl->getSurface()->getNextFrameNumber())
- .apply();
- Transaction().detachChildren(mFGSurfaceControl).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- Rect rect = Rect(74, 74, 84, 84);
- mCapture->expectBorder(rect, Color::RED);
- mCapture->expectColor(rect, Color{200, 200, 200, 255});
- }
-}
-
-TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 0, 0);
- t.setPosition(mFGSurfaceControl, 0, 0);
- });
-
- {
- mCapture = screenshot();
- // We've positioned the child in the top left.
- mCapture->expectChildColor(0, 0);
- // But it's only 10x15.
- mCapture->expectFGColor(10, 15);
- }
-
- asTransaction([&](Transaction& t) {
- t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- // We cause scaling by 2.
- t.setSize(mFGSurfaceControl, 128, 128);
- });
-
- {
- mCapture = screenshot();
- // We've positioned the child in the top left.
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(10, 10);
- mCapture->expectChildColor(19, 29);
- // And now it should be scaled all the way to 20x30
- mCapture->expectFGColor(20, 30);
- }
-}
-
-// Regression test for b/37673612
-TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 0, 0);
- t.setPosition(mFGSurfaceControl, 0, 0);
- });
-
- {
- mCapture = screenshot();
- // We've positioned the child in the top left.
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(9, 14);
- // But it's only 10x15.
- mCapture->expectFGColor(10, 15);
- }
- // We set things up as in b/37673612 so that there is a mismatch between the buffer size and
- // the WM specified state size.
- asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); });
- sp<Surface> s = mFGSurfaceControl->getSurface();
- auto anw = static_cast<ANativeWindow*>(s.get());
- native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
- native_window_set_buffers_dimensions(anw, 64, 128);
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
- waitForPostedBuffers();
-
- {
- // The child should still be in the same place and not have any strange scaling as in
- // b/37673612.
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectFGColor(10, 10);
- }
-}
-
-// A child with a buffer transform from its parents should be cropped by its parent bounds.
-TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferTransform) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 0, 0);
- t.setPosition(mFGSurfaceControl, 0, 0);
- t.setSize(mChild, 100, 100);
- });
- TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
-
- {
- mCapture = screenshot();
-
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(63, 63);
- mCapture->expectBGColor(64, 64);
- }
-
- asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); });
- sp<Surface> s = mFGSurfaceControl->getSurface();
- auto anw = static_cast<ANativeWindow*>(s.get());
- // Apply a 90 transform on the buffer.
- native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
- native_window_set_buffers_dimensions(anw, 64, 128);
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
- waitForPostedBuffers();
-
- // The child should be cropped by the new parent bounds.
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(99, 63);
- mCapture->expectFGColor(100, 63);
- mCapture->expectBGColor(128, 64);
- }
-}
-
-// A child with a scale transform from its parents should be cropped by its parent bounds.
-TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferScale) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 0, 0);
- t.setPosition(mFGSurfaceControl, 0, 0);
- t.setSize(mChild, 200, 200);
- });
- TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
-
- {
- mCapture = screenshot();
-
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(63, 63);
- mCapture->expectBGColor(64, 64);
- }
-
- asTransaction([&](Transaction& t) {
- t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- // Set a scaling by 2.
- t.setSize(mFGSurfaceControl, 128, 128);
- });
-
- // Child should inherit its parents scale but should be cropped by its parent bounds.
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(127, 127);
- mCapture->expectBGColor(128, 128);
- }
-}
-
-// Regression test for b/127368943
-// Child should ignore the buffer transform but apply parent scale transform.
-TEST_F(ChildLayerTest, ChildrenWithParentBufferTransformAndScale) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 0, 0);
- t.setPosition(mFGSurfaceControl, 0, 0);
- });
-
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(9, 14);
- mCapture->expectFGColor(10, 15);
- }
-
- // Change the size of the foreground to 128 * 64 so we can test rotation as well.
- asTransaction([&](Transaction& t) {
- t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- t.setSize(mFGSurfaceControl, 128, 64);
- });
- sp<Surface> s = mFGSurfaceControl->getSurface();
- auto anw = static_cast<ANativeWindow*>(s.get());
- // Apply a 90 transform on the buffer and submit a buffer half the expected size so that we
- // have an effective scale of 2.0 applied to the buffer along with a rotation transform.
- native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
- native_window_set_buffers_dimensions(anw, 32, 64);
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
- waitForPostedBuffers();
-
- // The child should ignore the buffer transform but apply the 2.0 scale from parent.
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(19, 29);
- mCapture->expectFGColor(20, 30);
- }
-}
-
-TEST_F(ChildLayerTest, Bug36858924) {
- // Destroy the child layer
- mChild.clear();
-
- // Now recreate it as hidden
- mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eHidden, mFGSurfaceControl.get());
-
- // Show the child layer in a deferred transaction
- asTransaction([&](Transaction& t) {
- t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(),
- mFGSurfaceControl->getSurface()->getNextFrameNumber());
- t.show(mChild);
- });
-
- // Render the foreground surface a few times
- //
- // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the third
- // frame because SurfaceFlinger would never process the deferred transaction and would therefore
- // never acquire/release the first buffer
- ALOGI("Filling 1");
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
- ALOGI("Filling 2");
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255);
- ALOGI("Filling 3");
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0);
- ALOGI("Filling 4");
- TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
-}
-
-TEST_F(ChildLayerTest, Reparent) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl->getHandle()); });
-
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- // In reparenting we should have exposed the entire foreground surface.
- mCapture->expectFGColor(74, 74);
- // And the child layer should now begin at 10, 10 (since the BG
- // layer is at (0, 0)).
- mCapture->expectBGColor(9, 9);
- mCapture->expectChildColor(10, 10);
- }
-}
-
-TEST_F(ChildLayerTest, ReparentToNoParent) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
- asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); });
- {
- mCapture = screenshot();
- // The surface should now be offscreen.
- mCapture->expectFGColor(64, 64);
- mCapture->expectFGColor(74, 74);
- mCapture->expectFGColor(84, 84);
- }
-}
-
-TEST_F(ChildLayerTest, ReparentFromNoParent) {
- sp<SurfaceControl> newSurface = createLayer(String8("New Surface"), 10, 10, 0);
- ASSERT_TRUE(newSurface != nullptr);
- ASSERT_TRUE(newSurface->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(newSurface, 63, 195, 63);
- asTransaction([&](Transaction& t) {
- t.hide(mChild);
- t.show(newSurface);
- t.setPosition(newSurface, 10, 10);
- t.setLayer(newSurface, INT32_MAX - 2);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // At 10, 10 we should see the new surface
- mCapture->checkPixel(10, 10, 63, 195, 63);
- }
-
- asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl->getHandle()); });
-
- {
- mCapture = screenshot();
- // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from
- // mFGSurface, putting it at 74, 74.
- mCapture->expectFGColor(64, 64);
- mCapture->checkPixel(74, 74, 63, 195, 63);
- mCapture->expectFGColor(84, 84);
- }
-}
-
-TEST_F(ChildLayerTest, NestedChildren) {
- sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
- TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
-
- {
- mCapture = screenshot();
- // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer
- // which begins at 64, 64
- mCapture->checkPixel(64, 64, 50, 50, 50);
- }
-}
-
-TEST_F(ChildLayerTest, ChildLayerRelativeLayer) {
- sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 128, 128, 0);
- TransactionUtils::fillSurfaceRGBA8(relative, 255, 255, 255);
-
- Transaction t;
- t.setLayer(relative, INT32_MAX)
- .setRelativeLayer(mChild, relative->getHandle(), 1)
- .setPosition(mFGSurfaceControl, 0, 0)
- .apply(true);
-
- // We expect that the child should have been elevated above our
- // INT_MAX layer even though it's not a child of it.
- {
- mCapture = screenshot();
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(9, 9);
- mCapture->checkPixel(10, 10, 255, 255, 255);
- }
-}
-
-class BoundlessLayerTest : public LayerUpdateTest {
-protected:
- std::unique_ptr<ScreenCapture> mCapture;
-};
-
-// Verify setting a size on a buffer layer has no effect.
-TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) {
- sp<SurfaceControl> bufferLayer =
- createSurface(mClient, "BufferLayer", 45, 45, PIXEL_FORMAT_RGBA_8888, 0,
- mFGSurfaceControl.get());
- ASSERT_TRUE(bufferLayer->isValid());
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30));
- asTransaction([&](Transaction& t) { t.show(bufferLayer); });
- {
- mCapture = screenshot();
- // Top left of background must now be visible
- mCapture->expectBGColor(0, 0);
- // Foreground Surface bounds must be color layer
- mCapture->expectColor(Rect(64, 64, 94, 94), Color::BLACK);
- // Buffer layer should not extend past buffer bounds
- mCapture->expectFGColor(95, 95);
- }
-}
-
-// Verify a boundless color layer will fill its parent bounds. The parent has a buffer size
-// which will crop the color layer.
-TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) {
- sp<SurfaceControl> colorLayer =
- createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get());
- ASSERT_TRUE(colorLayer->isValid());
- asTransaction([&](Transaction& t) {
- t.setColor(colorLayer, half3{0, 0, 0});
- t.show(colorLayer);
- });
- {
- mCapture = screenshot();
- // Top left of background must now be visible
- mCapture->expectBGColor(0, 0);
- // Foreground Surface bounds must be color layer
- mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
- // Color layer should not extend past foreground bounds
- mCapture->expectBGColor(129, 129);
- }
-}
-
-// Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has
-// a crop which will be used to crop the color layer.
-TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) {
- sp<SurfaceControl> cropLayer = createSurface(mClient, "CropLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
- 0 /* flags */, mFGSurfaceControl.get());
- ASSERT_TRUE(cropLayer->isValid());
- sp<SurfaceControl> colorLayer =
- createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get());
- ASSERT_TRUE(colorLayer->isValid());
- asTransaction([&](Transaction& t) {
- t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10));
- t.setColor(colorLayer, half3{0, 0, 0});
- t.show(cropLayer);
- t.show(colorLayer);
- });
- {
- mCapture = screenshot();
- // Top left of background must now be visible
- mCapture->expectBGColor(0, 0);
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // 5 pixels from the foreground we should see the child surface
- mCapture->expectColor(Rect(69, 69, 74, 74), Color::BLACK);
- // 10 pixels from the foreground we should be back to the foreground surface
- mCapture->expectFGColor(74, 74);
- }
-}
-
-// Verify for boundless layer with no children, their transforms have no effect.
-TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) {
- sp<SurfaceControl> colorLayer =
- createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get());
- ASSERT_TRUE(colorLayer->isValid());
- asTransaction([&](Transaction& t) {
- t.setPosition(colorLayer, 320, 320);
- t.setMatrix(colorLayer, 2, 0, 0, 2);
- t.setColor(colorLayer, half3{0, 0, 0});
- t.show(colorLayer);
- });
- {
- mCapture = screenshot();
- // Top left of background must now be visible
- mCapture->expectBGColor(0, 0);
- // Foreground Surface bounds must be color layer
- mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
- // Color layer should not extend past foreground bounds
- mCapture->expectBGColor(129, 129);
- }
-}
-
-// Verify for boundless layer with children, their transforms have an effect.
-TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) {
- sp<SurfaceControl> boundlessLayerRightShift =
- createSurface(mClient, "BoundlessLayerRightShift", 0, 0, PIXEL_FORMAT_RGBA_8888,
- 0 /* flags */, mFGSurfaceControl.get());
- ASSERT_TRUE(boundlessLayerRightShift->isValid());
- sp<SurfaceControl> boundlessLayerDownShift =
- createSurface(mClient, "BoundlessLayerLeftShift", 0, 0, PIXEL_FORMAT_RGBA_8888,
- 0 /* flags */, boundlessLayerRightShift.get());
- ASSERT_TRUE(boundlessLayerDownShift->isValid());
- sp<SurfaceControl> colorLayer =
- createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceColor, boundlessLayerDownShift.get());
- ASSERT_TRUE(colorLayer->isValid());
- asTransaction([&](Transaction& t) {
- t.setPosition(boundlessLayerRightShift, 32, 0);
- t.show(boundlessLayerRightShift);
- t.setPosition(boundlessLayerDownShift, 0, 32);
- t.show(boundlessLayerDownShift);
- t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
- t.setColor(colorLayer, half3{0, 0, 0});
- t.show(colorLayer);
- });
- {
- mCapture = screenshot();
- // Top left of background must now be visible
- mCapture->expectBGColor(0, 0);
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // Foreground Surface bounds must be color layer
- mCapture->expectColor(Rect(96, 96, 128, 128), Color::BLACK);
- // Color layer should not extend past foreground bounds
- mCapture->expectBGColor(129, 129);
- }
-}
-
-// Verify child layers do not get clipped if they temporarily move into the negative
-// coordinate space as the result of an intermediate transformation.
-TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) {
- sp<SurfaceControl> boundlessLayer =
- mClient->createSurface(String8("BoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
- 0 /* flags */, mFGSurfaceControl.get());
- ASSERT_TRUE(boundlessLayer != nullptr);
- ASSERT_TRUE(boundlessLayer->isValid());
- sp<SurfaceControl> colorLayer =
- mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceColor, boundlessLayer.get());
- ASSERT_TRUE(colorLayer != nullptr);
- ASSERT_TRUE(colorLayer->isValid());
- asTransaction([&](Transaction& t) {
- // shift child layer off bounds. If this layer was not boundless, we will
- // expect the child layer to be cropped.
- t.setPosition(boundlessLayer, 32, 32);
- t.show(boundlessLayer);
- t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
- // undo shift by parent
- t.setPosition(colorLayer, -32, -32);
- t.setColor(colorLayer, half3{0, 0, 0});
- t.show(colorLayer);
- });
- {
- mCapture = screenshot();
- // Top left of background must now be visible
- mCapture->expectBGColor(0, 0);
- // Foreground Surface bounds must be color layer
- mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
- // Color layer should not extend past foreground bounds
- mCapture->expectBGColor(129, 129);
- }
-}
-
-// Verify for boundless root layers with children, their transforms have an effect.
-TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) {
- sp<SurfaceControl> rootBoundlessLayer = createSurface(mClient, "RootBoundlessLayer", 0, 0,
- PIXEL_FORMAT_RGBA_8888, 0 /* flags */);
- ASSERT_TRUE(rootBoundlessLayer->isValid());
- sp<SurfaceControl> colorLayer =
- createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceColor, rootBoundlessLayer.get());
-
- ASSERT_TRUE(colorLayer->isValid());
- asTransaction([&](Transaction& t) {
- t.setLayer(rootBoundlessLayer, INT32_MAX - 1);
- t.setPosition(rootBoundlessLayer, 32, 32);
- t.show(rootBoundlessLayer);
- t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
- t.setColor(colorLayer, half3{0, 0, 0});
- t.show(colorLayer);
- t.hide(mFGSurfaceControl);
- });
- {
- mCapture = screenshot();
- // Top left of background must now be visible
- mCapture->expectBGColor(0, 0);
- // Top left of foreground must now be visible
- mCapture->expectBGColor(31, 31);
- // Foreground Surface bounds must be color layer
- mCapture->expectColor(Rect(32, 32, 96, 96), Color::BLACK);
- // Color layer should not extend past foreground bounds
- mCapture->expectBGColor(97, 97);
- }
-}
-
-class ScreenCaptureTest : public LayerUpdateTest {
-protected:
- std::unique_ptr<ScreenCapture> mCapture;
-};
-
-TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
- auto bgHandle = mBGSurfaceControl->getHandle();
- ScreenCapture::captureLayers(&mCapture, bgHandle);
- mCapture->expectBGColor(0, 0);
- // Doesn't capture FG layer which is at 64, 64
- mCapture->expectBGColor(64, 64);
-}
-
-TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- // Captures mFGSurfaceControl layer and its child.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- mCapture->expectChildColor(0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- // Captures mFGSurfaceControl's child
- ScreenCapture::captureChildLayers(&mCapture, fgHandle);
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->expectChildColor(0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureLayerExclude) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- .show(child2)
- .setLayer(child, 1)
- .setLayer(child2, 2)
- .apply(true);
-
- // Child2 would be visible but its excluded, so we should see child1 color instead.
- ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->checkPixel(0, 0, 200, 200, 200);
-}
-
-// Like the last test but verifies that children are also exclude.
-TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
- sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, child2.get());
- TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- .show(child2)
- .show(child3)
- .setLayer(child, 1)
- .setLayer(child2, 2)
- .apply(true);
-
- // Child2 would be visible but its excluded, so we should see child1 color instead.
- ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->checkPixel(0, 0, 200, 200, 200);
-}
-
-TEST_F(ScreenCaptureTest, CaptureTransparent) {
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- auto childHandle = child->getHandle();
-
- // Captures child
- ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20});
- mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
- // Area outside of child's bounds is transparent.
- mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0});
-}
-
-TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- ASSERT_NE(nullptr, child.get()) << "failed to create surface";
- sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0);
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- // Set relative layer above fg layer so should be shown above when computing all layers.
- .setRelativeLayer(relative, fgHandle, 1)
- .show(relative)
- .apply(true);
-
- // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- mCapture->expectChildColor(0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- // Set relative layer below fg layer but relative to child layer so it should be shown
- // above child layer.
- .setLayer(relative, -1)
- .setRelativeLayer(relative, child->getHandle(), 1)
- .show(relative)
- .apply(true);
-
- // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its
- // relative value should be taken into account, placing it above child layer.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- // Relative layer is showing on top of child layer
- mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255});
-}
-
-// In the following tests we verify successful skipping of a parent layer,
-// so we use the same verification logic and only change how we mutate
-// the parent layer to verify that various properties are ignored.
-class ScreenCaptureChildOnlyTest : public LayerUpdateTest {
-public:
- void SetUp() override {
- LayerUpdateTest::SetUp();
-
- mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
- mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(mChild).apply(true);
- }
-
- void verify(std::function<void()> verifyStartingState) {
- // Verify starting state before a screenshot is taken.
- verifyStartingState();
-
- // Verify child layer does not inherit any of the properties of its
- // parent when its screenshot is captured.
- auto fgHandle = mFGSurfaceControl->getHandle();
- ScreenCapture::captureChildLayers(&mCapture, fgHandle);
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->expectChildColor(0, 0);
-
- // Verify all assumptions are still true after the screenshot is taken.
- verifyStartingState();
- }
-
- std::unique_ptr<ScreenCapture> mCapture;
- sp<SurfaceControl> mChild;
-};
-
-// Regression test b/76099859
-TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) {
-
- SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true);
-
- // Even though the parent is hidden we should still capture the child.
-
- // Before and after reparenting, verify child is properly hidden
- // when rendering full-screen.
- verify([&] { screenshot()->expectBGColor(64, 64); });
-}
-
-TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) {
- SurfaceComposerClient::Transaction()
- .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1))
- .apply(true);
-
- // Even though the parent is cropped out we should still capture the child.
-
- // Before and after reparenting, verify child is cropped by parent.
- verify([&] { screenshot()->expectBGColor(65, 65); });
-}
-
-// Regression test b/124372894
-TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) {
- SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2).apply(true);
-
- // We should not inherit the parent scaling.
-
- // Before and after reparenting, verify child is properly scaled.
- verify([&] { screenshot()->expectChildColor(80, 80); });
-}
-
-
-TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
- PIXEL_FORMAT_RGBA_8888, 0, child.get());
-
- TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
- SurfaceComposerClient::Transaction()
- .show(child)
- .setPosition(grandchild, 5, 5)
- .show(grandchild)
- .apply(true);
-
- // Captures mFGSurfaceControl, its child, and the grandchild.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- mCapture->expectChildColor(0, 0);
- mCapture->checkPixel(5, 5, 50, 50, 50);
-}
-
-TEST_F(ScreenCaptureTest, CaptureChildOnly) {
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- auto childHandle = child->getHandle();
-
- SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
-
- // Captures only the child layer, and not the parent.
- ScreenCapture::captureLayers(&mCapture, childHandle);
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(9, 9);
-}
-
-TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- auto childHandle = child->getHandle();
-
- sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
- PIXEL_FORMAT_RGBA_8888, 0, child.get());
- TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- .setPosition(grandchild, 5, 5)
- .show(grandchild)
- .apply(true);
-
- auto grandchildHandle = grandchild->getHandle();
-
- // Captures only the grandchild.
- ScreenCapture::captureLayers(&mCapture, grandchildHandle);
- mCapture->checkPixel(0, 0, 50, 50, 50);
- mCapture->checkPixel(4, 4, 50, 50, 50);
-}
-
-TEST_F(ScreenCaptureTest, CaptureCrop) {
- sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
- sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
- PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
-
- SurfaceComposerClient::Transaction()
- .setLayer(redLayer, INT32_MAX - 1)
- .show(redLayer)
- .show(blueLayer)
- .apply(true);
-
- auto redLayerHandle = redLayer->getHandle();
-
- // Capturing full screen should have both red and blue are visible.
- ScreenCapture::captureLayers(&mCapture, redLayerHandle);
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
-
- const Rect crop = Rect(0, 0, 30, 30);
- ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
- // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
- // area visible.
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- mCapture->checkPixel(30, 30, 0, 0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureSize) {
- sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
- sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
- PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
-
- SurfaceComposerClient::Transaction()
- .setLayer(redLayer, INT32_MAX - 1)
- .show(redLayer)
- .show(blueLayer)
- .apply(true);
-
- auto redLayerHandle = redLayer->getHandle();
-
- // Capturing full screen should have both red and blue are visible.
- ScreenCapture::captureLayers(&mCapture, redLayerHandle);
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
-
- ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
- // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
- mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED);
- mCapture->checkPixel(30, 30, 0, 0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
- sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
-
- auto redLayerHandle = redLayer->getHandle();
- redLayer.clear();
- SurfaceComposerClient::Transaction().apply(true);
-
- sp<GraphicBuffer> outBuffer;
-
- // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0));
-}
-
-
-class DereferenceSurfaceControlTest : public LayerTransactionTest {
-protected:
- void SetUp() override {
- LayerTransactionTest::SetUp();
- bgLayer = createLayer("BG layer", 20, 20);
- fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20);
- fgLayer = createLayer("FG layer", 20, 20);
- fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20);
- Transaction().setLayer(fgLayer, mLayerZBase + 1).apply();
- {
- SCOPED_TRACE("before anything");
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE);
- }
- }
- void TearDown() override {
- LayerTransactionTest::TearDown();
- bgLayer = 0;
- fgLayer = 0;
- }
-
- sp<SurfaceControl> bgLayer;
- sp<SurfaceControl> fgLayer;
-};
-
-TEST_F(DereferenceSurfaceControlTest, LayerNotInTransaction) {
- fgLayer = nullptr;
- {
- SCOPED_TRACE("after setting null");
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 20, 20), Color::RED);
- }
-}
-
-TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) {
- auto transaction = Transaction().show(fgLayer);
- fgLayer = nullptr;
- {
- SCOPED_TRACE("after setting null");
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE);
- }
-}
-
-class MultiDisplayLayerBoundsTest : public LayerTransactionTest {
-protected:
- virtual void SetUp() {
- LayerTransactionTest::SetUp();
- ASSERT_EQ(NO_ERROR, mClient->initCheck());
-
- mMainDisplay = SurfaceComposerClient::getInternalDisplayToken();
- SurfaceComposerClient::getDisplayInfo(mMainDisplay, &mMainDisplayInfo);
-
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&mProducer, &consumer);
- consumer->setConsumerName(String8("Virtual disp consumer"));
- consumer->setDefaultBufferSize(mMainDisplayInfo.w, mMainDisplayInfo.h);
- }
-
- virtual void TearDown() {
- SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
- LayerTransactionTest::TearDown();
- mColorLayer = 0;
- }
-
- void createDisplay(const Rect& layerStackRect, uint32_t layerStack) {
- mVirtualDisplay =
- SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/);
- asTransaction([&](Transaction& t) {
- t.setDisplaySurface(mVirtualDisplay, mProducer);
- t.setDisplayLayerStack(mVirtualDisplay, layerStack);
- t.setDisplayProjection(mVirtualDisplay, mMainDisplayInfo.orientation, layerStackRect,
- Rect(mMainDisplayInfo.w, mMainDisplayInfo.h));
- });
- }
-
- void createColorLayer(uint32_t layerStack) {
- mColorLayer =
- createSurface(mClient, "ColorLayer", 0 /* buffer width */, 0 /* buffer height */,
- PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor);
- ASSERT_TRUE(mColorLayer != nullptr);
- ASSERT_TRUE(mColorLayer->isValid());
- asTransaction([&](Transaction& t) {
- t.setLayerStack(mColorLayer, layerStack);
- t.setCrop_legacy(mColorLayer, Rect(0, 0, 30, 40));
- t.setLayer(mColorLayer, INT32_MAX - 2);
- t.setColor(mColorLayer,
- half3{mExpectedColor.r / 255.0f, mExpectedColor.g / 255.0f,
- mExpectedColor.b / 255.0f});
- t.show(mColorLayer);
- });
- }
-
- DisplayInfo mMainDisplayInfo;
- sp<IBinder> mMainDisplay;
- sp<IBinder> mVirtualDisplay;
- sp<IGraphicBufferProducer> mProducer;
- sp<SurfaceControl> mColorLayer;
- Color mExpectedColor = {63, 63, 195, 255};
-};
-
-TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInVirtualDisplay) {
- createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 1 /* layerStack */);
- createColorLayer(1 /* layerStack */);
-
- asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); });
-
- // Verify color layer does not render on main display.
- std::unique_ptr<ScreenCapture> sc;
- ScreenCapture::captureScreen(&sc, mMainDisplay);
- sc->expectColor(Rect(10, 10, 40, 50), {0, 0, 0, 255});
- sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
-
- // Verify color layer renders correctly on virtual display.
- ScreenCapture::captureScreen(&sc, mVirtualDisplay);
- sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
- sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 0});
-}
-
-TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) {
- // Create a display and set its layer stack to the main display's layer stack so
- // the contents of the main display are mirrored on to the virtual display.
-
- // Assumption here is that the new mirrored display has the same viewport as the
- // primary display that it is mirroring.
- createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 0 /* layerStack */);
- createColorLayer(0 /* layerStack */);
-
- asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); });
-
- // Verify color layer renders correctly on main display and it is mirrored on the
- // virtual display.
- std::unique_ptr<ScreenCapture> sc;
- ScreenCapture::captureScreen(&sc, mMainDisplay);
- sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
- sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
-
- ScreenCapture::captureScreen(&sc, mVirtualDisplay);
- sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
- sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
-}
-
-class DisplayActiveConfigTest : public ::testing::Test {
-protected:
- void SetUp() override {
- mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
- SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &mDisplayconfigs);
- EXPECT_GT(mDisplayconfigs.size(), 0);
-
- // set display power to on to make sure config can be changed
- SurfaceComposerClient::setDisplayPowerMode(mDisplayToken, HWC_POWER_MODE_NORMAL);
- }
-
- sp<IBinder> mDisplayToken;
- Vector<DisplayInfo> mDisplayconfigs;
-};
-
-TEST_F(DisplayActiveConfigTest, allConfigsAllowed) {
- std::vector<int32_t> allowedConfigs;
-
- // Add all configs to the allowed configs
- for (int i = 0; i < mDisplayconfigs.size(); i++) {
- allowedConfigs.push_back(i);
- }
-
- status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs);
- EXPECT_EQ(res, NO_ERROR);
-
- std::vector<int32_t> outConfigs;
- res = SurfaceComposerClient::getAllowedDisplayConfigs(mDisplayToken, &outConfigs);
- EXPECT_EQ(res, NO_ERROR);
- EXPECT_EQ(allowedConfigs, outConfigs);
-}
-
-TEST_F(DisplayActiveConfigTest, changeAllowedConfig) {
- // we need at least 2 configs available for this test
- if (mDisplayconfigs.size() <= 1) return;
-
- int activeConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken);
-
- // We want to set the allowed config to everything but the active config
- std::vector<int32_t> allowedConfigs;
- for (int i = 0; i < mDisplayconfigs.size(); i++) {
- if (i != activeConfig) {
- allowedConfigs.push_back(i);
- }
- }
-
- status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs);
- EXPECT_EQ(res, NO_ERROR);
-
- // Allow some time for the config change
- std::this_thread::sleep_for(200ms);
-
- int newActiveConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken);
- EXPECT_NE(activeConfig, newActiveConfig);
-
- // Make sure the new config is part of allowed config
- EXPECT_TRUE(std::find(allowedConfigs.begin(), allowedConfigs.end(), newActiveConfig) !=
- allowedConfigs.end());
-}
-
-class RelativeZTest : public LayerTransactionTest {
-protected:
- virtual void SetUp() {
- LayerTransactionTest::SetUp();
- ASSERT_EQ(NO_ERROR, mClient->initCheck());
-
- const auto display = SurfaceComposerClient::getInternalDisplayToken();
- ASSERT_FALSE(display == nullptr);
-
- // Back layer
- mBackgroundLayer = createColorLayer("Background layer", Color::RED);
-
- // Front layer
- mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
-
- asTransaction([&](Transaction& t) {
- t.setDisplayLayerStack(display, 0);
- t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
- t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
- });
- }
-
- virtual void TearDown() {
- LayerTransactionTest::TearDown();
- mBackgroundLayer = 0;
- mForegroundLayer = 0;
- }
-
- sp<SurfaceControl> mBackgroundLayer;
- sp<SurfaceControl> mForegroundLayer;
-};
-
-// When a layer is reparented offscreen, remove relative z order if the relative parent
-// is still onscreen so that the layer is not drawn.
-TEST_F(RelativeZTest, LayerRemoved) {
- std::unique_ptr<ScreenCapture> sc;
-
- // Background layer (RED)
- // Child layer (WHITE) (relative to foregroud layer)
- // Foregroud layer (GREEN)
- sp<SurfaceControl> childLayer =
- createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get());
-
- Transaction{}
- .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1)
- .show(childLayer)
- .apply();
-
- {
- // The childLayer should be in front of the FG control.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
- }
-
- // Background layer (RED)
- // Foregroud layer (GREEN)
- Transaction{}.reparent(childLayer, nullptr).apply();
-
- // Background layer (RED)
- // Child layer (WHITE)
- // Foregroud layer (GREEN)
- Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply();
-
- {
- // The relative z info for child layer should be reset, leaving FG control on top.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
- }
-}
-
-// When a layer is reparented offscreen, preseve relative z order if the relative parent
-// is also offscreen. Regression test b/132613412
-TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) {
- std::unique_ptr<ScreenCapture> sc;
-
- // Background layer (RED)
- // Foregroud layer (GREEN)
- // child level 1 (WHITE)
- // child level 2a (BLUE)
- // child level 3 (GREEN) (relative to child level 2b)
- // child level 2b (BLACK)
- sp<SurfaceControl> childLevel1 =
- createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get());
- sp<SurfaceControl> childLevel2a =
- createColorLayer("child level 2a", Color::BLUE, childLevel1.get());
- sp<SurfaceControl> childLevel2b =
- createColorLayer("child level 2b", Color::BLACK, childLevel1.get());
- sp<SurfaceControl> childLevel3 =
- createColorLayer("child level 3", Color::GREEN, childLevel2a.get());
-
- Transaction{}
- .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1)
- .show(childLevel2a)
- .show(childLevel2b)
- .show(childLevel3)
- .apply();
-
- {
- // The childLevel3 should be in front of childLevel2b.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
- }
-
- // Background layer (RED)
- // Foregroud layer (GREEN)
- Transaction{}.reparent(childLevel1, nullptr).apply();
-
- // Background layer (RED)
- // Foregroud layer (GREEN)
- // child level 1 (WHITE)
- // child level 2 back (BLUE)
- // child level 3 (GREEN) (relative to child level 2b)
- // child level 2 front (BLACK)
- Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply();
-
- {
- // Nothing should change at this point since relative z info was preserved.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
- }
-}
-
-// This test ensures that when we drop an app buffer in SurfaceFlinger, we merge
-// the dropped buffer's damage region into the next buffer's damage region. If
-// we don't do this, we'll report an incorrect damage region to hardware
-// composer, resulting in broken rendering. This test checks the BufferQueue
-// case.
-//
-// Unfortunately, we don't currently have a way to inspect the damage region
-// SurfaceFlinger sends to hardware composer from a test, so this test requires
-// the dev to manually watch the device's screen during the test to spot broken
-// rendering. Because the results can't be automatically verified, this test is
-// marked disabled.
-TEST_F(LayerTransactionTest, DISABLED_BufferQueueLayerMergeDamageRegionWhenDroppingBuffers) {
- const int width = mDisplayWidth;
- const int height = mDisplayHeight;
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height));
- const auto producer = layer->getIGraphicBufferProducer();
- const sp<IProducerListener> dummyListener(new DummyProducerListener);
- IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
- ASSERT_EQ(OK,
- producer->connect(dummyListener, NATIVE_WINDOW_API_CPU, true, &queueBufferOutput));
-
- std::map<int, sp<GraphicBuffer>> slotMap;
- auto slotToBuffer = [&](int slot, sp<GraphicBuffer>* buf) {
- ASSERT_NE(nullptr, buf);
- const auto iter = slotMap.find(slot);
- ASSERT_NE(slotMap.end(), iter);
- *buf = iter->second;
- };
-
- auto dequeue = [&](int* outSlot) {
- ASSERT_NE(nullptr, outSlot);
- *outSlot = -1;
- int slot;
- sp<Fence> fence;
- uint64_t age;
- FrameEventHistoryDelta timestamps;
- const status_t dequeueResult =
- producer->dequeueBuffer(&slot, &fence, width, height, PIXEL_FORMAT_RGBA_8888,
- GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
- &age, ×tamps);
- if (dequeueResult == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
- sp<GraphicBuffer> newBuf;
- ASSERT_EQ(OK, producer->requestBuffer(slot, &newBuf));
- ASSERT_NE(nullptr, newBuf.get());
- slotMap[slot] = newBuf;
- } else {
- ASSERT_EQ(OK, dequeueResult);
- }
- *outSlot = slot;
- };
-
- auto queue = [&](int slot, const Region& damage, nsecs_t displayTime) {
- IGraphicBufferProducer::QueueBufferInput input(
- /*timestamp=*/displayTime, /*isAutoTimestamp=*/false, HAL_DATASPACE_UNKNOWN,
- /*crop=*/Rect::EMPTY_RECT, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
- /*transform=*/0, Fence::NO_FENCE);
- input.setSurfaceDamage(damage);
- IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, producer->queueBuffer(slot, input, &output));
- };
-
- auto fillAndPostBuffers = [&](const Color& color) {
- int slot1;
- ASSERT_NO_FATAL_FAILURE(dequeue(&slot1));
- int slot2;
- ASSERT_NO_FATAL_FAILURE(dequeue(&slot2));
-
- sp<GraphicBuffer> buf1;
- ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot1, &buf1));
- sp<GraphicBuffer> buf2;
- ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot2, &buf2));
- TransactionUtils::fillGraphicBufferColor(buf1, Rect(width, height), color);
- TransactionUtils::fillGraphicBufferColor(buf2, Rect(width, height), color);
-
- const auto displayTime = systemTime() + milliseconds_to_nanoseconds(100);
- ASSERT_NO_FATAL_FAILURE(queue(slot1, Region::INVALID_REGION, displayTime));
- ASSERT_NO_FATAL_FAILURE(
- queue(slot2, Region(Rect(width / 3, height / 3, 2 * width / 3, 2 * height / 3)),
- displayTime));
- };
-
- const auto startTime = systemTime();
- const std::array<Color, 3> colors = {Color::RED, Color::GREEN, Color::BLUE};
- int colorIndex = 0;
- while (nanoseconds_to_seconds(systemTime() - startTime) < 10) {
- ASSERT_NO_FATAL_FAILURE(fillAndPostBuffers(colors[colorIndex++ % colors.size()]));
- std::this_thread::sleep_for(1s);
- }
-
- ASSERT_EQ(OK, producer->disconnect(NATIVE_WINDOW_API_CPU));
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 539e0f4..b6fa2a6 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -878,11 +878,14 @@
FlingerLayerType layer =
Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
- return new BufferQueueLayer(
- LayerCreationArgs(test->mFlinger.mFlinger.get(), sp<Client>(),
- String8("test-layer"), LayerProperties::WIDTH,
- LayerProperties::HEIGHT,
- LayerProperties::LAYER_FLAGS, LayerMetadata()));
+ sp<Client> client;
+ String8 name("test-layer");
+ LayerCreationArgs args =
+ LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name,
+ LayerProperties::WIDTH, LayerProperties::HEIGHT,
+ LayerProperties::LAYER_FLAGS, LayerMetadata());
+ args.textureName = test->mFlinger.mutableTexturePool().back();
+ return new BufferQueueLayer(args);
});
LayerProperties::setupLayerState(test, layer);