diff options
30 files changed, 616 insertions, 215 deletions
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/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 4bea217930..a30df14bd6 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -54,6 +54,36 @@ static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_DEFAULT == IServiceManager: 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; @@ -64,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); } @@ -158,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/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index cd63a58bce..a675513793 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -26,10 +26,20 @@ 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.aidl */ 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/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/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/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/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index fa4539ab91..75fc0e9c06 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -673,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/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/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/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b9e95a6e46..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"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a9a4276592..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. 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/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index ee1f3aab94..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 { diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 926b8ac623..1cd1702f99 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.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. */ 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 |