Merge "Update SF dump to use proto3"
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index 273a5a6..c818c05 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -14,7 +14,8 @@
mmm -j frameworks/native/cmds/dumpstate
```
-If you're working on device-specific code, you might need to build them as well. Example:
+If you're working on device-specific code, you might need to build them as well.
+Example:
```
mmm -j frameworks/native/cmds/dumpstate device/acme/secret_device/dumpstate/ hardware/interfaces/dumpstate
@@ -23,20 +24,23 @@
## To build, deploy, and take a bugreport
```
-mmm -j frameworks/native/cmds/dumpstate && adb push ${OUT}/system/bin/dumpstate system/bin && adb shell am bug-report
+mmm -j frameworks/native/cmds/dumpstate && adb push ${OUT}/system/bin/dumpstate system/bin && adb push ${OUT}/system/lib64/*dumpstate*.so /system/lib64/ && adb shell am bug-report
```
-Make sure that the device is remounted before running the above command.
-* If you're working with `userdebug` variant, you may need to run the following to remount your device:
+Make sure that the device is remounted before running the above command. * If
+you're working with `userdebug` variant, you may need to run the following to
+remount your device:
- ```
+```
adb root && adb remount -R && adb wait-for-device && adb root && adb remount
- ```
-* If you're working with `eng` variant, you may need to run the following to remount your device:
+```
- ```
- adb root && adb remount
- ```
+* If you're working with `eng` variant, you may need to run the following to
+ remount your device:
+
+ ```
+ adb root && adb remount
+ ```
## To build, deploy, and run unit tests
@@ -82,7 +86,6 @@
adb shell setprop dumpstate.version split-dumpsys && adb shell dumpstate -v
```
-
Then to restore the default version:
```
@@ -91,8 +94,9 @@
## Code style and formatting
-Use the style defined at the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
-and make sure to run the following command prior to `repo upload`:
+Use the style defined at the
+[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) and
+make sure to run the following command prior to `repo upload`:
```
git clang-format --style=file HEAD~
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 61745b5..27abee2 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -113,6 +113,7 @@
#define LOGPERSIST_DATA_DIR "/data/misc/logd"
#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
+#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
#define WLUTIL "/vendor/xbin/wlutil"
#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
@@ -1455,9 +1456,12 @@
add_mountinfo();
DumpIpTablesAsRoot();
- // Capture any IPSec policies in play. No keys are exposed here.
+ // Capture any IPSec policies in play. No keys are exposed here.
RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
+ // Dump IPsec stats. No keys are exposed here.
+ DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
+
// Run ss as root so we can see socket marks.
RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
@@ -2598,21 +2602,26 @@
return Dumpstate::RunStatus::ERROR;
}
-/* Main entry point for dumpstate binary. */
-int run_main(int argc, char* argv[]) {
+Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
Dumpstate::RunStatus status = options->Initialize(argc, argv);
if (status == Dumpstate::RunStatus::OK) {
- ds.SetOptions(std::move(options));
+ SetOptions(std::move(options));
// When directly running dumpstate binary, the output is not expected to be written
// to any external file descriptor.
- assert(ds.options_->bugreport_fd.get() == -1);
+ assert(options_->bugreport_fd.get() == -1);
// calling_uid and calling_package are for user consent to share the bugreport with
// an app; they are irrelvant here because bugreport is only written to a local
// directory, and not shared.
- status = ds.Run(-1 /* calling_uid */, "" /* calling_package */);
+ status = Run(-1 /* calling_uid */, "" /* calling_package */);
}
+ return status;
+}
+
+/* Main entry point for dumpstate binary. */
+int run_main(int argc, char* argv[]) {
+ Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
switch (status) {
case Dumpstate::RunStatus::OK:
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7fb2f3b..9803f00 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -322,6 +322,8 @@
/* Main entry point for running a complete bugreport. */
RunStatus Run(int32_t calling_uid, const std::string& calling_package);
+ RunStatus ParseCommandlineAndRun(int argc, char* argv[]);
+
/* Sets runtime options. */
void SetOptions(std::unique_ptr<DumpOptions> options);
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 570c6c9..9f99114 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -109,7 +109,7 @@
ds.listener_name_ = "Smokey";
ds.report_section_ = true;
auto start = std::chrono::steady_clock::now();
- run_main(ARRAY_SIZE(argv), argv);
+ ds.ParseCommandlineAndRun(ARRAY_SIZE(argv), argv);
auto end = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 852aa79..3421800 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -352,6 +352,8 @@
bool generate_minidebug_info = kEnableMinidebugInfo &&
GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault);
+ std::string boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s");
+
// clang FORTIFY doesn't let us use strlen in constant array bounds, so we
// use arraysize instead.
std::string zip_fd_arg = StringPrintf("--zip-fd=%d", zip_fd);
@@ -366,7 +368,7 @@
std::string dex2oat_image_fd;
std::string target_sdk_version_arg;
if (target_sdk_version != 0) {
- StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version);
+ target_sdk_version_arg = StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version);
}
std::string class_loader_context_arg;
if (class_loader_context != nullptr) {
@@ -437,6 +439,7 @@
AddArg(instruction_set_variant_arg);
AddArg(instruction_set_features_arg);
+ AddRuntimeArg(boot_image);
AddRuntimeArg(dex2oat_Xms_arg);
AddRuntimeArg(dex2oat_Xmx_arg);
diff --git a/include/input/TouchVideoFrame.h b/include/input/TouchVideoFrame.h
index 640bf1f..566c334 100644
--- a/include/input/TouchVideoFrame.h
+++ b/include/input/TouchVideoFrame.h
@@ -30,42 +30,34 @@
*/
class TouchVideoFrame {
public:
- TouchVideoFrame(uint32_t width, uint32_t height, std::vector<int16_t> data,
- const struct timeval& timestamp) :
- mWidth(width), mHeight(height), mData(std::move(data)), mTimestamp(timestamp) {
- }
+ TouchVideoFrame(uint32_t height, uint32_t width, std::vector<int16_t> data,
+ const struct timeval& timestamp);
- bool operator==(const TouchVideoFrame& rhs) const {
- return mWidth == rhs.mWidth
- && mHeight == rhs.mHeight
- && mData == rhs.mData
- && mTimestamp.tv_sec == rhs.mTimestamp.tv_sec
- && mTimestamp.tv_usec == rhs.mTimestamp.tv_usec;
- }
+ bool operator==(const TouchVideoFrame& rhs) const;
/**
- * Width of the frame
- */
- uint32_t getWidth() const { return mWidth; }
- /**
* Height of the frame
*/
- uint32_t getHeight() const { return mHeight; }
+ uint32_t getHeight() const;
+ /**
+ * Width of the frame
+ */
+ uint32_t getWidth() const;
/**
* The touch strength data.
* The array is a 2-D row-major matrix, with dimensions (height, width).
* Total size of the array should equal getHeight() * getWidth().
* Data is allowed to be negative.
*/
- const std::vector<int16_t>& getData() const { return mData; }
+ const std::vector<int16_t>& getData() const;
/**
* Time at which the heatmap was taken.
*/
- const struct timeval& getTimestamp() const { return mTimestamp; }
+ const struct timeval& getTimestamp() const;
private:
- uint32_t mWidth;
uint32_t mHeight;
+ uint32_t mWidth;
std::vector<int16_t> mData;
struct timeval mTimestamp;
};
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_apex/android/binder_manager.h
index 80b6c07..055c79b 100644
--- a/libs/binder/ndk/include_apex/android/binder_manager.h
+++ b/libs/binder/ndk/include_apex/android/binder_manager.h
@@ -33,6 +33,15 @@
binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance);
/**
+ * Gets a binder object with this specific instance name. Will return nullptr immediately if the
+ * service is not available This also implicitly calls AIBinder_incStrong (so the caller of this
+ * function is responsible for calling AIBinder_decStrong).
+ *
+ * \param instance identifier of the service used to lookup the service.
+ */
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const char* instance);
+
+/**
* Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on
* it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
* for calling AIBinder_decStrong).
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index f0d25f7..655f4d5 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -91,6 +91,7 @@
ABinderProcess_setThreadPoolMaxThreadCount; # apex
ABinderProcess_startThreadPool; # apex
AServiceManager_addService; # apex
+ AServiceManager_checkService; # apex
AServiceManager_getService; # apex
local:
*;
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 9ddc555..d0b166d 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -37,6 +37,18 @@
status_t status = sm->addService(String16(instance), binder->getBinder());
return PruneStatusT(status);
}
+AIBinder* AServiceManager_checkService(const char* instance) {
+ if (instance == nullptr) {
+ return nullptr;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->checkService(String16(instance));
+
+ sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
+ AIBinder_incStrong(ret.get());
+ return ret.get();
+}
AIBinder* AServiceManager_getService(const char* instance) {
if (instance == nullptr) {
return nullptr;
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index c159d71..bff601e 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -35,6 +35,19 @@
// EXPECT_EQ(nullptr, foo.get());
// }
+TEST(NdkBinder, CheckServiceThatDoesntExist) {
+ AIBinder* binder = AServiceManager_checkService("asdfghkl;");
+ ASSERT_EQ(nullptr, binder);
+}
+
+TEST(NdkBinder, CheckServiceThatDoesExist) {
+ AIBinder* binder = AServiceManager_checkService(kExistingNonNdkService);
+ EXPECT_NE(nullptr, binder);
+ EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));
+
+ AIBinder_decStrong(binder);
+}
+
TEST(NdkBinder, DoubleNumber) {
sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
ASSERT_NE(foo, nullptr);
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 75fe2d3..386f9f0 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -157,27 +157,105 @@
}
void GraphicsEnv::setGpuStats(const std::string& driverPackageName,
- const std::string& driverVersionName,
- const uint64_t driverVersionCode, const std::string& appPackageName) {
+ const std::string& driverVersionName, uint64_t driverVersionCode,
+ const std::string& driverBuildDate,
+ const std::string& appPackageName) {
ATRACE_CALL();
+ std::lock_guard<std::mutex> lock(mStatsLock);
ALOGV("setGpuStats:\n"
"\tdriverPackageName[%s]\n"
"\tdriverVersionName[%s]\n"
"\tdriverVersionCode[%llu]\n"
+ "\tdriverBuildDate[%s]\n"
"\tappPackageName[%s]\n",
driverPackageName.c_str(), driverVersionName.c_str(),
- (unsigned long long)driverVersionCode, appPackageName.c_str());
+ (unsigned long long)driverVersionCode, driverBuildDate.c_str(), appPackageName.c_str());
- mGpuStats = {
- .driverPackageName = driverPackageName,
- .driverVersionName = driverVersionName,
- .driverVersionCode = driverVersionCode,
- .appPackageName = appPackageName,
- };
+ mGpuStats.driverPackageName = driverPackageName;
+ mGpuStats.driverVersionName = driverVersionName;
+ mGpuStats.driverVersionCode = driverVersionCode;
+ mGpuStats.driverBuildDate = driverBuildDate;
+ mGpuStats.appPackageName = appPackageName;
}
-void GraphicsEnv::sendGpuStats() {
+void GraphicsEnv::setDriverToLoad(GraphicsEnv::Driver driver) {
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mStatsLock);
+ switch (driver) {
+ case GraphicsEnv::Driver::GL:
+ case GraphicsEnv::Driver::GL_UPDATED:
+ case GraphicsEnv::Driver::ANGLE: {
+ if (mGpuStats.glDriverToLoad == GraphicsEnv::Driver::NONE) {
+ mGpuStats.glDriverToLoad = driver;
+ break;
+ }
+
+ if (mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE) {
+ mGpuStats.glDriverFallback = driver;
+ }
+ break;
+ }
+ case Driver::VULKAN:
+ case Driver::VULKAN_UPDATED: {
+ if (mGpuStats.vkDriverToLoad == GraphicsEnv::Driver::NONE) {
+ mGpuStats.vkDriverToLoad = driver;
+ break;
+ }
+
+ if (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE) {
+ mGpuStats.vkDriverFallback = driver;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void GraphicsEnv::setDriverLoaded(GraphicsEnv::Api api, bool isLoaded, int64_t driverLoadingTime) {
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mStatsLock);
+ GraphicsEnv::Driver driver = GraphicsEnv::Driver::NONE;
+ bool isIntendedDriverLoaded = false;
+ if (api == GraphicsEnv::Api::API_GL) {
+ driver = mGpuStats.glDriverToLoad;
+ isIntendedDriverLoaded = isLoaded &&
+ ((mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE) ||
+ (mGpuStats.glDriverToLoad == mGpuStats.glDriverFallback));
+ } else {
+ driver = mGpuStats.vkDriverToLoad;
+ isIntendedDriverLoaded =
+ isLoaded && (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE);
+ }
+
+ sendGpuStatsLocked(driver, isIntendedDriverLoaded, driverLoadingTime);
+}
+
+void GraphicsEnv::clearDriverLoadingInfo(GraphicsEnv::Api api) {
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mStatsLock);
+ if (api == GraphicsEnv::Api::API_GL) {
+ mGpuStats.glDriverToLoad = GraphicsEnv::Driver::NONE;
+ mGpuStats.glDriverFallback = GraphicsEnv::Driver::NONE;
+ }
+}
+
+static sp<IGpuService> getGpuService() {
+ const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
+ if (!binder) {
+ ALOGE("Failed to get gpu service");
+ return nullptr;
+ }
+
+ return interface_cast<IGpuService>(binder);
+}
+
+void GraphicsEnv::sendGpuStatsLocked(GraphicsEnv::Driver driver, bool isDriverLoaded,
+ int64_t driverLoadingTime) {
ATRACE_CALL();
// Do not sendGpuStats for those skipping the GraphicsEnvironment setup
@@ -187,20 +265,23 @@
"\tdriverPackageName[%s]\n"
"\tdriverVersionName[%s]\n"
"\tdriverVersionCode[%llu]\n"
- "\tappPackageName[%s]\n",
+ "\tdriverBuildDate[%s]\n"
+ "\tappPackageName[%s]\n"
+ "\tdriver[%d]\n"
+ "\tisDriverLoaded[%d]\n"
+ "\tdriverLoadingTime[%lld]",
mGpuStats.driverPackageName.c_str(), mGpuStats.driverVersionName.c_str(),
- (unsigned long long)mGpuStats.driverVersionCode, mGpuStats.appPackageName.c_str());
+ (unsigned long long)mGpuStats.driverVersionCode, mGpuStats.driverBuildDate.c_str(),
+ mGpuStats.appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded,
+ (long long)driverLoadingTime);
- const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
- if (!binder) {
- ALOGE("Failed to get gpu service for [%s]", mGpuStats.appPackageName.c_str());
- return;
+ const sp<IGpuService> gpuService = getGpuService();
+ if (gpuService) {
+ gpuService->setGpuStats(mGpuStats.driverPackageName, mGpuStats.driverVersionName,
+ mGpuStats.driverVersionCode, mGpuStats.driverBuildDate,
+ mGpuStats.appPackageName, driver, isDriverLoaded,
+ driverLoadingTime);
}
-
- interface_cast<IGpuService>(binder)->setGpuStats(mGpuStats.driverPackageName,
- mGpuStats.driverVersionName,
- mGpuStats.driverVersionCode,
- mGpuStats.appPackageName);
}
void* GraphicsEnv::loadLibrary(std::string name) {
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 762a27b..a8a07c2 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -28,17 +28,23 @@
explicit BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {}
virtual void setGpuStats(const std::string& driverPackageName,
- const std::string& driverVersionName, const uint64_t driverVersionCode,
- const std::string& appPackageName) {
+ const std::string& driverVersionName, uint64_t driverVersionCode,
+ const std::string& driverBuildDate, const std::string& appPackageName,
+ GraphicsEnv::Driver driver, bool isDriverLoaded,
+ int64_t driverLoadingTime) {
Parcel data, reply;
data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
data.writeUtf8AsUtf16(driverPackageName);
data.writeUtf8AsUtf16(driverVersionName);
data.writeUint64(driverVersionCode);
+ data.writeUtf8AsUtf16(driverBuildDate);
data.writeUtf8AsUtf16(appPackageName);
+ data.writeInt32(static_cast<int32_t>(driver));
+ data.writeBool(isDriverLoaded);
+ data.writeInt64(driverLoadingTime);
- remote()->transact(BnGpuService::SET_GPU_STATS, data, &reply);
+ remote()->transact(BnGpuService::SET_GPU_STATS, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -62,10 +68,24 @@
uint64_t driverVersionCode;
if ((status = data.readUint64(&driverVersionCode)) != OK) return status;
+ std::string driverBuildDate;
+ if ((status = data.readUtf8FromUtf16(&driverBuildDate)) != OK) return status;
+
std::string appPackageName;
if ((status = data.readUtf8FromUtf16(&appPackageName)) != OK) return status;
- setGpuStats(driverPackageName, driverVersionName, driverVersionCode, appPackageName);
+ int32_t driver;
+ if ((status = data.readInt32(&driver)) != OK) return status;
+
+ bool isDriverLoaded;
+ if ((status = data.readBool(&isDriverLoaded)) != OK) return status;
+
+ int64_t driverLoadingTime;
+ if ((status = data.readInt64(&driverLoadingTime)) != OK) return status;
+
+ setGpuStats(driverPackageName, driverVersionName, driverVersionCode, driverBuildDate,
+ appPackageName, static_cast<GraphicsEnv::Driver>(driver), isDriverLoaded,
+ driverLoadingTime);
return OK;
}
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index c4482b7..20b0205 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -28,11 +28,43 @@
struct NativeLoaderNamespace;
class GraphicsEnv {
+public:
+ enum Api {
+ API_GL = 0,
+ API_VK = 1,
+ };
+
+ enum Driver {
+ NONE = 0,
+ GL = 1,
+ GL_UPDATED = 2,
+ VULKAN = 3,
+ VULKAN_UPDATED = 4,
+ ANGLE = 5,
+ };
+
+private:
struct GpuStats {
std::string driverPackageName;
std::string driverVersionName;
uint64_t driverVersionCode;
+ std::string driverBuildDate;
std::string appPackageName;
+ Driver glDriverToLoad;
+ Driver glDriverFallback;
+ Driver vkDriverToLoad;
+ Driver vkDriverFallback;
+
+ GpuStats()
+ : driverPackageName(""),
+ driverVersionName(""),
+ driverVersionCode(0),
+ driverBuildDate(""),
+ appPackageName(""),
+ glDriverToLoad(Driver::NONE),
+ glDriverFallback(Driver::NONE),
+ vkDriverToLoad(Driver::NONE),
+ vkDriverFallback(Driver::NONE) {}
};
public:
@@ -48,8 +80,12 @@
void setDriverPath(const std::string path);
android_namespace_t* getDriverNamespace();
void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
- const uint64_t versionCode, const std::string& appPackageName);
- void sendGpuStats();
+ uint64_t versionCode, const std::string& driverBuildDate,
+ const std::string& appPackageName);
+ void setDriverToLoad(Driver driver);
+ void setDriverLoaded(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
+ void clearDriverLoadingInfo(Api api);
+ void sendGpuStatsLocked(Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
bool shouldUseAngle(std::string appName);
bool shouldUseAngle();
@@ -82,6 +118,7 @@
GraphicsEnv() = default;
std::string mDriverPath;
+ std::mutex mStatsLock;
GpuStats mGpuStats;
std::string mAnglePath;
std::string mAngleAppName;
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index 1e74d60..105a903 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -18,6 +18,7 @@
#include <binder/IInterface.h>
#include <cutils/compiler.h>
+#include <graphicsenv/GraphicsEnv.h>
#include <vector>
@@ -29,12 +30,14 @@
*/
class IGpuService : public IInterface {
public:
- DECLARE_META_INTERFACE(GpuService);
+ DECLARE_META_INTERFACE(GpuService)
// set GPU stats from GraphicsEnvironment.
virtual void setGpuStats(const std::string& driverPackageName,
- const std::string& driverVersionName, const uint64_t driverVersionCode,
- const std::string& appPackageName) = 0;
+ const std::string& driverVersionName, uint64_t driverVersionCode,
+ const std::string& driverBuildDate, const std::string& appPackageName,
+ GraphicsEnv::Driver driver, bool isDriverLoaded,
+ int64_t driverLoadingTime) = 0;
};
class BnGpuService : public BnInterface<IGpuService> {
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index d997674..8907de4 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -651,7 +651,7 @@
}
};
-IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer, HGraphicBufferProducer,
+IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer,
"android.gui.IGraphicBufferProducer");
// ----------------------------------------------------------------------
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index f77eeb2..9197262 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -806,6 +806,12 @@
}
return error;
}
+
+ virtual void setInputWindowsFinished() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ remote()->transact(BnSurfaceComposer::SET_INPUT_WINDOWS_FINISHED, data, &reply);
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -1317,6 +1323,11 @@
}
return removeRegionSamplingListener(listener);
}
+ case SET_INPUT_WINDOWS_FINISHED: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ setInputWindowsFinished();
+ return NO_ERROR;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 206bc30..962d263 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -414,10 +414,13 @@
.insert(transferTouchFocusCommands.end(),
std::make_move_iterator(other.transferTouchFocusCommands.begin()),
std::make_move_iterator(other.transferTouchFocusCommands.end()));
+
+ syncInputWindows |= other.syncInputWindows;
}
void InputWindowCommands::clear() {
transferTouchFocusCommands.clear();
+ syncInputWindows = false;
}
void InputWindowCommands::write(Parcel& output) const {
@@ -426,6 +429,8 @@
output.writeStrongBinder(transferTouchFocusCommand.fromToken);
output.writeStrongBinder(transferTouchFocusCommand.toToken);
}
+
+ output.writeBool(syncInputWindows);
}
void InputWindowCommands::read(const Parcel& input) {
@@ -437,6 +442,8 @@
transferTouchFocusCommand.toToken = input.readStrongBinder();
transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
}
+
+ syncInputWindows = input.readBool();
}
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index bf2a03d..8c2538c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1083,6 +1083,11 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInputWindows() {
+ mInputWindowCommands.syncInputWindows = true;
+ return *this;
+}
+
#endif
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform(
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 1a0b6bb..c2d7d28 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -359,6 +359,8 @@
* Removes a listener that was streaming median luma updates from SurfaceFlinger.
*/
virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) = 0;
+
+ virtual void setInputWindowsFinished() = 0;
};
// ----------------------------------------------------------------------------
@@ -406,6 +408,8 @@
GET_PHYSICAL_DISPLAY_IDS,
ADD_REGION_SAMPLING_LISTENER,
REMOVE_REGION_SAMPLING_LISTENER,
+ SET_INPUT_WINDOWS_FINISHED,
+
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index c780c07..8430874 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -254,6 +254,7 @@
};
std::vector<TransferTouchFocusCommand> transferTouchFocusCommands;
+ bool syncInputWindows;
void merge(const InputWindowCommands& other);
void clear();
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index aa99bd2..cb38209 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -378,6 +378,7 @@
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
Transaction& transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
+ Transaction& syncInputWindows();
#endif
// Set a color transform matrix on the given layer on the built-in display.
diff --git a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index c92fa9d..c4d0245 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -57,7 +57,6 @@
struct H2BGraphicBufferProducer : public ::android::H2BConverter<
HGraphicBufferProducer,
- BGraphicBufferProducer,
BnGraphicBufferProducer> {
explicit H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index f127853..8225647 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -679,6 +679,8 @@
return NO_ERROR;
}
+ void setInputWindowsFinished() override {}
+
protected:
IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index fc676f1..6aedb00 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -28,6 +28,7 @@
"Keyboard.cpp",
"KeyCharacterMap.cpp",
"KeyLayoutMap.cpp",
+ "TouchVideoFrame.cpp",
"VirtualKeyMap.cpp",
],
@@ -42,12 +43,12 @@
target: {
android: {
srcs: [
+ "IInputFlinger.cpp",
+ "InputApplication.cpp",
"InputTransport.cpp",
+ "InputWindow.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
- "InputApplication.cpp",
- "InputWindow.cpp",
- "IInputFlinger.cpp"
],
shared_libs: [
diff --git a/libs/input/TouchVideoFrame.cpp b/libs/input/TouchVideoFrame.cpp
new file mode 100644
index 0000000..35cb4a7
--- /dev/null
+++ b/libs/input/TouchVideoFrame.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 <input/TouchVideoFrame.h>
+
+namespace android {
+
+TouchVideoFrame::TouchVideoFrame(uint32_t height, uint32_t width, std::vector<int16_t> data,
+ const struct timeval& timestamp) :
+ mHeight(height), mWidth(width),mData(std::move(data)), mTimestamp(timestamp) {
+}
+
+bool TouchVideoFrame::operator==(const TouchVideoFrame& rhs) const {
+ return mHeight == rhs.mHeight
+ && mWidth == rhs.mWidth
+ && mData == rhs.mData
+ && mTimestamp.tv_sec == rhs.mTimestamp.tv_sec
+ && mTimestamp.tv_usec == rhs.mTimestamp.tv_usec;
+}
+
+uint32_t TouchVideoFrame::getHeight() const { return mHeight; }
+
+uint32_t TouchVideoFrame::getWidth() const { return mWidth; }
+
+const std::vector<int16_t>& TouchVideoFrame::getData() const { return mData; }
+
+const struct timeval& TouchVideoFrame::getTimestamp() const { return mTimestamp; }
+
+} // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index fdd945e..57ba2a2 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -5,8 +5,9 @@
"InputChannel_test.cpp",
"InputEvent_test.cpp",
"InputPublisherAndConsumer_test.cpp",
+ "InputWindow_test.cpp",
+ "TouchVideoFrame_test.cpp",
"VelocityTracker_test.cpp",
- "InputWindow_test.cpp"
],
cflags: [
"-Wall",
diff --git a/libs/input/tests/TouchVideoFrame_test.cpp b/libs/input/tests/TouchVideoFrame_test.cpp
new file mode 100644
index 0000000..3c1c7f3
--- /dev/null
+++ b/libs/input/tests/TouchVideoFrame_test.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 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 <gtest/gtest.h>
+
+#include <input/TouchVideoFrame.h>
+
+namespace android {
+namespace test {
+
+static const struct timeval TIMESTAMP = {1, 2};
+
+TEST(TouchVideoFrame, Constructor) {
+ const std::vector<int16_t> data = {1, 2, 3, 4, 5, 6};
+ constexpr uint32_t height = 3;
+ constexpr uint32_t width = 2;
+
+ TouchVideoFrame frame(height, width, data, TIMESTAMP);
+
+ ASSERT_EQ(data, frame.getData());
+ ASSERT_EQ(height, frame.getHeight());
+ ASSERT_EQ(width, frame.getWidth());
+ ASSERT_EQ(TIMESTAMP.tv_sec, frame.getTimestamp().tv_sec);
+ ASSERT_EQ(TIMESTAMP.tv_usec, frame.getTimestamp().tv_usec);
+}
+
+TEST(TouchVideoFrame, Equality) {
+ const std::vector<int16_t> data = {1, 2, 3, 4, 5, 6};
+ constexpr uint32_t height = 3;
+ constexpr uint32_t width = 2;
+ TouchVideoFrame frame(height, width, data, TIMESTAMP);
+
+ TouchVideoFrame identicalFrame(height, width, data, TIMESTAMP);
+ ASSERT_EQ(frame, identicalFrame);
+
+ // The two cases below create an invalid frame, but it is OK for comparison purposes.
+ // There aren't any checks currently enforced on the frame dimensions and data
+ // Change height
+ TouchVideoFrame changedHeightFrame(height + 1, width, data, TIMESTAMP);
+ ASSERT_FALSE(frame == changedHeightFrame);
+
+ // Change width
+ TouchVideoFrame changedWidthFrame(height, width + 1, data, TIMESTAMP);
+ ASSERT_FALSE(frame == changedWidthFrame);
+
+ // Change data
+ const std::vector<int16_t> differentData = {1, 2, 3, 3, 5, 6};
+ TouchVideoFrame changedDataFrame(height, width, differentData, TIMESTAMP);
+ ASSERT_FALSE(frame == changedDataFrame);
+
+ // Change timestamp
+ const struct timeval differentTimestamp = {TIMESTAMP.tv_sec + 1, TIMESTAMP.tv_usec + 1};
+ TouchVideoFrame changedTimestampFrame(height, width, data, differentTimestamp);
+ ASSERT_FALSE(frame == changedTimestampFrame);
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 634bce1..efc1a80 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -214,8 +214,8 @@
native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1);
token->data[0] = 0;
- auto b1 = BufferHubBuffer::import(NativeHandle::create(token, /*ownHandle=*/true));
- native_handle_delete(token);
+ sp<NativeHandle> tokenHandle = NativeHandle::create(token, /*ownHandle=*/true);
+ auto b1 = BufferHubBuffer::import(tokenHandle);
EXPECT_THAT(b1, IsNull());
}
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index c80b79a..c0bace8 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -154,8 +154,8 @@
"libbase",
"libhidlbase",
"libhidltransport",
- "libnativebridge",
- "libnativeloader",
+ "libnativebridge_lazy",
+ "libnativeloader_lazy",
"libutils",
],
static_libs: [
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 4cafe2b..259242b 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -27,6 +27,7 @@
#include <android/dlext.h>
#include <cutils/properties.h>
#include <log/log.h>
+#include <utils/Timers.h>
#ifndef __ANDROID_VNDK__
#include <graphicsenv/GraphicsEnv.h>
@@ -217,6 +218,7 @@
void* Loader::open(egl_connection_t* cnx)
{
ATRACE_CALL();
+ const nsecs_t openTime = systemTime();
void* dso;
driver_t* hnd = nullptr;
@@ -234,6 +236,8 @@
if (dso) {
hnd = new driver_t(dso);
} else {
+ android::GraphicsEnv::getInstance().clearDriverLoadingInfo(
+ android::GraphicsEnv::Api::API_GL);
// Always load EGL first
dso = load_driver("EGL", cnx, EGL);
if (dso) {
@@ -243,19 +247,30 @@
}
}
+ if (!hnd) {
+ android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+ false, systemTime() - openTime);
+ }
+
LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+ if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
+ android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+ false, systemTime() - openTime);
+ }
+
LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
"couldn't load system EGL wrapper libraries");
LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
"couldn't load system OpenGL ES wrapper libraries");
- android::GraphicsEnv::getInstance().sendGpuStats();
+ android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, true,
+ systemTime() - openTime);
return (void*)hnd;
}
@@ -591,17 +606,21 @@
void* dso = nullptr;
android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
if (ns) {
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::ANGLE);
dso = load_angle(kind, ns, cnx);
}
#ifndef __ANDROID_VNDK__
if (!dso) {
android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
if (ns) {
+ android::GraphicsEnv::getInstance().setDriverToLoad(
+ android::GraphicsEnv::Driver::GL_UPDATED);
dso = load_updated_driver(kind, ns);
}
}
#endif
if (!dso) {
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
dso = load_system_driver(kind);
if (!dso)
return nullptr;
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 68c185c..81b70c0 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -38,8 +38,10 @@
GpuService::GpuService() = default;
void GpuService::setGpuStats(const std::string& driverPackageName,
- const std::string& driverVersionName, const uint64_t driverVersionCode,
- const std::string& appPackageName) {
+ const std::string& driverVersionName, uint64_t driverVersionCode,
+ const std::string& driverBuildDate, const std::string& appPackageName,
+ GraphicsEnv::Driver driver, bool isDriverLoaded,
+ int64_t driverLoadingTime) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mStateLock);
@@ -47,9 +49,14 @@
"\tdriverPackageName[%s]\n"
"\tdriverVersionName[%s]\n"
"\tdriverVersionCode[%llu]\n"
- "\tappPackageName[%s]\n",
+ "\tdriverBuildDate[%s]\n"
+ "\tappPackageName[%s]\n"
+ "\tdriver[%d]\n"
+ "\tisDriverLoaded[%d]\n"
+ "\tdriverLoadingTime[%lld]",
driverPackageName.c_str(), driverVersionName.c_str(),
- (unsigned long long)driverVersionCode, appPackageName.c_str());
+ (unsigned long long)driverVersionCode, driverBuildDate.c_str(), appPackageName.c_str(),
+ static_cast<int32_t>(driver), isDriverLoaded, (long long)driverLoadingTime);
}
status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 5304fa1..76234a3 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -38,7 +38,9 @@
private:
// IGpuService interface
void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
- const uint64_t driverVersionCode, const std::string& appPackageName);
+ uint64_t driverVersionCode, const std::string& driverBuildDate,
+ const std::string& appPackageName, GraphicsEnv::Driver driver,
+ bool isDriverLoaded, int64_t driverLoadingTime);
// GpuStats access must be protected by mStateLock
std::mutex mStateLock;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index f84aa34..1a1ae21 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -4550,7 +4550,8 @@
mPointerController->setButtonState(mCurrentRawState.buttonState);
mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex,
- mCurrentCookedState.cookedPointerData.touchingIdBits);
+ mCurrentCookedState.cookedPointerData.touchingIdBits,
+ mViewport.displayId);
}
if (!mCurrentMotionAborted) {
@@ -5314,7 +5315,8 @@
if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
mPointerController->setSpots(mPointerGesture.currentGestureCoords,
mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.currentGestureIdBits);
+ mPointerGesture.currentGestureIdBits,
+ mPointerController->getDisplayId());
}
} else {
mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
diff --git a/services/inputflinger/TouchVideoDevice.cpp b/services/inputflinger/TouchVideoDevice.cpp
index ad70ccc..76df3a1 100644
--- a/services/inputflinger/TouchVideoDevice.cpp
+++ b/services/inputflinger/TouchVideoDevice.cpp
@@ -37,10 +37,10 @@
namespace android {
TouchVideoDevice::TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath,
- uint32_t width, uint32_t height,
+ uint32_t height, uint32_t width,
const std::array<const int16_t*, NUM_BUFFERS>& readLocations) :
mFd(fd), mName(std::move(name)), mPath(std::move(devicePath)),
- mWidth(width), mHeight(height),
+ mHeight(height), mWidth(width),
mReadLocations(readLocations) {
mFrames.reserve(MAX_QUEUE_SIZE);
};
@@ -87,9 +87,9 @@
ALOGE("VIDIOC_G_FMT failed: %s", strerror(errno));
return nullptr;
}
- const uint32_t width = v4l2_fmt.fmt.pix.width;
const uint32_t height = v4l2_fmt.fmt.pix.height;
- ALOGI("Frame dimensions: width = %" PRIu32 " height = %" PRIu32, width, height);
+ const uint32_t width = v4l2_fmt.fmt.pix.width;
+ ALOGI("Frame dimensions: height = %" PRIu32 " width = %" PRIu32, height, width);
struct v4l2_requestbuffers req;
req.count = NUM_BUFFERS;
@@ -116,7 +116,7 @@
ALOGE("VIDIOC_QUERYBUF failed: %s", strerror(errno));
return nullptr;
}
- if (buf.length != width * height * sizeof(int16_t)) {
+ if (buf.length != height * width * sizeof(int16_t)) {
ALOGE("Unexpected value of buf.length = %i (offset = %" PRIu32 ")",
buf.length, buf.m.offset);
return nullptr;
@@ -148,7 +148,7 @@
}
// Using 'new' to access a non-public constructor.
return std::unique_ptr<TouchVideoDevice>(new TouchVideoDevice(
- fd.release(), std::move(name), std::move(devicePath), width, height, readLocations));
+ fd.release(), std::move(name), std::move(devicePath), height, width, readLocations));
}
size_t TouchVideoDevice::readAndQueueFrames() {
@@ -193,10 +193,10 @@
ALOGW("The timestamp %ld.%ld was not acquired using CLOCK_MONOTONIC",
buf.timestamp.tv_sec, buf.timestamp.tv_usec);
}
- std::vector<int16_t> data(mWidth * mHeight);
+ std::vector<int16_t> data(mHeight * mWidth);
const int16_t* readFrom = mReadLocations[buf.index];
- std::copy(readFrom, readFrom + mWidth * mHeight, data.begin());
- TouchVideoFrame frame(mWidth, mHeight, std::move(data), buf.timestamp);
+ std::copy(readFrom, readFrom + mHeight * mWidth, data.begin());
+ TouchVideoFrame frame(mHeight, mWidth, std::move(data), buf.timestamp);
result = ioctl(mFd.get(), VIDIOC_QBUF, &buf);
if (result == -1) {
@@ -230,7 +230,7 @@
}
for (const int16_t* buffer : mReadLocations) {
void* bufferAddress = static_cast<void*>(const_cast<int16_t*>(buffer));
- result = munmap(bufferAddress, mWidth * mHeight * sizeof(int16_t));
+ result = munmap(bufferAddress, mHeight * mWidth * sizeof(int16_t));
if (result == -1) {
ALOGE("%s: Couldn't unmap: [%s]", __func__, strerror(errno));
}
@@ -238,9 +238,9 @@
}
std::string TouchVideoDevice::dump() const {
- return StringPrintf("Video device %s (%s) : width=%" PRIu32 ", height=%" PRIu32
+ return StringPrintf("Video device %s (%s) : height=%" PRIu32 ", width=%" PRIu32
", fd=%i, hasValidFd=%s",
- mName.c_str(), mPath.c_str(), mWidth, mHeight, mFd.get(),
+ mName.c_str(), mPath.c_str(), mHeight, mWidth, mFd.get(),
hasValidFd() ? "true" : "false");
}
diff --git a/services/inputflinger/TouchVideoDevice.h b/services/inputflinger/TouchVideoDevice.h
index 3d5c8c6..0e7e2ef 100644
--- a/services/inputflinger/TouchVideoDevice.h
+++ b/services/inputflinger/TouchVideoDevice.h
@@ -54,14 +54,14 @@
*/
const std::string& getPath() const { return mPath; }
/**
- * Get the width of the heatmap frame
- */
- uint32_t getWidth() const { return mWidth; }
- /**
* Get the height of the heatmap frame
*/
uint32_t getHeight() const { return mHeight; }
/**
+ * Get the width of the heatmap frame
+ */
+ uint32_t getWidth() const { return mWidth; }
+ /**
* Direct read of the frame. Stores the frame into internal buffer.
* Return the number of frames that were successfully read.
*
@@ -87,8 +87,8 @@
std::string mName;
std::string mPath;
- uint32_t mWidth;
uint32_t mHeight;
+ uint32_t mWidth;
static constexpr int INVALID_FD = -1;
/**
@@ -110,7 +110,7 @@
* To get a new TouchVideoDevice, use 'create' instead.
*/
explicit TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath,
- uint32_t width, uint32_t height,
+ uint32_t height, uint32_t width,
const std::array<const int16_t*, NUM_BUFFERS>& readLocations);
/**
* Read all currently available frames.
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index bc0f1f9..0ff28e4 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -94,7 +94,7 @@
* pressed (not hovering).
*/
virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
- BitSet32 spotIdBits) = 0;
+ BitSet32 spotIdBits, int32_t displayId) = 0;
/* Removes all spots. */
virtual void clearSpots() = 0;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 84c5ad6..fbacb9b 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -103,6 +103,10 @@
return mDisplayId;
}
+ const std::map<int32_t, std::vector<int32_t>>& getSpots() {
+ return mSpotsByDisplay;
+ }
+
private:
virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
*outMinX = mMinX;
@@ -130,11 +134,22 @@
virtual void setPresentation(Presentation) {
}
- virtual void setSpots(const PointerCoords*, const uint32_t*, BitSet32) {
+ virtual void setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
+ int32_t displayId) {
+ std::vector<int32_t> newSpots;
+ // Add spots for fingers that are down.
+ for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ newSpots.push_back(id);
+ }
+
+ mSpotsByDisplay[displayId] = newSpots;
}
virtual void clearSpots() {
}
+
+ std::map<int32_t, std::vector<int32_t>> mSpotsByDisplay;
};
@@ -228,6 +243,10 @@
mConfig.pointerCapture = enabled;
}
+ void setShowTouches(bool enabled) {
+ mConfig.showTouches = enabled;
+ }
+
private:
DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
int32_t orientation, const std::string& uniqueId, std::optional<uint8_t> physicalPort,
@@ -6315,4 +6334,85 @@
ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
}
+TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) {
+ // Setup the first touch screen device.
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+ prepareAxes(POSITION | ID | SLOT);
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ addMapperAndConfigure(mapper);
+
+ // Create the second touch screen device, and enable multi fingers.
+ const std::string USB2 = "USB2";
+ const int32_t SECOND_DEVICE_ID = 2;
+ InputDeviceIdentifier identifier;
+ identifier.name = DEVICE_NAME;
+ identifier.location = USB2;
+ InputDevice* device2 = new InputDevice(mFakeContext, SECOND_DEVICE_ID, DEVICE_GENERATION,
+ DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
+ mFakeEventHub->addDevice(SECOND_DEVICE_ID, DEVICE_NAME, 0 /*classes*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->setAbsoluteAxisValue(SECOND_DEVICE_ID, ABS_MT_SLOT, 0 /*value*/);
+ mFakeEventHub->addConfigurationProperty(SECOND_DEVICE_ID, String8("touch.deviceType"),
+ String8("touchScreen"));
+
+ // Setup the second touch screen device.
+ MultiTouchInputMapper* mapper2 = new MultiTouchInputMapper(device2);
+ device2->addMapper(mapper2);
+ device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0 /*changes*/);
+ device2->reset(ARBITRARY_TIME);
+
+ // Setup PointerController.
+ sp<FakePointerController> fakePointerController = new FakePointerController();
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ mFakePolicy->setPointerController(SECOND_DEVICE_ID, fakePointerController);
+
+ // Setup policy for associated displays and show touches.
+ const uint8_t hdmi1 = 0;
+ const uint8_t hdmi2 = 1;
+ mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
+ mFakePolicy->addInputPortAssociation(USB2, hdmi2);
+ mFakePolicy->setShowTouches(true);
+
+ // Create displays.
+ prepareDisplay(DISPLAY_ORIENTATION_0, hdmi1);
+ prepareSecondaryDisplay(ViewportType::VIEWPORT_EXTERNAL, hdmi2);
+
+ // Default device will reconfigure above, need additional reconfiguration for another device.
+ device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+ // Two fingers down at default display.
+ int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
+ processPosition(mapper, x1, y1);
+ processId(mapper, 1);
+ processSlot(mapper, 1);
+ processPosition(mapper, x2, y2);
+ processId(mapper, 2);
+ processSync(mapper);
+
+ std::map<int32_t, std::vector<int32_t>>::const_iterator iter =
+ fakePointerController->getSpots().find(DISPLAY_ID);
+ ASSERT_TRUE(iter != fakePointerController->getSpots().end());
+ ASSERT_EQ(size_t(2), iter->second.size());
+
+ // Two fingers down at second display.
+ processPosition(mapper2, x1, y1);
+ processId(mapper2, 1);
+ processSlot(mapper2, 1);
+ processPosition(mapper2, x2, y2);
+ processId(mapper2, 2);
+ processSync(mapper2);
+
+ iter = fakePointerController->getSpots().find(SECONDARY_DISPLAY_ID);
+ ASSERT_TRUE(iter != fakePointerController->getSpots().end());
+ ASSERT_EQ(size_t(2), iter->second.size());
+}
+
} // namespace android
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 89eee6b..2501fae 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -24,8 +24,12 @@
#include <mutex>
#include <compositionengine/CompositionEngine.h>
+#include <compositionengine/Display.h>
#include <compositionengine/Layer.h>
#include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/LayerCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
@@ -65,14 +69,6 @@
BufferLayer::~BufferLayer() {
mFlinger->deleteTextureAsync(mTextureName);
-
- if (!getBE().mHwcLayers.empty()) {
- ALOGE("Found stale hardware composer layers when destroying "
- "surface flinger layer %s",
- mName.string());
- destroyAllHwcLayersPlusChildren();
- }
-
mFlinger->mTimeStats->onDestroy(getSequence());
}
@@ -91,7 +87,7 @@
bool BufferLayer::isOpaque(const Layer::State& s) const {
// if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
// layer's opaque flag.
- if ((getBE().compositionInfo.hwc.sidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
+ if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
return false;
}
@@ -102,7 +98,7 @@
bool BufferLayer::isVisible() const {
return !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
- (mActiveBuffer != nullptr || getBE().compositionInfo.hwc.sidebandStream != nullptr);
+ (mActiveBuffer != nullptr || mSidebandStream != nullptr);
}
bool BufferLayer::isFixedSize() const {
@@ -171,7 +167,8 @@
layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
layer.source.buffer.isY410BT2020 = isHdrY410();
// TODO: we could be more subtle with isFixedSize()
- const bool useFiltering = needsFiltering() || renderArea.needsFiltering() || isFixedSize();
+ const bool useFiltering = needsFiltering(renderArea.getDisplayDevice()) ||
+ renderArea.needsFiltering() || isFixedSize();
// Query the texture matrix given our current filtering mode.
float textureMatrix[16];
@@ -237,26 +234,31 @@
// pixel format is HDR Y410 masquerading as RGBA_1010102
return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ &&
getDrawingApi() == NATIVE_WINDOW_API_MEDIA &&
- getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
+ mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
}
-void BufferLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform,
- const Rect& viewport, int32_t supportedPerFrameMetadata) {
- RETURN_IF_NO_HWC_LAYER(displayId);
+void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice,
+ const ui::Transform& transform, const Rect& viewport,
+ int32_t supportedPerFrameMetadata) {
+ RETURN_IF_NO_HWC_LAYER(displayDevice);
// Apply this display's projection's viewport to the visible region
// before giving it to the HWC HAL.
Region visible = transform.transform(visibleRegion.intersect(viewport));
- auto& hwcInfo = getBE().mHwcLayers[displayId];
- auto& hwcLayer = hwcInfo.layer;
+ const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
+
+ auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
auto error = hwcLayer->setVisibleRegion(visible);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
visible.dump(LOG_TAG);
}
- getBE().compositionInfo.hwc.visibleRegion = visible;
+ outputLayer->editState().visibleRegion = visible;
+
+ auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
if (error != HWC2::Error::None) {
@@ -264,29 +266,29 @@
to_string(error).c_str(), static_cast<int32_t>(error));
surfaceDamageRegion.dump(LOG_TAG);
}
- getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion;
+ layerCompositionState.surfaceDamage = surfaceDamageRegion;
// Sideband layers
- if (getBE().compositionInfo.hwc.sidebandStream.get()) {
- setCompositionType(displayId, HWC2::Composition::Sideband);
+ if (layerCompositionState.sidebandStream.get()) {
+ setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::SIDEBAND);
ALOGV("[%s] Requesting Sideband composition", mName.string());
- error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle());
+ error = hwcLayer->setSidebandStream(layerCompositionState.sidebandStream->handle());
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
- getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(),
+ layerCompositionState.sidebandStream->handle(), to_string(error).c_str(),
static_cast<int32_t>(error));
}
- getBE().compositionInfo.compositionType = HWC2::Composition::Sideband;
+ layerCompositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
return;
}
// Device or Cursor layers
if (mPotentialCursor) {
ALOGV("[%s] Requesting Cursor composition", mName.string());
- setCompositionType(displayId, HWC2::Composition::Cursor);
+ setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CURSOR);
} else {
ALOGV("[%s] Requesting Device composition", mName.string());
- setCompositionType(displayId, HWC2::Composition::Device);
+ setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::DEVICE);
}
ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace);
@@ -308,12 +310,11 @@
ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
}
- getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
- getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata();
- getBE().compositionInfo.hwc.supportedPerFrameMetadata = supportedPerFrameMetadata;
- getBE().compositionInfo.hwc.colorTransform = getColorTransform();
+ layerCompositionState.dataspace = mCurrentDataSpace;
+ layerCompositionState.colorTransform = getColorTransform();
+ layerCompositionState.hdrMetadata = metadata;
- setHwcLayerBuffer(displayId);
+ setHwcLayerBuffer(displayDevice);
}
bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
@@ -372,8 +373,7 @@
return true;
}
-bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) {
+bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
ATRACE_CALL();
bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
@@ -412,7 +412,7 @@
return false;
}
- status_t err = updateTexImage(recomputeVisibleRegions, latchTime, releaseFence);
+ status_t err = updateTexImage(recomputeVisibleRegions, latchTime);
if (err != NO_ERROR) {
return false;
}
@@ -605,9 +605,21 @@
return true;
}
-bool BufferLayer::needsFiltering() const {
- const auto displayFrame = getBE().compositionInfo.hwc.displayFrame;
- const auto sourceCrop = getBE().compositionInfo.hwc.sourceCrop;
+bool BufferLayer::needsFiltering(const sp<const DisplayDevice>& displayDevice) const {
+ // If we are not capturing based on the state of a known display device, we
+ // only return mNeedsFiltering
+ if (displayDevice == nullptr) {
+ return mNeedsFiltering;
+ }
+
+ const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ if (outputLayer == nullptr) {
+ return mNeedsFiltering;
+ }
+
+ const auto& compositionState = outputLayer->getState();
+ const auto displayFrame = compositionState.displayFrame;
+ const auto sourceCrop = compositionState.sourceCrop;
return mNeedsFiltering || sourceCrop.getHeight() != displayFrame.getHeight() ||
sourceCrop.getWidth() != displayFrame.getWidth();
}
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 0f8a350..e3b10fc 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -80,8 +80,8 @@
bool isHdrY410() const override;
- void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
- int32_t supportedPerFrameMetadata) override;
+ void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
+ const Rect& viewport, int32_t supportedPerFrameMetadata) override;
bool onPreComposition(nsecs_t refreshStartTime) override;
bool onPostComposition(const std::optional<DisplayId>& displayId,
@@ -93,11 +93,7 @@
// the visible regions need to be recomputed (this is a fairly heavy
// operation, so this should be set only if needed). Typically this is used
// to figure out if the content or size of a surface has changed.
- // If there was a GL composition step rendering the previous frame, then
- // releaseFence will be populated with a native fence that fires when
- // composition has completed.
- bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) override;
+ bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
bool isBufferLatched() const override { return mRefreshPending; }
@@ -142,13 +138,12 @@
virtual void setFilteringEnabled(bool enabled) = 0;
virtual status_t bindTextureImage() = 0;
- virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& flushFence) = 0;
+ virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
virtual status_t updateActiveBuffer() = 0;
virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
- virtual void setHwcLayerBuffer(DisplayId displayId) = 0;
+ virtual void setHwcLayerBuffer(const sp<const DisplayDevice>& displayDevice) = 0;
protected:
// Loads the corresponding system property once per process
@@ -177,7 +172,7 @@
private:
// Returns true if this layer requires filtering
- bool needsFiltering() const;
+ bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const;
uint64_t getHeadFrameNumber() const;
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 7ed8184..6866e5c 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -100,8 +100,7 @@
status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
bool* autoRefresh, bool* queuedBuffer,
- uint64_t maxFrameNumber,
- const sp<Fence>& releaseFence) {
+ uint64_t maxFrameNumber) {
ATRACE_CALL();
BLC_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex);
@@ -146,7 +145,7 @@
}
// Release the previous buffer.
- err = updateAndReleaseLocked(item, &mPendingRelease, releaseFence);
+ err = updateAndReleaseLocked(item, &mPendingRelease);
if (err != NO_ERROR) {
return err;
}
@@ -224,25 +223,11 @@
}
status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease,
- const sp<Fence>& releaseFence) {
+ PendingRelease* pendingRelease) {
status_t err = NO_ERROR;
int slot = item.mSlot;
- // Do whatever sync ops we need to do before releasing the old slot.
- if (slot != mCurrentTexture) {
- err = syncForReleaseLocked(releaseFence);
- if (err != NO_ERROR) {
- // Release the buffer we just acquired. It's not safe to
- // release the old buffer, so instead we just drop the new frame.
- // As we are still under lock since acquireBuffer, it is safe to
- // release by slot.
- releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
- return err;
- }
- }
-
BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
mCurrentTextureBuffer != nullptr ? mCurrentTextureBuffer->handle : 0, slot,
mSlots[slot].mGraphicBuffer->handle);
@@ -298,30 +283,6 @@
return mRE.bindExternalTextureBuffer(mTexName, mCurrentTextureBuffer, mCurrentFence, false);
}
-status_t BufferLayerConsumer::syncForReleaseLocked(const sp<Fence>& releaseFence) {
- BLC_LOGV("syncForReleaseLocked");
-
- if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- if (mRE.useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
- // TODO(alecmouri): fail further upstream if the fence is invalid
- if (!releaseFence->isValid()) {
- BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine");
- return UNKNOWN_ERROR;
- }
- status_t err =
- addReleaseFenceLocked(mCurrentTexture, mCurrentTextureBuffer, releaseFence);
- if (err != OK) {
- BLC_LOGE("syncForReleaseLocked: error adding release fence: "
- "%s (%d)",
- strerror(-err), err);
- return err;
- }
- }
- }
-
- return OK;
-}
-
void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
Mutex::Autolock lock(mMutex);
memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index e2ef399..e2a6d2e 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -92,8 +92,7 @@
// used to reject the newly acquired buffer. It also does not bind the
// RenderEngine texture until bindTextureImage is called.
status_t updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
- bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber,
- const sp<Fence>& releaseFence);
+ bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber);
// See BufferLayerConsumer::bindTextureImageLocked().
status_t bindTextureImage();
@@ -212,8 +211,7 @@
// completion of the method will instead be returned to the caller, so that
// it may call releaseBufferLocked itself later.
status_t updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease = nullptr,
- const sp<Fence>& releaseFence = Fence::NO_FENCE);
+ PendingRelease* pendingRelease = nullptr);
// Binds mTexName and the current buffer to TEXTURE_EXTERNAL target.
// If the bind succeeds, this calls doFenceWait.
@@ -244,12 +242,6 @@
// access the current texture buffer.
status_t doFenceWaitLocked() const;
- // syncForReleaseLocked performs the synchronization needed to release the
- // current slot from RenderEngine. If needed it will set the current
- // slot's fence to guard against a producer accessing the buffer before
- // the outstanding accesses have completed.
- status_t syncForReleaseLocked(const sp<Fence>& releaseFence);
-
// The default consumer usage flags that BufferLayerConsumer always sets on its
// BufferQueue instance; these will be OR:d with any additional flags passed
// from the BufferLayerConsumer user. In particular, BufferLayerConsumer will always
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 0313c32..b3e2a4b 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -14,13 +14,18 @@
* limitations under the License.
*/
+#include <compositionengine/Display.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/LayerCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <system/window.h>
+
#include "BufferQueueLayer.h"
#include "LayerRejecter.h"
#include "TimeStats/TimeStats.h"
-#include <system/window.h>
-
namespace android {
BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
@@ -195,8 +200,9 @@
if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
// mSidebandStreamChanged was changed to false
// replicated in LayerBE until FE/BE is ready to be synchronized
- getBE().compositionInfo.hwc.sidebandStream = mConsumer->getSidebandStream();
- if (getBE().compositionInfo.hwc.sidebandStream != nullptr) {
+ auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
+ layerCompositionState.sidebandStream = mConsumer->getSidebandStream();
+ if (layerCompositionState.sidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
@@ -219,8 +225,7 @@
return mConsumer->bindTextureImage();
}
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) {
+status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) {
// This boolean is used to make sure that SurfaceFlinger's shadow copy
// of the buffer queue isn't modified when the buffer queue is returning
// BufferItem's that weren't actually queued. This can happen in shared
@@ -231,9 +236,11 @@
getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
getTransformToDisplayInverse(), mFreezeGeometryUpdates);
- const nsecs_t expectedPresentTime = mFlinger->mUseScheduler
- ? mFlinger->mScheduler->expectedPresentTime()
- : mFlinger->mPrimaryDispSync->expectedPresentTime();
+ nsecs_t expectedPresentTime = mFlinger->mScheduler->expectedPresentTime();
+
+ if (isRemovedFromCurrentState()) {
+ expectedPresentTime = 0;
+ }
// updateTexImage() below might drop the some buffers at the head of the queue if there is a
// buffer behind them which is timely to be presented. However this buffer may not be signaled
@@ -253,9 +260,9 @@
}
const uint64_t maxFrameNumberToAcquire =
std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
- status_t updateResult =
- mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
- maxFrameNumberToAcquire, releaseFence);
+
+ status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
+ &queuedBuffer, maxFrameNumberToAcquire);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
@@ -325,8 +332,9 @@
status_t BufferQueueLayer::updateActiveBuffer() {
// update the active buffer
mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence);
- getBE().compositionInfo.mBuffer = mActiveBuffer;
- getBE().compositionInfo.mBufferSlot = mActiveBufferSlot;
+ auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
+ layerCompositionState.buffer = mActiveBuffer;
+ layerCompositionState.bufferSlot = mActiveBufferSlot;
if (mActiveBuffer == nullptr) {
// this can only happen if the very first buffer was rejected.
@@ -350,24 +358,28 @@
return NO_ERROR;
}
-void BufferQueueLayer::setHwcLayerBuffer(DisplayId displayId) {
- auto& hwcInfo = getBE().mHwcLayers[displayId];
- auto& hwcLayer = hwcInfo.layer;
+void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+ LOG_FATAL_IF(!outputLayer->getState.hwc);
+ auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
uint32_t hwcSlot = 0;
sp<GraphicBuffer> hwcBuffer;
- hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer);
+ (*outputLayer->editState().hwc)
+ .hwcBufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer);
auto acquireFence = mConsumer->getCurrentFence();
auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
- getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle,
+ to_string(error).c_str(), static_cast<int32_t>(error));
}
- getBE().compositionInfo.mBufferSlot = mActiveBufferSlot;
- getBE().compositionInfo.mBuffer = mActiveBuffer;
- getBE().compositionInfo.hwc.fence = acquireFence;
+
+ auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
+ layerCompositionState.bufferSlot = mActiveBufferSlot;
+ layerCompositionState.buffer = mActiveBuffer;
+ layerCompositionState.acquireFence = acquireFence;
}
// -----------------------------------------------------------------------
@@ -377,7 +389,7 @@
void BufferQueueLayer::fakeVsync() {
mRefreshPending = false;
bool ignored = false;
- latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
+ latchBuffer(ignored, systemTime());
usleep(16000);
releasePendingBuffer(systemTime());
}
@@ -386,10 +398,8 @@
// Add this buffer from our internal queue tracker
{ // Autolock scope
// Report the requested present time to the Scheduler.
- if (mFlinger->mUseScheduler) {
- mFlinger->mScheduler->addFramePresentTimeForLayer(item.mTimestamp,
- item.mIsAutoTimestamp, mName.c_str());
- }
+ mFlinger->mScheduler->addFramePresentTimeForLayer(item.mTimestamp, item.mIsAutoTimestamp,
+ mName.c_str());
Mutex::Autolock lock(mQueueItemLock);
// Reset the frame number tracker when we receive the first buffer after
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index d392a69..fbb8c14 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -91,13 +91,12 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void setHwcLayerBuffer(DisplayId displayId) override;
+ void setHwcLayerBuffer(const sp<const DisplayDevice>& displayDevice) override;
// -----------------------------------------------------------------------
// Interface implementation for BufferLayerConsumer::ContentsChangedListener
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 2d6da76..e48c41e 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -19,15 +19,19 @@
#define LOG_TAG "BufferStateLayer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include "BufferStateLayer.h"
-#include "ColorLayer.h"
+#include <limits>
-#include "TimeStats/TimeStats.h"
-
+#include <compositionengine/Display.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/LayerCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <private/gui/SyncFeatures.h>
#include <renderengine/Image.h>
-#include <limits>
+#include "BufferStateLayer.h"
+#include "ColorLayer.h"
+#include "TimeStats/TimeStats.h"
namespace android {
@@ -438,9 +442,10 @@
if (mSidebandStreamChanged.exchange(false)) {
const State& s(getDrawingState());
// mSidebandStreamChanged was true
- // replicated in LayerBE until FE/BE is ready to be synchronized
- getBE().compositionInfo.hwc.sidebandStream = s.sidebandStream;
- if (getBE().compositionInfo.hwc.sidebandStream != nullptr) {
+ LOG_ALWAYS_FATAL_IF(!getCompositionLayer());
+ mSidebandStream = s.sidebandStream;
+ getCompositionLayer()->editState().frontEnd.sidebandStream = mSidebandStream;
+ if (mSidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
@@ -468,8 +473,7 @@
return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence, false);
}
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
- const sp<Fence>& releaseFence) {
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
const State& s(getDrawingState());
if (!s.buffer) {
@@ -511,59 +515,7 @@
handle->latchTime = latchTime;
}
- // Handle sync fences
- if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
- // TODO(alecmouri): Fail somewhere upstream if the fence is invalid.
- if (!releaseFence->isValid()) {
- mFlinger->mTimeStats->onDestroy(layerID);
- return UNKNOWN_ERROR;
- }
-
- // Check status of fences first because merging is expensive.
- // Merging an invalid fence with any other fence results in an
- // invalid fence.
- auto currentStatus = s.acquireFence->getStatus();
- if (currentStatus == Fence::Status::Invalid) {
- ALOGE("Existing fence has invalid state");
- mFlinger->mTimeStats->onDestroy(layerID);
- return BAD_VALUE;
- }
-
- auto incomingStatus = releaseFence->getStatus();
- if (incomingStatus == Fence::Status::Invalid) {
- ALOGE("New fence has invalid state");
- mDrawingState.acquireFence = releaseFence;
- mFlinger->mTimeStats->onDestroy(layerID);
- return BAD_VALUE;
- }
-
- // If both fences are signaled or both are unsignaled, we need to merge
- // them to get an accurate timestamp.
- if (currentStatus == incomingStatus) {
- char fenceName[32] = {};
- snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber);
- sp<Fence> mergedFence =
- Fence::merge(fenceName, mDrawingState.acquireFence, releaseFence);
- if (!mergedFence.get()) {
- ALOGE("failed to merge release fences");
- // synchronization is broken, the best we can do is hope fences
- // signal in order so the new fence will act like a union
- mDrawingState.acquireFence = releaseFence;
- mFlinger->mTimeStats->onDestroy(layerID);
- return BAD_VALUE;
- }
- mDrawingState.acquireFence = mergedFence;
- } else if (incomingStatus == Fence::Status::Unsignaled) {
- // If one fence has signaled and the other hasn't, the unsignaled
- // fence will approximately correspond with the correct timestamp.
- // There's a small race if both fences signal at about the same time
- // and their statuses are retrieved with unfortunate timing. However,
- // by this point, they will have both signaled and only the timestamp
- // will be slightly off; any dependencies after this point will
- // already have been met.
- mDrawingState.acquireFence = releaseFence;
- }
- } else {
+ if (!SyncFeatures::getInstance().useNativeFenceSync()) {
// Bind the new buffer to the GL texture.
//
// Older devices require the "implicit" synchronization provided
@@ -594,8 +546,9 @@
mActiveBuffer = s.buffer;
mActiveBufferFence = s.acquireFence;
- getBE().compositionInfo.mBuffer = mActiveBuffer;
- getBE().compositionInfo.mBufferSlot = 0;
+ auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
+ layerCompositionState.buffer = mActiveBuffer;
+ layerCompositionState.bufferSlot = 0;
return NO_ERROR;
}
@@ -611,9 +564,10 @@
return NO_ERROR;
}
-void BufferStateLayer::setHwcLayerBuffer(DisplayId displayId) {
- auto& hwcInfo = getBE().mHwcLayers[displayId];
- auto& hwcLayer = hwcInfo.layer;
+void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
+ auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
const State& s(getDrawingState());
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 3320c5b..0b03f49 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -125,13 +125,12 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void setHwcLayerBuffer(DisplayId displayId) override;
+ void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override;
private:
void onFirstRef() override;
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0ca3759..e54b460 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -17,7 +17,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include <binder/PermissionCache.h>
#include <binder/IPCThreadState.h>
#include <private/android_filesystem_config.h>
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index d82ff0e..9ea0a46 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -23,8 +23,12 @@
#include <sys/types.h>
#include <compositionengine/CompositionEngine.h>
+#include <compositionengine/Display.h>
#include <compositionengine/Layer.h>
#include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/LayerCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <renderengine/RenderEngine.h>
#include <ui/GraphicBuffer.h>
#include <utils/Errors.h>
@@ -73,30 +77,36 @@
return true;
}
-void ColorLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform,
- const Rect& viewport, int32_t /* supportedPerFrameMetadata */) {
- RETURN_IF_NO_HWC_LAYER(displayId);
+void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& display,
+ const ui::Transform& transform, const Rect& viewport,
+ int32_t /* supportedPerFrameMetadata */) {
+ RETURN_IF_NO_HWC_LAYER(display);
Region visible = transform.transform(visibleRegion.intersect(viewport));
- auto& hwcInfo = getBE().mHwcLayers[displayId];
- auto& hwcLayer = hwcInfo.layer;
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
+
+ auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
+
auto error = hwcLayer->setVisibleRegion(visible);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
visible.dump(LOG_TAG);
}
- getBE().compositionInfo.hwc.visibleRegion = visible;
+ outputLayer->editState().visibleRegion = visible;
- setCompositionType(displayId, HWC2::Composition::SolidColor);
+ setCompositionType(display, Hwc2::IComposerClient::Composition::SOLID_COLOR);
error = hwcLayer->setDataspace(mCurrentDataSpace);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace,
to_string(error).c_str(), static_cast<int32_t>(error));
}
- getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
+
+ auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
+ layerCompositionState.dataspace = mCurrentDataSpace;
half4 color = getColor();
error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
@@ -106,9 +116,9 @@
ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(),
static_cast<int32_t>(error));
}
- getBE().compositionInfo.hwc.color = { static_cast<uint8_t>(std::round(255.0f * color.r)),
- static_cast<uint8_t>(std::round(255.0f * color.g)),
- static_cast<uint8_t>(std::round(255.0f * color.b)), 255 };
+ layerCompositionState.color = {static_cast<uint8_t>(std::round(255.0f * color.r)),
+ static_cast<uint8_t>(std::round(255.0f * color.g)),
+ static_cast<uint8_t>(std::round(255.0f * color.b)), 255};
// Clear out the transform, because it doesn't make sense absent a source buffer
error = hwcLayer->setTransform(HWC2::Transform::None);
@@ -116,14 +126,14 @@
ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(),
static_cast<int32_t>(error));
}
- getBE().compositionInfo.hwc.transform = HWC2::Transform::None;
+ outputLayer->editState().bufferTransform = static_cast<Hwc2::Transform>(0);
error = hwcLayer->setColorTransform(getColorTransform());
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
}
- getBE().compositionInfo.hwc.colorTransform = getColorTransform();
+ layerCompositionState.colorTransform = getColorTransform();
error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
if (error != HWC2::Error::None) {
@@ -131,7 +141,7 @@
to_string(error).c_str(), static_cast<int32_t>(error));
surfaceDamageRegion.dump(LOG_TAG);
}
- getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion;
+ layerCompositionState.surfaceDamage = surfaceDamageRegion;
}
std::shared_ptr<compositionengine::Layer> ColorLayer::getCompositionLayer() const {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index ed4c2d8..df0adac 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -35,8 +35,8 @@
bool setColor(const half3& color) override;
- void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
- int32_t supportedPerFrameMetadata) override;
+ void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
+ const Rect& viewport, int32_t supportedPerFrameMetadata) override;
bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; }
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index ce6b06c..e86d35d 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -5,6 +5,7 @@
"-DLOG_TAG=\"CompositionEngine\"",
],
shared_libs: [
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
@@ -28,6 +29,9 @@
"libtrace_proto",
],
header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ "android.hardware.graphics.composer@2.3-command-buffer",
"libsurfaceflinger_headers",
],
}
@@ -43,9 +47,11 @@
"src/DumpHelpers.cpp",
"src/HwcBufferCache.cpp",
"src/Layer.cpp",
+ "src/LayerCompositionState.cpp",
"src/Output.cpp",
"src/OutputCompositionState.cpp",
"src/OutputLayer.cpp",
+ "src/OutputLayerCompositionState.cpp",
"src/RenderSurface.cpp",
],
local_include_dirs: ["include"],
@@ -85,6 +91,7 @@
"tests/DisplayTest.cpp",
"tests/HwcBufferCacheTest.cpp",
"tests/LayerTest.cpp",
+ "tests/MockHWC2.cpp",
"tests/MockHWComposer.cpp",
"tests/OutputTest.cpp",
"tests/OutputLayerTest.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
index 29a7dea..8cb9203 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
@@ -17,6 +17,7 @@
#pragma once
#include <cstdint>
+#include <string>
#include <utils/StrongPointer.h>
@@ -29,6 +30,10 @@
class Display;
class LayerFE;
+namespace impl {
+struct LayerCompositionState;
+} // namespace impl
+
/**
* A layer contains the output-independent composition state for a front-end
* Layer
@@ -40,6 +45,21 @@
// Gets the front-end interface for this layer. Can return nullptr if the
// front-end layer no longer exists.
virtual sp<LayerFE> getLayerFE() const = 0;
+
+ using CompositionState = impl::LayerCompositionState;
+
+ // Gets the raw composition state data for the layer
+ // TODO(lpique): Make this protected once it is only internally called.
+ virtual const CompositionState& getState() const = 0;
+
+ // Allows mutable access to the raw composition state data for the layer.
+ // This is meant to be used by the various functions that are part of the
+ // composition process.
+ // TODO(lpique): Make this protected once it is only internally called.
+ virtual CompositionState& editState() = 0;
+
+ // Debugging
+ virtual void dump(std::string& result) const = 0;
};
} // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
new file mode 100644
index 0000000..785a6d7
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <gui/BufferQueue.h>
+#include <gui/HdrMetadata.h>
+#include <math/mat4.h>
+#include <ui/FloatRect.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicTypes.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <ui/Transform.h>
+
+#include "DisplayHardware/ComposerHal.h"
+
+namespace android::compositionengine {
+
+/*
+ * Used by LayerFE::getCompositionState
+ */
+struct LayerFECompositionState {
+ // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
+ // value recomputed / set every frame.
+ Region geomVisibleRegion;
+
+ /*
+ * Presentation
+ */
+
+ // The blend mode for this layer
+ Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID};
+
+ // The alpha value for this layer
+ float alpha{1.f};
+
+ /*
+ * Extra metadata
+ */
+
+ // The type for this layer
+ int type{0};
+
+ // The appId for this layer
+ int appId{0};
+
+ /*
+ * Per-frame content
+ */
+
+ // The type of composition for this layer
+ Hwc2::IComposerClient::Composition compositionType{Hwc2::IComposerClient::Composition::INVALID};
+
+ // The buffer and related state
+ sp<GraphicBuffer> buffer;
+ int bufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
+ sp<Fence> acquireFence;
+ Region surfaceDamage;
+
+ // The handle to use for a sideband stream for this layer
+ sp<NativeHandle> sidebandStream;
+
+ // The color for this layer
+ Hwc2::IComposerClient::Color color;
+
+ /*
+ * Per-frame presentation state
+ */
+
+ // The dataspace for this layer
+ ui::Dataspace dataspace{ui::Dataspace::UNKNOWN};
+
+ // The metadata for this layer
+ HdrMetadata hdrMetadata;
+
+ // The color transform
+ mat4 colorTransform;
+};
+
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 84b2423..54e6bd6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -17,6 +17,7 @@
#pragma once
#include <cstdint>
+#include <optional>
#include <string>
#include <math/mat4.h>
@@ -25,6 +26,8 @@
#include <ui/Transform.h>
#include <utils/StrongPointer.h>
+#include "DisplayHardware/DisplayIdentification.h"
+
namespace android::compositionengine {
class DisplayColorProfile;
@@ -117,7 +120,8 @@
// Gets the OutputLayer corresponding to the input Layer instance from the
// current ordered set of output layers. If there is no such layer, a new
// one is created and returned.
- virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::shared_ptr<Layer>,
+ virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::optional<DisplayId>,
+ std::shared_ptr<Layer>,
sp<LayerFE>) = 0;
// Sets the new ordered set of output layers for this output
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index 4b8ef38..e7a17c4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -16,14 +16,26 @@
#pragma once
+#include <optional>
+#include <string>
+
#include <utils/StrongPointer.h>
-namespace android::compositionengine {
+#include "DisplayHardware/DisplayIdentification.h"
+namespace android {
+
+namespace compositionengine {
+
+class CompositionEngine;
class Output;
class Layer;
class LayerFE;
+namespace impl {
+struct OutputLayerCompositionState;
+} // namespace impl
+
/**
* An output layer contains the output-dependent composition state for a layer
*/
@@ -39,6 +51,22 @@
// Gets the front-end layer interface this output layer represents
virtual LayerFE& getLayerFE() const = 0;
+
+ using CompositionState = compositionengine::impl::OutputLayerCompositionState;
+
+ // Gets the raw composition state data for the layer
+ // TODO(lpique): Make this protected once it is only internally called.
+ virtual const CompositionState& getState() const = 0;
+
+ // Allows mutable access to the raw composition state data for the layer.
+ // This is meant to be used by the various functions that are part of the
+ // composition process.
+ // TODO(lpique): Make this protected once it is only internally called.
+ virtual CompositionState& editState() = 0;
+
+ // Debugging
+ virtual void dump(std::string& result) const = 0;
};
-} // namespace android::compositionengine
+} // namespace compositionengine
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index ddeb730..2009380 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -29,8 +29,6 @@
class GraphicBuffer;
-struct CompositionInfo;
-
namespace compositionengine {
/**
@@ -70,7 +68,7 @@
virtual status_t beginFrame(bool mustRecompose) = 0;
// Prepares the frame for rendering
- virtual status_t prepareFrame(std::vector<CompositionInfo>& compositionData) = 0;
+ virtual status_t prepareFrame() = 0;
// Allocates a buffer as scratch space for GPU composition
virtual sp<GraphicBuffer> dequeueBuffer() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
index 631351b..3e56b21 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
@@ -19,6 +19,7 @@
#include <memory>
#include <compositionengine/Layer.h>
+#include <compositionengine/impl/LayerCompositionState.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
@@ -40,9 +41,16 @@
sp<LayerFE> getLayerFE() const override;
+ const LayerCompositionState& getState() const override;
+ LayerCompositionState& editState() override;
+
+ void dump(std::string& result) const override;
+
private:
const compositionengine::CompositionEngine& mCompositionEngine;
const wp<LayerFE> mLayerFE;
+
+ LayerCompositionState mState;
};
std::shared_ptr<compositionengine::Layer> createLayer(const compositionengine::CompositionEngine&,
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
new file mode 100644
index 0000000..67bea4b
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+#include <compositionengine/LayerFECompositionState.h>
+#include <renderengine/Mesh.h>
+
+namespace android {
+
+namespace compositionengine::impl {
+
+struct LayerCompositionState {
+ /*
+ * State intended to be set by LayerFE::getCompositionState
+ */
+
+ LayerFECompositionState frontEnd;
+
+ /*
+ * RE state
+ */
+
+ renderengine::Mesh reMesh{renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2};
+
+ // Debugging
+ void dump(std::string& result) const;
+};
+
+} // namespace compositionengine::impl
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 3fd057c..b1d1f42 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -67,7 +67,8 @@
compositionengine::OutputLayer* getOutputLayerForLayer(
compositionengine::Layer*) const override;
std::unique_ptr<compositionengine::OutputLayer> getOrCreateOutputLayer(
- std::shared_ptr<compositionengine::Layer>, sp<LayerFE>) override;
+ std::optional<DisplayId>, std::shared_ptr<compositionengine::Layer>,
+ sp<LayerFE>) override;
void setOutputLayersOrderedByZ(OutputLayers&&) override;
const OutputLayers& getOutputLayersOrderedByZ() const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index f3d0258..d8f0cdd 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -17,8 +17,12 @@
#pragma once
#include <memory>
+#include <string>
#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+
+#include "DisplayHardware/DisplayIdentification.h"
namespace android::compositionengine::impl {
@@ -28,18 +32,27 @@
sp<compositionengine::LayerFE>);
~OutputLayer() override;
+ void initialize(const CompositionEngine&, std::optional<DisplayId>);
+
const compositionengine::Output& getOutput() const override;
compositionengine::Layer& getLayer() const override;
compositionengine::LayerFE& getLayerFE() const override;
+ const OutputLayerCompositionState& getState() const override;
+ OutputLayerCompositionState& editState() override;
+
+ void dump(std::string& result) const override;
+
private:
const compositionengine::Output& mOutput;
std::shared_ptr<compositionengine::Layer> mLayer;
sp<compositionengine::LayerFE> mLayerFE;
+
+ OutputLayerCompositionState mState;
};
std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
- const compositionengine::Output&, std::shared_ptr<compositionengine::Layer>,
- sp<compositionengine::LayerFE>);
+ const CompositionEngine&, std::optional<DisplayId>, const compositionengine::Output&,
+ std::shared_ptr<compositionengine::Layer>, sp<compositionengine::LayerFE>);
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
new file mode 100644
index 0000000..b78e9e0
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <optional>
+#include <string>
+
+#include <compositionengine/impl/HwcBufferCache.h>
+#include <renderengine/Mesh.h>
+#include <ui/FloatRect.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include "DisplayHardware/ComposerHal.h"
+
+namespace HWC2 {
+class Layer;
+} // namespace HWC2
+
+namespace android {
+
+class HWComposer;
+
+namespace compositionengine::impl {
+
+struct OutputLayerCompositionState {
+ // The region of this layer which is visible on this output
+ Region visibleRegion;
+
+ // If true, client composition will be used on this output
+ bool forceClientComposition{false};
+
+ // If true, when doing client composition, the target may need to be cleared
+ bool clearClientTarget{false};
+
+ // The display frame for this layer on this output
+ Rect displayFrame;
+
+ // The source crop for this layer on this output
+ FloatRect sourceCrop;
+
+ // The buffer transform to use for this layer o on this output.
+ Hwc2::Transform bufferTransform{static_cast<Hwc2::Transform>(0)};
+
+ // The Z order index of this layer on this output
+ uint32_t z;
+
+ /*
+ * HWC state
+ */
+
+ struct Hwc {
+ explicit Hwc(std::shared_ptr<HWC2::Layer> hwcLayer) : hwcLayer(hwcLayer) {}
+
+ // The HWC Layer backing this layer
+ std::shared_ptr<HWC2::Layer> hwcLayer;
+
+ // The HWC composition type for this layer
+ Hwc2::IComposerClient::Composition hwcCompositionType{
+ Hwc2::IComposerClient::Composition::INVALID};
+
+ // The buffer cache for this layer. This is used to lower the
+ // cost of sending reused buffers to the HWC.
+ HwcBufferCache hwcBufferCache;
+ };
+
+ // The HWC state is optional, and is only set up if there is any potential
+ // HWC acceleration possible.
+ std::optional<Hwc> hwc;
+
+ // Debugging
+ void dump(std::string& result) const;
+};
+
+} // namespace compositionengine::impl
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 2f0fceb..58b13ed 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -51,7 +51,7 @@
void setDisplaySize(const ui::Size&) override;
void setProtected(bool useProtected) override;
status_t beginFrame(bool mustRecompose) override;
- status_t prepareFrame(std::vector<CompositionInfo>& compositionData) override;
+ status_t prepareFrame() override;
sp<GraphicBuffer> dequeueBuffer() override;
void queueBuffer(base::unique_fd&& readyFence) override;
void onPresentDisplayCompleted() override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h
index a7cc08e..cce3b97 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h
@@ -18,6 +18,7 @@
#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
+#include <compositionengine/impl/LayerCompositionState.h>
#include <gmock/gmock.h>
namespace android::compositionengine::mock {
@@ -28,6 +29,11 @@
virtual ~Layer();
MOCK_CONST_METHOD0(getLayerFE, sp<LayerFE>());
+
+ MOCK_CONST_METHOD0(getState, const CompositionState&());
+ MOCK_METHOD0(editState, CompositionState&());
+
+ MOCK_CONST_METHOD1(dump, void(std::string&));
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 2972ad7..d0e7b19 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -61,9 +61,9 @@
MOCK_CONST_METHOD1(getOutputLayerForLayer,
compositionengine::OutputLayer*(compositionengine::Layer*));
- MOCK_METHOD2(getOrCreateOutputLayer,
+ MOCK_METHOD3(getOrCreateOutputLayer,
std::unique_ptr<compositionengine::OutputLayer>(
- std::shared_ptr<compositionengine::Layer>,
+ std::optional<DisplayId>, std::shared_ptr<compositionengine::Layer>,
sp<compositionengine::LayerFE>));
MOCK_METHOD1(setOutputLayersOrderedByZ, void(OutputLayers&&));
MOCK_CONST_METHOD0(getOutputLayersOrderedByZ, OutputLayers&());
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index f5e5026..54c7407 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -16,10 +16,12 @@
#pragma once
+#include <compositionengine/CompositionEngine.h>
#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/Output.h>
#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <gmock/gmock.h>
namespace android::compositionengine::mock {
@@ -32,6 +34,11 @@
MOCK_CONST_METHOD0(getOutput, const compositionengine::Output&());
MOCK_CONST_METHOD0(getLayer, compositionengine::Layer&());
MOCK_CONST_METHOD0(getLayerFE, compositionengine::LayerFE&());
+
+ MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&());
+ MOCK_METHOD0(editState, impl::OutputLayerCompositionState&());
+
+ MOCK_CONST_METHOD1(dump, void(std::string&));
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index e9ff330..8442bef 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -20,7 +20,6 @@
#include <gmock/gmock.h>
#include <ui/GraphicBuffer.h>
-#include "LayerBE.h"
namespace android::compositionengine::mock {
@@ -37,7 +36,7 @@
MOCK_METHOD1(setProtected, void(bool));
MOCK_METHOD1(setBufferDataspace, void(ui::Dataspace));
MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
- MOCK_METHOD1(prepareFrame, status_t(std::vector<CompositionInfo>& compositionData));
+ MOCK_METHOD0(prepareFrame, status_t());
MOCK_METHOD0(dequeueBuffer, sp<GraphicBuffer>());
MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
MOCK_METHOD0(onPresentDisplayCompleted, void());
diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp
index aaa758e..109e9f8 100644
--- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <android-base/stringprintf.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/LayerCreationArgs.h>
#include <compositionengine/LayerFE.h>
@@ -42,5 +43,18 @@
return mLayerFE.promote();
}
+const LayerCompositionState& Layer::getState() const {
+ return mState;
+}
+
+LayerCompositionState& Layer::editState() {
+ return mState;
+}
+
+void Layer::dump(std::string& out) const {
+ android::base::StringAppendF(&out, " Layer %p\n", this);
+ mState.dump(out);
+}
+
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
new file mode 100644
index 0000000..517b641
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright 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 <android-base/stringprintf.h>
+#include <compositionengine/impl/DumpHelpers.h>
+#include <compositionengine/impl/LayerCompositionState.h>
+
+namespace android::compositionengine::impl {
+
+namespace {
+
+using android::compositionengine::impl::dumpVal;
+
+void dumpVal(std::string& out, const char* name, Hwc2::IComposerClient::Color value) {
+ using android::base::StringAppendF;
+ StringAppendF(&out, "%s=[%d %d %d] ", name, value.r, value.g, value.b);
+}
+
+void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) {
+ out.append(" ");
+ dumpVal(out, "blend", toString(state.blendMode), state.blendMode);
+ dumpVal(out, "alpha", state.alpha);
+
+ out.append("\n ");
+ dumpVal(out, "type", state.type);
+ dumpVal(out, "appId", state.appId);
+
+ dumpVal(out, "composition type", toString(state.compositionType), state.compositionType);
+
+ out.append("\n buffer: ");
+ dumpVal(out, "buffer", state.buffer.get());
+ dumpVal(out, "slot", state.bufferSlot);
+
+ out.append("\n ");
+ dumpVal(out, "sideband stream", state.sidebandStream.get());
+
+ out.append("\n ");
+ dumpVal(out, "color", state.color);
+
+ out.append("\n ");
+ dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace);
+ dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes);
+ dumpVal(out, "colorTransform", state.colorTransform);
+
+ out.append("\n");
+}
+
+} // namespace
+
+void LayerCompositionState::dump(std::string& out) const {
+ out.append(" frontend:\n");
+ dumpFrontEnd(out, frontEnd);
+}
+
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index e103ebe..ad4c7bf 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -146,6 +146,14 @@
} else {
out.append(" No render surface!\n");
}
+
+ out.append("\n %d Layers", mOutputLayersOrderedByZ.size());
+ for (const auto& outputLayer : mOutputLayersOrderedByZ) {
+ if (!outputLayer) {
+ continue;
+ }
+ outputLayer->dump(out);
+ }
}
compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
@@ -209,13 +217,14 @@
}
std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
- std::shared_ptr<compositionengine::Layer> layer, sp<compositionengine::LayerFE> layerFE) {
+ std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
+ sp<compositionengine::LayerFE> layerFE) {
for (auto& outputLayer : mOutputLayersOrderedByZ) {
if (outputLayer && &outputLayer->getLayer() == layer.get()) {
return std::move(outputLayer);
}
}
- return createOutputLayer(*this, layer, layerFE);
+ return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
}
void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index e95f3a6..10da49d 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -14,11 +14,15 @@
* limitations under the License.
*/
+#include <android-base/stringprintf.h>
+#include <compositionengine/CompositionEngine.h>
#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/Output.h>
#include <compositionengine/impl/OutputLayer.h>
+#include "DisplayHardware/HWComposer.h"
+
namespace android::compositionengine {
OutputLayer::~OutputLayer() = default;
@@ -26,9 +30,12 @@
namespace impl {
std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
- const compositionengine::Output& display, std::shared_ptr<compositionengine::Layer> layer,
+ const CompositionEngine& compositionEngine, std::optional<DisplayId> displayId,
+ const compositionengine::Output& output, std::shared_ptr<compositionengine::Layer> layer,
sp<compositionengine::LayerFE> layerFE) {
- return std::make_unique<OutputLayer>(display, layer, layerFE);
+ auto result = std::make_unique<OutputLayer>(output, layer, layerFE);
+ result->initialize(compositionEngine, displayId);
+ return result;
}
OutputLayer::OutputLayer(const Output& output, std::shared_ptr<Layer> layer, sp<LayerFE> layerFE)
@@ -36,6 +43,20 @@
OutputLayer::~OutputLayer() = default;
+void OutputLayer::initialize(const CompositionEngine& compositionEngine,
+ std::optional<DisplayId> displayId) {
+ if (!displayId) {
+ return;
+ }
+
+ auto& hwc = compositionEngine.getHwComposer();
+
+ mState.hwc.emplace(std::shared_ptr<HWC2::Layer>(hwc.createLayer(*displayId),
+ [&hwc, displayId](HWC2::Layer* layer) {
+ hwc.destroyLayer(*displayId, layer);
+ }));
+}
+
const compositionengine::Output& OutputLayer::getOutput() const {
return mOutput;
}
@@ -48,5 +69,20 @@
return *mLayerFE;
}
+const OutputLayerCompositionState& OutputLayer::getState() const {
+ return mState;
+}
+
+OutputLayerCompositionState& OutputLayer::editState() {
+ return mState;
+}
+
+void OutputLayer::dump(std::string& out) const {
+ using android::base::StringAppendF;
+
+ StringAppendF(&out, " Output Layer %p\n", this);
+ mState.dump(out);
+}
+
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
new file mode 100644
index 0000000..10f27b8
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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 <compositionengine/impl/DumpHelpers.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+
+#include "DisplayHardware/HWC2.h"
+
+namespace android::compositionengine::impl {
+
+namespace {
+
+void dumpHwc(const OutputLayerCompositionState::Hwc& hwc, std::string& out) {
+ out.append("\n hwc: ");
+
+ if (hwc.hwcLayer == nullptr) {
+ out.append("No layer ");
+ } else {
+ dumpHex(out, "layer", hwc.hwcLayer->getId());
+ }
+
+ dumpVal(out, "composition", toString(hwc.hwcCompositionType), hwc.hwcCompositionType);
+}
+
+} // namespace
+
+void OutputLayerCompositionState::dump(std::string& out) const {
+ out.append(" ");
+ dumpVal(out, "visibleRegion", visibleRegion);
+
+ out.append(" ");
+ dumpVal(out, "forceClientComposition", forceClientComposition);
+ dumpVal(out, "clearClientTarget", clearClientTarget);
+ dumpVal(out, "displayFrame", displayFrame);
+ dumpVal(out, "sourceCrop", sourceCrop);
+ dumpVal(out, "bufferTransform%", toString(bufferTransform), bufferTransform);
+ dumpVal(out, "z-index", z);
+
+ if (hwc) {
+ dumpHwc(*hwc, out);
+ }
+
+ out.append("\n");
+}
+
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 3f841d2..ebb1bc2 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -99,11 +99,11 @@
return mDisplaySurface->beginFrame(mustRecompose);
}
-status_t RenderSurface::prepareFrame(std::vector<CompositionInfo>& compositionData) {
+status_t RenderSurface::prepareFrame() {
auto& hwc = mCompositionEngine.getHwComposer();
const auto id = mDisplay.getId();
if (id) {
- status_t error = hwc.prepare(*id, compositionData);
+ status_t error = hwc.prepare(*id, mDisplay);
if (error != NO_ERROR) {
return error;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp
new file mode 100644
index 0000000..8c10341
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 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 "MockHWC2.h"
+
+namespace HWC2 {
+
+// This will go away once HWC2::Layer is moved into the "backend" library
+Layer::~Layer() = default;
+
+namespace mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+Layer::Layer() = default;
+Layer::~Layer() = default;
+
+} // namespace mock
+} // namespace HWC2
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
new file mode 100644
index 0000000..7fd6541
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+#include <ui/Fence.h>
+#include <ui/FloatRect.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicTypes.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <ui/Transform.h>
+
+#include "DisplayHardware/HWC2.h"
+
+namespace HWC2 {
+namespace mock {
+
+class Layer : public HWC2::Layer {
+public:
+ Layer();
+ ~Layer() override;
+
+ MOCK_CONST_METHOD0(getId, hwc2_layer_t());
+
+ MOCK_METHOD2(setCursorPosition, Error(int32_t, int32_t));
+ MOCK_METHOD3(setBuffer,
+ Error(uint32_t, const android::sp<android::GraphicBuffer>&,
+ const android::sp<android::Fence>&));
+ MOCK_METHOD1(setSurfaceDamage, Error(const android::Region&));
+ MOCK_METHOD1(setBlendMode, Error(BlendMode));
+ MOCK_METHOD1(setColor, Error(hwc_color_t));
+ MOCK_METHOD1(setCompositionType, Error(Composition));
+ MOCK_METHOD1(setDataspace, Error(android::ui::Dataspace));
+ MOCK_METHOD2(setPerFrameMetadata, Error(const int32_t, const android::HdrMetadata&));
+ MOCK_METHOD1(setDisplayFrame, Error(const android::Rect&));
+ MOCK_METHOD1(setPlaneAlpha, Error(float));
+ MOCK_METHOD1(setSidebandStream, Error(const native_handle_t*));
+ MOCK_METHOD1(setSourceCrop, Error(const android::FloatRect&));
+ MOCK_METHOD1(setTransform, Error(Transform));
+ MOCK_METHOD1(setVisibleRegion, Error(const android::Region&));
+ MOCK_METHOD1(setZOrder, Error(uint32_t));
+ MOCK_METHOD2(setInfo, Error(uint32_t, uint32_t));
+
+ MOCK_METHOD1(setColorTransform, Error(const android::mat4&));
+};
+
+} // namespace mock
+} // namespace HWC2
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index ece412f..885cdd4 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -16,10 +16,9 @@
#pragma once
+#include <compositionengine/Output.h>
#include <gmock/gmock.h>
-#include "LayerBE.h"
-
#include "DisplayHardware/HWComposer.h"
namespace android {
@@ -41,7 +40,7 @@
std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
- MOCK_METHOD2(prepare, status_t(DisplayId, std::vector<CompositionInfo>&));
+ MOCK_METHOD2(prepare, status_t(DisplayId, const compositionengine::Output&));
MOCK_METHOD5(setClientTarget,
status_t(DisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
ui::Dataspace));
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 0a929ac..f7dcf6f 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -15,16 +15,22 @@
*/
#include <compositionengine/impl/OutputLayer.h>
+#include <compositionengine/mock/CompositionEngine.h>
#include <compositionengine/mock/Layer.h>
#include <compositionengine/mock/LayerFE.h>
#include <compositionengine/mock/Output.h>
#include <gtest/gtest.h>
+#include "MockHWC2.h"
+#include "MockHWComposer.h"
+
namespace android::compositionengine {
namespace {
using testing::StrictMock;
+constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
+
class OutputLayerTest : public testing::Test {
public:
~OutputLayerTest() override = default;
@@ -43,5 +49,37 @@
TEST_F(OutputLayerTest, canInstantiateOutputLayer) {}
+/* ------------------------------------------------------------------------
+ * OutputLayer::initialize()
+ */
+
+TEST_F(OutputLayerTest, initializingOutputLayerWithoutHwcDoesNothingInteresting) {
+ StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
+
+ mOutputLayer.initialize(compositionEngine, std::nullopt);
+
+ EXPECT_FALSE(mOutputLayer.getState().hwc);
+}
+
+TEST_F(OutputLayerTest, initializingOutputLayerWithHwcDisplayCreatesHwcLayer) {
+ StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
+ StrictMock<android::mock::HWComposer> hwc;
+ StrictMock<HWC2::mock::Layer> hwcLayer;
+
+ EXPECT_CALL(compositionEngine, getHwComposer()).WillOnce(ReturnRef(hwc));
+ EXPECT_CALL(hwc, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer));
+
+ mOutputLayer.initialize(compositionEngine, DEFAULT_DISPLAY_ID);
+
+ const auto& state = mOutputLayer.getState();
+ ASSERT_TRUE(state.hwc);
+
+ const auto& hwcState = *state.hwc;
+ EXPECT_EQ(&hwcLayer, hwcState.hwcLayer.get());
+
+ EXPECT_CALL(hwc, destroyLayer(DEFAULT_DISPLAY_ID, &hwcLayer));
+ mOutputLayer.editState().hwc.reset();
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index cb71821..a84af3a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -338,7 +338,7 @@
// If there is no OutputLayer corresponding to the input layer, a
// new OutputLayer is constructed and returned.
EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(otherLayer));
- auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
+ auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
EXPECT_NE(existingOutputLayer, result.get());
EXPECT_TRUE(result.get() != nullptr);
EXPECT_EQ(layer.get(), &result->getLayer());
@@ -354,7 +354,7 @@
// If there is an existing OutputLayer for the requested layer, an owned
// pointer is returned
EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(*layer));
- auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
+ auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
EXPECT_EQ(existingOutputLayer, result.get());
// The corresponding entry in the ordered array should be cleared.
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index c56d92a..0a7c462 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -22,6 +22,7 @@
#include <compositionengine/mock/CompositionEngine.h>
#include <compositionengine/mock/Display.h>
#include <compositionengine/mock/DisplaySurface.h>
+#include <compositionengine/mock/OutputLayer.h>
#include <gtest/gtest.h>
#include <renderengine/mock/RenderEngine.h>
#include <system/window.h>
@@ -284,64 +285,66 @@
* RenderSurface::prepareFrame()
*/
-TEST_F(RenderSurfaceTest, prepareFrameTakesEarlyOutOnHwcError) {
- std::vector<CompositionInfo> data;
-
- EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data)))
+TEST_F(RenderSurfaceTest, prepareFramePassesOutputLayersToHwc) {
+ EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
.WillOnce(Return(INVALID_OPERATION));
- EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame(data));
+ EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
+}
+
+TEST_F(RenderSurfaceTest, prepareFrameTakesEarlyOutOnHwcError) {
+ EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+ .WillOnce(Return(INVALID_OPERATION));
+
+ EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
}
TEST_F(RenderSurfaceTest, prepareFrameHandlesMixedComposition) {
- std::vector<CompositionInfo> data;
- EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+ .WillOnce(Return(NO_ERROR));
EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_MIXED))
.WillOnce(Return(INVALID_OPERATION));
- EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame(data));
+ EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
}
TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyGlesComposition) {
- std::vector<CompositionInfo> data;
-
- EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+ .WillOnce(Return(NO_ERROR));
EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_GLES))
.WillOnce(Return(NO_ERROR));
- EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data));
+ EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
}
TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyHwcComposition) {
- std::vector<CompositionInfo> data;
-
- EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+ .WillOnce(Return(NO_ERROR));
EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC))
.WillOnce(Return(NO_ERROR));
- EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data));
+ EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
}
TEST_F(RenderSurfaceTest, prepareFrameHandlesNoComposition) {
- std::vector<CompositionInfo> data;
-
- EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+ .WillOnce(Return(NO_ERROR));
EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC))
.WillOnce(Return(NO_ERROR));
- EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data));
+ EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
}
/* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 941b4ad..22c40d7 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -39,6 +39,7 @@
return !isHiddenByPolicy();
}
-void ContainerLayer::setPerFrameData(DisplayId, const ui::Transform&, const Rect&, int32_t) {}
+void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&, const ui::Transform&,
+ const Rect&, int32_t) {}
} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index fec82d7..c69997d 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -33,8 +33,8 @@
bool canReceiveInput() const override;
- void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
- int32_t supportedPerFrameMetadata) override;
+ void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
+ const Rect& viewport, int32_t supportedPerFrameMetadata) override;
bool isCreatedFromMainThread() const override { return true; }
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 9674f0d..a827c47 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -266,6 +266,7 @@
int getHeight() const override { return mDevice->getHeight(); }
int getWidth() const override { return mDevice->getWidth(); }
bool isSecure() const override { return mDevice->isSecure(); }
+ const sp<const DisplayDevice> getDisplayDevice() const override { return mDevice; }
bool needsFiltering() const override {
// check if the projection from the logical display to the physical
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 68e7876..bca0abc 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -308,8 +308,7 @@
return static_cast<Error>(intError);
}
-Error Display::createLayer(Layer** outLayer)
-{
+Error Display::createLayer(HWC2::Layer** outLayer) {
if (!outLayer) {
return Error::BadParameter;
}
@@ -320,15 +319,13 @@
return error;
}
- auto layer = std::make_unique<Layer>(
- mComposer, mCapabilities, mId, layerId);
+ auto layer = std::make_unique<impl::Layer>(mComposer, mCapabilities, mId, layerId);
*outLayer = layer.get();
mLayers.emplace(layerId, std::move(layer));
return Error::None;
}
-Error Display::destroyLayer(Layer* layer)
-{
+Error Display::destroyLayer(HWC2::Layer* layer) {
if (!layer) {
return Error::BadParameter;
}
@@ -388,9 +385,7 @@
return Error::None;
}
-Error Display::getChangedCompositionTypes(
- std::unordered_map<Layer*, Composition>* outTypes)
-{
+Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Composition>* outTypes) {
std::vector<Hwc2::Layer> layerIds;
std::vector<Hwc2::IComposerClient::Composition> types;
auto intError = mComposer.getChangedCompositionTypes(
@@ -492,8 +487,7 @@
}
Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
- std::unordered_map<Layer*, LayerRequest>* outLayerRequests)
-{
+ std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) {
uint32_t intDisplayRequests;
std::vector<Hwc2::Layer> layerIds;
std::vector<uint32_t> layerRequests;
@@ -574,9 +568,7 @@
return static_cast<Error>(intError);
}
-Error Display::getReleaseFences(
- std::unordered_map<Layer*, sp<Fence>>* outFences) const
-{
+Error Display::getReleaseFences(std::unordered_map<HWC2::Layer*, sp<Fence>>* outFences) const {
std::vector<Hwc2::Layer> layerIds;
std::vector<int> fenceFds;
auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds);
@@ -586,7 +578,7 @@
return error;
}
- std::unordered_map<Layer*, sp<Fence>> releaseFences;
+ std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
releaseFences.reserve(numElements);
for (uint32_t element = 0; element < numElements; ++element) {
auto layer = getLayerById(layerIds[element]);
@@ -787,8 +779,7 @@
// Other Display methods
-Layer* Display::getLayerById(hwc2_layer_t id) const
-{
+HWC2::Layer* Display::getLayerById(hwc2_layer_t id) const {
if (mLayers.count(id) == 0) {
return nullptr;
}
@@ -799,6 +790,10 @@
// Layer methods
+Layer::~Layer() = default;
+
+namespace impl {
+
Layer::Layer(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
hwc2_display_t displayId, hwc2_layer_t layerId)
: mComposer(composer),
@@ -817,15 +812,6 @@
ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
" failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(),
intError);
- if (mLayerDestroyedListener) {
- mLayerDestroyedListener(this);
- }
-}
-
-void Layer::setLayerDestroyedListener(std::function<void(Layer*)> listener) {
- LOG_ALWAYS_FATAL_IF(mLayerDestroyedListener && listener,
- "Attempt to set layer destroyed listener multiple times");
- mLayerDestroyedListener = listener;
}
Error Layer::setCursorPosition(int32_t x, int32_t y)
@@ -1033,4 +1019,6 @@
auto intError = mComposer.setLayerColorTransform(mDisplayId, mId, matrix.asArray());
return static_cast<Error>(intError);
}
+
+} // namespace impl
} // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index c1f481a..70358a0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -364,52 +364,73 @@
};
} // namespace impl
+class Layer {
+public:
+ virtual ~Layer();
+
+ virtual hwc2_layer_t getId() const = 0;
+
+ [[clang::warn_unused_result]] virtual Error setCursorPosition(int32_t x, int32_t y) = 0;
+ [[clang::warn_unused_result]] virtual Error setBuffer(
+ uint32_t slot, const android::sp<android::GraphicBuffer>& buffer,
+ const android::sp<android::Fence>& acquireFence) = 0;
+ [[clang::warn_unused_result]] virtual Error setSurfaceDamage(const android::Region& damage) = 0;
+
+ [[clang::warn_unused_result]] virtual Error setBlendMode(BlendMode mode) = 0;
+ [[clang::warn_unused_result]] virtual Error setColor(hwc_color_t color) = 0;
+ [[clang::warn_unused_result]] virtual Error setCompositionType(Composition type) = 0;
+ [[clang::warn_unused_result]] virtual Error setDataspace(android::ui::Dataspace dataspace) = 0;
+ [[clang::warn_unused_result]] virtual Error setPerFrameMetadata(
+ const int32_t supportedPerFrameMetadata, const android::HdrMetadata& metadata) = 0;
+ [[clang::warn_unused_result]] virtual Error setDisplayFrame(const android::Rect& frame) = 0;
+ [[clang::warn_unused_result]] virtual Error setPlaneAlpha(float alpha) = 0;
+ [[clang::warn_unused_result]] virtual Error setSidebandStream(
+ const native_handle_t* stream) = 0;
+ [[clang::warn_unused_result]] virtual Error setSourceCrop(const android::FloatRect& crop) = 0;
+ [[clang::warn_unused_result]] virtual Error setTransform(Transform transform) = 0;
+ [[clang::warn_unused_result]] virtual Error setVisibleRegion(const android::Region& region) = 0;
+ [[clang::warn_unused_result]] virtual Error setZOrder(uint32_t z) = 0;
+ [[clang::warn_unused_result]] virtual Error setInfo(uint32_t type, uint32_t appId) = 0;
+
+ // Composer HAL 2.3
+ [[clang::warn_unused_result]] virtual Error setColorTransform(const android::mat4& matrix) = 0;
+};
+
+namespace impl {
+
// Convenience C++ class to access hwc2_device_t Layer functions directly.
-class Layer
-{
+
+class Layer : public HWC2::Layer {
public:
Layer(android::Hwc2::Composer& composer,
const std::unordered_set<Capability>& capabilities,
hwc2_display_t displayId, hwc2_layer_t layerId);
- ~Layer();
+ ~Layer() override;
- hwc2_layer_t getId() const { return mId; }
+ hwc2_layer_t getId() const override { return mId; }
- // Register a listener to be notified when the layer is destroyed. When the
- // listener function is called, the Layer will be in the process of being
- // destroyed, so it's not safe to call methods on it.
- void setLayerDestroyedListener(std::function<void(Layer*)> listener);
+ Error setCursorPosition(int32_t x, int32_t y) override;
+ Error setBuffer(uint32_t slot, const android::sp<android::GraphicBuffer>& buffer,
+ const android::sp<android::Fence>& acquireFence) override;
+ Error setSurfaceDamage(const android::Region& damage) override;
- [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
- [[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
- const android::sp<android::GraphicBuffer>& buffer,
- const android::sp<android::Fence>& acquireFence);
- [[clang::warn_unused_result]] Error setSurfaceDamage(
- const android::Region& damage);
-
- [[clang::warn_unused_result]] Error setBlendMode(BlendMode mode);
- [[clang::warn_unused_result]] Error setColor(hwc_color_t color);
- [[clang::warn_unused_result]] Error setCompositionType(Composition type);
- [[clang::warn_unused_result]] Error setDataspace(
- android::ui::Dataspace dataspace);
- [[clang::warn_unused_result]] Error setPerFrameMetadata(
- const int32_t supportedPerFrameMetadata,
- const android::HdrMetadata& metadata);
- [[clang::warn_unused_result]] Error setDisplayFrame(
- const android::Rect& frame);
- [[clang::warn_unused_result]] Error setPlaneAlpha(float alpha);
- [[clang::warn_unused_result]] Error setSidebandStream(
- const native_handle_t* stream);
- [[clang::warn_unused_result]] Error setSourceCrop(
- const android::FloatRect& crop);
- [[clang::warn_unused_result]] Error setTransform(Transform transform);
- [[clang::warn_unused_result]] Error setVisibleRegion(
- const android::Region& region);
- [[clang::warn_unused_result]] Error setZOrder(uint32_t z);
- [[clang::warn_unused_result]] Error setInfo(uint32_t type, uint32_t appId);
+ Error setBlendMode(BlendMode mode) override;
+ Error setColor(hwc_color_t color) override;
+ Error setCompositionType(Composition type) override;
+ Error setDataspace(android::ui::Dataspace dataspace) override;
+ Error setPerFrameMetadata(const int32_t supportedPerFrameMetadata,
+ const android::HdrMetadata& metadata) override;
+ Error setDisplayFrame(const android::Rect& frame) override;
+ Error setPlaneAlpha(float alpha) override;
+ Error setSidebandStream(const native_handle_t* stream) override;
+ Error setSourceCrop(const android::FloatRect& crop) override;
+ Error setTransform(Transform transform) override;
+ Error setVisibleRegion(const android::Region& region) override;
+ Error setZOrder(uint32_t z) override;
+ Error setInfo(uint32_t type, uint32_t appId) override;
// Composer HAL 2.3
- [[clang::warn_unused_result]] Error setColorTransform(const android::mat4& matrix);
+ Error setColorTransform(const android::mat4& matrix) override;
private:
// These are references to data owned by HWC2::Device, which will outlive
@@ -422,10 +443,11 @@
hwc2_layer_t mId;
android::ui::Dataspace mDataSpace = android::ui::Dataspace::UNKNOWN;
android::HdrMetadata mHdrMetadata;
- std::function<void(Layer*)> mLayerDestroyedListener;
android::mat4 mColorMatrix;
};
+} // namespace impl
+
} // namespace HWC2
#endif // ANDROID_SF_HWC2_H
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 5b4d347..3b9e0e6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -20,13 +20,14 @@
#define LOG_TAG "HWComposer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Errors.h>
-#include <utils/Trace.h>
-
+#include <compositionengine/Output.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <log/log.h>
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
-
-#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/Trace.h>
#include "HWComposer.h"
#include "HWC2.h"
@@ -398,7 +399,7 @@
return NO_ERROR;
}
-status_t HWComposer::prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) {
+status_t HWComposer::prepare(DisplayId displayId, const compositionengine::Output& output) {
ATRACE_CALL();
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -462,47 +463,42 @@
displayData.hasClientComposition = false;
displayData.hasDeviceComposition = false;
- for (auto& compositionInfo : compositionData) {
- auto hwcLayer = compositionInfo.hwc.hwcLayer;
+ for (auto& outputLayer : output.getOutputLayersOrderedByZ()) {
+ auto& state = outputLayer->editState();
+ LOG_FATAL_IF(!state.hwc.);
+ auto hwcLayer = (*state.hwc).hwcLayer;
- if (changedTypes.count(&*hwcLayer) != 0) {
- // We pass false so we only update our state and don't call back
- // into the HWC device
- validateChange(compositionInfo.compositionType,
- changedTypes[&*hwcLayer]);
- compositionInfo.compositionType = changedTypes[&*hwcLayer];
- compositionInfo.layer->mLayer->setCompositionType(displayId,
- compositionInfo.compositionType,
- false);
+ if (auto it = changedTypes.find(hwcLayer.get()); it != changedTypes.end()) {
+ auto newCompositionType = it->second;
+ validateChange(static_cast<HWC2::Composition>((*state.hwc).hwcCompositionType),
+ newCompositionType);
+ (*state.hwc).hwcCompositionType =
+ static_cast<Hwc2::IComposerClient::Composition>(newCompositionType);
}
- switch (compositionInfo.compositionType) {
- case HWC2::Composition::Client:
+ switch ((*state.hwc).hwcCompositionType) {
+ case Hwc2::IComposerClient::Composition::CLIENT:
displayData.hasClientComposition = true;
break;
- case HWC2::Composition::Device:
- case HWC2::Composition::SolidColor:
- case HWC2::Composition::Cursor:
- case HWC2::Composition::Sideband:
+ case Hwc2::IComposerClient::Composition::DEVICE:
+ case Hwc2::IComposerClient::Composition::SOLID_COLOR:
+ case Hwc2::IComposerClient::Composition::CURSOR:
+ case Hwc2::IComposerClient::Composition::SIDEBAND:
displayData.hasDeviceComposition = true;
break;
default:
break;
}
- if (layerRequests.count(&*hwcLayer) != 0 &&
- layerRequests[&*hwcLayer] ==
- HWC2::LayerRequest::ClearClientTarget) {
- compositionInfo.hwc.clearClientTarget = true;
- compositionInfo.layer->mLayer->setClearClientTarget(displayId, true);
- } else {
- if (layerRequests.count(&*hwcLayer) != 0) {
+ state.clearClientTarget = false;
+ if (auto it = layerRequests.find(hwcLayer.get()); it != layerRequests.end()) {
+ auto request = it->second;
+ if (request == HWC2::LayerRequest::ClearClientTarget) {
+ state.clearClientTarget = true;
+ } else {
LOG_DISPLAY_ERROR(displayId,
- ("Unknown layer request " + to_string(layerRequests[&*hwcLayer]))
- .c_str());
+ ("Unknown layer request " + to_string(request)).c_str());
}
- compositionInfo.hwc.clearClientTarget = false;
- compositionInfo.layer->mLayer->setClearClientTarget(displayId, false);
}
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index f42f860..ca59a26 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -45,6 +45,10 @@
class Composer;
} // namespace Hwc2
+namespace compositionengine {
+class Output;
+} // namespace compositionengine
+
class HWComposer {
public:
virtual ~HWComposer();
@@ -68,8 +72,7 @@
virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
// Asks the HAL what it can do
- virtual status_t prepare(DisplayId displayId,
- std::vector<CompositionInfo>& compositionData) = 0;
+ virtual status_t prepare(DisplayId displayId, const compositionengine::Output&) = 0;
virtual status_t setClientTarget(DisplayId displayId, uint32_t slot,
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
@@ -205,7 +208,7 @@
void destroyLayer(DisplayId displayId, HWC2::Layer* layer) override;
// Asks the HAL what it can do
- status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) override;
+ status_t prepare(DisplayId displayId, const compositionengine::Output&) override;
status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
const sp<GraphicBuffer>& target, ui::Dataspace dataspace) override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 26a09e7..daef7c6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -24,44 +24,42 @@
#include <stdlib.h>
#include <sys/types.h>
#include <algorithm>
+#include <mutex>
#include <android-base/stringprintf.h>
-
+#include <compositionengine/Display.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/LayerCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
-
+#include <gui/BufferItem.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/DebugUtils.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/NativeHandle.h>
#include <utils/StopWatch.h>
#include <utils/Trace.h>
-#include <ui/DebugUtils.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/PixelFormat.h>
-
-#include <gui/BufferItem.h>
-#include <gui/LayerDebugInfo.h>
-#include <gui/Surface.h>
-
#include "BufferLayer.h"
#include "ColorLayer.h"
#include "Colorizer.h"
#include "DisplayDevice.h"
+#include "DisplayHardware/HWComposer.h"
#include "Layer.h"
+#include "LayerProtoHelper.h"
#include "LayerRejecter.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
-
-#include "DisplayHardware/HWComposer.h"
#include "TimeStats/TimeStats.h"
-#include <renderengine/RenderEngine.h>
-
-#include <mutex>
-#include "LayerProtoHelper.h"
-
#define DEBUG_RESIZE 0
namespace android {
@@ -128,8 +126,6 @@
mFrameTracker.logAndResetStats(mName);
- destroyAllHwcLayersPlusChildren();
-
mFlinger->onLayerDestroyed();
}
@@ -211,52 +207,18 @@
// h/w composer set-up
// ---------------------------------------------------------------------------
-bool Layer::createHwcLayer(HWComposer* hwc, DisplayId displayId) {
- LOG_ALWAYS_FATAL_IF(hasHwcLayer(displayId), "Already have a layer for display %s",
- to_string(displayId).c_str());
- auto layer = std::shared_ptr<HWC2::Layer>(
- hwc->createLayer(displayId),
- [hwc, displayId](HWC2::Layer* layer) {
- hwc->destroyLayer(displayId, layer); });
- if (!layer) {
- return false;
- }
- LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[displayId];
- hwcInfo.hwc = hwc;
- hwcInfo.layer = layer;
- layer->setLayerDestroyedListener(
- [this, displayId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(displayId); });
- return true;
+bool Layer::hasHwcLayer(const sp<const DisplayDevice>& displayDevice) {
+ auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ LOG_FATAL_IF(!outputLayer);
+ return outputLayer->getState().hwc && (*outputLayer->getState().hwc).hwcLayer != nullptr;
}
-bool Layer::destroyHwcLayer(DisplayId displayId) {
- if (!hasHwcLayer(displayId)) {
- return false;
+HWC2::Layer* Layer::getHwcLayer(const sp<const DisplayDevice>& displayDevice) {
+ auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ if (!outputLayer || !outputLayer->getState().hwc) {
+ return nullptr;
}
- auto& hwcInfo = getBE().mHwcLayers[displayId];
- LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
- LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
- hwcInfo.layer = nullptr;
-
- return true;
-}
-
-void Layer::destroyHwcLayersForAllDisplays() {
- size_t numLayers = getBE().mHwcLayers.size();
- for (size_t i = 0; i < numLayers; ++i) {
- LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed");
- destroyHwcLayer(getBE().mHwcLayers.begin()->first);
- }
-}
-
-void Layer::destroyAllHwcLayersPlusChildren() {
- destroyHwcLayersForAllDisplays();
- LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(),
- "All hardware composer layers should have been destroyed");
-
- for (const sp<Layer>& child : mDrawingChildren) {
- child->destroyAllHwcLayersPlusChildren();
- }
+ return (*outputLayer->getState().hwc).hwcLayer.get();
}
Rect Layer::getContentCrop() const {
@@ -266,9 +228,9 @@
if (!mCurrentCrop.isEmpty()) {
// if the buffer crop is defined, we use that
crop = mCurrentCrop;
- } else if (getBE().compositionInfo.mBuffer != nullptr) {
+ } else if (mActiveBuffer != nullptr) {
// otherwise we use the whole buffer
- crop = getBE().compositionInfo.mBuffer->getBounds();
+ crop = mActiveBuffer->getBounds();
} else {
// if we don't have a buffer yet, we use an empty/invalid crop
crop.makeInvalid();
@@ -322,18 +284,18 @@
// for in the transform. We need to mirror this scaling to child surfaces
// or we will break the contract where WM can treat child surfaces as
// pixels in the parent surface.
- if (!isFixedSize() || !getBE().compositionInfo.mBuffer) {
+ if (!isFixedSize() || !mActiveBuffer) {
return mEffectiveTransform;
}
int bufferWidth;
int bufferHeight;
if ((mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) {
- bufferWidth = getBE().compositionInfo.mBuffer->getWidth();
- bufferHeight = getBE().compositionInfo.mBuffer->getHeight();
+ bufferWidth = mActiveBuffer->getWidth();
+ bufferHeight = mActiveBuffer->getHeight();
} else {
- bufferHeight = getBE().compositionInfo.mBuffer->getWidth();
- bufferWidth = getBE().compositionInfo.mBuffer->getHeight();
+ bufferHeight = mActiveBuffer->getWidth();
+ bufferWidth = mActiveBuffer->getHeight();
}
float sx = getActiveWidth(getDrawingState()) / static_cast<float>(bufferWidth);
float sy = getActiveHeight(getDrawingState()) / static_cast<float>(bufferHeight);
@@ -421,7 +383,8 @@
win.top -= roundedCornersCrop.top;
win.bottom -= roundedCornersCrop.top;
- renderengine::Mesh::VertexArray<vec2> cropCoords(getBE().mMesh.getCropCoordArray<vec2>());
+ renderengine::Mesh::VertexArray<vec2> cropCoords(
+ getCompositionLayer()->editState().reMesh.getCropCoordArray<vec2>());
cropCoords[0] = vec2(win.left, win.top);
cropCoords[1] = vec2(win.left, win.top + win.getHeight());
cropCoords[2] = vec2(win.right, win.top + win.getHeight());
@@ -494,19 +457,27 @@
}
void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) {
- const auto displayId = display->getId();
- LOG_ALWAYS_FATAL_IF(!displayId);
- RETURN_IF_NO_HWC_LAYER(*displayId);
- auto& hwcInfo = getBE().mHwcLayers[*displayId];
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+ LOG_FATAL_IF(!outputLayer->getState().hwc);
+ auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
- // enable this layer
- hwcInfo.forceClientComposition = false;
-
- if (isSecure() && !display->isSecure()) {
- hwcInfo.forceClientComposition = true;
+ if (!hasHwcLayer(display)) {
+ ALOGE("[%s] failed to setGeometry: no HWC layer found (%s)", mName.string(),
+ display->getDebugName().c_str());
+ return;
}
- auto& hwcLayer = hwcInfo.layer;
+ LOG_FATAL_IF(!getCompositionLayer());
+ auto& commonCompositionState = getCompositionLayer()->editState().frontEnd;
+ auto& compositionState = outputLayer->editState();
+
+ // enable this layer
+ compositionState.forceClientComposition = false;
+
+ if (isSecure() && !display->isSecure()) {
+ compositionState.forceClientComposition = true;
+ }
// this gives us only the "orientation" component of the transform
const State& s(getDrawingState());
@@ -522,7 +493,7 @@
" %s (%d)",
mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(),
static_cast<int32_t>(error));
- getBE().compositionInfo.hwc.blendMode = blendMode;
+ commonCompositionState.blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
@@ -567,9 +538,8 @@
transformedFrame.left, transformedFrame.top, transformedFrame.right,
transformedFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
} else {
- hwcInfo.displayFrame = transformedFrame;
+ compositionState.displayFrame = transformedFrame;
}
- getBE().compositionInfo.hwc.displayFrame = transformedFrame;
FloatRect sourceCrop = computeCrop(display);
error = hwcLayer->setSourceCrop(sourceCrop);
@@ -579,9 +549,8 @@
mName.string(), sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom,
to_string(error).c_str(), static_cast<int32_t>(error));
} else {
- hwcInfo.sourceCrop = sourceCrop;
+ compositionState.sourceCrop = sourceCrop;
}
- getBE().compositionInfo.hwc.sourceCrop = sourceCrop;
float alpha = static_cast<float>(getAlpha());
error = hwcLayer->setPlaneAlpha(alpha);
@@ -589,12 +558,12 @@
"[%s] Failed to set plane alpha %.3f: "
"%s (%d)",
mName.string(), alpha, to_string(error).c_str(), static_cast<int32_t>(error));
- getBE().compositionInfo.hwc.alpha = alpha;
+ commonCompositionState.alpha = alpha;
error = hwcLayer->setZOrder(z);
ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z,
to_string(error).c_str(), static_cast<int32_t>(error));
- getBE().compositionInfo.hwc.z = z;
+ compositionState.z = z;
int type = s.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
int appId = s.metadata.getInt32(METADATA_OWNER_UID, 0);
@@ -613,8 +582,8 @@
ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(),
static_cast<int32_t>(error));
- getBE().compositionInfo.hwc.type = type;
- getBE().compositionInfo.hwc.appId = appId;
+ commonCompositionState.type = type;
+ commonCompositionState.appId = appId;
/*
* Transformations are applied in this order:
@@ -651,35 +620,39 @@
const uint32_t orientation = transform.getOrientation();
if (orientation & ui::Transform::ROT_INVALID) {
// we can only handle simple transformation
- hwcInfo.forceClientComposition = true;
- getBE().mHwcLayers[*displayId].compositionType = HWC2::Composition::Client;
+ compositionState.forceClientComposition = true;
+ (*compositionState.hwc).hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
} else {
auto transform = static_cast<HWC2::Transform>(orientation);
- hwcInfo.transform = transform;
auto error = hwcLayer->setTransform(transform);
ALOGE_IF(error != HWC2::Error::None,
"[%s] Failed to set transform %s: "
"%s (%d)",
mName.string(), to_string(transform).c_str(), to_string(error).c_str(),
static_cast<int32_t>(error));
- getBE().compositionInfo.hwc.transform = transform;
+ compositionState.bufferTransform = static_cast<Hwc2::Transform>(transform);
}
}
-void Layer::forceClientComposition(DisplayId displayId) {
- RETURN_IF_NO_HWC_LAYER(displayId);
- getBE().mHwcLayers[displayId].forceClientComposition = true;
+void Layer::forceClientComposition(const sp<DisplayDevice>& display) {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+ outputLayer->editState().forceClientComposition = true;
}
-bool Layer::getForceClientComposition(DisplayId displayId) {
- RETURN_IF_NO_HWC_LAYER(displayId, false);
- return getBE().mHwcLayers[displayId].forceClientComposition;
+bool Layer::getForceClientComposition(const sp<DisplayDevice>& display) {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+ return outputLayer->getState().forceClientComposition;
}
void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) {
- const auto displayId = display->getId();
- LOG_ALWAYS_FATAL_IF(!displayId);
- if (!hasHwcLayer(*displayId) || getCompositionType(displayId) != HWC2::Composition::Cursor) {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+
+ if (!outputLayer->getState().hwc ||
+ (*outputLayer->getState().hwc).hwcCompositionType !=
+ Hwc2::IComposerClient::Composition::CURSOR) {
return;
}
@@ -697,8 +670,7 @@
auto position = displayTransform.transform(frame);
auto error =
- getBE().mHwcLayers[*displayId].layer->setCursorPosition(position.left, position.top);
-
+ (*outputLayer->getState().hwc).hwcLayer->setCursorPosition(position.left, position.top);
ALOGE_IF(error != HWC2::Error::None,
"[%s] Failed to set cursor position "
"to (%d, %d): %s (%d)",
@@ -760,65 +732,50 @@
void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
float alpha) const {
auto& engine(mFlinger->getRenderEngine());
- computeGeometry(renderArea, getBE().mMesh, false);
+ computeGeometry(renderArea, getCompositionLayer()->editState().reMesh, false);
engine.setupFillWithColor(red, green, blue, alpha);
- engine.drawMesh(getBE().mMesh);
+ engine.drawMesh(getCompositionLayer()->getState().reMesh);
}
void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
clearWithOpenGL(renderArea, 0, 0, 0, 0);
}
-void Layer::setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc) {
- if (getBE().mHwcLayers.count(displayId) == 0) {
- ALOGE("setCompositionType called without a valid HWC layer");
- return;
- }
- auto& hwcInfo = getBE().mHwcLayers[displayId];
- auto& hwcLayer = hwcInfo.layer;
- ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (hwcLayer)->getId(), to_string(type).c_str(),
- static_cast<int>(callIntoHwc));
- if (hwcInfo.compositionType != type) {
+void Layer::setCompositionType(const sp<const DisplayDevice>& display,
+ Hwc2::IComposerClient::Composition type) {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+ LOG_FATAL_IF(!outputLayer->getState().hwc);
+ auto& compositionState = outputLayer->editState();
+
+ ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", ((*compositionState.hwc).hwcLayer)->getId(),
+ toString(type).c_str(), 1);
+ if ((*compositionState.hwc).hwcCompositionType != type) {
ALOGV(" actually setting");
- hwcInfo.compositionType = type;
- if (callIntoHwc) {
- auto error = (hwcLayer)->setCompositionType(type);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set "
- "composition type %s: %s (%d)",
- mName.string(), to_string(type).c_str(), to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
+ (*compositionState.hwc).hwcCompositionType = type;
+
+ auto error = (*compositionState.hwc)
+ .hwcLayer->setCompositionType(static_cast<HWC2::Composition>(type));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set "
+ "composition type %s: %s (%d)",
+ mName.string(), toString(type).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
}
}
-HWC2::Composition Layer::getCompositionType(const std::optional<DisplayId>& displayId) const {
- if (!displayId) {
- // If we're querying the composition type for a display that does not
- // have a HWC counterpart, then it will always be Client
- return HWC2::Composition::Client;
- }
- if (getBE().mHwcLayers.count(*displayId) == 0) {
- ALOGE("getCompositionType called with an invalid HWC layer");
- return HWC2::Composition::Invalid;
- }
- return getBE().mHwcLayers.at(*displayId).compositionType;
+Hwc2::IComposerClient::Composition Layer::getCompositionType(
+ const sp<const DisplayDevice>& display) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+ return outputLayer->getState().hwc ? (*outputLayer->getState().hwc).hwcCompositionType
+ : Hwc2::IComposerClient::Composition::CLIENT;
}
-void Layer::setClearClientTarget(DisplayId displayId, bool clear) {
- if (getBE().mHwcLayers.count(displayId) == 0) {
- ALOGE("setClearClientTarget called without a valid HWC layer");
- return;
- }
- getBE().mHwcLayers[displayId].clearClientTarget = clear;
-}
-
-bool Layer::getClearClientTarget(DisplayId displayId) const {
- if (getBE().mHwcLayers.count(displayId) == 0) {
- ALOGE("getClearClientTarget called without a valid HWC layer");
- return false;
- }
- return getBE().mHwcLayers.at(displayId).clearClientTarget;
+bool Layer::getClearClientTarget(const sp<const DisplayDevice>& display) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ LOG_FATAL_IF(!outputLayer);
+ return outputLayer->getState().clearClientTarget;
}
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
@@ -1037,9 +994,9 @@
const bool resizePending =
((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) ||
(stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) &&
- (getBE().compositionInfo.mBuffer != nullptr);
+ (mActiveBuffer != nullptr);
if (!isFixedSize()) {
- if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) {
+ if (resizePending && mSidebandStream == nullptr) {
flags |= eDontUpdateGeometryState;
}
}
@@ -1535,8 +1492,9 @@
result.append("-----------------------------\n");
}
-void Layer::miniDump(std::string& result, DisplayId displayId) const {
- if (!hasHwcLayer(displayId)) {
+void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice) const {
+ auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ if (!outputLayer) {
return;
}
@@ -1554,26 +1512,24 @@
StringAppendF(&result, " %s\n", name.c_str());
const State& layerState(getDrawingState());
- const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId);
+ const auto& compositionState = outputLayer->getState();
+
if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
StringAppendF(&result, " rel %6d | ", layerState.z);
} else {
StringAppendF(&result, " %10d | ", layerState.z);
}
- StringAppendF(&result, "%10s | ", to_string(getCompositionType(displayId)).c_str());
- StringAppendF(&result, "%10s | ", to_string(hwcInfo.transform).c_str());
- const Rect& frame = hwcInfo.displayFrame;
+ StringAppendF(&result, "%10s | ", toString(getCompositionType(displayDevice)).c_str());
+ StringAppendF(&result, "%10s | ",
+ toString(getCompositionLayer() ? compositionState.bufferTransform
+ : static_cast<Hwc2::Transform>(0))
+ .c_str());
+ const Rect& frame = compositionState.displayFrame;
StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
- const FloatRect& crop = hwcInfo.sourceCrop;
+ const FloatRect& crop = compositionState.sourceCrop;
StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right,
crop.bottom);
- result.append("- - - - - - - - - - - - - - - -\n");
-
- std::string compositionInfoStr;
- getBE().compositionInfo.dump(compositionInfoStr, "compositionInfo");
- result.append(compositionInfoStr);
-
result.append("- - - - - - - - - - - - - - - -");
result.append("- - - - - - - - - - - - - - - -");
result.append("- - - - - - - - - - - - - - -\n");
@@ -2136,8 +2092,7 @@
layerInfo->set_z_order_relative_of(-1);
}
- // XXX getBE().compositionInfo.mBuffer is not protected
- auto buffer = getBE().compositionInfo.mBuffer;
+ auto buffer = mActiveBuffer;
if (buffer != nullptr) {
LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer());
LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
@@ -2168,25 +2123,29 @@
LayerProtoHelper::writeToProto(mBounds, layerInfo->mutable_bounds());
}
-void Layer::writeToProto(LayerProto* layerInfo, DisplayId displayId) {
- if (!hasHwcLayer(displayId)) {
+void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice) {
+ auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ if (!outputLayer) {
return;
}
writeToProto(layerInfo, LayerVector::StateSet::Drawing);
- const auto& hwcInfo = getBE().mHwcLayers.at(displayId);
+ const auto& compositionState = outputLayer->getState();
- const Rect& frame = hwcInfo.displayFrame;
+ const Rect& frame = compositionState.displayFrame;
LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame());
- const FloatRect& crop = hwcInfo.sourceCrop;
+ const FloatRect& crop = compositionState.sourceCrop;
LayerProtoHelper::writeToProto(crop, layerInfo->mutable_hwc_crop());
- const int32_t transform = static_cast<int32_t>(hwcInfo.transform);
+ const int32_t transform =
+ getCompositionLayer() ? static_cast<int32_t>(compositionState.bufferTransform) : 0;
layerInfo->set_hwc_transform(transform);
- const int32_t compositionType = static_cast<int32_t>(hwcInfo.compositionType);
+ const int32_t compositionType =
+ static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
+ : Hwc2::IComposerClient::Composition::CLIENT);
layerInfo->set_hwc_composition_type(compositionType);
if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
@@ -2253,6 +2212,11 @@
return isVisible();
}
+compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
+ const sp<const DisplayDevice>& display) const {
+ return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionLayer().get());
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9241e71..1375a39 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -51,6 +51,7 @@
#include "SurfaceFlinger.h"
#include "TransactionCompletedThread.h"
+#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/HWComposer.h"
#include "RenderArea.h"
@@ -70,6 +71,7 @@
namespace compositionengine {
class Layer;
+class OutputLayer;
}
namespace impl {
@@ -419,7 +421,7 @@
void writeToProto(LayerProto* layerInfo,
LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
- void writeToProto(LayerProto* layerInfo, DisplayId displayId);
+ void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice);
virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
@@ -443,17 +445,19 @@
virtual bool isHdrY410() const { return false; }
void setGeometry(const sp<const DisplayDevice>& display, uint32_t z);
- void forceClientComposition(DisplayId displayId);
- bool getForceClientComposition(DisplayId displayId);
- virtual void setPerFrameData(DisplayId displayId, const ui::Transform& transform,
- const Rect& viewport, int32_t supportedPerFrameMetadata) = 0;
+ void forceClientComposition(const sp<DisplayDevice>& display);
+ bool getForceClientComposition(const sp<DisplayDevice>& display);
+ virtual void setPerFrameData(const sp<const DisplayDevice>& display,
+ const ui::Transform& transform, const Rect& viewport,
+ int32_t supportedPerFrameMetadata) = 0;
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
- void setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc = true);
- HWC2::Composition getCompositionType(const std::optional<DisplayId>& displayId) const;
- void setClearClientTarget(DisplayId displayId, bool clear);
- bool getClearClientTarget(DisplayId displayId) const;
+ void setCompositionType(const sp<const DisplayDevice>& display,
+ Hwc2::IComposerClient::Composition type);
+ Hwc2::IComposerClient::Composition getCompositionType(
+ const sp<const DisplayDevice>& display) const;
+ bool getClearClientTarget(const sp<const DisplayDevice>& display) const;
void updateCursorPosition(const sp<const DisplayDevice>& display);
/*
@@ -530,8 +534,7 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
- const sp<Fence>& /*releaseFence*/) {
+ virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) {
return {};
}
@@ -567,27 +570,8 @@
// -----------------------------------------------------------------------
- bool createHwcLayer(HWComposer* hwc, DisplayId displayId);
- bool destroyHwcLayer(DisplayId displayId);
- void destroyHwcLayersForAllDisplays();
- void destroyAllHwcLayersPlusChildren();
-
- bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; }
-
- HWC2::Layer* getHwcLayer(DisplayId displayId) {
- if (!hasHwcLayer(displayId)) {
- return nullptr;
- }
- return getBE().mHwcLayers[displayId].layer.get();
- }
-
- bool setHwcLayer(DisplayId displayId) {
- if (!hasHwcLayer(displayId)) {
- return false;
- }
- getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[displayId].layer;
- return true;
- }
+ bool hasHwcLayer(const sp<const DisplayDevice>& displayDevice);
+ HWC2::Layer* getHwcLayer(const sp<const DisplayDevice>& displayDevice);
// -----------------------------------------------------------------------
void clearWithOpenGL(const RenderArea& renderArea) const;
@@ -600,7 +584,7 @@
/* always call base class first */
static void miniDumpHeader(std::string& result);
- void miniDump(std::string& result, DisplayId displayId) const;
+ void miniDump(std::string& result, const sp<DisplayDevice>& display) const;
void dumpFrameStats(std::string& result) const;
void dumpFrameEvents(std::string& result);
void clearFrameStats();
@@ -676,6 +660,9 @@
return parentBounds;
}
+ compositionengine::OutputLayer* findOutputLayerForDisplay(
+ const sp<const DisplayDevice>& display) const;
+
protected:
// constant
sp<SurfaceFlinger> mFlinger;
@@ -832,6 +819,7 @@
FenceTimeline mReleaseTimeline;
// main thread
+ sp<NativeHandle> mSidebandStream;
// Active buffer fields
sp<GraphicBuffer> mActiveBuffer;
sp<Fence> mActiveBufferFence;
@@ -920,11 +908,11 @@
} // namespace android
-#define RETURN_IF_NO_HWC_LAYER(displayId, ...) \
+#define RETURN_IF_NO_HWC_LAYER(displayDevice, ...) \
do { \
- if (!hasHwcLayer(displayId)) { \
+ if (!hasHwcLayer(displayDevice)) { \
ALOGE("[%s] %s failed: no HWC layer found for display %s", mName.string(), \
- __FUNCTION__, to_string(displayId).c_str()); \
+ __FUNCTION__, displayDevice->getDebugName().c_str()); \
return __VA_ARGS__; \
} \
} while (false)
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index e39babe..9f63440 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -21,45 +21,14 @@
#include "Layer.h"
-#include <android-base/stringprintf.h>
-#include <renderengine/RenderEngine.h>
-
-#include <string>
-
-namespace {
-
-const char* getCompositionName(HWC2::Composition compositionType) {
- switch (compositionType) {
- case HWC2::Composition::Invalid:
- return "Invalid";
- case HWC2::Composition::Client:
- return "Client";
- case HWC2::Composition::Device:
- return "Device";
- case HWC2::Composition::SolidColor:
- return "Solid Color";
- case HWC2::Composition::Cursor:
- return "Cursor";
- case HWC2::Composition::Sideband:
- return "Sideband";
- }
- return "Invalid";
-}
-
-} // namespace anonymous
-
namespace android {
-LayerBE::LayerBE(Layer* layer, std::string layerName)
- : mLayer(layer),
- mMesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2) {
+LayerBE::LayerBE(Layer* layer, std::string layerName) : mLayer(layer) {
compositionInfo.layer = std::make_shared<LayerBE>(*this);
compositionInfo.layerName = layerName;
}
-LayerBE::LayerBE(const LayerBE& layer)
- : mLayer(layer.mLayer),
- mMesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2) {
+LayerBE::LayerBE(const LayerBE& layer) : mLayer(layer.mLayer) {
compositionInfo.layer = layer.compositionInfo.layer;
compositionInfo.layerName = layer.mLayer->getName().string();
}
@@ -68,101 +37,4 @@
mLayer->onLayerDisplayed(releaseFence);
}
-void LayerBE::clear(renderengine::RenderEngine& engine) {
- engine.setupFillWithColor(0, 0, 0, 0);
- engine.drawMesh(mMesh);
-}
-
-void CompositionInfo::dump(const char* tag) const
-{
- std::string logString;
- dump(logString, tag);
- ALOGV("%s", logString.c_str());
-}
-
-void CompositionInfo::dumpHwc(std::string& result, const char* tag) const {
- if (tag == nullptr) {
- result += base::StringPrintf("HWC parameters\n");
- } else {
- result += base::StringPrintf("[%s]HWC parameters\n", tag);
- }
-
- result += base::StringPrintf("\thwcLayer=%p\n", static_cast<HWC2::Layer*>(&*hwc.hwcLayer));
- result += base::StringPrintf("\tfence=%p\n", hwc.fence.get());
- result += base::StringPrintf("\tblendMode=%d\n", hwc.blendMode);
- result += base::StringPrintf("\ttransform=%d\n", hwc.transform);
- result += base::StringPrintf("\tz=%d\n", hwc.z);
- result += base::StringPrintf("\ttype=%d\n", hwc.type);
- result += base::StringPrintf("\tappId=%d\n", hwc.appId);
- result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left,
- hwc.displayFrame.top, hwc.displayFrame.right,
- hwc.displayFrame.bottom);
- result += base::StringPrintf("\talpha=%.3f", hwc.alpha);
- result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left,
- hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
-
- hwc.visibleRegion.dump(result, "visibleRegion");
- hwc.surfaceDamage.dump(result, "surfaceDamage");
-
- result += base::StringPrintf("\tcolor transform matrix:\n"
- "\t\t[%f, %f, %f, %f,\n"
- "\t\t %f, %f, %f, %f,\n"
- "\t\t %f, %f, %f, %f,\n"
- "\t\t %f, %f, %f, %f]\n",
- hwc.colorTransform[0][0], hwc.colorTransform[1][0],
- hwc.colorTransform[2][0], hwc.colorTransform[3][0],
- hwc.colorTransform[0][1], hwc.colorTransform[1][1],
- hwc.colorTransform[2][1], hwc.colorTransform[3][1],
- hwc.colorTransform[0][2], hwc.colorTransform[1][2],
- hwc.colorTransform[2][2], hwc.colorTransform[3][2],
- hwc.colorTransform[0][3], hwc.colorTransform[1][3],
- hwc.colorTransform[2][3], hwc.colorTransform[3][3]);
-}
-
-void CompositionInfo::dumpRe(std::string& result, const char* tag) const {
- if (tag == nullptr) {
- result += base::StringPrintf("RenderEngine parameters:\n");
- } else {
- result += base::StringPrintf("[%s]RenderEngine parameters:\n", tag);
- }
-
- result += base::StringPrintf("\tblackoutLayer=%d\n", re.blackoutLayer);
- result += base::StringPrintf("\tclearArea=%d\n", re.clearArea);
- result += base::StringPrintf("\tpreMultipliedAlpha=%d\n", re.preMultipliedAlpha);
- result += base::StringPrintf("\topaque=%d\n", re.opaque);
- result += base::StringPrintf("\tdisableTexture=%d\n", re.disableTexture);
- result += base::StringPrintf("\tuseIdentityTransform=%d\n", re.useIdentityTransform);
-}
-
-void CompositionInfo::dump(std::string& result, const char* tag) const
-{
- if (tag == nullptr) {
- result += base::StringPrintf("CompositionInfo\n");
- } else {
- result += base::StringPrintf("[%s]CompositionInfo\n", tag);
- }
- result += base::StringPrintf("\tLayerName: %s\n", layerName.c_str());
- result += base::StringPrintf("\tCompositionType: %s\n",
- getCompositionName(compositionType));
- result += base::StringPrintf("\tmBuffer = %p\n", mBuffer.get());
- result += base::StringPrintf("\tmBufferSlot=%d\n", mBufferSlot);
- result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left,
- hwc.displayFrame.top, hwc.displayFrame.right,
- hwc.displayFrame.bottom);
- result += base::StringPrintf("\talpha=%f\n", hwc.alpha);
- result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left,
- hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
-
- switch (compositionType) {
- case HWC2::Composition::Device:
- dumpHwc(result, tag);
- break;
- case HWC2::Composition::Client:
- dumpRe(result, tag);
- break;
- default:
- break;
- }
-}
-
}; // namespace android
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 6270efa..51f7857 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -17,18 +17,12 @@
#pragma once
#include <stdint.h>
-#include <sys/types.h>
+#include <string.h>
-#include <compositionengine/impl/HwcBufferCache.h>
-
-#include <renderengine/Mesh.h>
-#include <renderengine/RenderEngine.h>
-#include <renderengine/Texture.h>
-#include <ui/Region.h>
+#include <ui/Fence.h>
+#include <utils/StrongPointer.h>
#include "DisplayHardware/DisplayIdentification.h"
-#include "DisplayHardware/HWComposer.h"
-#include "SurfaceFlinger.h"
namespace android {
@@ -36,48 +30,10 @@
struct CompositionInfo {
std::string layerName;
- HWC2::Composition compositionType;
- bool firstClear = false;
- sp<GraphicBuffer> mBuffer = nullptr;
- int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
std::shared_ptr<LayerBE> layer;
struct {
- std::shared_ptr<HWC2::Layer> hwcLayer;
DisplayId displayId;
- sp<Fence> fence;
- HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
- Rect displayFrame;
- float alpha;
- FloatRect sourceCrop;
- HWC2::Transform transform = HWC2::Transform::None;
- int z;
- int type;
- int appId;
- Region visibleRegion;
- Region surfaceDamage;
- sp<NativeHandle> sidebandStream;
- ui::Dataspace dataspace;
- hwc_color_t color;
- bool clearClientTarget = false;
- bool supportedPerFrameMetadata = false;
- HdrMetadata hdrMetadata;
- mat4 colorTransform;
} hwc;
- struct {
- bool blackoutLayer = false;
- bool clearArea = false;
- bool preMultipliedAlpha = false;
- bool opaque = false;
- bool disableTexture = false;
- half4 color;
- bool useIdentityTransform = false;
- bool Y410BT2020 = false;
- } re;
-
- void dump(const char* tag) const;
- void dump(std::string& result, const char* tag = nullptr) const;
- void dumpHwc(std::string& result, const char* tag = nullptr) const;
- void dumpRe(std::string& result, const char* tag = nullptr) const;
};
class LayerBE {
@@ -96,41 +52,10 @@
explicit LayerBE(const LayerBE& layer);
void onLayerDisplayed(const sp<Fence>& releaseFence);
- void clear(renderengine::RenderEngine& renderEngine);
- renderengine::Mesh& getMesh() { return mMesh; }
Layer*const mLayer;
+
private:
- // The mesh used to draw the layer in GLES composition mode
- renderengine::Mesh mMesh;
-
- // HWC items, accessed from the main thread
- struct HWCInfo {
- HWCInfo()
- : hwc(nullptr),
- layer(nullptr),
- forceClientComposition(false),
- compositionType(HWC2::Composition::Invalid),
- clearClientTarget(false),
- transform(HWC2::Transform::None) {}
-
- HWComposer* hwc;
- std::shared_ptr<HWC2::Layer> layer;
- bool forceClientComposition;
- HWC2::Composition compositionType;
- bool clearClientTarget;
- Rect displayFrame;
- FloatRect sourceCrop;
- compositionengine::impl::HwcBufferCache bufferCache;
- HWC2::Transform transform;
- };
-
- // A layer can be attached to multiple displays when operating in mirror mode
- // (a.k.a: when several displays are attached with equal layerStack). In this
- // case we need to keep track. In non-mirror mode, a layer will have only one
- // HWCInfo.
- std::unordered_map<DisplayId, HWCInfo> mHwcLayers;
-
CompositionInfo compositionInfo;
};
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 9bad6de..edc6442 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -7,6 +7,8 @@
namespace android {
+class DisplayDevice;
+
// RenderArea describes a rectangular area that layers can be rendered to.
//
// There is a logical render area and a physical render area. When a layer is
@@ -76,6 +78,8 @@
// covered by any rendered layer should be filled with this color.
CaptureFill getCaptureFill() const { return mCaptureFill; };
+ virtual const sp<const DisplayDevice> getDisplayDevice() const = 0;
+
private:
const uint32_t mReqWidth;
const uint32_t mReqHeight;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index af439f7..30fba3c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -189,6 +189,49 @@
}
}
+void Scheduler::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
+ {
+ std::lock_guard<std::mutex> lock(mHWVsyncLock);
+ if (makeAvailable) {
+ mHWVsyncAvailable = makeAvailable;
+ } else if (!mHWVsyncAvailable) {
+ // Hardware vsync is not currently available, so abort the resync
+ // attempt for now
+ return;
+ }
+ }
+
+ if (period <= 0) {
+ return;
+ }
+
+ setVsyncPeriod(period);
+}
+
+ResyncCallback Scheduler::makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
+ std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
+ return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
+ if (const auto vsync = ptr.lock()) {
+ vsync->resync(getVsyncPeriod);
+ }
+ };
+}
+
+void Scheduler::VsyncState::resync(const GetVsyncPeriod& getVsyncPeriod) {
+ static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+
+ const nsecs_t now = systemTime();
+ const nsecs_t last = lastResyncTime.exchange(now);
+
+ if (now - last > kIgnoreDelay) {
+ scheduler.resyncToHardwareVsync(false, getVsyncPeriod());
+ }
+}
+
+void Scheduler::setRefreshSkipCount(int count) {
+ mPrimaryDispSync->setRefreshSkipCount(count);
+}
+
void Scheduler::setVsyncPeriod(const nsecs_t period) {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
mPrimaryDispSync->reset();
@@ -229,16 +272,6 @@
mPrimaryDispSync->setIgnorePresentFences(ignore);
}
-void Scheduler::makeHWSyncAvailable(bool makeAvailable) {
- std::lock_guard<std::mutex> lock(mHWVsyncLock);
- mHWVsyncAvailable = makeAvailable;
-}
-
-bool Scheduler::getHWSyncAvailable() {
- std::lock_guard<std::mutex> lock(mHWVsyncLock);
- return mHWVsyncAvailable;
-}
-
nsecs_t Scheduler::expectedPresentTime() {
return mPrimaryDispSync->expectedPresentTime();
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index d628e40..7b5278c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -37,6 +37,7 @@
class Scheduler {
public:
using ExpiredIdleTimerCallback = std::function<void()>;
+ using GetVsyncPeriod = std::function<nsecs_t()>;
using ResetIdleTimerCallback = std::function<void()>;
// Enum to indicate whether to start the transaction early, or at vsync time.
@@ -67,6 +68,16 @@
const std::unique_ptr<EventThread> thread;
};
+ // Stores per-display state about VSYNC.
+ struct VsyncState {
+ explicit VsyncState(Scheduler& scheduler) : scheduler(scheduler) {}
+
+ void resync(const GetVsyncPeriod&);
+
+ Scheduler& scheduler;
+ std::atomic<nsecs_t> lastResyncTime = 0;
+ };
+
explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function);
virtual ~Scheduler();
@@ -104,13 +115,13 @@
void enableHardwareVsync();
void disableHardwareVsync(bool makeUnavailable);
- void setVsyncPeriod(const nsecs_t period);
+ void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
+ // Creates a callback for resyncing.
+ ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
+ void setRefreshSkipCount(int count);
void addResyncSample(const nsecs_t timestamp);
void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
void setIgnorePresentFences(bool ignore);
- void makeHWSyncAvailable(bool makeAvailable);
- // returns HWSyncAvailable flag to SF would enable HW vsync based on this
- bool getHWSyncAvailable();
nsecs_t expectedPresentTime();
// Adds the present time for given layer to the history of present times.
void addFramePresentTimeForLayer(const nsecs_t framePresentTime, bool isAutoTimestamp,
@@ -133,6 +144,8 @@
impl::EventThread::InterceptVSyncsCallback interceptCallback);
private:
+ friend class TestableScheduler;
+
// Creates a connection on the given EventThread and forwards the given callbacks.
sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&);
@@ -150,6 +163,8 @@
void resetTimerCallback();
// Function that is called when the timer expires.
void expiredTimerCallback();
+ // Sets vsync period.
+ void setVsyncPeriod(const nsecs_t period);
// If fences from sync Framework are supported.
const bool mHasSyncFramework;
@@ -167,6 +182,7 @@
std::mutex mHWVsyncLock;
bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock);
bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock);
+ const std::shared_ptr<VsyncState> mPrimaryVsyncState{std::make_shared<VsyncState>(*this)};
std::unique_ptr<DispSync> mPrimaryDispSync;
std::unique_ptr<EventControlThread> mEventControlThread;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dc3409b..3bec6dc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -43,7 +43,9 @@
#include <compositionengine/Layer.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/RenderSurface.h>
+#include <compositionengine/impl/LayerCompositionState.h>
#include <compositionengine/impl/OutputCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <dvr/vr_flinger.h>
#include <gui/BufferQueue.h>
#include <gui/GuiConfig.h>
@@ -290,8 +292,6 @@
mLastTransactionTime(0),
mForceFullDamage(false),
mTimeStats(factory.createTimeStats()),
- mPrimaryHWVsyncEnabled(false),
- mHWVsyncAvailable(false),
mRefreshStartTime(0),
mHasPoweredOff(false),
mNumLayers(0),
@@ -393,14 +393,8 @@
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
- property_get("debug.sf.use_scheduler", value, "0");
- mUseScheduler = atoi(value);
-
- if (!mUseScheduler) {
- mPrimaryDispSync =
- getFactory().createDispSync("PrimaryDispSync", SurfaceFlinger::hasSyncFramework,
- SurfaceFlinger::dispSyncPresentTimeOffset);
- }
+ property_get("debug.sf.use_90Hz", value, "0");
+ mUse90Hz = atoi(value);
const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
mVsyncModulator.setPhaseOffsets(early, gl, late);
@@ -622,52 +616,28 @@
ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
Mutex::Autolock _l(mStateLock);
-
- auto resyncCallback = makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
-
// start the EventThread
- if (mUseScheduler) {
- mScheduler = getFactory().createScheduler(
- [this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
+ mScheduler =
+ getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
+ auto resyncCallback =
+ mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
- // TODO(b/113612090): Currently we assume that if scheduler is turned on, then the refresh
- // rate is 90. Once b/122905403 is completed, this should be updated accordingly.
+ mAppConnectionHandle =
+ mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
+ resyncCallback,
+ impl::EventThread::InterceptVSyncsCallback());
+ mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
+ resyncCallback, [this](nsecs_t timestamp) {
+ mInterceptor->saveVSyncEvent(timestamp);
+ });
+
+ mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
+ mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
+ mSfConnectionHandle.get());
+
+ if (mUse90Hz) {
mPhaseOffsets->setRefreshRateType(
scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
-
- mAppConnectionHandle =
- mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
- resyncCallback,
- impl::EventThread::InterceptVSyncsCallback());
- mSfConnectionHandle =
- mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
- resyncCallback, [this](nsecs_t timestamp) {
- mInterceptor->saveVSyncEvent(timestamp);
- });
-
- mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
- mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
- mSfConnectionHandle.get());
- } else {
- mEventThreadSource =
- std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
- mPhaseOffsets->getCurrentAppOffset(), true, "app");
- mEventThread =
- std::make_unique<impl::EventThread>(mEventThreadSource.get(),
- impl::EventThread::InterceptVSyncsCallback(),
- "appEventThread");
- mSfEventThreadSource =
- std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
- mPhaseOffsets->getCurrentSfOffset(), true, "sf");
-
- mSFEventThread =
- std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
- [this](nsecs_t timestamp) {
- mInterceptor->saveVSyncEvent(timestamp);
- },
- "sfEventThread");
- mEventQueue->setEventThread(mSFEventThread.get(), std::move(resyncCallback));
- mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
}
// Get a RenderEngine for the given display / config (can't fail)
@@ -717,11 +687,6 @@
}
}
- if (!mUseScheduler) {
- mEventControlThread = getFactory().createEventControlThread(
- [this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
- }
-
// initialize our drawing state
mDrawingState = mCurrentState;
@@ -740,21 +705,18 @@
ALOGE("Run StartPropertySetThread failed!");
}
- if (mUseScheduler) {
- mScheduler->setExpiredIdleTimerCallback([this] {
- Mutex::Autolock lock(mStateLock);
- setRefreshRateTo(RefreshRateType::DEFAULT);
- });
- mScheduler->setResetIdleTimerCallback([this] {
- Mutex::Autolock lock(mStateLock);
- setRefreshRateTo(RefreshRateType::PERFORMANCE);
- });
+ mScheduler->setExpiredIdleTimerCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::DEFAULT);
+ });
+ mScheduler->setResetIdleTimerCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::PERFORMANCE);
+ });
- mRefreshRateStats =
- std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
- *display->getId()),
- mTimeStats);
- }
+ mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
+ *display->getId()),
+ mTimeStats);
ALOGV("Done initializing");
}
@@ -943,12 +905,7 @@
return BAD_VALUE;
}
- if (mUseScheduler) {
- mScheduler->getDisplayStatInfo(stats);
- } else {
- stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
- stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
- }
+ mScheduler->getDisplayStatInfo(stats);
return NO_ERROR;
}
@@ -1014,6 +971,7 @@
if (!display) {
return;
}
+
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
@@ -1027,9 +985,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mActiveConfigLock);
- if (mUseScheduler) {
- mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
- }
+ mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
const auto display = getDisplayDeviceLocked(mUpcomingActiveConfig.displayToken);
display->setActiveConfig(mUpcomingActiveConfig.configId);
@@ -1037,7 +993,7 @@
mSetActiveConfigState = SetActiveConfigState::NONE;
ATRACE_INT("SetActiveConfigState", mSetActiveConfigState);
- resyncToHardwareVsync(true, getVsyncPeriod());
+ mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
}
@@ -1258,7 +1214,8 @@
return;
}
- auto resyncCallback = makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
+ auto resyncCallback =
+ mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
// TODO(akrulec): Part of the Injector should be refactored, so that it
// can be passed to Scheduler.
@@ -1274,7 +1231,8 @@
mEventQueue->setEventThread(mInjectorEventThread.get(), std::move(resyncCallback));
} else {
ALOGV("VSync Injections disabled");
- mEventQueue->setEventThread(mSFEventThread.get(), std::move(resyncCallback));
+ mEventQueue->setEventThread(mScheduler->getEventThread(mSfConnectionHandle),
+ std::move(resyncCallback));
}
mInjectVSyncs = enable;
@@ -1342,23 +1300,15 @@
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource) {
- auto resyncCallback = makeResyncCallback([this] {
+ auto resyncCallback = mScheduler->makeResyncCallback([this] {
Mutex::Autolock lock(mStateLock);
return getVsyncPeriod();
});
- if (mUseScheduler) {
- const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle
- : mAppConnectionHandle;
+ const auto& handle =
+ vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
- return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
- } else {
- if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mSFEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
- } else {
- return mEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
- }
- }
+ return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
}
// ----------------------------------------------------------------------------
@@ -1410,79 +1360,6 @@
return config ? config->getVsyncPeriod() : 0;
}
-void SurfaceFlinger::enableHardwareVsync() {
- assert(!mUseScheduler);
- Mutex::Autolock _l(mHWVsyncLock);
- if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
- mPrimaryDispSync->beginResync();
- mEventControlThread->setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
- }
-}
-
-void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
- Mutex::Autolock _l(mHWVsyncLock);
- // TODO(b/113612090): This is silly, but necessary evil until we turn on the flag for good.
- if (mUseScheduler) {
- if (makeAvailable) {
- mScheduler->makeHWSyncAvailable(true);
- } else if (!mScheduler->getHWSyncAvailable()) {
- // Hardware vsync is not currently available, so abort the resync
- // attempt for now
- return;
- }
- } else {
- if (makeAvailable) {
- mHWVsyncAvailable = true;
- } else if (!mHWVsyncAvailable) {
- // Hardware vsync is not currently available, so abort the resync
- // attempt for now
- return;
- }
- }
-
- if (period <= 0) {
- return;
- }
-
- if (mUseScheduler) {
- mScheduler->setVsyncPeriod(period);
- } else {
- mPrimaryDispSync->reset();
- mPrimaryDispSync->setPeriod(period);
-
- if (!mPrimaryHWVsyncEnabled) {
- mPrimaryDispSync->beginResync();
- mEventControlThread->setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
- }
- }
-}
-
-void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
- assert(!mUseScheduler);
- Mutex::Autolock _l(mHWVsyncLock);
- if (mPrimaryHWVsyncEnabled) {
- mEventControlThread->setVsyncEnabled(false);
- mPrimaryDispSync->endResync();
- mPrimaryHWVsyncEnabled = false;
- }
- if (makeUnavailable) {
- mHWVsyncAvailable = false;
- }
-}
-
-void SurfaceFlinger::VsyncState::resync(const GetVsyncPeriod& getVsyncPeriod) {
- static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
-
- const nsecs_t now = systemTime();
- const nsecs_t last = lastResyncTime.exchange(now);
-
- if (now - last > kIgnoreDelay) {
- flinger.resyncToHardwareVsync(false, getVsyncPeriod());
- }
-}
-
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
int64_t timestamp) {
ATRACE_NAME("SF onVsync");
@@ -1502,23 +1379,7 @@
return;
}
- if (mUseScheduler) {
- mScheduler->addResyncSample(timestamp);
- } else {
- bool needsHwVsync = false;
- { // Scope for the lock
- Mutex::Autolock _l(mHWVsyncLock);
- if (mPrimaryHWVsyncEnabled) {
- needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
- }
- }
-
- if (needsHwVsync) {
- enableHardwareVsync();
- } else {
- disableHardwareVsync(false);
- }
- }
+ mScheduler->addResyncSample(timestamp);
}
void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
@@ -1619,11 +1480,7 @@
// Note: it is assumed the caller holds |mStateLock| when this is called
void SurfaceFlinger::resetDisplayState() {
- if (mUseScheduler) {
- mScheduler->disableHardwareVsync(true);
- } else {
- disableHardwareVsync(true);
- }
+ mScheduler->disableHardwareVsync(true);
// Clear the drawing state so that the logic inside of
// handleTransactionLocked will fire. It will determine the delta between
// mCurrentState and mDrawingState and re-apply all changes when we make the
@@ -1652,7 +1509,18 @@
sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
LOG_ALWAYS_FATAL_IF(!display);
+
const int currentDisplayPowerMode = display->getPowerMode();
+
+ // Clear out all the output layers from the composition engine for all
+ // displays before destroying the hardware composer interface. This ensures
+ // any HWC layers are destroyed through that interface before it becomes
+ // invalid.
+ for (const auto& [token, displayDevice] : mDisplays) {
+ displayDevice->getCompositionDisplay()->setOutputLayersOrderedByZ(
+ compositionengine::Output::OutputLayers());
+ }
+
// This DisplayDevice will no longer be relevant once resetDisplayState() is
// called below. Clear the reference now so we don't accidentally use it
// later.
@@ -1690,20 +1558,14 @@
// The present fences returned from vr_hwc are not an accurate
// representation of vsync times.
- if (mUseScheduler) {
- mScheduler->setIgnorePresentFences(getHwComposer().isUsingVrComposer() ||
- !hasSyncFramework);
- } else {
- mPrimaryDispSync->setIgnorePresentFences(getHwComposer().isUsingVrComposer() ||
- !hasSyncFramework);
- }
+ mScheduler->setIgnorePresentFences(getHwComposer().isUsingVrComposer() || !hasSyncFramework);
// Use phase of 0 since phase is not known.
// Use latency of 0, which will snap to the ideal latency.
DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
setCompositorTimingSnapped(stats, 0);
- resyncToHardwareVsync(false, vsyncPeriod);
+ mScheduler->resyncToHardwareVsync(false, vsyncPeriod);
mRepaintEverything = true;
setTransactionFlags(eDisplayTransactionNeeded);
@@ -1717,10 +1579,9 @@
break;
}
- if (mUseScheduler) {
- // This call is made each time SF wakes up and creates a new frame.
- mScheduler->incrementFrameCounter();
- }
+ // This call is made each time SF wakes up and creates a new frame.
+ mScheduler->incrementFrameCounter();
+
bool frameMissed = !mHadClientComposition && mPreviousPresentFence != Fence::NO_FENCE &&
(mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled);
mFrameMissedCount += frameMissed;
@@ -1811,26 +1672,9 @@
mHadClientComposition || getHwComposer().hasClientComposition(displayId);
}
- // Setup RenderEngine sync fences if native sync is supported.
- if (getRenderEngine().useNativeFenceSync()) {
- if (mHadClientComposition) {
- base::unique_fd flushFence(getRenderEngine().flush());
- ALOGE_IF(flushFence < 0, "Failed to flush RenderEngine!");
- getBE().flushFence = new Fence(std::move(flushFence));
- } else {
- // Cleanup for hygiene.
- getBE().flushFence = Fence::NO_FENCE;
- }
- }
-
mVsyncModulator.onRefreshed(mHadClientComposition);
getBE().mEndOfFrameCompositionInfo = std::move(getBE().mCompositionInfo);
- for (const auto& [token, display] : mDisplays) {
- for (auto& compositionInfo : getBE().mEndOfFrameCompositionInfo[token]) {
- compositionInfo.hwc.hwcLayer = nullptr;
- }
- }
mLayersWithQueuedFrames.clear();
}
@@ -1871,16 +1715,14 @@
for (size_t i = 0; i < currentLayers.size(); i++) {
const auto& layer = currentLayers[i];
- if (!layer->hasHwcLayer(*displayId)) {
- if (!layer->createHwcLayer(&getHwComposer(), *displayId)) {
- layer->forceClientComposition(*displayId);
- continue;
- }
+ if (!layer->hasHwcLayer(displayDevice)) {
+ layer->forceClientComposition(displayDevice);
+ continue;
}
layer->setGeometry(displayDevice, i);
if (mDebugDisableHWC || mDebugRegion) {
- layer->forceClientComposition(*displayId);
+ layer->forceClientComposition(displayDevice);
}
}
}
@@ -1900,34 +1742,35 @@
}
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
if (layer->isHdrY410()) {
- layer->forceClientComposition(*displayId);
+ layer->forceClientComposition(displayDevice);
} else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
!profile->hasHDR10Support()) {
- layer->forceClientComposition(*displayId);
+ layer->forceClientComposition(displayDevice);
} else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
!profile->hasHLGSupport()) {
- layer->forceClientComposition(*displayId);
+ layer->forceClientComposition(displayDevice);
}
// TODO(b/111562338) remove when composer 2.3 is shipped.
if (layer->hasColorTransform()) {
- layer->forceClientComposition(*displayId);
+ layer->forceClientComposition(displayDevice);
}
if (layer->getRoundedCornerState().radius > 0.0f) {
- layer->forceClientComposition(*displayId);
+ layer->forceClientComposition(displayDevice);
}
- if (layer->getForceClientComposition(*displayId)) {
+ if (layer->getForceClientComposition(displayDevice)) {
ALOGV("[%s] Requesting Client composition", layer->getName().string());
- layer->setCompositionType(*displayId, HWC2::Composition::Client);
+ layer->setCompositionType(displayDevice,
+ Hwc2::IComposerClient::Composition::CLIENT);
continue;
}
const auto& displayState = display->getState();
- layer->setPerFrameData(*displayId, displayState.transform, displayState.viewport,
+ layer->setPerFrameData(displayDevice, displayState.transform, displayState.viewport,
displayDevice->getSupportedPerFrameMetadata());
}
@@ -1942,20 +1785,15 @@
mDrawingState.colorMatrixChanged = false;
- for (const auto& [token, display] : mDisplays) {
- for (auto& layer : display->getVisibleLayersSortedByZ()) {
+ for (const auto& [token, displayDevice] : mDisplays) {
+ auto display = displayDevice->getCompositionDisplay();
+ for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
const auto displayId = display->getId();
- layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId);
-
- if (displayId) {
- if (!layer->setHwcLayer(*displayId)) {
- ALOGV("Need to create HWCLayer for %s", layer->getName().string());
- }
- layer->getBE().compositionInfo.hwc.displayId = *displayId;
- }
-
+ auto& layerState = layer->getCompositionLayer()->editState().frontEnd;
+ layerState.compositionType = static_cast<Hwc2::IComposerClient::Composition>(
+ layer->getCompositionType(displayDevice));
+ layer->getBE().compositionInfo.hwc.displayId = *displayId;
getBE().mCompositionInfo[token].push_back(layer->getBE().compositionInfo);
- layer->getBE().compositionInfo.hwc.hwcLayer = nullptr;
}
}
}
@@ -2003,7 +1841,7 @@
if (CC_UNLIKELY(mLayerStats.isEnabled())) {
for (const auto& [token, display] : mDisplays) {
if (display->isPrimary()) {
- mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(*display));
+ mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(display));
return;
}
}
@@ -2180,12 +2018,7 @@
DisplayStatInfo stats;
DEFINE_STACK_GUARD(stats);
- if (mUseScheduler) {
- mScheduler->getDisplayStatInfo(&stats);
- } else {
- stats.vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
- stats.vsyncPeriod = mPrimaryDispSync->getPeriod();
- }
+ mScheduler->getDisplayStatInfo(&stats);
ASSERT_ON_STACK_GUARD();
@@ -2218,27 +2051,14 @@
if (presentFenceTime->isValid()) {
ASSERT_ON_STACK_GUARD();
- if (mUseScheduler) {
- mScheduler->addPresentFence(presentFenceTime);
- ASSERT_ON_STACK_GUARD();
- } else {
- if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
- enableHardwareVsync();
- } else {
- disableHardwareVsync(false);
- }
- ASSERT_ON_STACK_GUARD();
- }
+ mScheduler->addPresentFence(presentFenceTime);
+ ASSERT_ON_STACK_GUARD();
}
if (!hasSyncFramework) {
if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) &&
displayDevice->isPoweredOn()) {
- if (mUseScheduler) {
- mScheduler->enableHardwareVsync();
- } else {
- enableHardwareVsync();
- }
+ mScheduler->enableHardwareVsync();
}
}
@@ -2381,42 +2201,42 @@
return;
}
- bool hwcLayerDestroyed = false;
const auto displayId = displayDevice->getId();
sp<compositionengine::LayerFE> layerFE = compositionLayer->getLayerFE();
LOG_ALWAYS_FATAL_IF(layerFE.get() == nullptr);
+ bool needsOutputLayer = false;
+
if (display->belongsInOutput(layer->getLayerStack(),
layer->getPrimaryDisplayOnly())) {
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
if (!drawRegion.isEmpty()) {
- layersSortedByZ.emplace_back(
- display->getOrCreateOutputLayer(layer->getCompositionLayer(),
- layerFE));
-
- deprecated_layersSortedByZ.add(layer);
- } else {
- // Clear out the HWC layer if this layer was
- // previously visible, but no longer is
- hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId);
+ needsOutputLayer = true;
}
- } else {
- // WM changes display->layerStack upon sleep/awake.
- // Here we make sure we delete the HWC layers even if
- // WM changed their layer stack.
- hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId);
}
- // If a layer is not going to get a release fence because
- // it is invisible, but it is also going to release its
- // old buffer, add it to the list of layers needing
- // fences.
- if (hwcLayerDestroyed) {
- auto found = std::find(mLayersWithQueuedFrames.cbegin(),
- mLayersWithQueuedFrames.cend(), layer);
- if (found != mLayersWithQueuedFrames.cend()) {
+ if (needsOutputLayer) {
+ layersSortedByZ.emplace_back(
+ display->getOrCreateOutputLayer(displayId, compositionLayer,
+ layerFE));
+ deprecated_layersSortedByZ.add(layer);
+
+ auto& outputLayerState = layersSortedByZ.back()->editState();
+ outputLayerState.visibleRegion =
+ tr.transform(layer->visibleRegion.intersect(displayState.viewport));
+ } else if (displayId) {
+ // For layers that are being removed from a HWC display,
+ // and that have queued frames, add them to a a list of
+ // released layers so we can properly set a fence.
+ bool hasExistingOutputLayer =
+ display->getOutputLayerForLayer(compositionLayer.get()) != nullptr;
+ bool hasQueuedFrames = std::find(mLayersWithQueuedFrames.cbegin(),
+ mLayersWithQueuedFrames.cend(),
+ layer) != mLayersWithQueuedFrames.cend();
+
+ if (hasExistingOutputLayer && hasQueuedFrames) {
layersNeedingFences.add(layer);
}
}
@@ -2576,8 +2396,7 @@
return;
}
- status_t result = display->getRenderSurface()->prepareFrame(
- getBE().mCompositionInfo[displayDevice->getDisplayToken()]);
+ status_t result = display->getRenderSurface()->prepareFrame();
ALOGE_IF(result != NO_ERROR, "prepareFrame failed for %s: %d (%s)",
displayDevice->getDebugName().c_str(), result, strerror(-result));
}
@@ -2635,9 +2454,10 @@
// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
// signaled. Always get the release fence from HWC first.
- if (displayId && layer->hasHwcLayer(*displayId)) {
- releaseFence = getHwComposer().getLayerReleaseFence(*displayId,
- layer->getHwcLayer(*displayId));
+ if (displayId && layer->hasHwcLayer(displayDevice)) {
+ releaseFence =
+ getHwComposer().getLayerReleaseFence(*displayId,
+ layer->getHwcLayer(displayDevice));
}
// If the layer was client composited in the previous frame, we
@@ -2645,7 +2465,8 @@
// Since we do not track that, always merge with the current
// client target acquire fence when it is available, even though
// this is suboptimal.
- if (layer->getCompositionType(displayId) == HWC2::Composition::Client) {
+ if (layer->getCompositionType(displayDevice) ==
+ Hwc2::IComposerClient::Composition::CLIENT) {
releaseFence =
Fence::merge("LayerRelease", releaseFence,
display->getRenderSurface()->getClientTargetAcquireFence());
@@ -2740,13 +2561,8 @@
}
void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected) {
- if (mUseScheduler) {
- mScheduler->hotplugReceived(mAppConnectionHandle, displayId, connected);
- mScheduler->hotplugReceived(mSfConnectionHandle, displayId, connected);
- } else {
- mEventThread->onHotplugReceived(displayId, connected);
- mSFEventThread->onHotplugReceived(displayId, connected);
- }
+ mScheduler->hotplugReceived(mAppConnectionHandle, displayId, connected);
+ mScheduler->hotplugReceived(mSfConnectionHandle, displayId, connected);
}
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
@@ -3162,16 +2978,8 @@
void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
if (layer->hasReadyFrame()) {
- nsecs_t expectedPresentTime;
- if (mUseScheduler) {
- expectedPresentTime = mScheduler->expectedPresentTime();
- } else {
- expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
- }
- if (layer->shouldPresentNow(expectedPresentTime)) {
- bool ignored = false;
- layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
- }
+ bool ignored = false;
+ layer->latchBuffer(ignored, systemTime());
}
layer->releasePendingBuffer(systemTime());
}
@@ -3184,12 +2992,8 @@
recordBufferingStats(l->getName().string(),
l->getOccupancyHistory(true));
- // We need to release the HWC layers when the Layer is removed
- // from the current state otherwise the HWC layer just continues
- // showing at its last configured state until we eventually
- // abandon the buffer queue.
+ // Ensure any buffers set to display on any children are released.
if (l->isRemovedFromCurrentState()) {
- l->destroyHwcLayersForAllDisplays();
latchAndReleaseBuffer(l);
}
}
@@ -3400,11 +3204,7 @@
if (layer->hasReadyFrame()) {
frameQueued = true;
nsecs_t expectedPresentTime;
- if (mUseScheduler) {
- expectedPresentTime = mScheduler->expectedPresentTime();
- } else {
- expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
- }
+ expectedPresentTime = mScheduler->expectedPresentTime();
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
@@ -3421,7 +3221,7 @@
Mutex::Autolock lock(mStateLock);
for (auto& layer : mLayersWithQueuedFrames) {
- if (layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence)) {
+ if (layer->latchBuffer(visibleRegions, latchTime)) {
mLayersPendingRefresh.push_back(layer);
}
layer->useSurfaceDamage();
@@ -3431,11 +3231,6 @@
}
}
- // Clear the renderengine fence here...
- // downstream code assumes that a cleared fence == NO_FENCE, so reassign to
- // clear instead of sp::clear.
- getBE().flushFence = Fence::NO_FENCE;
-
mVisibleRegionsDirty |= visibleRegions;
// If we will need to wake up at some time in the future to deal with a
@@ -3562,16 +3357,16 @@
const Region viewportRegion(displayState.viewport);
const Region clip(viewportRegion.intersect(layer->visibleRegion));
ALOGV("Layer: %s", layer->getName().string());
- ALOGV(" Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str());
+ ALOGV(" Composition type: %s", toString(layer->getCompositionType(displayDevice)).c_str());
if (!clip.isEmpty()) {
- switch (layer->getCompositionType(displayId)) {
- case HWC2::Composition::Cursor:
- case HWC2::Composition::Device:
- case HWC2::Composition::Sideband:
- case HWC2::Composition::SolidColor: {
+ switch (layer->getCompositionType(displayDevice)) {
+ case Hwc2::IComposerClient::Composition::CURSOR:
+ case Hwc2::IComposerClient::Composition::DEVICE:
+ case Hwc2::IComposerClient::Composition::SIDEBAND:
+ case Hwc2::IComposerClient::Composition::SOLID_COLOR: {
LOG_ALWAYS_FATAL_IF(!displayId);
const Layer::State& state(layer->getDrawingState());
- if (layer->getClearClientTarget(*displayId) && !firstLayer &&
+ if (layer->getClearClientTarget(displayDevice) && !firstLayer &&
layer->isOpaque(state) && (layer->getAlpha() == 1.0f) &&
layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
// never clear the very first layer since we're
@@ -3591,7 +3386,7 @@
}
break;
}
- case HWC2::Composition::Client: {
+ case Hwc2::IComposerClient::Composition::CLIENT: {
renderengine::LayerSettings layerSettings;
bool prepared =
layer->prepareClientLayer(renderArea, clip, clearRegion, layerSettings);
@@ -3708,11 +3503,12 @@
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
- const auto& [states, displays, flags, desiredPresentTime] = transactionQueue.front();
+ const auto& [states, displays, flags, desiredPresentTime, privileged] =
+ transactionQueue.front();
if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
break;
}
- applyTransactionState(states, displays, flags, mPendingInputWindowCommands);
+ applyTransactionState(states, displays, flags, mPendingInputWindowCommands, privileged);
transactionQueue.pop();
}
@@ -3745,12 +3541,7 @@
bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
const Vector<ComposerState>& states) {
- nsecs_t expectedPresentTime;
- if (mUseScheduler) {
- expectedPresentTime = mScheduler->expectedPresentTime();
- } else {
- expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
- }
+ nsecs_t expectedPresentTime = mScheduler->expectedPresentTime();
// Do not present if the desiredPresentTime has not passed unless it is more than one second
// in the future. We ignore timestamps more than 1 second in the future for stability reasons.
if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
@@ -3776,6 +3567,9 @@
const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime) {
ATRACE_CALL();
+
+ bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
+
Mutex::Autolock _l(mStateLock);
if (containsAnyInvalidClientState(states)) {
@@ -3785,17 +3579,19 @@
// If its TransactionQueue already has a pending TransactionState or if it is pending
if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
- mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime);
+ mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
+ privileged);
setTransactionFlags(eTransactionNeeded);
return;
}
- applyTransactionState(states, displays, flags, inputWindowCommands);
+ applyTransactionState(states, displays, flags, inputWindowCommands, privileged);
}
void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands) {
+ const InputWindowCommands& inputWindowCommands,
+ bool privileged) {
uint32_t transactionFlags = 0;
if (flags & eAnimation) {
@@ -3820,7 +3616,7 @@
uint32_t clientStateFlags = 0;
for (const ComposerState& state : states) {
- clientStateFlags |= setClientStateLocked(state);
+ clientStateFlags |= setClientStateLocked(state, privileged);
}
// If the state doesn't require a traversal and there are callbacks, send them now
if (!(clientStateFlags & eTraversalNeeded)) {
@@ -3918,7 +3714,7 @@
return flags;
}
-bool callingThreadHasUnscopedSurfaceFlingerAccess() {
+bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess() {
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
@@ -3929,7 +3725,8 @@
return true;
}
-uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) {
+uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState,
+ bool privileged) {
const layer_state_t& s = composerState.state;
sp<Client> client(static_cast<Client*>(composerState.client.get()));
@@ -4030,7 +3827,7 @@
// of cropped areas, we need to prevent non-root clients without permission ACCESS_SURFACE_FLINGER
// (a.k.a. everyone except WindowManager and tests) from setting non rectangle preserving
// transformations.
- if (layer->setMatrix(s.matrix, callingThreadHasUnscopedSurfaceFlingerAccess()))
+ if (layer->setMatrix(s.matrix, privileged))
flags |= eTraversalNeeded;
}
if (what & layer_state_t::eTransparentRegionChanged) {
@@ -4180,6 +3977,10 @@
flags |= eTraversalNeeded;
}
+ if (inputWindowCommands.syncInputWindows) {
+ flags |= eTraversalNeeded;
+ }
+
mPendingInputWindowCommands.merge(inputWindowCommands);
return flags;
}
@@ -4441,12 +4242,8 @@
// Turn on the display
getHwComposer().setPowerMode(*displayId, mode);
if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
- if (mUseScheduler) {
- mScheduler->onScreenAcquired(mAppConnectionHandle);
- } else {
- mEventThread->onScreenAcquired();
- }
- resyncToHardwareVsync(true, getVsyncPeriod());
+ mScheduler->onScreenAcquired(mAppConnectionHandle);
+ mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
}
mVisibleRegionsDirty = true;
@@ -4466,16 +4263,8 @@
}
if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
- if (mUseScheduler) {
- mScheduler->disableHardwareVsync(true);
- } else {
- disableHardwareVsync(true); // also cancels any in-progress resync
- }
- if (mUseScheduler) {
- mScheduler->onScreenReleased(mAppConnectionHandle);
- } else {
- mEventThread->onScreenReleased();
- }
+ mScheduler->disableHardwareVsync(true);
+ mScheduler->onScreenReleased(mAppConnectionHandle);
}
getHwComposer().setPowerMode(*displayId, mode);
@@ -4486,26 +4275,14 @@
// Update display while dozing
getHwComposer().setPowerMode(*displayId, mode);
if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
- if (mUseScheduler) {
- mScheduler->onScreenAcquired(mAppConnectionHandle);
- } else {
- mEventThread->onScreenAcquired();
- }
- resyncToHardwareVsync(true, getVsyncPeriod());
+ mScheduler->onScreenAcquired(mAppConnectionHandle);
+ mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
}
} else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
// Leave display going to doze
if (display->isPrimary()) {
- if (mUseScheduler) {
- mScheduler->disableHardwareVsync(true);
- } else {
- disableHardwareVsync(true); // also cancels any in-progress resync
- }
- if (mUseScheduler) {
- mScheduler->onScreenReleased(mAppConnectionHandle);
- } else {
- mEventThread->onScreenReleased();
- }
+ mScheduler->disableHardwareVsync(true);
+ mScheduler->onScreenReleased(mAppConnectionHandle);
}
getHwComposer().setPowerMode(*displayId, mode);
} else {
@@ -4515,7 +4292,7 @@
if (display->isPrimary()) {
mTimeStats->setPowerMode(mode);
- if (mUseScheduler && mRefreshRateStats) {
+ if (mRefreshRateStats) {
// Update refresh rate stats.
mRefreshRateStats->setPowerMode(mode);
}
@@ -4572,15 +4349,10 @@
{"--disable-layer-stats"s, dumper([this](std::string&) { mLayerStats.disable(); })},
{"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
{"--dispsync"s, dumper([this](std::string& s) {
- if (mUseScheduler) {
mScheduler->dumpPrimaryDispSync(s);
- } else {
- mPrimaryDispSync->dump(s);
- }
})},
{"--dump-layer-stats"s, dumper([this](std::string& s) { mLayerStats.dump(s); })},
{"--enable-layer-stats"s, dumper([this](std::string&) { mLayerStats.enable(); })},
- {"--frame-composition"s, dumper(&SurfaceFlinger::dumpFrameCompositionInfo)},
{"--frame-events"s, dumper(&SurfaceFlinger::dumpFrameEventsLocked)},
{"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)},
{"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)},
@@ -4677,13 +4449,8 @@
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
dispSyncPresentTimeOffset, getVsyncPeriod());
- StringAppendF(&result, "Scheduler: %s\n\n", mUseScheduler ? "enabled" : "disabled");
-
- if (mUseScheduler) {
- mScheduler->dump(mAppConnectionHandle, result);
- } else {
- mEventThread->dump(result);
- }
+ StringAppendF(&result, "Scheduler enabled. 90Hz feature: %s\n\n", mUse90Hz ? "on" : "off");
+ mScheduler->dump(mAppConnectionHandle, result);
}
void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const {
@@ -4834,23 +4601,6 @@
result.append("\n");
}
-void SurfaceFlinger::dumpFrameCompositionInfo(std::string& result) const {
- for (const auto& [token, display] : mDisplays) {
- const auto it = getBE().mEndOfFrameCompositionInfo.find(token);
- if (it == getBE().mEndOfFrameCompositionInfo.end()) {
- continue;
- }
-
- const auto& compositionInfoList = it->second;
- StringAppendF(&result, "%s\n", display->getDebugName().c_str());
- StringAppendF(&result, "numComponents: %zu\n", compositionInfoList.size());
- for (const auto& compositionInfo : compositionInfoList) {
- compositionInfo.dump(result, nullptr);
- result.append("\n");
- }
- }
-}
-
LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const {
LayersProto layersProto;
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
@@ -4863,26 +4613,27 @@
return layersProto;
}
-LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& displayDevice) const {
+LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
+ const sp<DisplayDevice>& displayDevice) const {
LayersProto layersProto;
SizeProto* resolution = layersProto.mutable_resolution();
- resolution->set_w(displayDevice.getWidth());
- resolution->set_h(displayDevice.getHeight());
+ resolution->set_w(displayDevice->getWidth());
+ resolution->set_h(displayDevice->getHeight());
- auto display = displayDevice.getCompositionDisplay();
+ auto display = displayDevice->getCompositionDisplay();
const auto& displayState = display->getState();
layersProto.set_color_mode(decodeColorMode(displayState.colorMode));
layersProto.set_color_transform(decodeColorTransform(displayState.colorTransform));
layersProto.set_global_transform(displayState.orientation);
- const auto displayId = displayDevice.getId();
+ const auto displayId = displayDevice->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(*displayId)) {
+ if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) {
LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProto(layerProto, *displayId);
+ layer->writeToProto(layerProto, displayDevice);
}
});
@@ -4951,10 +4702,6 @@
result.append("\n");
}
- result.append("\nFrame-Composition information:\n");
- dumpFrameCompositionInfo(result);
- result.append("\n");
-
/*
* Dump Display state
*/
@@ -5018,7 +4765,9 @@
StringAppendF(&result, "Display %s HWC layers:\n", to_string(*displayId).c_str());
Layer::miniDumpHeader(result);
- mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, *displayId); });
+ const sp<DisplayDevice> displayDevice = display;
+ mCurrentState.traverseInZOrder(
+ [&](Layer* layer) { layer->miniDump(result, displayDevice); });
result.append("\n");
}
@@ -5050,11 +4799,9 @@
/**
* Scheduler dump state.
*/
- if (mUseScheduler) {
- result.append("\nScheduler state:\n");
- result.append(mScheduler->doDump() + "\n");
- result.append(mRefreshRateStats->doDump() + "\n");
- }
+ result.append("\nScheduler state:\n");
+ result.append(mScheduler->doDump() + "\n");
+ result.append(mRefreshRateStats->doDump() + "\n");
}
const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) {
@@ -5154,7 +4901,8 @@
case GET_COLOR_MANAGEMENT:
case GET_COMPOSITION_PREFERENCE:
case GET_PROTECTED_CONTENT_SUPPORT:
- case IS_WIDE_COLOR_DISPLAY: {
+ case IS_WIDE_COLOR_DISPLAY:
+ case SET_INPUT_WINDOWS_FINISHED: {
return OK;
}
case CAPTURE_LAYERS:
@@ -5330,7 +5078,7 @@
case 1016: {
n = data.readInt32();
// TODO(b/113612090): Evaluate if this can be removed.
- mPrimaryDispSync->setRefreshSkipCount(n);
+ mScheduler->setRefreshSkipCount(n);
return NO_ERROR;
}
case 1017: {
@@ -5340,20 +5088,12 @@
}
case 1018: { // Modify Choreographer's phase offset
n = data.readInt32();
- if (mUseScheduler) {
- mScheduler->setPhaseOffset(mAppConnectionHandle, static_cast<nsecs_t>(n));
- } else {
- mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
- }
+ mScheduler->setPhaseOffset(mAppConnectionHandle, static_cast<nsecs_t>(n));
return NO_ERROR;
}
case 1019: { // Modify SurfaceFlinger's phase offset
n = data.readInt32();
- if (mUseScheduler) {
- mScheduler->setPhaseOffset(mSfConnectionHandle, static_cast<nsecs_t>(n));
- } else {
- mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
- }
+ mScheduler->setPhaseOffset(mSfConnectionHandle, static_cast<nsecs_t>(n));
return NO_ERROR;
}
case 1020: { // Layer updates interceptor
@@ -5570,6 +5310,7 @@
}
bool isSecure() const override { return false; }
bool needsFiltering() const override { return mNeedsFiltering; }
+ const sp<const DisplayDevice> getDisplayDevice() const override { return nullptr; }
Rect getSourceCrop() const override {
if (mCrop.isEmpty()) {
return getBounds();
@@ -5589,7 +5330,7 @@
newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform());
oldParent->setChildrenDrawingParent(newParent);
}
- ~ReparentForDrawing() { newParent->setChildrenDrawingParent(oldParent); }
+ ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); }
};
void render(std::function<void()> drawLayers) override {
@@ -5887,6 +5628,8 @@
return NO_ERROR;
}
+void SurfaceFlinger::setInputWindowsFinished() {}
+
// ---------------------------------------------------------------------------
void SurfaceFlinger::State::traverseInZOrder(const LayerVector::Visitor& visitor) const {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ea7a32d..b1f0992 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -169,9 +169,6 @@
nsecs_t mTotalTime;
std::atomic<nsecs_t> mLastSwapTime;
- // Synchronization fence from a GL composition.
- sp<Fence> flushFence = Fence::NO_FENCE;
-
// Double- vs. triple-buffering stats
struct BufferingStats {
BufferingStats()
@@ -408,6 +405,7 @@
*/
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
+ bool callingThreadHasUnscopedSurfaceFlingerAccess() EXCLUDES(mStateLock);
/* ------------------------------------------------------------------------
* ISurfaceComposer interface
@@ -479,6 +477,7 @@
status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) override;
status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override;
+ void setInputWindowsFinished() override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
@@ -534,11 +533,11 @@
void handleMessageRefresh();
void handleTransaction(uint32_t transactionFlags);
- void handleTransactionLocked(uint32_t transactionFlags);
+ void handleTransactionLocked(uint32_t transactionFlags) REQUIRES(mStateLock);
void updateInputFlinger();
void updateInputWindowInfo();
- void commitInputWindowCommands();
+ void commitInputWindowCommands() REQUIRES(mStateLock);
void executeInputWindowCommands();
void updateCursorAsync();
@@ -553,7 +552,8 @@
*/
void applyTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands) REQUIRES(mStateLock);
+ const InputWindowCommands& inputWindowCommands,
+ bool privileged) REQUIRES(mStateLock);
bool flushTransactionQueues();
uint32_t getTransactionFlags(uint32_t flags);
uint32_t peekTransactionFlags();
@@ -565,9 +565,10 @@
bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
const Vector<ComposerState>& states);
- uint32_t setClientStateLocked(const ComposerState& composerState);
+ uint32_t setClientStateLocked(const ComposerState& composerState, bool privileged);
uint32_t setDisplayStateLocked(const DisplayState& s);
- uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands);
+ uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
+ REQUIRES(mStateLock);
/* ------------------------------------------------------------------------
* Layer management
@@ -786,37 +787,11 @@
* VSync
*/
nsecs_t getVsyncPeriod() const REQUIRES(mStateLock);
- void enableHardwareVsync();
- void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
- void disableHardwareVsync(bool makeUnavailable);
// Sets the refresh rate by switching active configs, if they are available for
// the desired refresh rate.
void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType) REQUIRES(mStateLock);
- using GetVsyncPeriod = std::function<nsecs_t()>;
-
- // Stores per-display state about VSYNC.
- struct VsyncState {
- explicit VsyncState(SurfaceFlinger& flinger) : flinger(flinger) {}
-
- void resync(const GetVsyncPeriod&);
-
- SurfaceFlinger& flinger;
- std::atomic<nsecs_t> lastResyncTime = 0;
- };
-
- const std::shared_ptr<VsyncState> mPrimaryVsyncState{std::make_shared<VsyncState>(*this)};
-
- auto makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
- std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
- return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
- if (const auto vsync = ptr.lock()) {
- vsync->resync(getVsyncPeriod);
- }
- };
- }
-
/*
* Display identification
*/
@@ -894,9 +869,8 @@
void dumpBufferingStats(std::string& result) const;
void dumpDisplayIdentificationData(std::string& result) const;
void dumpWideColorInfo(std::string& result) const;
- void dumpFrameCompositionInfo(std::string& result) const;
LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
- LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const;
+ LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
@@ -955,11 +929,7 @@
// constant members (no synchronization needed for access)
nsecs_t mBootTime;
bool mGpuToCpuSupported;
- std::unique_ptr<EventThread> mEventThread;
- std::unique_ptr<EventThread> mSFEventThread;
std::unique_ptr<EventThread> mInjectorEventThread;
- std::unique_ptr<VSyncSource> mEventThreadSource;
- std::unique_ptr<VSyncSource> mSfEventThreadSource;
std::unique_ptr<InjectVSyncSource> mVSyncInjector;
std::unique_ptr<EventControlThread> mEventControlThread;
@@ -1026,16 +996,11 @@
// these are thread safe
mutable std::unique_ptr<MessageQueue> mEventQueue{mFactory.createMessageQueue()};
FrameTracker mAnimFrameTracker;
- std::unique_ptr<DispSync> mPrimaryDispSync;
// protected by mDestroyedLayerLock;
mutable Mutex mDestroyedLayerLock;
Vector<Layer const *> mDestroyedLayers;
- // protected by mHWVsyncLock
- Mutex mHWVsyncLock;
- bool mPrimaryHWVsyncEnabled;
- bool mHWVsyncAvailable;
nsecs_t mRefreshStartTime;
std::atomic<bool> mRefreshPending{false};
@@ -1055,16 +1020,19 @@
struct TransactionState {
TransactionState(const Vector<ComposerState>& composerStates,
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
- int64_t desiredPresentTime)
+ int64_t desiredPresentTime,
+ bool privileged)
: states(composerStates),
displays(displayStates),
flags(transactionFlags),
- time(desiredPresentTime) {}
+ time(desiredPresentTime),
+ privileged(privileged) {}
Vector<ComposerState> states;
Vector<DisplayState> displays;
uint32_t flags;
int64_t time;
+ bool privileged;
};
std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IBinderHash> mTransactionQueues;
@@ -1108,7 +1076,7 @@
/* ------------------------------------------------------------------------
* Scheduler
*/
- bool mUseScheduler = false;
+ bool mUse90Hz = false;
std::unique_ptr<Scheduler> mScheduler;
sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
@@ -1145,9 +1113,8 @@
/* ------------------------------------------------------------------------ */
sp<IInputFlinger> mInputFlinger;
- // Access must be protected by mStateLock.
- InputWindowCommands mPendingInputWindowCommands;
- // Should only be accessed by the drawing thread.
+ InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
+ // Should only be accessed by the main thread.
InputWindowCommands mInputWindowCommands;
ui::DisplayPrimaries mInternalDisplayPrimaries;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 7b21dbc..181dac6 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -5126,23 +5126,35 @@
SurfaceComposerClient::Transaction().show(mChild).apply(true);
}
- void verify() {
+ 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.
- verify();
+
+ // Before and after reparenting, verify child is properly hidden
+ // when rendering full-screen.
+ verify([&] { screenshot()->expectBGColor(64, 64); });
}
TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) {
@@ -5151,25 +5163,19 @@
.apply(true);
// Even though the parent is cropped out we should still capture the child.
- verify();
+
+ // 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);
+ SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2).apply(true);
// We should not inherit the parent scaling.
- verify();
-}
-TEST_F(ScreenCaptureChildOnlyTest, RegressionTest76099859) {
- SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true);
-
- // Even though the parent is hidden we should still capture the child.
- verify();
-
- // Verify everything was properly hidden when rendering the full-screen.
- screenshot()->expectBGColor(0,0);
+ // Before and after reparenting, verify child is properly scaled.
+ verify([&] { screenshot()->expectChildColor(80, 80); });
}
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 68cf61e..a2c0611 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -31,7 +31,6 @@
"libutils",
],
static_libs: [
- "libcompositionengine",
"libgmock",
"librenderengine",
"libtrace_proto",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 3fb8708..d0f7b90 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -17,6 +17,7 @@
#undef LOG_TAG
#define LOG_TAG "CompositionTest"
+#include <compositionengine/Display.h>
#include <compositionengine/mock/DisplaySurface.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -32,6 +33,7 @@
#include "ColorLayer.h"
#include "Layer.h"
+#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDispSync.h"
@@ -89,11 +91,9 @@
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
- mFlinger.mutableEventControlThread().reset(mEventControlThread);
- mFlinger.mutableEventThread().reset(mEventThread);
mFlinger.mutableEventQueue().reset(mMessageQueue);
+ setupScheduler();
- mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync);
EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
EXPECT_CALL(*mPrimaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
@@ -123,6 +123,18 @@
Mock::VerifyAndClear(mComposer);
}
+ void setupScheduler() {
+ mScheduler = new TestableScheduler();
+ mScheduler->mutableEventControlThread().reset(mEventControlThread);
+ mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
+ EXPECT_CALL(*mEventThread.get(), registerDisplayEventConnection(_));
+ sp<Scheduler::ConnectionHandle> connectionHandle =
+ mScheduler->addConnection(std::move(mEventThread));
+ mFlinger.mutableSfConnectionHandle() = std::move(connectionHandle);
+
+ mFlinger.mutableScheduler().reset(mScheduler);
+ }
+
void setupForceGeometryDirty() {
// TODO: This requires the visible region and other related
// state to be set, and is problematic for BufferLayers since they are
@@ -144,6 +156,7 @@
std::unordered_set<HWC2::Capability> mDefaultCapabilities = {HWC2::Capability::SidebandStream};
+ TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
sp<DisplayDevice> mDisplay;
sp<DisplayDevice> mExternalDisplay;
@@ -154,7 +167,7 @@
sp<GraphicBuffer> mBuffer = new GraphicBuffer();
ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer();
- mock::EventThread* mEventThread = new mock::EventThread();
+ std::unique_ptr<mock::EventThread> mEventThread = std::make_unique<mock::EventThread>();
mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
Hwc2::mock::Composer* mComposer = nullptr;
@@ -481,7 +494,7 @@
EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
bool ignoredRecomputeVisibleRegions;
- layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, Fence::NO_FENCE);
+ layer->latchBuffer(ignoredRecomputeVisibleRegions, 0);
Mock::VerifyAndClear(test->mRenderEngine);
}
@@ -756,9 +769,13 @@
EXPECT_CALL(*test->mComposer, createLayer(HWC_DISPLAY, _))
.WillOnce(DoAll(SetArgPointee<1>(HWC_LAYER), Return(Error::NONE)));
- const auto displayId = test->mDisplay->getId();
- ASSERT_TRUE(displayId);
- layer->createHwcLayer(&test->mFlinger.getHwComposer(), *displayId);
+ std::vector<std::unique_ptr<compositionengine::OutputLayer>> outputLayers;
+ outputLayers.emplace_back(test->mDisplay->getCompositionDisplay()
+ ->getOrCreateOutputLayer(DEFAULT_DISPLAY_ID,
+ layer->getCompositionLayer(),
+ layer));
+
+ test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(std::move(outputLayers));
Mock::VerifyAndClear(test->mComposer);
@@ -771,11 +788,9 @@
static void cleanupInjectedLayers(CompositionTest* test) {
EXPECT_CALL(*test->mComposer, destroyLayer(HWC_DISPLAY, HWC_LAYER))
.WillOnce(Return(Error::NONE));
- const auto displayId = test->mDisplay->getId();
- ASSERT_TRUE(displayId);
- for (auto layer : test->mFlinger.mutableDrawingState().layersSortedByZ) {
- layer->destroyHwcLayer(*displayId);
- }
+
+ test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(
+ std::vector<std::unique_ptr<compositionengine::OutputLayer>>());
test->mFlinger.mutableDrawingState().layersSortedByZ.clear();
}
};
@@ -963,8 +978,8 @@
};
struct ForcedClientCompositionResultVariant : public RECompositionResultVariant {
- static void setupLayerState(CompositionTest*, sp<Layer> layer) {
- layer->forceClientComposition(DEFAULT_DISPLAY_ID);
+ static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
+ layer->forceClientComposition(test->mDisplay);
}
template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 6659d4a..19f308b 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -29,6 +29,7 @@
#include <ui/DebugUtils.h>
#include "DisplayIdentificationTest.h"
+#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDispSync.h"
@@ -94,6 +95,8 @@
DisplayTransactionTest();
~DisplayTransactionTest() override;
+ void setupScheduler();
+
// --------------------------------------------------------------------
// Mock/Fake injection
@@ -116,6 +119,7 @@
// --------------------------------------------------------------------
// Test instances
+ TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
mock::EventThread* mEventThread = new mock::EventThread();
mock::EventThread* mSFEventThread = new mock::EventThread();
@@ -160,13 +164,10 @@
return nullptr;
});
- mFlinger.mutableEventControlThread().reset(mEventControlThread);
- mFlinger.mutableEventThread().reset(mEventThread);
- mFlinger.mutableSFEventThread().reset(mSFEventThread);
+ setupScheduler();
mFlinger.mutableEventQueue().reset(mMessageQueue);
mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);
- mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync);
injectMockComposer(0);
}
@@ -177,6 +178,22 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
+void DisplayTransactionTest::setupScheduler() {
+ mScheduler = new TestableScheduler();
+ mScheduler->mutableEventControlThread().reset(mEventControlThread);
+ mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
+ EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*mSFEventThread, registerDisplayEventConnection(_));
+
+ sp<Scheduler::ConnectionHandle> sfConnectionHandle =
+ mScheduler->addConnection(std::unique_ptr<EventThread>(mSFEventThread));
+ mFlinger.mutableSfConnectionHandle() = std::move(sfConnectionHandle);
+ sp<Scheduler::ConnectionHandle> appConnectionHandle =
+ mScheduler->addConnection(std::unique_ptr<EventThread>(mEventThread));
+ mFlinger.mutableAppConnectionHandle() = std::move(appConnectionHandle);
+ mFlinger.mutableScheduler().reset(mScheduler);
+}
+
void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) {
mComposer = new Hwc2::mock::Composer();
EXPECT_CALL(*mComposer, getCapabilities())
@@ -1106,8 +1123,8 @@
// Preconditions
// vsync is enabled and available
- mFlinger.mutablePrimaryHWVsyncEnabled() = true;
- mFlinger.mutableHWVsyncAvailable() = true;
+ mScheduler->mutablePrimaryHWVsyncEnabled() = true;
+ mScheduler->mutableHWVsyncAvailable() = true;
// A display exists
auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
@@ -1131,8 +1148,8 @@
// Postconditions
// vsyncs should be off and not available.
- EXPECT_FALSE(mFlinger.mutablePrimaryHWVsyncEnabled());
- EXPECT_FALSE(mFlinger.mutableHWVsyncAvailable());
+ EXPECT_FALSE(mScheduler->mutablePrimaryHWVsyncEnabled());
+ EXPECT_FALSE(mScheduler->mutableHWVsyncAvailable());
// The display should have been removed from the display map.
EXPECT_FALSE(hasDisplayDevice(existing.token()));
@@ -1557,7 +1574,6 @@
Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
-
expectHotplugReceived<Case, true>(mEventThread);
expectHotplugReceived<Case, true>(mSFEventThread);
}
@@ -3008,7 +3024,7 @@
}
static void setInitialPrimaryHWVsyncEnabled(DisplayTransactionTest* test, bool enabled) {
- test->mFlinger.mutablePrimaryHWVsyncEnabled() = enabled;
+ test->mScheduler->mutablePrimaryHWVsyncEnabled() = enabled;
}
static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
new file mode 100644
index 0000000..dcbf973
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "Scheduler/EventThread.h"
+#include "Scheduler/Scheduler.h"
+
+namespace android {
+
+class TestableScheduler : public Scheduler {
+public:
+ TestableScheduler() : Scheduler([](bool) {}) {}
+
+ // Creates EventThreadConnection with the given eventThread. Creates Scheduler::Connection
+ // and adds it to the list of connectins. Returns the ConnectionHandle for the
+ // Scheduler::Connection. This allows plugging in mock::EventThread.
+ sp<Scheduler::ConnectionHandle> addConnection(std::unique_ptr<EventThread> eventThread) {
+ sp<EventThreadConnection> eventThreadConnection =
+ new EventThreadConnection(eventThread.get(), ResyncCallback(),
+ ResetIdleTimerCallback());
+ const int64_t id = sNextId++;
+ mConnections.emplace(id,
+ std::make_unique<Scheduler::Connection>(new ConnectionHandle(id),
+ eventThreadConnection,
+ std::move(eventThread)));
+ return mConnections[id]->handle;
+ }
+
+ /* ------------------------------------------------------------------------
+ * Read-write access to private data to set up preconditions and assert
+ * post-conditions.
+ */
+ auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
+ auto& mutableEventControlThread() { return mEventControlThread; }
+ auto& mutablePrimaryDispSync() { return mPrimaryDispSync; }
+ auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
+
+ ~TestableScheduler() {
+ // All these pointer and container clears help ensure that GMock does
+ // not report a leaked object, since the Scheduler instance may
+ // still be referenced by something despite our best efforts to destroy
+ // it after each test is done.
+ mutableEventControlThread().reset();
+ mutablePrimaryDispSync().reset();
+ mConnections.clear();
+ };
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index e639b4d..6313f1f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -16,7 +16,12 @@
#pragma once
+#include <compositionengine/Display.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/CompositionEngine.h>
+#include <compositionengine/impl/LayerCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
@@ -203,9 +208,18 @@
void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) {
layer->mDrawingState.sidebandStream = sidebandStream;
- layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream;
+ layer->mSidebandStream = sidebandStream;
+ layer->getCompositionLayer()->editState().frontEnd.sidebandStream = sidebandStream;
}
+ void setLayerCompositionType(sp<Layer> layer, HWC2::Composition type) {
+ auto outputLayer = layer->findOutputLayerForDisplay(mFlinger->getDefaultDisplayDevice());
+ LOG_ALWAYS_FATAL_IF(!outputLayer);
+ auto& state = outputLayer->editState();
+ LOG_ALWAYS_FATAL_IF(!outputLayer->getState().hwc);
+ (*state.hwc).hwcCompositionType = static_cast<Hwc2::IComposerClient::Composition>(type);
+ };
+
void setLayerPotentialCursor(sp<Layer> layer, bool potentialCursor) {
layer->mPotentialCursor = potentialCursor;
}
@@ -234,6 +248,7 @@
}
auto handleTransactionLocked(uint32_t transactionFlags) {
+ Mutex::Autolock _l(mFlinger->mStateLock);
return mFlinger->handleTransactionLocked(transactionFlags);
}
@@ -284,7 +299,6 @@
const auto& getAnimFrameTracker() const { return mFlinger->mAnimFrameTracker; }
const auto& getHasPoweredOff() const { return mFlinger->mHasPoweredOff; }
- const auto& getHWVsyncAvailable() const { return mFlinger->mHWVsyncAvailable; }
const auto& getVisibleRegionsDirty() const { return mFlinger->mVisibleRegionsDirty; }
auto& getHwComposer() const {
return static_cast<impl::HWComposer&>(mFlinger->getHwComposer());
@@ -305,18 +319,12 @@
auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; }
auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableDrawingState() { return mFlinger->mDrawingState; }
- auto& mutableEventControlThread() { return mFlinger->mEventControlThread; }
auto& mutableEventQueue() { return mFlinger->mEventQueue; }
- auto& mutableEventThread() { return mFlinger->mEventThread; }
- auto& mutableSFEventThread() { return mFlinger->mSFEventThread; }
auto& mutableGeometryInvalid() { return mFlinger->mGeometryInvalid; }
- auto& mutableHWVsyncAvailable() { return mFlinger->mHWVsyncAvailable; }
auto& mutableInterceptor() { return mFlinger->mInterceptor; }
auto& mutableMainThreadId() { return mFlinger->mMainThreadId; }
auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
auto& mutablePhysicalDisplayTokens() { return mFlinger->mPhysicalDisplayTokens; }
- auto& mutablePrimaryDispSync() { return mFlinger->mPrimaryDispSync; }
- auto& mutablePrimaryHWVsyncEnabled() { return mFlinger->mPrimaryHWVsyncEnabled; }
auto& mutableTexturePool() { return mFlinger->mTexturePool; }
auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }
auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; }
@@ -326,6 +334,9 @@
auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; }
auto& mutableInternalHwcDisplayId() { return getHwComposer().mInternalHwcDisplayId; }
auto& mutableExternalHwcDisplayId() { return getHwComposer().mExternalHwcDisplayId; }
+ auto& mutableScheduler() { return mFlinger->mScheduler; }
+ auto& mutableAppConnectionHandle() { return mFlinger->mAppConnectionHandle; }
+ auto& mutableSfConnectionHandle() { return mFlinger->mSfConnectionHandle; }
~TestableSurfaceFlinger() {
// All these pointer and container clears help ensure that GMock does
@@ -333,12 +344,9 @@
// still be referenced by something despite our best efforts to destroy
// it after each test is done.
mutableDisplays().clear();
- mutableEventControlThread().reset();
mutableEventQueue().reset();
- mutableEventThread().reset();
- mutableSFEventThread().reset();
mutableInterceptor().reset();
- mutablePrimaryDispSync().reset();
+ mutableScheduler().reset();
mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
mFlinger->mCompositionEngine->setRenderEngine(
std::unique_ptr<renderengine::RenderEngine>());
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 3a8e34e..b3259de 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -33,6 +33,7 @@
#include <configstore/Utils.h>
#include <cutils/properties.h>
#include <graphicsenv/GraphicsEnv.h>
+#include <utils/Timers.h>
#include <utils/Trace.h>
#include <utils/Vector.h>
@@ -210,6 +211,8 @@
auto ns = android_get_exported_namespace("sphal");
if (!ns)
return -ENOENT;
+ android::GraphicsEnv::getInstance().setDriverToLoad(
+ android::GraphicsEnv::Driver::VULKAN);
return LoadDriver(ns, module);
}
@@ -219,12 +222,16 @@
auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
if (!ns)
return -ENOENT;
+ android::GraphicsEnv::getInstance().setDriverToLoad(
+ android::GraphicsEnv::Driver::VULKAN_UPDATED);
return LoadDriver(ns, module);
}
bool Hal::Open() {
ATRACE_CALL();
+ const nsecs_t openTime = systemTime();
+
ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
// Use a stub device unless we successfully open a real HAL device.
@@ -250,11 +257,12 @@
}
}
if (result != 0) {
+ android::GraphicsEnv::getInstance().setDriverLoaded(
+ android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
return true;
}
- android::GraphicsEnv::getInstance().sendGpuStats();
hwvulkan_device_t* device;
ATRACE_BEGIN("hwvulkan module open");
@@ -263,6 +271,8 @@
reinterpret_cast<hw_device_t**>(&device));
ATRACE_END();
if (result != 0) {
+ android::GraphicsEnv::getInstance().setDriverLoaded(
+ android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
// Any device with a Vulkan HAL should be able to open the device.
ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
result);
@@ -273,6 +283,9 @@
hal_.InitDebugReportIndex();
+ android::GraphicsEnv::getInstance().setDriverLoaded(
+ android::GraphicsEnv::Api::API_VK, true, systemTime() - openTime);
+
return true;
}