diff options
89 files changed, 1969 insertions, 514 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 4f7cdf3e5e..3fa5430d52 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -5,6 +5,7 @@ clang_format = true # Only turn on clang-format check for the following subfolders. clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp include/input/ + libs/binder/fuzzer/ libs/binder/ndk/ libs/graphicsenv/ libs/gui/ diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 89baf6875d..369c3deb99 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -300,12 +300,10 @@ static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot( * Returns a vector of dump fds under |dir_path| with a given |file_prefix|. * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime| * is set, the vector only contains files that were written in the last 30 minutes. - * If |limit_by_count| is set, the vector only contains the ten latest files. */ static std::vector<DumpData> GetDumpFds(const std::string& dir_path, const std::string& file_prefix, - bool limit_by_mtime, - bool limit_by_count = true) { + bool limit_by_mtime) { const time_t thirty_minutes_ago = ds.now_ - 60 * 30; std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); @@ -349,15 +347,6 @@ static std::vector<DumpData> GetDumpFds(const std::string& dir_path, dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime}); } - // Sort in descending modification time so that we only keep the newest - // reports if |limit_by_count| is true. - std::sort(dump_data.begin(), dump_data.end(), - [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; }); - - if (limit_by_count && dump_data.size() > 10) { - dump_data.erase(dump_data.begin() + 10, dump_data.end()); - } - return dump_data; } @@ -1571,6 +1560,10 @@ static Dumpstate::RunStatus DumpstateDefault() { RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"}); } + DumpFile("PSI cpu", "/proc/pressure/cpu"); + DumpFile("PSI memory", "/proc/pressure/memory"); + DumpFile("PSI io", "/proc/pressure/io"); + if (!DropRootUser()) { return Dumpstate::RunStatus::ERROR; } diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index dbbcdff63e..fbb01f5e99 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -214,8 +214,8 @@ class ZippedBugreportGenerationTest : public Test { duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); } - static const char* getZipFilePath() { - return ds.GetPath(".zip").c_str(); + static const std::string getZipFilePath() { + return ds.GetPath(".zip"); } }; std::shared_ptr<std::vector<SectionInfo>> ZippedBugreportGenerationTest::sections = @@ -224,12 +224,12 @@ Dumpstate& ZippedBugreportGenerationTest::ds = Dumpstate::GetInstance(); std::chrono::milliseconds ZippedBugreportGenerationTest::duration = 0s; TEST_F(ZippedBugreportGenerationTest, IsGeneratedWithoutErrors) { - EXPECT_EQ(access(getZipFilePath(), F_OK), 0); + EXPECT_EQ(access(getZipFilePath().c_str(), F_OK), 0); } TEST_F(ZippedBugreportGenerationTest, Is3MBto30MBinSize) { struct stat st; - EXPECT_EQ(stat(getZipFilePath(), &st), 0); + EXPECT_EQ(stat(getZipFilePath().c_str(), &st), 0); EXPECT_GE(st.st_size, 3000000 /* 3MB */); EXPECT_LE(st.st_size, 30000000 /* 30MB */); } @@ -248,7 +248,7 @@ class ZippedBugReportContentsTest : public Test { public: ZipArchiveHandle handle; void SetUp() { - ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath(), &handle), 0); + ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath().c_str(), &handle), 0); } void TearDown() { CloseArchive(handle); @@ -312,7 +312,7 @@ TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) { class BugreportSectionTest : public Test { public: static void SetUpTestCase() { - ParseSections(ZippedBugreportGenerationTest::getZipFilePath(), + ParseSections(ZippedBugreportGenerationTest::getZipFilePath().c_str(), ZippedBugreportGenerationTest::sections.get()); } diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index 7eee749be9..838d11d6d8 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -303,6 +303,9 @@ static const char* ENABLE_APEX_IMAGE = "enable_apex_image"; // Location of the apex image. static const char* kApexImage = "/system/framework/apex.art"; +// Phenotype property name for enabling profiling the boot class path. +static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath"; + class RunDex2Oat : public ExecVHelper { public: RunDex2Oat(int zip_fd, @@ -402,7 +405,15 @@ class RunDex2Oat : public ExecVHelper { server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE, ENABLE_APEX_IMAGE, /*default_value=*/ ""); - if (use_apex_image == "true") { + + std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", ""); + profile_boot_class_path = + server_configurable_flags::GetServerConfigurableFlag( + RUNTIME_NATIVE_BOOT_NAMESPACE, + PROFILE_BOOT_CLASS_PATH, + /*default_value=*/ profile_boot_class_path); + + if (use_apex_image == "true" || profile_boot_class_path == "true") { boot_image = StringPrintf("-Ximage:%s", kApexImage); } else { boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s"); @@ -709,8 +720,7 @@ class RunProfman : public ExecVHelper { const unique_fd& reference_profile_fd, const std::vector<unique_fd>& apk_fds, const std::vector<std::string>& dex_locations, - bool copy_and_update, - bool store_aggregation_counters) { + bool copy_and_update) { // TODO(calin): Assume for now we run in the bg compile job (which is in // most of the invocation). With the current data flow, is not very easy or @@ -742,10 +752,6 @@ class RunProfman : public ExecVHelper { AddArg("--copy-and-update-profile-key"); } - if (store_aggregation_counters) { - AddArg("--store-aggregation-counters"); - } - // Do not add after dex2oat_flags, they should override others for debugging. PrepareArgs(profman_bin); } @@ -753,14 +759,12 @@ class RunProfman : public ExecVHelper { void SetupMerge(const std::vector<unique_fd>& profiles_fd, const unique_fd& reference_profile_fd, const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(), - const std::vector<std::string>& dex_locations = std::vector<std::string>(), - bool store_aggregation_counters = false) { + const std::vector<std::string>& dex_locations = std::vector<std::string>()) { SetupArgs(profiles_fd, reference_profile_fd, apk_fds, dex_locations, - /*copy_and_update=*/false, - store_aggregation_counters); + /*copy_and_update=*/false); } void SetupCopyAndUpdate(unique_fd&& profile_fd, @@ -777,8 +781,7 @@ class RunProfman : public ExecVHelper { reference_profile_fd_, apk_fds_, dex_locations, - /*copy_and_update=*/true, - /*store_aggregation_counters=*/false); + /*copy_and_update=*/true); } void SetupDump(const std::vector<unique_fd>& profiles_fd, @@ -792,8 +795,7 @@ class RunProfman : public ExecVHelper { reference_profile_fd, apk_fds, dex_locations, - /*copy_and_update=*/false, - /*store_aggregation_counters=*/false); + /*copy_and_update=*/false); } void Exec() { @@ -2828,8 +2830,7 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, - dex_locations, - /*store_aggregation_counters=*/true); + dex_locations); pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp index db0907017c..5a5cb53431 100644 --- a/cmds/installd/tests/installd_cache_test.cpp +++ b/cmds/installd/tests/installd_cache_test.cpp @@ -67,29 +67,29 @@ bool create_cache_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED, } static void mkdir(const char* path) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - ::mkdir(fullPath, 0755); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + ::mkdir(fullPath.c_str(), 0755); } static void touch(const char* path, int len, int time) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - int fd = ::open(fullPath, O_RDWR | O_CREAT, 0644); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + int fd = ::open(fullPath.c_str(), O_RDWR | O_CREAT, 0644); ::fallocate(fd, 0, 0, len); ::close(fd); struct utimbuf times; times.actime = times.modtime = std::time(0) + time; - ::utime(fullPath, ×); + ::utime(fullPath.c_str(), ×); } static int exists(const char* path) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - return ::access(fullPath, F_OK); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + return ::access(fullPath.c_str(), F_OK); } static int64_t size(const char* path) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); struct stat buf; - if (!stat(fullPath, &buf)) { + if (!stat(fullPath.c_str(), &buf)) { return buf.st_size; } else { return -1; @@ -107,8 +107,8 @@ static int64_t free() { } static void setxattr(const char* path, const char* key) { - const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str(); - ::setxattr(fullPath, key, "", 0, 0); + const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path); + ::setxattr(fullPath.c_str(), key, "", 0, 0); } class CacheTest : public testing::Test { diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp index 606477fee7..b7e520f2f1 100644 --- a/cmds/servicemanager/Access.cpp +++ b/cmds/servicemanager/Access.cpp @@ -137,7 +137,7 @@ bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const c bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) { char *tctx = nullptr; - if (selabel_lookup(getSehandle(), &tctx, name.c_str(), 0) != 0) { + if (selabel_lookup(getSehandle(), &tctx, name.c_str(), SELABEL_CTX_ANDROID_SERVICE) != 0) { LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n"; return false; } diff --git a/headers/media_plugin/media/openmax/OMX_IndexExt.h b/headers/media_plugin/media/openmax/OMX_IndexExt.h index 479e9b8714..bbb3193dd1 100644 --- a/headers/media_plugin/media/openmax/OMX_IndexExt.h +++ b/headers/media_plugin/media/openmax/OMX_IndexExt.h @@ -101,6 +101,7 @@ typedef enum OMX_INDEXEXTTYPE { OMX_IndexConfigOperatingRate, /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */ OMX_IndexParamConsumerUsageBits, /**< reference: OMX_PARAM_U32TYPE */ OMX_IndexConfigLatency, /**< reference: OMX_PARAM_U32TYPE */ + OMX_IndexConfigLowLatency, /**< reference: OMX_CONFIG_BOOLEANTYPE */ OMX_IndexExtOtherEndUnused, /* Time configurations */ diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 296e3f6c53..643a956b4a 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -71,7 +71,12 @@ cc_library { // libbinder does not offer a stable wire protocol. // if a second copy of it is installed, then it may break after security // or dessert updates. Instead, apex users should use libbinder_ndk. - no_apex: true, + apex_available: [ + "//apex_available:platform", + // TODO(b/139016109) remove these three + "com.android.media.swcodec", + "test_com.android.media.swcodec", + ], srcs: [ "Binder.cpp", diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index ee637e24bf..a30df14bd6 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -43,6 +43,47 @@ namespace android { using AidlServiceManager = android::os::IServiceManager; using android::binder::Status; +// libbinder's IServiceManager.h can't rely on the values generated by AIDL +// because many places use its headers via include_dirs (meaning, without +// declaring the dependency in the build system). So, for now, we can just check +// the values here. +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_CRITICAL == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_HIGH == IServiceManager::DUMP_FLAG_PRIORITY_HIGH); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_NORMAL == IServiceManager::DUMP_FLAG_PRIORITY_NORMAL); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_DEFAULT == IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT); +static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_ALL == IServiceManager::DUMP_FLAG_PRIORITY_ALL); +static_assert(AidlServiceManager::DUMP_FLAG_PROTO == IServiceManager::DUMP_FLAG_PROTO); + +const String16& IServiceManager::getInterfaceDescriptor() const { + return AidlServiceManager::descriptor; +} +IServiceManager::IServiceManager() {} +IServiceManager::~IServiceManager() {} + +// From the old libbinder IServiceManager interface to IServiceManager. +class ServiceManagerShim : public IServiceManager +{ +public: + explicit ServiceManagerShim (const sp<AidlServiceManager>& impl); + + sp<IBinder> getService(const String16& name) const override; + sp<IBinder> checkService(const String16& name) const override; + status_t addService(const String16& name, const sp<IBinder>& service, + bool allowIsolated, int dumpsysPriority) override; + Vector<String16> listServices(int dumpsysPriority) override; + sp<IBinder> waitForService(const String16& name16) override; + + // for legacy ABI + const String16& getInterfaceDescriptor() const override { + return mTheRealServiceManager->getInterfaceDescriptor(); + } + IBinder* onAsBinder() override { + return IInterface::asBinder(mTheRealServiceManager).get(); + } +private: + sp<AidlServiceManager> mTheRealServiceManager; +}; + sp<IServiceManager> defaultServiceManager() { static Mutex gDefaultServiceManagerLock; @@ -53,8 +94,9 @@ sp<IServiceManager> defaultServiceManager() { AutoMutex _l(gDefaultServiceManagerLock); while (gDefaultServiceManager == nullptr) { - gDefaultServiceManager = interface_cast<IServiceManager>( - ProcessState::self()->getContextObject(nullptr)); + gDefaultServiceManager = new ServiceManagerShim( + interface_cast<AidlServiceManager>( + ProcessState::self()->getContextObject(nullptr))); if (gDefaultServiceManager == nullptr) sleep(1); } @@ -147,142 +189,136 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid) // ---------------------------------------------------------------------- -class BpServiceManager : public BpInterface<IServiceManager> +ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl) + : mTheRealServiceManager(impl) +{} + +sp<IBinder> ServiceManagerShim::getService(const String16& name) const { -public: - explicit BpServiceManager(const sp<IBinder>& impl) - : BpInterface<IServiceManager>(impl), - mTheRealServiceManager(interface_cast<AidlServiceManager>(impl)) - { + static bool gSystemBootCompleted = false; + + sp<IBinder> svc = checkService(name); + if (svc != nullptr) return svc; + + const bool isVendorService = + strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; + const long timeout = uptimeMillis() + 5000; + // Vendor code can't access system properties + if (!gSystemBootCompleted && !isVendorService) { +#ifdef __ANDROID__ + char bootCompleted[PROPERTY_VALUE_MAX]; + property_get("sys.boot_completed", bootCompleted, "0"); + gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false; +#else + gSystemBootCompleted = true; +#endif } + // retry interval in millisecond; note that vendor services stay at 100ms + const long sleepTime = gSystemBootCompleted ? 1000 : 100; - sp<IBinder> getService(const String16& name) const override - { - static bool gSystemBootCompleted = false; + int n = 0; + while (uptimeMillis() < timeout) { + n++; + ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), + ProcessState::self()->getDriverName().c_str()); + usleep(1000*sleepTime); sp<IBinder> svc = checkService(name); if (svc != nullptr) return svc; + } + ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); + return nullptr; +} - const bool isVendorService = - strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; - const long timeout = uptimeMillis() + 5000; - // Vendor code can't access system properties - if (!gSystemBootCompleted && !isVendorService) { -#ifdef __ANDROID__ - char bootCompleted[PROPERTY_VALUE_MAX]; - property_get("sys.boot_completed", bootCompleted, "0"); - gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false; -#else - gSystemBootCompleted = true; -#endif - } - // retry interval in millisecond; note that vendor services stay at 100ms - const long sleepTime = gSystemBootCompleted ? 1000 : 100; - - int n = 0; - while (uptimeMillis() < timeout) { - n++; - ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), - ProcessState::self()->getDriverName().c_str()); - usleep(1000*sleepTime); - - sp<IBinder> svc = checkService(name); - if (svc != nullptr) return svc; - } - ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); +sp<IBinder> ServiceManagerShim::checkService(const String16& name) const +{ + sp<IBinder> ret; + if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { return nullptr; } + return ret; +} - sp<IBinder> checkService(const String16& name) const override { - sp<IBinder> ret; - if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { - return nullptr; - } - return ret; +status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service, + bool allowIsolated, int dumpsysPriority) +{ + Status status = mTheRealServiceManager->addService( + String8(name).c_str(), service, allowIsolated, dumpsysPriority); + return status.exceptionCode(); +} + +Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority) +{ + std::vector<std::string> ret; + if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) { + return {}; } - status_t addService(const String16& name, const sp<IBinder>& service, - bool allowIsolated, int dumpsysPriority) override { - Status status = mTheRealServiceManager->addService(String8(name).c_str(), service, allowIsolated, dumpsysPriority); - return status.exceptionCode(); + Vector<String16> res; + res.setCapacity(ret.size()); + for (const std::string& name : ret) { + res.push(String16(name.c_str())); } + return res; +} - virtual Vector<String16> listServices(int dumpsysPriority) { - std::vector<std::string> ret; - if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) { - return {}; +sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) +{ + class Waiter : public android::os::BnServiceCallback { + Status onRegistration(const std::string& /*name*/, + const sp<IBinder>& binder) override { + std::unique_lock<std::mutex> lock(mMutex); + mBinder = binder; + lock.unlock(); + mCv.notify_one(); + return Status::ok(); } + public: + sp<IBinder> mBinder; + std::mutex mMutex; + std::condition_variable mCv; + }; - Vector<String16> res; - res.setCapacity(ret.size()); - for (const std::string& name : ret) { - res.push(String16(name.c_str())); - } - return res; + const std::string name = String8(name16).c_str(); + + sp<IBinder> out; + if (!mTheRealServiceManager->getService(name, &out).isOk()) { + return nullptr; } + if(out != nullptr) return out; - sp<IBinder> waitForService(const String16& name16) override { - class Waiter : public android::os::BnServiceCallback { - Status onRegistration(const std::string& /*name*/, - const sp<IBinder>& binder) override { - std::unique_lock<std::mutex> lock(mMutex); - mBinder = binder; - lock.unlock(); - mCv.notify_one(); - return Status::ok(); - } - public: - sp<IBinder> mBinder; - std::mutex mMutex; - std::condition_variable mCv; - }; + sp<Waiter> waiter = new Waiter; + if (!mTheRealServiceManager->registerForNotifications( + name, waiter).isOk()) { + return nullptr; + } - const std::string name = String8(name16).c_str(); + while(true) { + { + std::unique_lock<std::mutex> lock(waiter->mMutex); + using std::literals::chrono_literals::operator""s; + waiter->mCv.wait_for(lock, 1s, [&] { + return waiter->mBinder != nullptr; + }); + if (waiter->mBinder != nullptr) return waiter->mBinder; + } - sp<IBinder> out; + // Handle race condition for lazy services. Here is what can happen: + // - the service dies (not processed by init yet). + // - sm processes death notification. + // - sm gets getService and calls init to start service. + // - init gets the start signal, but the service already appears + // started, so it does nothing. + // - init gets death signal, but doesn't know it needs to restart + // the service + // - we need to request service again to get it to start if (!mTheRealServiceManager->getService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; - sp<Waiter> waiter = new Waiter; - if (!mTheRealServiceManager->registerForNotifications( - name, waiter).isOk()) { - return nullptr; - } - - while(true) { - { - std::unique_lock<std::mutex> lock(waiter->mMutex); - using std::literals::chrono_literals::operator""s; - waiter->mCv.wait_for(lock, 1s, [&] { - return waiter->mBinder != nullptr; - }); - if (waiter->mBinder != nullptr) return waiter->mBinder; - } - - // Handle race condition for lazy services. Here is what can happen: - // - the service dies (not processed by init yet). - // - sm processes death notification. - // - sm gets getService and calls init to start service. - // - init gets the start signal, but the service already appears - // started, so it does nothing. - // - init gets death signal, but doesn't know it needs to restart - // the service - // - we need to request service again to get it to start - if (!mTheRealServiceManager->getService(name, &out).isOk()) { - return nullptr; - } - if(out != nullptr) return out; - - ALOGW("Waited one second for %s", name.c_str()); - } + ALOGW("Waited one second for %s", name.c_str()); } - -private: - sp<AidlServiceManager> mTheRealServiceManager; -}; - -IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); +} } // namespace android diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp index f3e42291ea..d2f0d37207 100644 --- a/libs/binder/fuzzer/Android.bp +++ b/libs/binder/fuzzer/Android.bp @@ -1,8 +1,10 @@ cc_fuzz { name: "binder_parcel_fuzzer", + defaults: ["libbinder_ndk_host_user"], host_supported: true, srcs: [ "binder.cpp", + "binder_ndk.cpp", "hwbinder.cpp", "main.cpp", "util.cpp", @@ -22,10 +24,16 @@ cc_fuzz { target: { android: { - shared_libs: ["libbinder"], + shared_libs: [ + "libbinder_ndk", + "libbinder", + ], }, host: { - static_libs: ["libbinder"], + static_libs: [ + "libbinder_ndk", + "libbinder", + ], }, }, } diff --git a/libs/binder/fuzzer/binder.cpp b/libs/binder/fuzzer/binder.cpp index ce21178ea2..86264dbe9d 100644 --- a/libs/binder/fuzzer/binder.cpp +++ b/libs/binder/fuzzer/binder.cpp @@ -18,8 +18,48 @@ #include "binder.h" #include "util.h" +#include <android/os/IServiceManager.h> + using ::android::status_t; +class ExampleParcelable : public android::Parcelable { +public: + status_t writeToParcel(android::Parcel* /*parcel*/) const override { + FUZZ_LOG() << "should not reach"; + abort(); + } + status_t readFromParcel(const android::Parcel* parcel) override { + mExampleExtraField++; + return parcel->readInt64(&(this->mExampleUsedData)); + } +private: + int64_t mExampleExtraField = 0; + int64_t mExampleUsedData = 0; +}; + +struct ExampleFlattenable : public android::Flattenable<ExampleFlattenable> { +public: + size_t getFlattenedSize() const { return sizeof(mValue); } + size_t getFdCount() const { return 0; } + status_t flatten(void*& /*buffer*/, size_t& /*size*/, int*& /*fds*/, size_t& /*count*/) const { + FUZZ_LOG() << "should not reach"; + abort(); + } + status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) { + if (size < sizeof(mValue)) { + return android::NO_MEMORY; + } + android::FlattenableUtils::read(buffer, size, mValue); + return android::OK; + } +private: + int32_t mValue = 0xFEEDBEEF; +}; + +struct ExampleLightFlattenable : public android::LightFlattenablePod<ExampleLightFlattenable> { + int32_t mValue = 0; +}; + #define PARCEL_READ_WITH_STATUS(T, FUN) \ [] (const ::android::Parcel& p, uint8_t /*data*/) {\ FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\ @@ -85,7 +125,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { [] (const ::android::Parcel& p, uint8_t len) { FUZZ_LOG() << "about to readInplace"; const void* r = p.readInplace(len); - FUZZ_LOG() << "readInplace done. pointer: " << r; + FUZZ_LOG() << "readInplace done. pointer: " << r << " bytes: " << hexString(r, len); }, PARCEL_READ_OPT_STATUS(int32_t, readInt32), PARCEL_READ_OPT_STATUS(uint32_t, readUint32), @@ -108,13 +148,26 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_OPT_STATUS(android::String8, readString8), PARCEL_READ_OPT_STATUS(android::String16, readString16), PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16), - // TODO: readString16Inplace + [] (const ::android::Parcel& p, uint8_t /*data*/) { + FUZZ_LOG() << "about to readString16Inplace"; + size_t outLen = 0; + const char16_t* str = p.readString16Inplace(&outLen); + FUZZ_LOG() << "readString16Inplace: " << hexString(str, sizeof(char16_t) * outLen) + << " size: " << outLen; + }, PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readNullableStrongBinder), - // TODO: all templated versions of readParcelableVector, readParcelable - // TODO: readParcelable - // TODO: templated versions of readStrongBinder, readNullableStrongBinder + // only reading one parcelable type for now + // TODO(b/131868573): can force read of arbitrarily sized vector + // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<ExampleParcelable>>>, readParcelableVector), + // PARCEL_READ_WITH_STATUS(std::vector<ExampleParcelable>, readParcelableVector), + PARCEL_READ_WITH_STATUS(ExampleParcelable, readParcelable), + PARCEL_READ_WITH_STATUS(std::unique_ptr<ExampleParcelable>, readParcelable), + + // only reading one binder type for now + PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder), + PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder), // TODO(b/131868573): can force read of arbitrarily sized vector // PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), @@ -144,12 +197,34 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<std::string>>>, readUtf8VectorFromUtf16Vector), // PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector), - // TODO: read(Flattenable<T>) - // TODO: read(LightFlattenable<T>) + [] (const android::Parcel& p, uint8_t /*len*/) { + FUZZ_LOG() << "about to read flattenable"; + ExampleFlattenable f; + status_t status = p.read(f); + FUZZ_LOG() << "read flattenable: " << status; + }, + [] (const android::Parcel& p, uint8_t /*len*/) { + FUZZ_LOG() << "about to read lite flattenable"; + ExampleLightFlattenable f; + status_t status = p.read(f); + FUZZ_LOG() << "read lite flattenable: " << status; + }, + + // TODO(b/131868573): can force read of arbitrarily sized vector // TODO: resizeOutVector PARCEL_READ_NO_STATUS(int32_t, readExceptionCode), - // TODO: readNativeHandle + [] (const android::Parcel& p, uint8_t /*len*/) { + FUZZ_LOG() << "about to readNativeHandle"; + native_handle_t* t = p.readNativeHandle(); + FUZZ_LOG() << "readNativeHandle: " << t; + if (t != nullptr) { + FUZZ_LOG() << "about to free readNativeHandle"; + native_handle_close(t); + native_handle_delete(t); + FUZZ_LOG() << "readNativeHandle freed"; + } + }, PARCEL_READ_NO_STATUS(int, readFileDescriptor), PARCEL_READ_NO_STATUS(int, readParcelFileDescriptor), PARCEL_READ_WITH_STATUS(android::base::unique_fd, readUniqueFileDescriptor), @@ -164,7 +239,12 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { status_t status = p.readBlob(len, &blob); FUZZ_LOG() << "readBlob status: " << status; }, - // TODO: readObject + [] (const android::Parcel& p, uint8_t options) { + FUZZ_LOG() << "about to readObject"; + bool nullMetaData = options & 0x1; + const void* obj = static_cast<const void*>(p.readObject(nullMetaData)); + FUZZ_LOG() << "readObject: " << obj; + }, PARCEL_READ_NO_STATUS(uid_t, readCallingWorkSourceUid), PARCEL_READ_NO_STATUS(size_t, getBlobAshmemSize), PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize), diff --git a/libs/binder/fuzzer/binder.h b/libs/binder/fuzzer/binder.h index 32dcc79ee6..b224ef49a1 100644 --- a/libs/binder/fuzzer/binder.h +++ b/libs/binder/fuzzer/binder.h @@ -17,6 +17,6 @@ #include <binder/Parcel.h> #include <vector> -#include "parcel.h" +#include "parcel_fuzzer.h" extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS; diff --git a/libs/binder/fuzzer/binder_ndk.cpp b/libs/binder/fuzzer/binder_ndk.cpp new file mode 100644 index 0000000000..29da8f7537 --- /dev/null +++ b/libs/binder/fuzzer/binder_ndk.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define FUZZ_LOG_TAG "binder_ndk" + +#include "binder_ndk.h" + +#include <android/binder_parcel_utils.h> + +#include "util.h" + +// TODO(b/142061461): parent class +class SomeParcelable { +public: + binder_status_t readFromParcel(const AParcel* parcel) { + return AParcel_readInt32(parcel, &mValue); + } + +private: + int32_t mValue = 0; +}; + +#define PARCEL_READ(T, FUN) \ + [](const NdkParcelAdapter& p, uint8_t /*data*/) { \ + FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ + T t{}; \ + binder_status_t status = FUN(p.aParcel(), &t); \ + FUZZ_LOG() << #T " status: " << status /* << " value: " << t*/; \ + } + +// clang-format off +std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ + // methods from binder_parcel.h + [](const NdkParcelAdapter& p, uint8_t pos) { + FUZZ_LOG() << "about to set data position to " << pos; + binder_status_t status = AParcel_setDataPosition(p.aParcel(), pos); + FUZZ_LOG() << "set data position: " << status; + }, + [](const NdkParcelAdapter& p, uint8_t /*data*/) { + FUZZ_LOG() << "about to read status header"; + ndk::ScopedAStatus t; + binder_status_t status = AParcel_readStatusHeader(p.aParcel(), t.getR()); + FUZZ_LOG() << "read status header: " << status; + }, + PARCEL_READ(int32_t, AParcel_readInt32), + PARCEL_READ(uint32_t, AParcel_readUint32), + PARCEL_READ(int64_t, AParcel_readInt64), + PARCEL_READ(uint64_t, AParcel_readUint64), + PARCEL_READ(float, AParcel_readFloat), + PARCEL_READ(double, AParcel_readDouble), + PARCEL_READ(bool, AParcel_readBool), + PARCEL_READ(char16_t, AParcel_readChar), + PARCEL_READ(int8_t, AParcel_readByte), + + // methods from binder_parcel_utils.h + PARCEL_READ(ndk::SpAIBinder, ndk::AParcel_readNullableStrongBinder), + PARCEL_READ(ndk::SpAIBinder, ndk::AParcel_readRequiredStrongBinder), + PARCEL_READ(ndk::ScopedFileDescriptor, ndk::AParcel_readNullableParcelFileDescriptor), + PARCEL_READ(ndk::ScopedFileDescriptor, ndk::AParcel_readRequiredParcelFileDescriptor), + PARCEL_READ(std::string, ndk::AParcel_readString), + PARCEL_READ(std::optional<std::string>, ndk::AParcel_readString), + // TODO(b/131868573): can force process to allocate arbitrary amount of + // memory + // PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, + // ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>, + // ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<float>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<double>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector), + // PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector), + // PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector), + // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector), +}; +// clang-format on diff --git a/libs/binder/fuzzer/binder_ndk.h b/libs/binder/fuzzer/binder_ndk.h new file mode 100644 index 0000000000..622cafc7df --- /dev/null +++ b/libs/binder/fuzzer/binder_ndk.h @@ -0,0 +1,46 @@ +/* + * 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 <android/binder_auto_utils.h> +#include <vector> + +#include <android/binder_parcel.h> +#include "parcel_fuzzer.h" + +// libbinder_ndk doesn't export this header which breaks down its API for NDK +// and APEX users, but we need access to it to fuzz. +#include "../ndk/parcel_internal.h" + +class NdkParcelAdapter { +public: + NdkParcelAdapter() : mParcel(new AParcel(nullptr /*binder*/)) {} + + const AParcel* aParcel() const { return mParcel.get(); } + AParcel* aParcel() { return mParcel.get(); } + + size_t dataSize() const { return aParcel()->get()->dataSize(); } + size_t dataAvail() const { return aParcel()->get()->dataAvail(); } + size_t dataPosition() const { return aParcel()->get()->dataPosition(); } + size_t dataCapacity() const { return aParcel()->get()->dataCapacity(); } + android::status_t setData(const uint8_t* buffer, size_t len) { + return aParcel()->get()->setData(buffer, len); + } + +private: + ndk::ScopedAParcel mParcel; +}; + +extern std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS; diff --git a/libs/binder/fuzzer/hwbinder.h b/libs/binder/fuzzer/hwbinder.h index 03ab510d0d..a6c66beb44 100644 --- a/libs/binder/fuzzer/hwbinder.h +++ b/libs/binder/fuzzer/hwbinder.h @@ -17,6 +17,6 @@ #include <hwbinder/Parcel.h> #include <vector> -#include "parcel.h" +#include "parcel_fuzzer.h" extern std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS; diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp index 03fde3ac4e..369aa34a9b 100644 --- a/libs/binder/fuzzer/main.cpp +++ b/libs/binder/fuzzer/main.cpp @@ -16,6 +16,7 @@ #define FUZZ_LOG_TAG "main" #include "binder.h" +#include "binder_ndk.h" #include "hwbinder.h" #include "util.h" @@ -50,6 +51,7 @@ void fuzz(uint8_t options, const std::vector<uint8_t>& input, const std::vector< // although they will do completely different things, might as well fuzz both doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input, instructions); doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions); + doFuzz<NdkParcelAdapter>(BINDER_NDK_PARCEL_READ_FUNCTIONS, input, instructions); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { diff --git a/libs/binder/fuzzer/parcel.h b/libs/binder/fuzzer/parcel_fuzzer.h index 5f05335706..10cf17c328 100644 --- a/libs/binder/fuzzer/parcel.h +++ b/libs/binder/fuzzer/parcel_fuzzer.h @@ -16,5 +16,3 @@ template <typename P> using ParcelRead = std::function<void(const P& p, uint8_t data)>; - - diff --git a/libs/binder/fuzzer/util.cpp b/libs/binder/fuzzer/util.cpp index b3a4ee745d..b1213e9007 100644 --- a/libs/binder/fuzzer/util.cpp +++ b/libs/binder/fuzzer/util.cpp @@ -21,11 +21,17 @@ #include <iomanip> #include <sstream> -std::string hexString(const std::vector<uint8_t>& hash) { +std::string hexString(const void* bytes, size_t len) { + if (bytes == nullptr) return "<null>"; + std::ostringstream s; s << std::hex << std::setfill('0'); - for (uint8_t i : hash) { - s << std::setw(2) << static_cast<int>(i); + for (size_t i = 0; i < len; i++) { + s << std::setw(2) << static_cast<int>( + static_cast<const uint8_t*>(bytes)[i]); } return s.str(); } +std::string hexString(const std::vector<uint8_t>& bytes) { + return hexString(bytes.data(), bytes.size()); +} diff --git a/libs/binder/fuzzer/util.h b/libs/binder/fuzzer/util.h index 07e68a8211..416c3a718e 100644 --- a/libs/binder/fuzzer/util.h +++ b/libs/binder/fuzzer/util.h @@ -45,4 +45,5 @@ private: std::stringstream mOs; }; -std::string hexString(const std::vector<uint8_t>& hash); +std::string hexString(const void* bytes, size_t len); +std::string hexString(const std::vector<uint8_t>& bytes); diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h index 5793a1cf6b..28ffa48e32 100644 --- a/libs/binder/include/binder/IInterface.h +++ b/libs/binder/include/binder/IInterface.h @@ -88,8 +88,12 @@ private: \ public: \ +#define __IINTF_CONCAT(x, y) (x ## y) #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ - const ::android::String16 I##INTERFACE::descriptor(NAME); \ + const ::android::StaticString16 \ + I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\ + const ::android::String16 I##INTERFACE::descriptor( \ + I##INTERFACE##_descriptor_static_str16); \ const ::android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index def1bea974..a675513793 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -26,12 +26,22 @@ namespace android { // ---------------------------------------------------------------------- +/** + * Service manager for C++ services. + * + * IInterface is only for legacy ABI compatibility + */ class IServiceManager : public IInterface { public: - DECLARE_META_INTERFACE(ServiceManager) + // for ABI compatibility + virtual const String16& getInterfaceDescriptor() const; + + IServiceManager(); + virtual ~IServiceManager(); + /** - * Must match values in IServiceManager.java + * Must match values in IServiceManager.aidl */ /* Allows services to dump sections according to priorities. */ static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0; diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp index 62a0f9f9b1..22344b6173 100644 --- a/libs/binder/ndk/Android.bp +++ b/libs/binder/ndk/Android.bp @@ -27,7 +27,7 @@ cc_defaults { }, } -cc_library_shared { +cc_library { name: "libbinder_ndk", defaults: ["libbinder_ndk_host_user"], @@ -69,6 +69,12 @@ cc_library_shared { ], target: { + android: { + // Only one copy of this library on an Android device + static: { + enabled: false, + }, + }, linux: { version_script: "libbinder_ndk.map.txt", }, diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp index 9080ce13db..a8f7d92b41 100644 --- a/libs/cputimeinstate/Android.bp +++ b/libs/cputimeinstate/Android.bp @@ -8,6 +8,7 @@ cc_library { "liblog", "libnetdutils" ], + header_libs: ["bpf_prog_headers"], cflags: [ "-Werror", "-Wall", @@ -25,6 +26,7 @@ cc_test { "libtimeinstate", "libnetdutils", ], + header_libs: ["bpf_prog_headers"], cflags: [ "-Werror", "-Wall", diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp index f255512704..45fea850aa 100644 --- a/libs/cputimeinstate/cputimeinstate.cpp +++ b/libs/cputimeinstate/cputimeinstate.cpp @@ -17,7 +17,7 @@ #define LOG_TAG "libtimeinstate" #include "cputimeinstate.h" -#include "timeinstate.h" +#include <bpf_timeinstate.h> #include <dirent.h> #include <errno.h> @@ -110,9 +110,10 @@ static bool initGlobals() { std::string path = StringPrintf("%s/%s/scaling_%s_frequencies", basepath, policy.c_str(), name); auto nums = readNumbersFromFile(path); - if (!nums) return false; + if (!nums) continue; freqs.insert(freqs.end(), nums->begin(), nums->end()); } + if (freqs.empty()) return false; std::sort(freqs.begin(), freqs.end()); gPolicyFreqs.emplace_back(freqs); diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp index 15f6214bff..c0cd3e07ff 100644 --- a/libs/cputimeinstate/testtimeinstate.cpp +++ b/libs/cputimeinstate/testtimeinstate.cpp @@ -1,5 +1,5 @@ -#include "timeinstate.h" +#include <bpf_timeinstate.h> #include <sys/sysinfo.h> diff --git a/libs/cputimeinstate/timeinstate.h b/libs/cputimeinstate/timeinstate.h deleted file mode 100644 index 6d4f913f80..0000000000 --- a/libs/cputimeinstate/timeinstate.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> - -#define BPF_FS_PATH "/sys/fs/bpf/" - -#define FREQS_PER_ENTRY 32 -#define CPUS_PER_ENTRY 8 - -struct time_key_t { - uint32_t uid; - uint32_t bucket; -}; - -struct tis_val_t { - uint64_t ar[FREQS_PER_ENTRY]; -}; - -struct concurrent_val_t { - uint64_t active[CPUS_PER_ENTRY]; - uint64_t policy[CPUS_PER_ENTRY]; -}; - -struct freq_idx_key_t { - uint32_t policy; - uint32_t freq; -}; diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 3f8b436b2d..da51675035 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -32,6 +32,8 @@ cc_library_shared { defaults: ["libgui_bufferqueue-defaults"], srcs: [ + ":libgui_bufferqueue_sources", + "BitTube.cpp", "BufferHubConsumer.cpp", "BufferHubProducer.cpp", @@ -104,32 +106,14 @@ cc_library_static { ], defaults: ["libgui_bufferqueue-defaults"], -} - -// Common build config shared by libgui and libgui_bufferqueue_static. -cc_defaults { - name: "libgui_bufferqueue-defaults", - - clang: true, - cflags: [ - "-Wall", - "-Werror", - ], - cppflags: [ - "-Wextra", - "-DDEBUG_ONLY_CODE=0", + srcs: [ + ":libgui_bufferqueue_sources", ], +} - product_variables: { - eng: { - cppflags: [ - "-UDEBUG_ONLY_CODE", - "-DDEBUG_ONLY_CODE=1", - ], - }, - }, - +filegroup { + name: "libgui_bufferqueue_sources", srcs: [ "BufferItem.cpp", "BufferQueue.cpp", @@ -157,6 +141,31 @@ cc_defaults { "bufferqueue/2.0/H2BProducerListener.cpp", "bufferqueue/2.0/types.cpp", ], +} + +// Common build config shared by libgui and libgui_bufferqueue_static. +cc_defaults { + name: "libgui_bufferqueue-defaults", + + clang: true, + cflags: [ + "-Wall", + "-Werror", + ], + + cppflags: [ + "-Wextra", + "-DDEBUG_ONLY_CODE=0", + ], + + product_variables: { + eng: { + cppflags: [ + "-UDEBUG_ONLY_CODE", + "-DDEBUG_ONLY_CODE=1", + ], + }, + }, shared_libs: [ "android.hardware.graphics.bufferqueue@1.0", @@ -204,4 +213,21 @@ cc_defaults { ], } +// GMocks for use by external code +cc_library_static { + name: "libgui_mocks", + vendor_available: false, + + defaults: ["libgui_bufferqueue-defaults"], + static_libs: [ + "libgtest", + "libgmock", + ], + + srcs: [ + "mock/GraphicBufferConsumer.cpp", + "mock/GraphicBufferProducer.cpp", + ], +} + subdirs = ["tests"] diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 129558bd15..b98e48b52a 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -34,7 +34,8 @@ enum class Tag : uint32_t { CREATE_WITH_SURFACE_PARENT, CLEAR_LAYER_FRAME_STATS, GET_LAYER_FRAME_STATS, - LAST = GET_LAYER_FRAME_STATS, + MIRROR_SURFACE, + LAST = MIRROR_SURFACE, }; } // Anonymous namespace @@ -80,6 +81,12 @@ public: &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GET_LAYER_FRAME_STATS, handle, outStats); } + + status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) override { + return callRemote<decltype(&ISurfaceComposerClient::mirrorSurface)>(Tag::MIRROR_SURFACE, + mirrorFromHandle, + outHandle); + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -105,6 +112,8 @@ status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats); case Tag::GET_LAYER_FRAME_STATS: return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats); + case Tag::MIRROR_SURFACE: + return callLocal(data, reply, &ISurfaceComposerClient::mirrorSurface); } } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index fb9d7427d7..e490d6d17d 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1087,6 +1087,12 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT: res = dispatchSetDequeueTimeout(args); break; + case NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION: + res = dispatchGetLastDequeueDuration(args); + break; + case NATIVE_WINDOW_GET_LAST_QUEUE_DURATION: + res = dispatchGetLastQueueDuration(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1303,6 +1309,18 @@ int Surface::dispatchSetDequeueTimeout(va_list args) { return setDequeueTimeout(timeout); } +int Surface::dispatchGetLastDequeueDuration(va_list args) { + int64_t* lastDequeueDuration = va_arg(args, int64_t*); + *lastDequeueDuration = mLastDequeueDuration; + return NO_ERROR; +} + +int Surface::dispatchGetLastQueueDuration(va_list args) { + int64_t* lastQueueDuration = va_arg(args, int64_t*); + *lastQueueDuration = mLastQueueDuration; + return NO_ERROR; +} + bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6b5021d1b4..7b256f5c02 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1327,7 +1327,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeome break; } setMatrix(sc, matrix[0], matrix[1], matrix[2], matrix[3]); - setPosition(sc, x, y); + float offsetX = xScale * source.left; + float offsetY = yScale * source.top; + setPosition(sc, x - offsetX, y - offsetY); return *this; } @@ -1503,6 +1505,20 @@ status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32 return err; } +sp<SurfaceControl> SurfaceComposerClient::mirrorSurface(SurfaceControl* mirrorFromSurface) { + if (mirrorFromSurface == nullptr) { + return nullptr; + } + + sp<IBinder> handle; + sp<IBinder> mirrorFromHandle = mirrorFromSurface->getHandle(); + status_t err = mClient->mirrorSurface(mirrorFromHandle, &handle); + if (err == NO_ERROR) { + return new SurfaceControl(this, handle, nullptr, true /* owned */); + } + return nullptr; +} + status_t SurfaceComposerClient::clearLayerFrameStats(const sp<IBinder>& token) const { if (mStatus != NO_ERROR) { return mStatus; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 32ac9e8928..5fe7ca5344 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -76,6 +76,8 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const = 0; + + virtual status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) = 0; }; class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> { diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 2527ec0a75..e582509b6e 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -246,6 +246,8 @@ private: int dispatchSetAutoPrerotation(va_list args); int dispatchGetLastDequeueStartTime(va_list args); int dispatchSetDequeueTimeout(va_list args); + int dispatchGetLastDequeueDuration(va_list args); + int dispatchGetLastQueueDuration(va_list args); bool transformToDisplayInverse(); protected: diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 15287e2cb6..6676be4837 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -245,6 +245,17 @@ public: LayerMetadata metadata = LayerMetadata() // metadata ); + // Creates a mirrored hierarchy for the mirrorFromSurface. This returns a SurfaceControl + // which is a parent of the root of the mirrored hierarchy. + // + // Real Hierarchy Mirror + // SC (value that's returned) + // | + // A A' + // | | + // B B' + sp<SurfaceControl> mirrorSurface(SurfaceControl* mirrorFromSurface); + //! Create a virtual display static sp<IBinder> createDisplay(const String8& displayName, bool secure); diff --git a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h index 98f24c2d44..98f24c2d44 100644 --- a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferConsumer.h +++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h diff --git a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferProducer.h b/libs/gui/include/gui/mock/GraphicBufferProducer.h index c98f39f43c..c98f39f43c 100644 --- a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferProducer.h +++ b/libs/gui/include/gui/mock/GraphicBufferProducer.h diff --git a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferConsumer.cpp b/libs/gui/mock/GraphicBufferConsumer.cpp index a17b73f0fc..4a6c0815e1 100644 --- a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferConsumer.cpp +++ b/libs/gui/mock/GraphicBufferConsumer.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "mock/gui/MockGraphicBufferConsumer.h" +#include <gui/mock/GraphicBufferConsumer.h> namespace android { namespace mock { diff --git a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferProducer.cpp b/libs/gui/mock/GraphicBufferProducer.cpp index a7fd667b54..239a80a2e1 100644 --- a/services/surfaceflinger/tests/unittests/mock/gui/MockGraphicBufferProducer.cpp +++ b/libs/gui/mock/GraphicBufferProducer.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "mock/gui/MockGraphicBufferProducer.h" +#include <gui/mock/GraphicBufferProducer.h> namespace android { namespace mock { diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp index fecfa193df..0ba01f4da4 100644 --- a/libs/nativewindow/ANativeWindow.cpp +++ b/libs/nativewindow/ANativeWindow.cpp @@ -33,6 +33,12 @@ static int32_t query(ANativeWindow* window, int what) { return res < 0 ? res : value; } +static int64_t query64(ANativeWindow* window, int what) { + int64_t value; + int res = window->perform(window, what, &value); + return res < 0 ? res : value; +} + static bool isDataSpaceValid(ANativeWindow* window, int32_t dataSpace) { bool supported = false; switch (dataSpace) { @@ -271,18 +277,16 @@ int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation * apex-stable **************************************************************************************************/ -int ANativeWindow_getLastDequeueDuration(ANativeWindow* window) { - return query(window, NATIVE_WINDOW_LAST_DEQUEUE_DURATION); +int64_t ANativeWindow_getLastDequeueDuration(ANativeWindow* window) { + return query64(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION); } -int ANativeWindow_getLastQueueDuration(ANativeWindow* window) { - return query(window, NATIVE_WINDOW_LAST_QUEUE_DURATION); +int64_t ANativeWindow_getLastQueueDuration(ANativeWindow* window) { + return query64(window, NATIVE_WINDOW_GET_LAST_QUEUE_DURATION); } int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window) { - int64_t time; - int success = window->perform(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_START, &time); - return success < 0 ? success : time; + return query64(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_START); } int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout) { diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h index 9798c2fd47..869b22ec19 100644 --- a/libs/nativewindow/include/apex/window.h +++ b/libs/nativewindow/include/apex/window.h @@ -27,17 +27,17 @@ __BEGIN_DECLS * Retrieves how long it took for the last time a buffer was dequeued. * * \return a negative value on error, otherwise returns the duration in - * microseconds. + * nanoseconds */ -int ANativeWindow_getLastDequeueDuration(ANativeWindow* window); +int64_t ANativeWindow_getLastDequeueDuration(ANativeWindow* window); /** * Retrieves how long it took for the last time a buffer was queued. * * \return a negative value on error, otherwise returns the duration in - * microseconds + * nanoseconds. */ -int ANativeWindow_getLastQueueDuration(ANativeWindow* window); +int64_t ANativeWindow_getLastQueueDuration(ANativeWindow* window); /** * Retrieves the system time in nanoseconds when the last time a buffer diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 8f850070b6..1814ab5568 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -63,9 +63,9 @@ __BEGIN_DECLS /* attributes queriable with query() */ enum { - NATIVE_WINDOW_WIDTH = 0, - NATIVE_WINDOW_HEIGHT = 1, - NATIVE_WINDOW_FORMAT = 2, + NATIVE_WINDOW_WIDTH = 0, + NATIVE_WINDOW_HEIGHT = 1, + NATIVE_WINDOW_FORMAT = 2, /* see ANativeWindowQuery in vndk/window.h */ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS = ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS, @@ -147,11 +147,15 @@ enum { /* * Returns the duration of the last dequeueBuffer call in microseconds + * Deprecated: please use NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION in + * perform() instead, which supports nanosecond precision. */ NATIVE_WINDOW_LAST_DEQUEUE_DURATION = 14, /* * Returns the duration of the last queueBuffer call in microseconds + * Deprecated: please use NATIVE_WINDOW_GET_LAST_QUEUE_DURATION in + * perform() instead, which supports nanosecond precision. */ NATIVE_WINDOW_LAST_QUEUE_DURATION = 15, @@ -241,6 +245,8 @@ enum { NATIVE_WINDOW_SET_AUTO_PREROTATION = 35, NATIVE_WINDOW_GET_LAST_DEQUEUE_START = 36, /* private */ NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT = 37, /* private */ + NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */ + NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */ // clang-format on }; diff --git a/libs/nativewindow/tests/ANativeWindowTest.cpp b/libs/nativewindow/tests/ANativeWindowTest.cpp index 4d2b8c8f3b..6cf8291da2 100644 --- a/libs/nativewindow/tests/ANativeWindowTest.cpp +++ b/libs/nativewindow/tests/ANativeWindowTest.cpp @@ -74,7 +74,7 @@ protected: TEST_F(ANativeWindowTest, getLastDequeueDuration_noDequeue_returnsZero) { int result = ANativeWindow_getLastDequeueDuration(mWindow.get()); EXPECT_EQ(0, result); - EXPECT_EQ(0, mWindow->getLastDequeueDuration() / 1000); + EXPECT_EQ(0, mWindow->getLastDequeueDuration()); } TEST_F(ANativeWindowTest, getLastDequeueDuration_withDequeue_returnsTime) { @@ -86,7 +86,7 @@ TEST_F(ANativeWindowTest, getLastDequeueDuration_withDequeue_returnsTime) { result = ANativeWindow_getLastDequeueDuration(mWindow.get()); EXPECT_GT(result, 0); - EXPECT_EQ(result, mWindow->getLastDequeueDuration() / 1000); + EXPECT_EQ(result, mWindow->getLastDequeueDuration()); } TEST_F(ANativeWindowTest, getLastQueueDuration_noDequeue_returnsZero) { @@ -118,7 +118,7 @@ TEST_F(ANativeWindowTest, getLastQueueDuration_withQueue_returnsTime) { result = ANativeWindow_getLastQueueDuration(mWindow.get()); EXPECT_GT(result, 0); - EXPECT_EQ(result, mWindow->getLastQueueDuration() / 1000); + EXPECT_EQ(result, mWindow->getLastQueueDuration()); } TEST_F(ANativeWindowTest, getLastDequeueStartTime_noDequeue_returnsZero) { diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index f39f0663ac..b8cf0ea083 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -457,8 +457,10 @@ Framebuffer* GLESRenderEngine::getFramebufferForDrawing() { } void GLESRenderEngine::primeCache() const { - ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext, - mFeatureFlags & USE_COLOR_MANAGEMENT); + ProgramCache::getInstance().primeCache( + mInProtectedContext ? mProtectedEGLContext : mEGLContext, + mFeatureFlags & USE_COLOR_MANAGEMENT, + mFeatureFlags & PRECACHE_TONE_MAPPER_SHADER_ONLY); } base::unique_fd GLESRenderEngine::flush() { diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp index d242677f0c..494623e67e 100644 --- a/libs/renderengine/gl/ProgramCache.cpp +++ b/libs/renderengine/gl/ProgramCache.cpp @@ -77,9 +77,38 @@ Formatter& dedent(Formatter& f) { return f; } -void ProgramCache::primeCache(EGLContext context, bool useColorManagement) { +void ProgramCache::primeCache( + EGLContext context, bool useColorManagement, bool toneMapperShaderOnly) { auto& cache = mCaches[context]; uint32_t shaderCount = 0; + + if (toneMapperShaderOnly) { + Key shaderKey; + // base settings used by HDR->SDR tonemap only + shaderKey.set(Key::BLEND_MASK | Key::INPUT_TRANSFORM_MATRIX_MASK | + Key::OUTPUT_TRANSFORM_MATRIX_MASK | Key::OUTPUT_TF_MASK | + Key::OPACITY_MASK | Key::ALPHA_MASK | + Key::ROUNDED_CORNERS_MASK | Key::TEXTURE_MASK, + Key::BLEND_NORMAL | Key::INPUT_TRANSFORM_MATRIX_ON | + Key::OUTPUT_TRANSFORM_MATRIX_ON | Key::OUTPUT_TF_SRGB | + Key::OPACITY_OPAQUE | Key::ALPHA_EQ_ONE | + Key::ROUNDED_CORNERS_OFF | Key::TEXTURE_EXT); + for (int i = 0; i < 4; i++) { + // Cache input transfer for HLG & ST2084 + shaderKey.set(Key::INPUT_TF_MASK, (i & 1) ? + Key::INPUT_TF_HLG : Key::INPUT_TF_ST2084); + + // Cache Y410 input on or off + shaderKey.set(Key::Y410_BT2020_MASK, (i & 2) ? + Key::Y410_BT2020_ON : Key::Y410_BT2020_OFF); + if (cache.count(shaderKey) == 0) { + cache.emplace(shaderKey, generateProgram(shaderKey)); + shaderCount++; + } + } + return; + } + uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK | Key::ROUNDED_CORNERS_MASK; // Prime the cache for all combinations of the above masks, diff --git a/libs/renderengine/gl/ProgramCache.h b/libs/renderengine/gl/ProgramCache.h index 400ad74fca..175c6e83cc 100644 --- a/libs/renderengine/gl/ProgramCache.h +++ b/libs/renderengine/gl/ProgramCache.h @@ -179,7 +179,7 @@ public: ~ProgramCache() = default; // Generate shaders to populate the cache - void primeCache(const EGLContext context, bool useColorManagement); + void primeCache(const EGLContext context, bool useColorManagement, bool toneMapperShaderOnly); size_t getSize(const EGLContext context) { return mCaches[context].size(); } diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 205782bca1..9dcd5103fa 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -66,6 +66,9 @@ public: // Create a protected context when if possible ENABLE_PROTECTED_CONTEXT = 1 << 2, + + // Only precache HDR to SDR tone-mapping shaders + PRECACHE_TONE_MAPPER_SHADER_ONLY = 1 << 3, }; static std::unique_ptr<impl::RenderEngine> create(int hwcFormat, uint32_t featureFlags, diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp index 139987e6a9..abc910302c 100644 --- a/libs/sensor/Sensor.cpp +++ b/libs/sensor/Sensor.cpp @@ -577,7 +577,8 @@ void Sensor::flattenString8(void*& buffer, size_t& size, uint32_t len = static_cast<uint32_t>(string8.length()); FlattenableUtils::write(buffer, size, len); memcpy(static_cast<char*>(buffer), string8.string(), len); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); + FlattenableUtils::advance(buffer, size, len); + size -= FlattenableUtils::align<4>(buffer); } bool Sensor::unflattenString8(void const*& buffer, size_t& size, String8& outputString8) { diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp index 2053344bf0..04493f0cd3 100644 --- a/libs/vr/libvrflinger/Android.bp +++ b/libs/vr/libvrflinger/Android.bp @@ -40,6 +40,7 @@ sharedLibraries = [ "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.composer@2.4", "libbinder", "libbase", "libbufferhubqueue", diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index aa51e23040..4db9ae2125 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2772,7 +2772,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { "yCursorPosition=%f, downTime=%" PRId64, args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags, args->action, args->actionButton, args->flags, args->metaState, args->buttonState, - args->edgeFlags, args->xPrecision, args->yPrecision, arg->xCursorPosition, + args->edgeFlags, args->xPrecision, args->yPrecision, args->xCursorPosition, args->yCursorPosition, args->downTime); for (uint32_t i = 0; i < args->pointerCount; i++) { ALOGD(" Pointer %d: id=%d, toolType=%d, " diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index a64f4ddc47..3c1607096e 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -50,6 +50,7 @@ cc_library_shared { shared_libs: [ "libbase", + "libcap", "libinputflinger_base", "libcrypto", "libcutils", diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index efe3809f1d..c8da0ab29f 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -24,6 +24,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/capability.h> #include <sys/epoll.h> #include <sys/inotify.h> #include <sys/ioctl.h> @@ -237,6 +238,47 @@ bool EventHub::Device::hasValidFd() { return !isVirtual && enabled; } +/** + * Get the capabilities for the current process. + * Crashes the system if unable to create / check / destroy the capabilities object. + */ +class Capabilities final { +public: + explicit Capabilities() { + mCaps = cap_get_proc(); + LOG_ALWAYS_FATAL_IF(mCaps == nullptr, "Could not get capabilities of the current process"); + } + + /** + * Check whether the current process has a specific capability + * in the set of effective capabilities. + * Return CAP_SET if the process has the requested capability + * Return CAP_CLEAR otherwise. + */ + cap_flag_value_t checkEffectiveCapability(cap_value_t capability) { + cap_flag_value_t value; + const int result = cap_get_flag(mCaps, capability, CAP_EFFECTIVE, &value); + LOG_ALWAYS_FATAL_IF(result == -1, "Could not obtain the requested capability"); + return value; + } + + ~Capabilities() { + const int result = cap_free(mCaps); + LOG_ALWAYS_FATAL_IF(result == -1, "Could not release the capabilities structure"); + } + +private: + cap_t mCaps; +}; + +static void ensureProcessCanBlockSuspend() { + Capabilities capabilities; + const bool canBlockSuspend = + capabilities.checkEffectiveCapability(CAP_BLOCK_SUSPEND) == CAP_SET; + LOG_ALWAYS_FATAL_IF(!canBlockSuspend, + "Input must be able to block suspend to properly process events"); +} + // --- EventHub --- const int EventHub::EPOLL_MAX_EVENTS; @@ -253,6 +295,7 @@ EventHub::EventHub(void) mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { + ensureProcessCanBlockSuspend(); acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); mEpollFd = epoll_create1(EPOLL_CLOEXEC); diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index b404836d99..e5d23d0d1f 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -29,6 +29,7 @@ cc_defaults { "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.composer@2.4", "android.hardware.power@1.0", "android.hardware.power@1.3", "libbase", @@ -92,6 +93,7 @@ cc_defaults { "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.composer@2.4", "android.hardware.power@1.3", "libhidlbase", ], @@ -166,6 +168,7 @@ filegroup { "Scheduler/VSyncModulator.cpp", "StartPropertySetThread.cpp", "SurfaceFlinger.cpp", + "SurfaceFlingerDefaultFactory.cpp", "SurfaceInterceptor.cpp", "SurfaceTracing.cpp", "TransactionCompletedThread.cpp", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d189846dd5..b500ad3eee 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -295,7 +295,7 @@ bool BufferLayer::onPostComposition(const std::optional<DisplayId>& displayId, const CompositorTiming& compositorTiming) { // mFrameLatencyNeeded is true when a new frame was latched for the // composition. - if (!mFrameLatencyNeeded) return false; + if (!mBufferInfo.mFrameLatencyNeeded) return false; // Update mFrameEventHistory. { @@ -337,7 +337,7 @@ bool BufferLayer::onPostComposition(const std::optional<DisplayId>& displayId, } mFrameTracker.advanceFrame(); - mFrameLatencyNeeded = false; + mBufferInfo.mFrameLatencyNeeded = false; return true; } @@ -401,7 +401,7 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, gatherBufferInfo(); mRefreshPending = true; - mFrameLatencyNeeded = true; + mBufferInfo.mFrameLatencyNeeded = true; if (oldBufferInfo.mBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. @@ -735,6 +735,35 @@ void BufferLayer::setInitialValuesForClone(const sp<Layer>& clonedFrom) { mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha; mPotentialCursor = bufferClonedFrom->mPotentialCursor; mProtectedByApp = bufferClonedFrom->mProtectedByApp; + + updateCloneBufferInfo(); +} + +void BufferLayer::updateCloneBufferInfo() { + if (!isClone() || !isClonedFromAlive()) { + return; + } + + sp<BufferLayer> clonedFrom = static_cast<BufferLayer*>(getClonedFrom().get()); + mBufferInfo = clonedFrom->mBufferInfo; + mSidebandStream = clonedFrom->mSidebandStream; + surfaceDamageRegion = clonedFrom->surfaceDamageRegion; + mCurrentFrameNumber = clonedFrom->mCurrentFrameNumber.load(); + mPreviousFrameNumber = clonedFrom->mPreviousFrameNumber; + + // After buffer info is updated, the drawingState from the real layer needs to be copied into + // the cloned. This is because some properties of drawingState can change when latchBuffer is + // called. However, copying the drawingState would also overwrite the cloned layer's relatives. + // Therefore, temporarily store the relatives so they can be set in the cloned drawingState + // again. + wp<Layer> tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf; + SortedVector<wp<Layer>> tmpZOrderRelatives = mDrawingState.zOrderRelatives; + mDrawingState = clonedFrom->mDrawingState; + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; + mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf; + mDrawingState.zOrderRelatives = tmpZOrderRelatives; } } // namespace android diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b2c06183a6..656ba12a19 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -165,6 +165,8 @@ protected: sp<GraphicBuffer> mBuffer; int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; + + bool mFrameLatencyNeeded{false}; }; BufferInfo mBufferInfo; @@ -195,6 +197,8 @@ protected: ui::Dataspace translateDataspace(ui::Dataspace dataspace); void setInitialValuesForClone(const sp<Layer>& clonedFrom); + void updateCloneBufferInfo() override; + uint64_t mPreviousFrameNumber = 0; private: // Returns true if this layer requires filtering diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index eb13f658d9..d80a70e4c6 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -531,7 +531,7 @@ sp<Layer> BufferQueueLayer::createClone() { LayerCreationArgs args = LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; - sp<BufferQueueLayer> layer = new BufferQueueLayer(args); + sp<BufferQueueLayer> layer = mFlinger->getFactory().createBufferQueueLayer(args); layer->setInitialValuesForClone(this); return layer; diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 36dff156e1..f3e8a19a7d 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -111,8 +111,6 @@ private: PixelFormat mFormat{PIXEL_FORMAT_NONE}; - // Only accessed on the main thread. - uint64_t mPreviousFrameNumber{0}; bool mUpdateTexImageFailed{false}; uint64_t mPreviousBufferId = 0; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 30fdbe14e8..75fc0e9c06 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -125,9 +125,10 @@ bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { bool BufferStateLayer::willPresentCurrentTransaction() const { // Returns true if the most recent Transaction applied to CurrentState will be presented. - return getSidebandStreamChanged() || getAutoRefresh() || + return (getSidebandStreamChanged() || getAutoRefresh() || (mCurrentState.modified && - (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)); + (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) && + !mLayerDetached; } void BufferStateLayer::pushPendingState() { @@ -672,7 +673,7 @@ sp<Layer> BufferStateLayer::createClone() { LayerCreationArgs args = LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; - sp<BufferStateLayer> layer = new BufferStateLayer(args); + sp<BufferStateLayer> layer = mFlinger->getFactory().createBufferStateLayer(args); layer->mHwcSlotGenerator = mHwcSlotGenerator; layer->setInitialValuesForClone(this); return layer; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index e951ccf97a..3dfe76cf9f 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -143,7 +143,6 @@ private: sp<Fence> mPreviousReleaseFence; uint64_t mPreviousBufferId = 0; - uint64_t mPreviousFrameNumber = 0; uint64_t mPreviousReleasedFrameNumber = 0; mutable bool mCurrentStateModified = false; diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 6bfd302b5c..c7ed9b0412 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -106,6 +106,10 @@ status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32 nullptr, layer); } +status_t Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) { + return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle); +} + status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const { sp<Layer> layer = getLayerUser(handle); if (layer == nullptr) { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 74e48188d6..7d7cef8c50 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -62,6 +62,8 @@ private: LayerMetadata metadata, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp); + status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* handle); + virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const; virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 5b620543ac..172d44556a 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -109,7 +109,7 @@ ui::Dataspace ColorLayer::getDataSpace() const { sp<Layer> ColorLayer::createClone() { String8 name = mName + " (Mirror)"; - sp<ColorLayer> layer = new ColorLayer( + sp<ColorLayer> layer = mFlinger->getFactory().createColorLayer( LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); layer->setInitialValuesForClone(this); return layer; diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 1407ef7de6..738a2a47ab 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -11,6 +11,7 @@ cc_defaults { "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.composer@2.4", "android.hardware.power@1.0", "android.hardware.power@1.3", "libbase", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index 389b6059f3..a9a95cdb92 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -74,7 +74,7 @@ public: // Recalculates the state of the output layer from the output-independent // layer. If includeGeometry is false, the geometry state can be skipped. - virtual void updateCompositionState(bool includeGeometry) = 0; + virtual void updateCompositionState(bool includeGeometry, bool forceClientComposition) = 0; // Writes the geometry state to the HWC, or does nothing if this layer does // not use the HWC. If includeGeometry is false, the geometry state can be diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index 34dbfb777d..95c8afbede 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -39,7 +39,7 @@ public: void setHwcLayer(std::shared_ptr<HWC2::Layer>) override; - void updateCompositionState(bool) override; + void updateCompositionState(bool includeGeometry, bool forceClientComposition) override; void writeStateToHWC(bool) override; void writeCursorPositionToHWC() const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 4f2afacd63..631760afe7 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -40,7 +40,7 @@ public: MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&()); MOCK_METHOD0(editState, impl::OutputLayerCompositionState&()); - MOCK_METHOD1(updateCompositionState, void(bool)); + MOCK_METHOD2(updateCompositionState, void(bool, bool)); MOCK_METHOD1(writeStateToHWC, void(bool)); MOCK_CONST_METHOD0(writeCursorPositionToHWC, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 2007ea3068..aa638b7d91 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -552,11 +552,8 @@ void Output::updateAndWriteCompositionState( ALOGV(__FUNCTION__); for (auto* layer : getOutputLayersOrderedByZ()) { - if (refreshArgs.devOptForceClientComposition) { - layer->editState().forceClientComposition = true; - } - - layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame); + layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame, + refreshArgs.devOptForceClientComposition); // Send the updated state to the HWC, if appropriate. layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 0124e5b5d9..721e953d25 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -259,7 +259,7 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { return transform.getOrientation(); } // namespace impl -void OutputLayer::updateCompositionState(bool includeGeometry) { +void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientComposition) { const auto& layerFEState = getLayer().getFEState(); const auto& outputState = getOutput().getState(); const auto& profile = *getOutput().getDisplayColorProfile(); @@ -294,7 +294,8 @@ void OutputLayer::updateCompositionState(bool includeGeometry) { // These are evaluated every frame as they can potentially change at any // time. - if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(state.dataspace)) { + if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(state.dataspace) || + forceClientComposition) { state.forceClientComposition = true; } } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 0347f759e7..a33878448f 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -501,7 +501,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { setupGeometryChildCallValues(); - mOutputLayer.updateCompositionState(true); + mOutputLayer.updateCompositionState(true, false); validateComputedGeometryState(); @@ -515,7 +515,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setupGeometryChildCallValues(); - mOutputLayer.updateCompositionState(true); + mOutputLayer.updateCompositionState(true, false); validateComputedGeometryState(); @@ -531,7 +531,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setupGeometryChildCallValues(); - mOutputLayer.updateCompositionState(true); + mOutputLayer.updateCompositionState(true, false); validateComputedGeometryState(); @@ -546,7 +546,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly // should use the layers requested colorspace. mLayerFEState.isColorspaceAgnostic = false; - mOutputLayer.updateCompositionState(false); + mOutputLayer.updateCompositionState(false, false); EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutputLayer.getState().dataspace); @@ -554,7 +554,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly // should use the colorspace chosen for the whole output. mLayerFEState.isColorspaceAgnostic = true; - mOutputLayer.updateCompositionState(false); + mOutputLayer.updateCompositionState(false, false); EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace); } @@ -562,7 +562,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) { mOutputLayer.editState().forceClientComposition = false; - mOutputLayer.updateCompositionState(false); + mOutputLayer.updateCompositionState(false, false); EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition); } @@ -571,7 +571,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, doesNotClearForceClientCompositionIfNotDoingGeometry) { mOutputLayer.editState().forceClientComposition = true; - mOutputLayer.updateCompositionState(false); + mOutputLayer.updateCompositionState(false, false); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } @@ -580,7 +580,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEn mLayerFEState.forceClientComposition = true; mOutputLayer.editState().forceClientComposition = false; - mOutputLayer.updateCompositionState(false); + mOutputLayer.updateCompositionState(false, false); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } @@ -590,7 +590,24 @@ TEST_F(OutputLayerUpdateCompositionStateTest, mOutputLayer.editState().forceClientComposition = false; EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(false)); - mOutputLayer.updateCompositionState(false); + mOutputLayer.updateCompositionState(false, false); + + EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); +} + +TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromArgumentFlag) { + mLayerFEState.forceClientComposition = false; + mOutputLayer.editState().forceClientComposition = false; + + mOutputLayer.updateCompositionState(false, true); + + EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); + + mOutputLayer.editState().forceClientComposition = false; + + setupGeometryChildCallValues(); + + mOutputLayer.updateCompositionState(true, true); EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index cb50d9ff6d..e58e6f425e 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -32,7 +32,7 @@ bool ContainerLayer::isVisible() const { sp<Layer> ContainerLayer::createClone() { String8 name = mName + " (Mirror)"; - sp<ContainerLayer> layer = new ContainerLayer( + sp<ContainerLayer> layer = mFlinger->getFactory().createContainerLayer( LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); layer->setInitialValuesForClone(this); return layer; diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index e53d09949c..acddc42601 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -17,9 +17,11 @@ #undef LOG_TAG #define LOG_TAG "HwcComposer" -#include <inttypes.h> #include <log/log.h> +#include <algorithm> +#include <cinttypes> + #include "ComposerHal.h" #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> @@ -173,7 +175,16 @@ Composer::Composer(const std::string& serviceName) LOG_ALWAYS_FATAL("failed to get hwcomposer service"); } - if (sp<IComposer> composer_2_3 = IComposer::castFrom(mComposer)) { + if (sp<IComposer> composer_2_4 = IComposer::castFrom(mComposer)) { + composer_2_4->createClient_2_4([&](const auto& tmpError, const auto& tmpClient) { + if (tmpError == Error::NONE) { + mClient = tmpClient; + mClient_2_2 = tmpClient; + mClient_2_3 = tmpClient; + mClient_2_4 = tmpClient; + } + }); + } else if (sp<V2_3::IComposer> composer_2_3 = V2_3::IComposer::castFrom(mComposer)) { composer_2_3->createClient_2_3([&](const auto& tmpError, const auto& tmpClient) { if (tmpError == Error::NONE) { mClient = tmpClient; @@ -456,23 +467,6 @@ Error Composer::getDisplayRequests(Display display, return Error::NONE; } -Error Composer::getDisplayType(Display display, - IComposerClient::DisplayType* outType) -{ - Error error = kDefaultError; - mClient->getDisplayType(display, - [&](const auto& tmpError, const auto& tmpType) { - error = tmpError; - if (error != Error::NONE) { - return; - } - - *outType = tmpType; - }); - - return error; -} - Error Composer::getDozeSupport(Display display, bool* outSupport) { Error error = kDefaultError; @@ -1113,23 +1107,6 @@ Error Composer::getDisplayedContentSamplingAttributes(Display display, PixelForm return error; } -Error Composer::getDisplayCapabilities(Display display, - std::vector<DisplayCapability>* outCapabilities) { - if (!mClient_2_3) { - return Error::UNSUPPORTED; - } - Error error = kDefaultError; - mClient_2_3->getDisplayCapabilities(display, - [&](const auto& tmpError, const auto& tmpCapabilities) { - error = tmpError; - if (error != Error::NONE) { - return; - } - *outCapabilities = tmpCapabilities; - }); - return error; -} - Error Composer::setDisplayContentSamplingEnabled(Display display, bool enabled, uint8_t componentMask, uint64_t maxFrames) { if (!mClient_2_3) { @@ -1187,6 +1164,60 @@ Error Composer::setDisplayBrightness(Display display, float brightness) { return mClient_2_3->setDisplayBrightness(display, brightness); } +// Composer HAL 2.4 + +Error Composer::getDisplayCapabilities(Display display, + std::vector<DisplayCapability>* outCapabilities) { + if (!mClient_2_3) { + return Error::UNSUPPORTED; + } + + Error error = kDefaultError; + if (mClient_2_4) { + mClient_2_4->getDisplayCapabilities_2_4(display, + [&](const auto& tmpError, const auto& tmpCaps) { + error = tmpError; + if (error != Error::NONE) { + return; + } + *outCapabilities = tmpCaps; + }); + } else { + mClient_2_3 + ->getDisplayCapabilities(display, [&](const auto& tmpError, const auto& tmpCaps) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + outCapabilities->resize(tmpCaps.size()); + std::transform(tmpCaps.begin(), tmpCaps.end(), outCapabilities->begin(), + [](auto cap) { return static_cast<DisplayCapability>(cap); }); + }); + } + + return error; +} + +Error Composer::getDisplayConnectionType(Display display, + IComposerClient::DisplayConnectionType* outType) { + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + Error error = kDefaultError; + mClient_2_4->getDisplayConnectionType(display, [&](const auto& tmpError, const auto& tmpType) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outType = tmpType; + }); + + return error; +} + CommandReader::~CommandReader() { resetData(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 9f6cac22b7..e743e59bb6 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -27,8 +27,8 @@ #include <android/frameworks/vr/composer/2.0/IVrComposerClient.h> #endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER #include <android/hardware/graphics/common/1.1/types.h> -#include <android/hardware/graphics/composer/2.3/IComposer.h> -#include <android/hardware/graphics/composer/2.3/IComposerClient.h> +#include <android/hardware/graphics/composer/2.4/IComposer.h> +#include <android/hardware/graphics/composer/2.4/IComposerClient.h> #include <composer-command-buffer/2.3/ComposerCommandBuffer.h> #include <gui/HdrMetadata.h> #include <math/mat4.h> @@ -49,6 +49,7 @@ namespace types = hardware::graphics::common; namespace V2_1 = hardware::graphics::composer::V2_1; namespace V2_2 = hardware::graphics::composer::V2_2; namespace V2_3 = hardware::graphics::composer::V2_3; +namespace V2_4 = hardware::graphics::composer::V2_4; using types::V1_0::ColorTransform; using types::V1_0::Transform; @@ -65,8 +66,8 @@ using V2_1::IComposerCallback; using V2_1::Layer; using V2_3::CommandReaderBase; using V2_3::CommandWriterBase; -using V2_3::IComposer; -using V2_3::IComposerClient; +using V2_4::IComposer; +using V2_4::IComposerClient; using DisplayCapability = IComposerClient::DisplayCapability; using PerFrameMetadata = IComposerClient::PerFrameMetadata; using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey; @@ -118,7 +119,6 @@ public: std::vector<Layer>* outLayers, std::vector<uint32_t>* outLayerRequestMasks) = 0; - virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0; virtual Error getDozeSupport(Display display, bool* outSupport) = 0; virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance, float* outMaxAverageLuminance, @@ -203,11 +203,15 @@ public: uint8_t componentMask, uint64_t maxFrames) = 0; virtual Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp, DisplayedFrameStats* outStats) = 0; - virtual Error getDisplayCapabilities(Display display, - std::vector<DisplayCapability>* outCapabilities) = 0; virtual Error setLayerPerFrameMetadataBlobs( Display display, Layer layer, const std::vector<PerFrameMetadataBlob>& metadata) = 0; virtual Error setDisplayBrightness(Display display, float brightness) = 0; + + // Composer HAL 2.4 + virtual Error getDisplayCapabilities(Display display, + std::vector<DisplayCapability>* outCapabilities) = 0; + virtual Error getDisplayConnectionType(Display display, + IComposerClient::DisplayConnectionType* outType) = 0; }; namespace impl { @@ -334,7 +338,6 @@ public: std::vector<Layer>* outLayers, std::vector<uint32_t>* outLayerRequestMasks) override; - Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override; Error getDozeSupport(Display display, bool* outSupport) override; Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance, float* outMaxAverageLuminance, float* outMinLuminance) override; @@ -414,13 +417,17 @@ public: uint64_t maxFrames) override; Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp, DisplayedFrameStats* outStats) override; - Error getDisplayCapabilities(Display display, - std::vector<DisplayCapability>* outCapabilities) override; Error setLayerPerFrameMetadataBlobs( Display display, Layer layer, const std::vector<IComposerClient::PerFrameMetadataBlob>& metadata) override; Error setDisplayBrightness(Display display, float brightness) override; + // Composer HAL 2.4 + Error getDisplayCapabilities(Display display, + std::vector<DisplayCapability>* outCapabilities) override; + Error getDisplayConnectionType(Display display, + IComposerClient::DisplayConnectionType* outType) override; + private: #if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER class CommandWriter : public CommandWriterBase { @@ -455,7 +462,8 @@ private: sp<V2_1::IComposerClient> mClient; sp<V2_2::IComposerClient> mClient_2_2; - sp<IComposerClient> mClient_2_3; + sp<V2_3::IComposerClient> mClient_2_3; + sp<IComposerClient> mClient_2_4; // 64KiB minus a small space for metadata such as read/write pointers static constexpr size_t kWriterInitialSize = diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index c463c4e40a..6f7428a44a 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -169,20 +169,8 @@ void Device::onHotplug(hwc2_display_t displayId, Connection connection) { } mDisplays.erase(displayId); - DisplayType displayType; - auto intError = mComposer->getDisplayType(displayId, - reinterpret_cast<Hwc2::IComposerClient::DisplayType *>( - &displayType)); - auto error = static_cast<Error>(intError); - if (error != Error::None) { - ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). " - "Aborting hotplug attempt.", - displayId, to_string(error).c_str(), intError); - return; - } - auto newDisplay = std::make_unique<impl::Display>(*mComposer.get(), mCapabilities, - displayId, displayType); + displayId, DisplayType::Physical); newDisplay->setConnected(true); mDisplays.emplace(displayId, std::move(newDisplay)); } else if (connection == Connection::Disconnected) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 079bc66303..6a45625c89 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -780,6 +780,15 @@ uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); if (mLayerDetached) { + // Ensure BLAST buffer callbacks are processed. + // detachChildren and mLayerDetached were implemented to avoid geometry updates + // to layers in the cases of animation. For BufferQueue layers buffers are still + // consumed as normal. This is useful as otherwise the client could get hung + // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue + // even though it is a little consistent. detachChildren is shortly slated for removal + // by the hierarchy mirroring work so we don't need to worry about it too much. + mDrawingState.callbackHandles = mCurrentState.callbackHandles; + mCurrentState.callbackHandles = {}; return flags; } @@ -2025,6 +2034,118 @@ void Layer::setInitialValuesForClone(const sp<Layer>& clonedFrom) { // InputWindows per client token yet. mDrawingState.inputInfo.token = nullptr; } + +void Layer::updateMirrorInfo() { + if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) { + // If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false, + // it means that there is a clone, but the layer it was cloned from has been destroyed. In + // that case, we want to delete the reference to the clone since we want it to get + // destroyed. The root, this layer, will still be around since the client can continue + // to hold a reference, but no cloned layers will be displayed. + mClonedChild = nullptr; + return; + } + + std::map<sp<Layer>, sp<Layer>> clonedLayersMap; + // If the real layer exists and is in current state, add the clone as a child of the root. + // There's no need to remove from drawingState when the layer is offscreen since currentState is + // copied to drawingState for the root layer. So the clonedChild is always removed from + // drawingState and then needs to be added back each traversal. + if (!mClonedChild->getClonedFrom()->isRemovedFromCurrentState()) { + addChildToDrawing(mClonedChild); + } + + mClonedChild->updateClonedDrawingState(clonedLayersMap); + mClonedChild->updateClonedChildren(this, clonedLayersMap); + mClonedChild->updateClonedRelatives(clonedLayersMap); +} + +void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { + // If the layer the clone was cloned from is alive, copy the content of the drawingState + // to the clone. If the real layer is no longer alive, continue traversing the children + // since we may be able to pull out other children that are still alive. + if (isClonedFromAlive()) { + sp<Layer> clonedFrom = getClonedFrom(); + mDrawingState = clonedFrom->mDrawingState; + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; + clonedLayersMap.emplace(clonedFrom, this); + } + + // The clone layer may have children in drawingState since they may have been created and + // added from a previous request to updateMirorInfo. This is to ensure we don't recreate clones + // that already exist, since we can just re-use them. + // The drawingChildren will not get overwritten by the currentChildren since the clones are + // not updated in the regular traversal. They are skipped since the root will lose the + // reference to them when it copies its currentChildren to drawing. + for (sp<Layer>& child : mDrawingChildren) { + child->updateClonedDrawingState(clonedLayersMap); + } +} + +void Layer::updateClonedChildren(const sp<Layer>& mirrorRoot, + std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { + mDrawingChildren.clear(); + + if (!isClonedFromAlive()) { + return; + } + + sp<Layer> clonedFrom = getClonedFrom(); + for (sp<Layer>& child : clonedFrom->mDrawingChildren) { + if (child == mirrorRoot) { + // This is to avoid cyclical mirroring. + continue; + } + sp<Layer> clonedChild = clonedLayersMap[child]; + if (clonedChild == nullptr) { + clonedChild = child->createClone(); + clonedLayersMap[child] = clonedChild; + } + addChildToDrawing(clonedChild); + clonedChild->updateClonedChildren(mirrorRoot, clonedLayersMap); + } +} + +void Layer::updateClonedRelatives(std::map<sp<Layer>, sp<Layer>> clonedLayersMap) { + mDrawingState.zOrderRelativeOf = nullptr; + mDrawingState.zOrderRelatives.clear(); + + if (!isClonedFromAlive()) { + return; + } + + sp<Layer> clonedFrom = getClonedFrom(); + for (wp<Layer>& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) { + sp<Layer> relative = relativeWeak.promote(); + auto clonedRelative = clonedLayersMap[relative]; + if (clonedRelative != nullptr) { + mDrawingState.zOrderRelatives.add(clonedRelative); + } + } + + // Check if the relativeLayer for the real layer is part of the cloned hierarchy. + // It's possible that the layer it's relative to is outside the requested cloned hierarchy. + // In that case, we treat the layer as if the relativeOf has been removed. This way, it will + // still traverse the children, but the layer with the missing relativeOf will not be shown + // on screen. + sp<Layer> relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); + sp<Layer> clonedRelativeOf = clonedLayersMap[relativeOf]; + if (clonedRelativeOf != nullptr) { + mDrawingState.zOrderRelativeOf = clonedRelativeOf; + } + + for (sp<Layer>& child : mDrawingChildren) { + child->updateClonedRelatives(clonedLayersMap); + } +} + +void Layer::addChildToDrawing(const sp<Layer>& layer) { + mDrawingChildren.add(layer); + layer->mDrawingParent = this; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 610df25637..3023cf5df3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -468,13 +468,30 @@ public: virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } virtual bool needsFiltering(const sp<const DisplayDevice>&) const { return false; } -protected: + // This layer is not a clone, but it's the parent to the cloned hierarchy. The + // variable mClonedChild represents the top layer that will be cloned so this + // layer will be the parent of mClonedChild. + // The layers in the cloned hierarchy will match the lifetime of the real layers. That is + // if the real layer is destroyed, then the clone layer will also be destroyed. + sp<Layer> mClonedChild; + virtual sp<Layer> createClone() = 0; + void updateMirrorInfo(); + virtual void updateCloneBufferInfo(){}; + +protected: sp<Layer> getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; } + bool isClone() { return mClonedFrom != nullptr; } + bool isClonedFromAlive() { return getClonedFrom() != nullptr; } - bool isClone() { return getClonedFrom() != nullptr; } virtual void setInitialValuesForClone(const sp<Layer>& clonedFrom); + void updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap); + void updateClonedChildren(const sp<Layer>& mirrorRoot, + std::map<sp<Layer>, sp<Layer>>& clonedLayersMap); + void updateClonedRelatives(std::map<sp<Layer>, sp<Layer>> clonedLayersMap); + void addChildToDrawing(const sp<Layer>& layer); + public: /* * compositionengine::LayerFE overrides @@ -838,7 +855,6 @@ protected: // We encode unset as -1. int32_t mOverrideScalingMode{-1}; std::atomic<uint64_t> mCurrentFrameNumber{0}; - bool mFrameLatencyNeeded{false}; // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 86997477b3..54e20659a7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -258,7 +258,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mFrameTracer(std::make_unique<FrameTracer>()), mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()), - mPhaseOffsets(mFactory.createPhaseOffsets()) {} + mPhaseOffsets(mFactory.createPhaseOffsets()), + mPendingSyncInputWindows(false) {} SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) { ALOGI("SurfaceFlinger is starting"); @@ -876,7 +877,16 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { return BAD_VALUE; } - return display->getActiveConfig(); + if (display->isPrimary()) { + std::lock_guard<std::mutex> lock(mActiveConfigLock); + if (mDesiredActiveConfigChanged) { + return mDesiredActiveConfig.configId; + } else { + return display->getActiveConfig(); + } + } else { + return display->getActiveConfig(); + } } void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { @@ -2600,6 +2610,7 @@ void SurfaceFlinger::commitTransactionLocked() { }); commitOffscreenLayers(); + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateMirrorInfo(); }); } void SurfaceFlinger::withTracingLock(std::function<void()> lockedOperation) { @@ -2718,6 +2729,8 @@ bool SurfaceFlinger::handlePageFlip() mBootStage = BootStage::BOOTANIMATION; } + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateCloneBufferInfo(); }); + // Only continue with the refresh if there is actually new work to do return !mLayersWithQueuedFrames.empty() && newDataLatched; } @@ -3385,6 +3398,35 @@ uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& input return flags; } +status_t SurfaceFlinger::mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle, + sp<IBinder>* outHandle) { + if (!mirrorFromHandle) { + return NAME_NOT_FOUND; + } + + sp<Layer> mirrorLayer; + sp<Layer> mirrorFrom; + String8 uniqueName = getUniqueLayerName(String8("MirrorRoot")); + + { + Mutex::Autolock _l(mStateLock); + mirrorFrom = fromHandle(mirrorFromHandle); + if (!mirrorFrom) { + return NAME_NOT_FOUND; + } + + status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(), + outHandle, &mirrorLayer); + if (result != NO_ERROR) { + return result; + } + + mirrorLayer->mClonedChild = mirrorFrom->createClone(); + } + + return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, nullptr, false); +} + status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, LayerMetadata metadata, sp<IBinder>* handle, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2ea8f78c66..9f3a914366 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -338,6 +338,7 @@ private: // For unit tests friend class TestableSurfaceFlinger; + friend class TransactionApplicationTest; // This value is specified in number of frames. Log frame stats at most // every half hour. @@ -623,6 +624,9 @@ private: uint32_t h, uint32_t flags, LayerMetadata metadata, sp<IBinder>* outHandle, sp<Layer>* outLayer); + status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle, + sp<IBinder>* outHandle); + String8 getUniqueLayerName(const String8& name); // called when all clients have released all their references to diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp new file mode 100644 index 0000000000..f0457e3e8a --- /dev/null +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -0,0 +1,120 @@ +/* + * 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/CompositionEngine.h> +#include <ui/GraphicBuffer.h> + +#include "BufferQueueLayer.h" +#include "BufferStateLayer.h" +#include "ColorLayer.h" +#include "ContainerLayer.h" +#include "DisplayDevice.h" +#include "Layer.h" +#include "NativeWindowSurface.h" +#include "StartPropertySetThread.h" +#include "SurfaceFlingerDefaultFactory.h" +#include "SurfaceInterceptor.h" + +#include "DisplayHardware/ComposerHal.h" +#include "Scheduler/DispSync.h" +#include "Scheduler/EventControlThread.h" +#include "Scheduler/MessageQueue.h" +#include "Scheduler/PhaseOffsets.h" +#include "Scheduler/Scheduler.h" + +namespace android::surfaceflinger { + +DefaultFactory::~DefaultFactory() = default; + +std::unique_ptr<DispSync> DefaultFactory::createDispSync(const char* name, bool hasSyncFramework) { + return std::make_unique<android::impl::DispSync>(name, hasSyncFramework); +} + +std::unique_ptr<EventControlThread> DefaultFactory::createEventControlThread( + SetVSyncEnabled setVSyncEnabled) { + return std::make_unique<android::impl::EventControlThread>(std::move(setVSyncEnabled)); +} + +std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) { + return std::make_unique<android::impl::HWComposer>( + std::make_unique<Hwc2::impl::Composer>(serviceName)); +} + +std::unique_ptr<MessageQueue> DefaultFactory::createMessageQueue() { + return std::make_unique<android::impl::MessageQueue>(); +} + +std::unique_ptr<scheduler::PhaseOffsets> DefaultFactory::createPhaseOffsets() { + return std::make_unique<scheduler::impl::PhaseOffsets>(); +} + +std::unique_ptr<Scheduler> DefaultFactory::createScheduler( + SetVSyncEnabled setVSyncEnabled, const scheduler::RefreshRateConfigs& configs) { + return std::make_unique<Scheduler>(std::move(setVSyncEnabled), configs); +} + +std::unique_ptr<SurfaceInterceptor> DefaultFactory::createSurfaceInterceptor( + SurfaceFlinger* flinger) { + return std::make_unique<android::impl::SurfaceInterceptor>(flinger); +} + +sp<StartPropertySetThread> DefaultFactory::createStartPropertySetThread( + bool timestampPropertyValue) { + return new StartPropertySetThread(timestampPropertyValue); +} + +sp<DisplayDevice> DefaultFactory::createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) { + return new DisplayDevice(std::move(creationArgs)); +} + +sp<GraphicBuffer> DefaultFactory::createGraphicBuffer(uint32_t width, uint32_t height, + PixelFormat format, uint32_t layerCount, + uint64_t usage, std::string requestorName) { + return new GraphicBuffer(width, height, format, layerCount, usage, requestorName); +} + +void DefaultFactory::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, + sp<IGraphicBufferConsumer>* outConsumer, + bool consumerIsSurfaceFlinger) { + BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); +} + +std::unique_ptr<surfaceflinger::NativeWindowSurface> DefaultFactory::createNativeWindowSurface( + const sp<IGraphicBufferProducer>& producer) { + return surfaceflinger::impl::createNativeWindowSurface(producer); +} + +std::unique_ptr<compositionengine::CompositionEngine> DefaultFactory::createCompositionEngine() { + return compositionengine::impl::createCompositionEngine(); +} + +sp<ContainerLayer> DefaultFactory::createContainerLayer(const LayerCreationArgs& args) { + return new ContainerLayer(args); +} + +sp<BufferQueueLayer> DefaultFactory::createBufferQueueLayer(const LayerCreationArgs& args) { + return new BufferQueueLayer(args); +} + +sp<BufferStateLayer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) { + return new BufferStateLayer(args); +} + +sp<ColorLayer> DefaultFactory::createColorLayer(const LayerCreationArgs& args) { + return new ColorLayer(args); +} + +} // namespace android::surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h new file mode 100644 index 0000000000..89e0679c83 --- /dev/null +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h @@ -0,0 +1,54 @@ +/* + * 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 "SurfaceFlingerFactory.h" + +namespace android::surfaceflinger { + +// A default implementation of the factory which creates the standard +// implementation types for each interface. +class DefaultFactory : public surfaceflinger::Factory { +public: + virtual ~DefaultFactory(); + + std::unique_ptr<DispSync> createDispSync(const char* name, bool hasSyncFramework) override; + std::unique_ptr<EventControlThread> createEventControlThread(SetVSyncEnabled) override; + std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) override; + std::unique_ptr<MessageQueue> createMessageQueue() override; + std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override; + std::unique_ptr<Scheduler> createScheduler(SetVSyncEnabled, + const scheduler::RefreshRateConfigs&) override; + std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) override; + sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override; + sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&&) override; + sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, + uint32_t layerCount, uint64_t usage, + std::string requestorName) override; + void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, + sp<IGraphicBufferConsumer>* outConsumer, + bool consumerIsSurfaceFlinger) override; + std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface( + const sp<IGraphicBufferProducer>&) override; + std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override; + sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) override; + sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) override; + sp<ColorLayer> createColorLayer(const LayerCreationArgs& args) override; + sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) override; +}; + +} // namespace android::surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp index 4ddc132a2e..9b1f658661 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp @@ -14,116 +14,13 @@ * limitations under the License. */ -#include <compositionengine/impl/CompositionEngine.h> -#include <ui/GraphicBuffer.h> - -#include "BufferQueueLayer.h" -#include "BufferStateLayer.h" -#include "ColorLayer.h" -#include "ContainerLayer.h" -#include "DisplayDevice.h" -#include "Layer.h" -#include "NativeWindowSurface.h" -#include "StartPropertySetThread.h" #include "SurfaceFlinger.h" -#include "SurfaceFlingerFactory.h" -#include "SurfaceInterceptor.h" - -#include "DisplayHardware/ComposerHal.h" -#include "Scheduler/DispSync.h" -#include "Scheduler/EventControlThread.h" -#include "Scheduler/MessageQueue.h" -#include "Scheduler/PhaseOffsets.h" -#include "Scheduler/Scheduler.h" +#include "SurfaceFlingerDefaultFactory.h" namespace android::surfaceflinger { sp<SurfaceFlinger> createSurfaceFlinger() { - class Factory final : public surfaceflinger::Factory { - public: - Factory() = default; - ~Factory() = default; - - std::unique_ptr<DispSync> createDispSync(const char* name, bool hasSyncFramework) override { - return std::make_unique<android::impl::DispSync>(name, hasSyncFramework); - } - - std::unique_ptr<EventControlThread> createEventControlThread( - SetVSyncEnabled setVSyncEnabled) override { - return std::make_unique<android::impl::EventControlThread>(std::move(setVSyncEnabled)); - } - - std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) override { - return std::make_unique<android::impl::HWComposer>( - std::make_unique<Hwc2::impl::Composer>(serviceName)); - } - - std::unique_ptr<MessageQueue> createMessageQueue() override { - return std::make_unique<android::impl::MessageQueue>(); - } - - std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override { - return std::make_unique<scheduler::impl::PhaseOffsets>(); - } - - std::unique_ptr<Scheduler> createScheduler( - SetVSyncEnabled setVSyncEnabled, - const scheduler::RefreshRateConfigs& configs) override { - return std::make_unique<Scheduler>(std::move(setVSyncEnabled), configs); - } - - std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor( - SurfaceFlinger* flinger) override { - return std::make_unique<android::impl::SurfaceInterceptor>(flinger); - } - - sp<StartPropertySetThread> createStartPropertySetThread( - bool timestampPropertyValue) override { - return new StartPropertySetThread(timestampPropertyValue); - } - - sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) override { - return new DisplayDevice(std::move(creationArgs)); - } - - sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, - uint32_t layerCount, uint64_t usage, - std::string requestorName) override { - return new GraphicBuffer(width, height, format, layerCount, usage, requestorName); - } - - void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, - sp<IGraphicBufferConsumer>* outConsumer, - bool consumerIsSurfaceFlinger) override { - BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); - } - - std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface( - const sp<IGraphicBufferProducer>& producer) override { - return surfaceflinger::impl::createNativeWindowSurface(producer); - } - - std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override { - return compositionengine::impl::createCompositionEngine(); - } - - sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) override { - return new ContainerLayer(args); - } - - sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) override { - return new BufferQueueLayer(args); - } - - sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) override { - return new BufferStateLayer(args); - } - - sp<ColorLayer> createColorLayer(const LayerCreationArgs& args) override { - return new ColorLayer(args); - } - }; - static Factory factory; + static DefaultFactory factory; return new SurfaceFlinger(factory); } diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index d6b9b60774..d021fc2859 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -19,18 +19,20 @@ cc_test { srcs: [ "BufferGenerator.cpp", "Credentials_test.cpp", - "DereferenceSurfaceControl_test.cpp", + "DereferenceSurfaceControl_test.cpp", "DisplayActiveConfig_test.cpp", - "InvalidHandles_test.cpp", + "InvalidHandles_test.cpp", "LayerCallback_test.cpp", - "LayerRenderTypeTransaction_test.cpp", - "LayerTransaction_test.cpp", - "LayerTypeAndRenderTypeTransaction_test.cpp", - "LayerTypeTransaction_test.cpp", - "LayerUpdate_test.cpp", - "MultiDisplayLayerBounds_test.cpp", - "RelativeZ_test.cpp", - "Stress_test.cpp", + "LayerRenderTypeTransaction_test.cpp", + "LayerTransaction_test.cpp", + "LayerTypeAndRenderTypeTransaction_test.cpp", + "LayerTypeTransaction_test.cpp", + "LayerUpdate_test.cpp", + "MirrorLayer_test.cpp", + "MultiDisplayLayerBounds_test.cpp", + "RelativeZ_test.cpp", + "SetGeometry_test.cpp", + "Stress_test.cpp", "SurfaceInterceptor_test.cpp", "VirtualDisplay_test.cpp", ], diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp new file mode 100644 index 0000000000..0bcac1a880 --- /dev/null +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerTransactionTest.h" + +namespace android { + +class MirrorLayerTest : public LayerTransactionTest { +protected: + virtual void SetUp() { + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); + + const auto display = SurfaceComposerClient::getInternalDisplayToken(); + ASSERT_FALSE(display == nullptr); + + mParentLayer = createColorLayer("Parent layer", Color::RED); + mChildLayer = createColorLayer("Child layer", Color::GREEN, mParentLayer.get()); + asTransaction([&](Transaction& t) { + t.setDisplayLayerStack(display, 0); + t.setLayer(mParentLayer, INT32_MAX - 2).show(mParentLayer); + t.setCrop_legacy(mChildLayer, Rect(0, 0, 400, 400)).show(mChildLayer); + t.setPosition(mChildLayer, 50, 50); + t.setFlags(mParentLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); + t.setFlags(mChildLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); + }); + } + + virtual void TearDown() { + LayerTransactionTest::TearDown(); + mParentLayer = 0; + mChildLayer = 0; + } + + sp<SurfaceControl> mParentLayer; + sp<SurfaceControl> mChildLayer; +}; + +TEST_F(MirrorLayerTest, MirrorColorLayer) { + sp<SurfaceControl> grandchild = + createColorLayer("Grandchild layer", Color::BLUE, mChildLayer.get()); + Transaction() + .setFlags(grandchild, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque) + .setCrop_legacy(grandchild, Rect(0, 0, 200, 200)) + .show(grandchild) + .apply(); + + // Mirror mChildLayer + sp<SurfaceControl> mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); + ASSERT_NE(mirrorLayer, nullptr); + + // Add mirrorLayer as child of mParentLayer so it's shown on the display + Transaction() + .reparent(mirrorLayer, mParentLayer->getHandle()) + .setPosition(mirrorLayer, 500, 500) + .show(mirrorLayer) + .apply(); + + { + SCOPED_TRACE("Initial Mirror"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + // Set color to white on grandchild layer. + Transaction().setColor(grandchild, half3{1, 1, 1}).apply(); + { + SCOPED_TRACE("Updated Grandchild Layer Color"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + // Set color to black on child layer. + Transaction().setColor(mChildLayer, half3{0, 0, 0}).apply(); + { + SCOPED_TRACE("Updated Child Layer Color"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK); + } + + // Remove grandchild layer + Transaction().reparent(grandchild, nullptr).apply(); + { + SCOPED_TRACE("Removed Grandchild Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLACK); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK); + } + + // Remove child layer + Transaction().reparent(mChildLayer, nullptr).apply(); + { + SCOPED_TRACE("Removed Child Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::RED); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::RED); + } + + // Add grandchild layer to offscreen layer + Transaction().reparent(grandchild, mChildLayer->getHandle()).apply(); + { + SCOPED_TRACE("Added Grandchild Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::RED); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::RED); + } + + // Add child layer + Transaction().reparent(mChildLayer, mParentLayer->getHandle()).apply(); + { + SCOPED_TRACE("Added Child Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK); + } +} + +TEST_F(MirrorLayerTest, MirrorBufferLayer) { + sp<SurfaceControl> bufferQueueLayer = + createLayer("BufferQueueLayer", 200, 200, 0, mChildLayer.get()); + fillBufferQueueLayerColor(bufferQueueLayer, Color::BLUE, 200, 200); + Transaction().show(bufferQueueLayer).apply(); + + sp<SurfaceControl> mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); + Transaction() + .reparent(mirrorLayer, mParentLayer->getHandle()) + .setPosition(mirrorLayer, 500, 500) + .show(mirrorLayer) + .apply(); + + { + SCOPED_TRACE("Initial Mirror BufferQueueLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + fillBufferQueueLayerColor(bufferQueueLayer, Color::WHITE, 200, 200); + { + SCOPED_TRACE("Update BufferQueueLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + Transaction().reparent(bufferQueueLayer, nullptr).apply(); + { + SCOPED_TRACE("Removed BufferQueueLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::GREEN); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + sp<SurfaceControl> bufferStateLayer = + createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, + mChildLayer.get()); + fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); + Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); + + { + SCOPED_TRACE("Initial Mirror BufferStateLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + fillBufferStateLayerColor(bufferStateLayer, Color::WHITE, 200, 200); + { + SCOPED_TRACE("Update BufferStateLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + Transaction().reparent(bufferStateLayer, nullptr).apply(); + { + SCOPED_TRACE("Removed BufferStateLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::GREEN); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } +} + +} // namespace android diff --git a/services/surfaceflinger/tests/SetGeometry_test.cpp b/services/surfaceflinger/tests/SetGeometry_test.cpp new file mode 100644 index 0000000000..dca06ec8d4 --- /dev/null +++ b/services/surfaceflinger/tests/SetGeometry_test.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerTransactionTest.h" + +namespace android { + +class SetGeometryTest : public LayerTransactionTest { +protected: + void SetUp() { + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); + + mLayer = createLayer("Layer", mLayerWidth, mLayerHeight); + fillBufferQueueLayerColor(mLayer, Color::RED, mLayerWidth, mLayerHeight); + asTransaction([&](Transaction& t) { t.setLayer(mLayer, INT32_MAX - 1).show(mLayer); }); + + { + SCOPED_TRACE("init"); + ScreenCapture::captureScreen(&sc); + sc->expectColor(Rect(0, 0, mLayerWidth, mLayerHeight), Color::RED); + sc->expectBorder(Rect(0, 0, mLayerWidth, mLayerHeight), Color::BLACK); + } + } + + void TearDown() { + LayerTransactionTest::TearDown(); + sc = 0; + mLayer = 0; + } + + std::unique_ptr<ScreenCapture> sc; + sp<SurfaceControl> mLayer; + const int mLayerWidth = 100; + const int mLayerHeight = 200; +}; + +TEST_F(SetGeometryTest, SourceAtZeroNoScale) { + Rect source = Rect(0, 0, 30, 30); + Rect dest = Rect(60, 60, 90, 90); + Transaction{}.setGeometry(mLayer, source, dest, 0).apply(); + + { + SCOPED_TRACE("geometry applied"); + ScreenCapture::captureScreen(&sc); + sc->expectColor(dest, Color::RED); + sc->expectBorder(dest, Color::BLACK); + } +} + +TEST_F(SetGeometryTest, SourceNotAtZero) { + Rect source = Rect(40, 40, 70, 70); + Rect dest = Rect(60, 60, 90, 90); + Transaction{}.setGeometry(mLayer, source, dest, 0).apply(); + + { + SCOPED_TRACE("geometry applied"); + ScreenCapture::captureScreen(&sc); + sc->expectColor(dest, Color::RED); + sc->expectBorder(dest, Color::BLACK); + } +} + +TEST_F(SetGeometryTest, Scale) { + Rect source = Rect(0, 0, 100, 200); + Rect dest = Rect(0, 0, 200, 400); + Transaction{}.setGeometry(mLayer, source, dest, 0).apply(); + + { + SCOPED_TRACE("Scaled by 2"); + ScreenCapture::captureScreen(&sc); + sc->expectColor(dest, Color::RED); + sc->expectBorder(dest, Color::BLACK); + } + + dest = Rect(0, 0, 50, 100); + Transaction{}.setGeometry(mLayer, source, dest, 0).apply(); + { + SCOPED_TRACE("Scaled by .5"); + ScreenCapture::captureScreen(&sc); + sc->expectColor(dest, Color::RED); + sc->expectBorder(dest, Color::BLACK); + } +} + +} // namespace android diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 6b4634ae76..b19668422b 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*:RelativeZTest.*" + "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*:RelativeZTest.*:SetGeometryTest.*" } } diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index c949d7c1a9..67faa57195 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -127,7 +127,6 @@ class DisplayTest : public ::testing::Test { public: class MockComposerClient : public FakeComposerClient { public: - MOCK_METHOD2(getDisplayType, Error(Display display, ComposerClient::DisplayType* outType)); MOCK_METHOD4(getDisplayAttribute, Error(Display display, Config config, IComposerClient::Attribute attribute, int32_t* outValue)); @@ -176,9 +175,6 @@ void DisplayTest::SetUp() { android::hardware::ProcessState::self()->startThreadPool(); android::ProcessState::self()->startThreadPool(); - EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _)) - .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL), - Return(Error::NONE))); // Primary display will be queried twice for all 5 attributes. One // set of queries comes from the SurfaceFlinger proper an the // other set from the VR composer. @@ -270,10 +266,6 @@ bool DisplayTest::waitForHotplugEvent(PhysicalDisplayId displayId, bool connecte TEST_F(DisplayTest, Hotplug) { ALOGD("DisplayTest::Hotplug"); - EXPECT_CALL(*mMockComposer, getDisplayType(EXTERNAL_DISPLAY, _)) - .Times(2) - .WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL), - Return(Error::NONE))); // The attribute queries will get done twice. This is for defaults EXPECT_CALL(*mMockComposer, getDisplayAttribute(EXTERNAL_DISPLAY, 1, _, _)) .Times(2 * 3) @@ -381,10 +373,6 @@ TEST_F(DisplayTest, HotplugPrimaryDisplay) { mMockComposer->clearFrames(); - EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _)) - .Times(2) - .WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL), - Return(Error::NONE))); // The attribute queries will get done twice. This is for defaults EXPECT_CALL(*mMockComposer, getDisplayAttribute(PRIMARY_DISPLAY, 1, _, _)) .Times(2 * 3) diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 8d98af6298..2183d34866 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -52,11 +52,10 @@ cc_test { "RegionSamplingTest.cpp", "TimeStatsTest.cpp", "FrameTracerTest.cpp", + "TransactionApplicationTest.cpp", "mock/DisplayHardware/MockComposer.cpp", "mock/DisplayHardware/MockDisplay.cpp", "mock/DisplayHardware/MockPowerAdvisor.cpp", - "mock/gui/MockGraphicBufferConsumer.cpp", - "mock/gui/MockGraphicBufferProducer.cpp", "mock/MockDispSync.cpp", "mock/MockEventControlThread.cpp", "mock/MockEventThread.cpp", @@ -71,6 +70,7 @@ cc_test { "libgmock", "libcompositionengine", "libcompositionengine_mocks", + "libgui_mocks", "libperfetto_client_experimental", "librenderengine_mocks", "libtimestats", diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index b6fa2a6403..8aff096d5e 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -1039,6 +1039,26 @@ struct ForcedClientCompositionResultVariant : public CompositionResultBaseVarian static void setupCallExpectationsForDirtyFrame(CompositionTest*) {} }; +struct ForcedClientCompositionViaDebugOptionResultVariant : public CompositionResultBaseVariant { + static void setupLayerState(CompositionTest* test, sp<Layer>) { + test->mFlinger.mutableDebugDisableHWC() = true; + } + + template <typename Case> + static void setupCallExpectations(CompositionTest* test) { + Case::Display::setupNonEmptyFrameCompositionCallExpectations(test); + Case::Display::setupHwcForcedClientCompositionCallExpectations(test); + Case::Display::setupRECompositionCallExpectations(test); + Case::Display::template setupRELayerCompositionCallExpectations<Case>(test); + } + + template <typename Case> + static void setupCallExpectationsForDirtyGeometry(CompositionTest*) {} + + template <typename Case> + static void setupCallExpectationsForDirtyFrame(CompositionTest*) {} +}; + struct EmptyScreenshotResultVariant { static void setupLayerState(CompositionTest*, sp<Layer>) {} @@ -1350,5 +1370,23 @@ TEST_F(CompositionTest, captureScreenNormalBufferLayerOnPoweredOffDisplay) { NoCompositionTypeVariant, REScreenshotResultVariant>>(); } +/* ------------------------------------------------------------------------ + * Client composition forced through debug/developer settings + */ + +TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirtyGeometry) { + displayRefreshCompositionDirtyGeometry< + CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>, + KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>, + ForcedClientCompositionViaDebugOptionResultVariant>>(); +} + +TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirtyFrame) { + displayRefreshCompositionDirtyFrame< + CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>, + KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>, + ForcedClientCompositionViaDebugOptionResultVariant>>(); +} + } // namespace } // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index fcce57b382..b1a4951451 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -24,6 +24,8 @@ #include <compositionengine/mock/DisplaySurface.h> #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <gui/mock/GraphicBufferConsumer.h> +#include <gui/mock/GraphicBufferProducer.h> #include <log/log.h> #include <renderengine/mock/RenderEngine.h> #include <ui/DebugUtils.h> @@ -38,8 +40,6 @@ #include "mock/MockMessageQueue.h" #include "mock/MockNativeWindowSurface.h" #include "mock/MockSurfaceInterceptor.h" -#include "mock/gui/MockGraphicBufferConsumer.h" -#include "mock/gui/MockGraphicBufferProducer.h" #include "mock/system/window/MockNativeWindow.h" namespace android { @@ -445,10 +445,6 @@ struct HwcDisplayVariant { } static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getDisplayType(HWC_DISPLAY_ID, _)) - .WillOnce(DoAll(SetArgPointee<1>(static_cast<IComposerClient::DisplayType>( - HWC_DISPLAY_TYPE)), - Return(Error::NONE))); EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE)); EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _)) .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{HWC_ACTIVE_CONFIG_ID}), diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index b77f82a7f8..b85c1b622e 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -35,7 +35,7 @@ #include "Scheduler/RefreshRateConfigs.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" -#include "SurfaceFlingerFactory.h" +#include "SurfaceFlingerDefaultFactory.h" #include "SurfaceInterceptor.h" #include "TestableScheduler.h" @@ -232,6 +232,8 @@ public: auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mCurrentState; } auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mDrawingState; } + auto& mutableStateLock() { return mFlinger->mStateLock; } + void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) { layer->mDrawingState.sidebandStream = sidebandStream; layer->mSidebandStream = sidebandStream; @@ -320,6 +322,22 @@ public: return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries); } + auto& getTransactionQueue() { return mFlinger->mTransactionQueues; } + + auto setTransactionState(const Vector<ComposerState>& states, + const Vector<DisplayState>& displays, uint32_t flags, + const sp<IBinder>& applyToken, + const InputWindowCommands& inputWindowCommands, + int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, + bool hasListenerCallbacks, + std::vector<ListenerCallbacks>& listenerCallbacks) { + return mFlinger->setTransactionState(states, displays, flags, applyToken, + inputWindowCommands, desiredPresentTime, uncacheBuffer, + hasListenerCallbacks, listenerCallbacks); + } + + auto flushTransactionQueues() { return mFlinger->flushTransactionQueues(); }; + /* ------------------------------------------------------------------------ * Read-only access to private data to assert post-conditions. */ @@ -356,6 +374,7 @@ public: auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; } auto& mutablePowerAdvisor() { return mFlinger->mPowerAdvisor; } + auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; } auto& mutableComposerSequenceId() { return mFlinger->getBE().mComposerSequenceId; } auto& mutableHwcDisplayData() { return getHwComposer().mDisplayData; } diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp new file mode 100644 index 0000000000..a465388e8d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -0,0 +1,318 @@ +/* + * 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. + */ + +#undef LOG_TAG +#define LOG_TAG "CompositionTest" + +#include <compositionengine/Display.h> +#include <compositionengine/mock/DisplaySurface.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <gui/SurfaceComposerClient.h> +#include <log/log.h> +#include <utils/String8.h> + +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/MockDispSync.h" +#include "mock/MockEventControlThread.h" +#include "mock/MockEventThread.h" +#include "mock/MockMessageQueue.h" + +namespace android { + +using testing::_; +using testing::Return; + +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; + +class TransactionApplicationTest : public testing::Test { +public: + TransactionApplicationTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + mFlinger.mutableEventQueue().reset(mMessageQueue); + setupScheduler(); + } + + ~TransactionApplicationTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); + } + + void setupScheduler() { + auto eventThread = std::make_unique<mock::EventThread>(); + auto sfEventThread = std::make_unique<mock::EventThread>(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return( + new EventThreadConnection(eventThread.get(), ResyncCallback(), + ISurfaceComposer::eConfigChangedSuppress))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return( + new EventThreadConnection(sfEventThread.get(), ResyncCallback(), + ISurfaceComposer::eConfigChangedSuppress))); + + EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0)); + EXPECT_CALL(*mPrimaryDispSync, getPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE)); + + mFlinger.setupScheduler(std::unique_ptr<mock::DispSync>(mPrimaryDispSync), + std::make_unique<mock::EventControlThread>(), + std::move(eventThread), std::move(sfEventThread)); + } + + TestableScheduler* mScheduler; + TestableSurfaceFlinger mFlinger; + + std::unique_ptr<mock::EventThread> mEventThread = std::make_unique<mock::EventThread>(); + mock::EventControlThread* mEventControlThread = new mock::EventControlThread(); + + mock::MessageQueue* mMessageQueue = new mock::MessageQueue(); + mock::DispSync* mPrimaryDispSync = new mock::DispSync(); + + struct TransactionInfo { + Vector<ComposerState> states; + Vector<DisplayState> displays; + uint32_t flags = 0; + sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + InputWindowCommands inputWindowCommands; + int64_t desiredPresentTime = -1; + client_cache_t uncacheBuffer; + }; + + void checkEqual(TransactionInfo info, SurfaceFlinger::TransactionState state) { + EXPECT_EQ(0, info.states.size()); + EXPECT_EQ(0, state.states.size()); + + EXPECT_EQ(0, info.displays.size()); + EXPECT_EQ(0, state.displays.size()); + EXPECT_EQ(info.flags, state.flags); + EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime); + } + + void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows, + int64_t desiredPresentTime) { + mTransactionNumber++; + transaction.flags |= flags; // ISurfaceComposer::eSynchronous; + transaction.inputWindowCommands.syncInputWindows = syncInputWindows; + transaction.desiredPresentTime = desiredPresentTime; + } + + void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) { + ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + // called in SurfaceFlinger::signalTransaction + EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()).WillOnce(Return(systemTime())); + TransactionInfo transaction; + setupSingle(transaction, flags, syncInputWindows, + /*desiredPresentTime*/ -1); + nsecs_t applicationTime = systemTime(); + mFlinger.setTransactionState(transaction.states, transaction.displays, transaction.flags, + transaction.applyToken, transaction.inputWindowCommands, + transaction.desiredPresentTime, transaction.uncacheBuffer, + mHasListenerCallbacks, mCallbacks); + + // This transaction should not have been placed on the transaction queue. + // If transaction is synchronous or syncs input windows, SF + // applyTransactionState should time out (5s) wating for SF to commit + // the transaction or to receive a signal that syncInputWindows has + // completed. If this is animation, it should not time out waiting. + nsecs_t returnedTime = systemTime(); + if (flags & ISurfaceComposer::eSynchronous || syncInputWindows) { + EXPECT_GE(returnedTime, applicationTime + s2ns(5)); + } else { + EXPECT_LE(returnedTime, applicationTime + s2ns(5)); + } + auto transactionQueue = mFlinger.getTransactionQueue(); + EXPECT_EQ(0, transactionQueue.size()); + } + + void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) { + ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + // called in SurfaceFlinger::signalTransaction + EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + + // first check will see desired present time has not passed, + // but afterwards it will look like the desired present time has passed + nsecs_t time = systemTime(); + EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()) + .WillOnce(Return(time + nsecs_t(5 * 1e8))); + TransactionInfo transaction; + setupSingle(transaction, flags, syncInputWindows, + /*desiredPresentTime*/ time + s2ns(1)); + nsecs_t applicationSentTime = systemTime(); + mFlinger.setTransactionState(transaction.states, transaction.displays, transaction.flags, + transaction.applyToken, transaction.inputWindowCommands, + transaction.desiredPresentTime, transaction.uncacheBuffer, + mHasListenerCallbacks, mCallbacks); + + nsecs_t returnedTime = systemTime(); + EXPECT_LE(returnedTime, applicationSentTime + s2ns(5)); + // This transaction should have been placed on the transaction queue + auto transactionQueue = mFlinger.getTransactionQueue(); + EXPECT_EQ(1, transactionQueue.size()); + } + + void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) { + ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + // called in SurfaceFlinger::signalTransaction + nsecs_t time = systemTime(); + EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()) + .WillOnce(Return(time + nsecs_t(5 * 1e8))); + // transaction that should go on the pending thread + TransactionInfo transactionA; + setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, + /*desiredPresentTime*/ time + s2ns(1)); + + // transaction that would not have gone on the pending thread if not + // blocked + TransactionInfo transactionB; + setupSingle(transactionB, flags, syncInputWindows, + /*desiredPresentTime*/ -1); + + nsecs_t applicationSentTime = systemTime(); + mFlinger.setTransactionState(transactionA.states, transactionA.displays, transactionA.flags, + transactionA.applyToken, transactionA.inputWindowCommands, + transactionA.desiredPresentTime, transactionA.uncacheBuffer, + mHasListenerCallbacks, mCallbacks); + + // This thread should not have been blocked by the above transaction + // (5s is the timeout period that applyTransactionState waits for SF to + // commit the transaction) + EXPECT_LE(systemTime(), applicationSentTime + s2ns(5)); + + applicationSentTime = systemTime(); + mFlinger.setTransactionState(transactionB.states, transactionB.displays, transactionB.flags, + transactionB.applyToken, transactionB.inputWindowCommands, + transactionB.desiredPresentTime, transactionB.uncacheBuffer, + mHasListenerCallbacks, mCallbacks); + + // this thread should have been blocked by the above transaction + // if this is an animation, this thread should be blocked for 5s + // in setTransactionState waiting for transactionA to flush. Otherwise, + // the transaction should be placed on the pending queue + if (flags & ISurfaceComposer::eAnimation) { + EXPECT_GE(systemTime(), applicationSentTime + s2ns(5)); + } else { + EXPECT_LE(systemTime(), applicationSentTime + s2ns(5)); + } + + // check that there is one binder on the pending queue. + auto transactionQueue = mFlinger.getTransactionQueue(); + EXPECT_EQ(1, transactionQueue.size()); + + auto& [applyToken, transactionStates] = *(transactionQueue.begin()); + EXPECT_EQ(2, transactionStates.size()); + + auto& transactionStateA = transactionStates.front(); + transactionStates.pop(); + checkEqual(transactionA, transactionStateA); + auto& transactionStateB = transactionStates.front(); + checkEqual(transactionB, transactionStateB); + } + + bool mHasListenerCallbacks = false; + std::vector<ListenerCallbacks> mCallbacks; + int mTransactionNumber = 0; +}; + +TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { + ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + // called in SurfaceFlinger::signalTransaction + EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + + // nsecs_t time = systemTime(); + EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()) + .WillOnce(Return(nsecs_t(5 * 1e8))) + .WillOnce(Return(s2ns(2))); + TransactionInfo transactionA; // transaction to go on pending queue + setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, + /*desiredPresentTime*/ s2ns(1)); + mFlinger.setTransactionState(transactionA.states, transactionA.displays, transactionA.flags, + transactionA.applyToken, transactionA.inputWindowCommands, + transactionA.desiredPresentTime, transactionA.uncacheBuffer, + mHasListenerCallbacks, mCallbacks); + + auto& transactionQueue = mFlinger.getTransactionQueue(); + ASSERT_EQ(1, transactionQueue.size()); + + auto& [applyToken, transactionStates] = *(transactionQueue.begin()); + ASSERT_EQ(1, transactionStates.size()); + + auto& transactionState = transactionStates.front(); + checkEqual(transactionA, transactionState); + + // because flushing uses the cached expected present time, we send an empty + // transaction here (sending a null applyToken to fake it as from a + // different process) to re-query and reset the cached expected present time + TransactionInfo empty; + empty.applyToken = sp<IBinder>(); + mFlinger.setTransactionState(empty.states, empty.displays, empty.flags, empty.applyToken, + empty.inputWindowCommands, empty.desiredPresentTime, + empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks); + + // flush transaction queue should flush as desiredPresentTime has + // passed + mFlinger.flushTransactionQueues(); + + EXPECT_EQ(0, transactionQueue.size()); +} + +TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Synchronous) { + NotPlacedOnTransactionQueue(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false); +} + +TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Animation) { + NotPlacedOnTransactionQueue(ISurfaceComposer::eAnimation, /*syncInputWindows*/ false); +} + +TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_SyncInputWindows) { + NotPlacedOnTransactionQueue(/*flags*/ 0, /*syncInputWindows*/ true); +} + +TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_Synchronous) { + PlaceOnTransactionQueue(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false); +} + +TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_Animation) { + PlaceOnTransactionQueue(ISurfaceComposer::eAnimation, /*syncInputWindows*/ false); +} + +TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_SyncInputWindows) { + PlaceOnTransactionQueue(/*flags*/ 0, /*syncInputWindows*/ true); +} + +TEST_F(TransactionApplicationTest, BlockWithPriorTransaction_Synchronous) { + BlockedByPriorTransaction(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false); +} + +TEST_F(TransactionApplicationTest, BlockWithPriorTransaction_Animation) { + BlockedByPriorTransaction(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false); +} + +TEST_F(TransactionApplicationTest, BlockWithPriorTransaction_SyncInputWindows) { + BlockedByPriorTransaction(/*flags*/ 0, /*syncInputWindows*/ true); +} + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 3c7e1da334..98c6aa0236 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -41,7 +41,7 @@ using android::hardware::graphics::composer::V2_1::Error; using android::hardware::graphics::composer::V2_1::IComposer; using android::hardware::graphics::composer::V2_1::IComposerCallback; using android::hardware::graphics::composer::V2_1::Layer; -using android::hardware::graphics::composer::V2_3::IComposerClient; +using android::hardware::graphics::composer::V2_4::IComposerClient; class Composer : public Hwc2::Composer { public: @@ -71,7 +71,6 @@ public: MOCK_METHOD2(getDisplayName, Error(Display, std::string*)); MOCK_METHOD4(getDisplayRequests, Error(Display, uint32_t*, std::vector<Layer>*, std::vector<uint32_t>*)); - MOCK_METHOD2(getDisplayType, Error(Display, IComposerClient::DisplayType*)); MOCK_METHOD2(getDozeSupport, Error(Display, bool*)); MOCK_METHOD5(getHdrCapabilities, Error(Display, std::vector<Hdr>*, float*, float*, float*)); MOCK_METHOD1(getPerFrameMetadataKeys, @@ -118,10 +117,11 @@ public: MOCK_METHOD4(setDisplayContentSamplingEnabled, Error(Display, bool, uint8_t, uint64_t)); MOCK_METHOD4(getDisplayedContentSample, Error(Display, uint64_t, uint64_t, DisplayedFrameStats*)); - MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*)); MOCK_METHOD3(setLayerPerFrameMetadataBlobs, Error(Display, Layer, const std::vector<IComposerClient::PerFrameMetadataBlob>&)); MOCK_METHOD2(setDisplayBrightness, Error(Display, float)); + MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*)); + MOCK_METHOD2(getDisplayConnectionType, Error(Display, IComposerClient::DisplayConnectionType*)); }; } // namespace mock |