diff options
261 files changed, 9592 insertions, 5787 deletions
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp index 423853175b..0616adda61 100644 --- a/cmds/cmd/cmd.cpp +++ b/cmds/cmd/cmd.cpp @@ -103,12 +103,12 @@ public: } if (is_selinux_enabled() && seLinuxContext.size() > 0) { String8 seLinuxContext8(seLinuxContext); - security_context_t tmp = NULL; + security_context_t tmp = nullptr; getfilecon(fullPath.string(), &tmp); Unique_SecurityContext context(tmp); if (checkWrite) { int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(), - "file", "write", NULL); + "file", "write", nullptr); if (accessGranted != 0) { #if DEBUG ALOGD("openFile: failed selinux write check!"); @@ -122,7 +122,7 @@ public: } if (checkRead) { int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(), - "file", "read", NULL); + "file", "read", nullptr); if (accessGranted != 0) { #if DEBUG ALOGD("openFile: failed selinux read check!"); @@ -174,7 +174,7 @@ int main(int argc, char* const argv[]) #endif sp<IServiceManager> sm = defaultServiceManager(); fflush(stdout); - if (sm == NULL) { + if (sm == nullptr) { ALOGW("Unable to get default service manager!"); aerr << "cmd: Unable to get default service manager!" << endl; return 20; @@ -192,7 +192,7 @@ int main(int argc, char* const argv[]) for (size_t i=0; i<services.size(); i++) { sp<IBinder> service = sm->checkService(services[i]); - if (service != NULL) { + if (service != nullptr) { aout << " " << services[i] << endl; } } @@ -205,7 +205,7 @@ int main(int argc, char* const argv[]) } String16 cmd = String16(argv[1]); sp<IBinder> service = sm->checkService(cmd); - if (service == NULL) { + if (service == nullptr) { ALOGW("Can't find service %s", argv[1]); aerr << "cmd: Can't find service: " << argv[1] << endl; return 20; diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp index 85eb464104..600a500e86 100644 --- a/cmds/dumpstate/DumpstateUtil.cpp +++ b/cmds/dumpstate/DumpstateUtil.cpp @@ -56,11 +56,11 @@ static bool waitpid_with_timeout(pid_t pid, int timeout_ms, int* status) { timespec ts; ts.tv_sec = MSEC_TO_SEC(timeout_ms); ts.tv_nsec = (timeout_ms % 1000) * 1000000; - int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts)); + int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, nullptr, &ts)); int saved_errno = errno; // Set the signals back the way they were. - if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) { + if (sigprocmask(SIG_SETMASK, &old_mask, nullptr) == -1) { printf("*** sigprocmask failed: %s\n", strerror(errno)); if (ret == 0) { return false; @@ -310,7 +310,7 @@ int RunCommandToFd(int fd, const std::string& title, const std::vector<std::stri struct sigaction sigact; memset(&sigact, 0, sizeof(sigact)); sigact.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &sigact, NULL); + sigaction(SIGPIPE, &sigact, nullptr); execvp(path, (char**)args.data()); // execvp's result will be handled after waitpid_with_timeout() below, but diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 30c5b6a6e6..2c248c664a 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1370,7 +1370,7 @@ static void dumpstate() { printf("== Running Application Services (platform)\n"); printf("========================================================\n"); - RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform"}, + RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"}, DUMPSYS_COMPONENTS_OPTIONS); printf("========================================================\n"); diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 8f60881bfe..3ada15398c 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -371,8 +371,8 @@ TEST_F(DumpsysTest, PassAllFlagsToNormalServices) { IServiceManager::DUMP_FLAG_PRIORITY_NORMAL); ExpectCheckService("Locksmith"); ExpectCheckService("Valet"); - ExpectDumpWithArgs("Locksmith", {"-a", "--dump-priority", "NORMAL"}, "dump1"); - ExpectDumpWithArgs("Valet", {"-a", "--dump-priority", "NORMAL"}, "dump2"); + ExpectDumpWithArgs("Locksmith", {"--dump-priority", "NORMAL", "-a"}, "dump1"); + ExpectDumpWithArgs("Valet", {"--dump-priority", "NORMAL", "-a"}, "dump2"); CallMain({"--priority", "NORMAL"}); diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp index 515f915b8b..e29ff4c248 100644 --- a/cmds/installd/CacheItem.cpp +++ b/cmds/installd/CacheItem.cpp @@ -73,7 +73,7 @@ int CacheItem::purge() { FTS *fts; FTSENT *p; char *argv[] = { (char*) path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { PLOG(WARNING) << "Failed to fts_open " << path; return -1; } diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp index ea0cd9e4e2..a7242c35cf 100644 --- a/cmds/installd/CacheTracker.cpp +++ b/cmds/installd/CacheTracker.cpp @@ -103,7 +103,7 @@ void CacheTracker::loadItemsFrom(const std::string& path) { FTS *fts; FTSENT *p; char *argv[] = { (char*) path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { PLOG(WARNING) << "Failed to fts_open " << path; return; } diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 860a68b273..9e32bc63c6 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -715,7 +715,7 @@ binder::Status InstalldNativeService::fixupAppData(const std::unique_ptr<std::st auto ce_path = create_data_user_ce_path(uuid_, user); auto de_path = create_data_user_de_path(uuid_, user); char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { return error("Failed to fts_open"); } while ((p = fts_read(fts)) != nullptr) { @@ -840,7 +840,7 @@ binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std: }; LOG(DEBUG) << "Copying " << from << " to " << to; - int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); + int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); goto fail; @@ -886,7 +886,7 @@ binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std: argv[7] = (char*) to.c_str(); LOG(DEBUG) << "Copying " << from << " to " << to; - int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); + int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); goto fail; @@ -899,7 +899,7 @@ binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std: argv[7] = (char*) to.c_str(); LOG(DEBUG) << "Copying " << from << " to " << to; - int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); + int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); goto fail; @@ -922,20 +922,20 @@ fail: // Nuke everything we might have already copied { auto to = create_data_app_package_path(to_uuid, data_app_name); - if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { + if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { LOG(WARNING) << "Failed to rollback " << to; } } for (auto user : users) { { auto to = create_data_user_de_package_path(to_uuid, user, package_name); - if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { + if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { LOG(WARNING) << "Failed to rollback " << to; } } { auto to = create_data_user_ce_package_path(to_uuid, user, package_name); - if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { + if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { LOG(WARNING) << "Failed to rollback " << to; } } @@ -1045,10 +1045,10 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin auto media_path = findDataMediaPath(uuid, user) + "/Android/data/"; char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), (char*) media_path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { return error("Failed to fts_open"); } - while ((p = fts_read(fts)) != NULL) { + while ((p = fts_read(fts)) != nullptr) { if (p->fts_info == FTS_D && p->fts_level == 1) { uid_t uid = p->fts_statp->st_uid; if (multiuser_get_app_id(uid) == AID_MEDIA_RW) { @@ -1398,11 +1398,11 @@ static void collectManualExternalStatsForUser(const std::string& path, struct st FTS *fts; FTSENT *p; char *argv[] = { (char*) path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { PLOG(ERROR) << "Failed to fts_open " << path; return; } - while ((p = fts_read(fts)) != NULL) { + while ((p = fts_read(fts)) != nullptr) { p->fts_number = p->fts_parent->fts_number; switch (p->fts_info) { case FTS_D: @@ -1808,10 +1808,10 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std: FTSENT *p; auto path = create_data_media_path(uuid_, userId); char *argv[] = { (char*) path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { return error("Failed to fts_open " + path); } - while ((p = fts_read(fts)) != NULL) { + while ((p = fts_read(fts)) != nullptr) { char* ext; int64_t size = (p->fts_statp->st_blocks * 512); switch (p->fts_info) { @@ -2040,7 +2040,7 @@ binder::Status InstalldNativeService::linkNativeLibraryDirectory( } } else { if (S_ISDIR(libStat.st_mode)) { - if (delete_dir_contents(libsymlink, 1, NULL) < 0) { + if (delete_dir_contents(libsymlink, 1, nullptr) < 0) { res = error("Failed to delete " + _libsymlink); goto out; } @@ -2082,14 +2082,14 @@ out: static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) { execl(kIdMapPath, kIdMapPath, "--fd", target_apk, overlay_apk, - StringPrintf("%d", idmap_fd).c_str(), (char*)NULL); + StringPrintf("%d", idmap_fd).c_str(), (char*)nullptr); PLOG(ERROR) << "execl (" << kIdMapPath << ") failed"; } static void run_verify_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) { execl(kIdMapPath, kIdMapPath, "--verify", target_apk, overlay_apk, - StringPrintf("%d", idmap_fd).c_str(), (char*)NULL); + StringPrintf("%d", idmap_fd).c_str(), (char*)nullptr); PLOG(ERROR) << "execl (" << kIdMapPath << ") failed"; } @@ -2140,7 +2140,7 @@ static bool delete_stale_idmap(const char* target_apk, const char* overlay_apk, static int flatten_path(const char *prefix, const char *suffix, const char *overlay_path, char *idmap_path, size_t N) { - if (overlay_path == NULL || idmap_path == NULL) { + if (overlay_path == nullptr || idmap_path == nullptr) { return -1; } const size_t len_overlay_path = strlen(overlay_path); @@ -2481,7 +2481,7 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa std::to_string(shmSize)); } auto data = std::unique_ptr<void, std::function<void (void *)>>( - mmap(NULL, contentSize, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0), + mmap(nullptr, contentSize, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0), [contentSize] (void* ptr) { if (ptr != MAP_FAILED) { munmap(ptr, contentSize); diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index 0fd2dd4afd..0e78e3a875 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -190,9 +190,9 @@ static int split_count(const char *str) strlcpy(buf, str, sizeof(buf)); char *pBuf = buf; - while(strtok_r(pBuf, " ", &ctx) != NULL) { + while(strtok_r(pBuf, " ", &ctx) != nullptr) { count++; - pBuf = NULL; + pBuf = nullptr; } return count; @@ -205,9 +205,9 @@ static int split(char *buf, const char **argv) char *tok; char *pBuf = buf; - while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) { + while((tok = strtok_r(pBuf, " ", &ctx)) != nullptr) { argv[count++] = tok; - pBuf = NULL; + pBuf = nullptr; } return count; @@ -216,7 +216,7 @@ static int split(char *buf, const char **argv) static const char* get_location_from_path(const char* path) { static constexpr char kLocationSeparator = '/'; const char *location = strrchr(path, kLocationSeparator); - if (location == NULL) { + if (location == nullptr) { return path; } else { // Skip the separator character. @@ -243,17 +243,17 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd const char* relative_input_file_name = get_location_from_path(input_file_name); char dex2oat_Xms_flag[kPropertyValueMax]; - bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0; + bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, nullptr) > 0; char dex2oat_Xmx_flag[kPropertyValueMax]; - bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0; + bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, nullptr) > 0; char dex2oat_threads_buf[kPropertyValueMax]; bool have_dex2oat_threads_flag = get_property(post_bootcomplete ? "dalvik.vm.dex2oat-threads" : "dalvik.vm.boot-dex2oat-threads", dex2oat_threads_buf, - NULL) > 0; + nullptr) > 0; char dex2oat_threads_arg[kPropertyValueMax + 2]; if (have_dex2oat_threads_flag) { sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf); @@ -263,20 +263,20 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set); char dex2oat_isa_features[kPropertyValueMax]; bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key, - dex2oat_isa_features, NULL) > 0; + dex2oat_isa_features, nullptr) > 0; char dex2oat_isa_variant_key[kPropertyKeyMax]; sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set); char dex2oat_isa_variant[kPropertyValueMax]; bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key, - dex2oat_isa_variant, NULL) > 0; + dex2oat_isa_variant, nullptr) > 0; const char *dex2oat_norelocation = "-Xnorelocate"; bool have_dex2oat_relocation_skip_flag = false; char dex2oat_flags[kPropertyValueMax]; int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags", - dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags); + dex2oat_flags, nullptr) <= 0 ? 0 : split_count(dex2oat_flags); ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags); // If we are booting without the real /data, don't spend time compiling. @@ -291,14 +291,14 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd char app_image_format[kPropertyValueMax]; char image_format_arg[strlen("--image-format=") + kPropertyValueMax]; bool have_app_image_format = - image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0; + image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, nullptr) > 0; if (have_app_image_format) { sprintf(image_format_arg, "--image-format=%s", app_image_format); } char dex2oat_large_app_threshold[kPropertyValueMax]; bool have_dex2oat_large_app_threshold = - get_property("dalvik.vm.dex2oat-very-large", dex2oat_large_app_threshold, NULL) > 0; + get_property("dalvik.vm.dex2oat-very-large", dex2oat_large_app_threshold, nullptr) > 0; char dex2oat_large_app_threshold_arg[strlen("--very-large-app-threshold=") + kPropertyValueMax]; if (have_dex2oat_large_app_threshold) { sprintf(dex2oat_large_app_threshold_arg, @@ -400,7 +400,7 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd if (!have_dex2oat_compiler_filter_flag) { char dex2oat_compiler_filter_flag[kPropertyValueMax]; have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter", - dex2oat_compiler_filter_flag, NULL) > 0; + dex2oat_compiler_filter_flag, nullptr) > 0; if (have_dex2oat_compiler_filter_flag) { sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", @@ -552,7 +552,7 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd argv[i++] = compilation_reason_arg.c_str(); } // Do not add after dex2oat_flags, they should override others for debugging. - argv[i] = NULL; + argv[i] = nullptr; execv(dex2oat_bin, (char * const *)argv); PLOG(ERROR) << "execv(" << dex2oat_bin << ") failed"; @@ -792,7 +792,7 @@ static void run_profman(const std::vector<unique_fd>& profile_fds, } // Do not add after dex2oat_flags, they should override others for debugging. - argv[i] = NULL; + argv[i] = nullptr; execv(profman_bin, (char * const *)argv); PLOG(ERROR) << "execv(" << profman_bin << ") failed"; @@ -948,7 +948,7 @@ static void run_profman_dump(const std::vector<unique_fd>& profile_fds, for (const std::string& profman_arg : profman_args) { argv[i++] = profman_arg.c_str(); } - argv[i] = NULL; + argv[i] = nullptr; execv(PROFMAN_BIN, (char * const *)argv); PLOG(ERROR) << "execv(" << PROFMAN_BIN << ") failed"; @@ -1308,7 +1308,7 @@ Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, } char app_image_format[kPropertyValueMax]; bool have_app_image_format = - get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0; + get_property("dalvik.vm.appimageformat", app_image_format, nullptr) > 0; if (!have_app_image_format) { return Dex2oatFileWrapper(); } @@ -1629,7 +1629,7 @@ static void exec_dexoptanalyzer(const std::string& dex_file, int vdex_fd, int oa if (class_loader_context != nullptr) { argv[i++] = class_loader_context_arg.c_str(); } - argv[i] = NULL; + argv[i] = nullptr; execv(dexoptanalyzer_bin, (char * const *)argv); ALOGE("execv(%s) failed: %s\n", dexoptanalyzer_bin, strerror(errno)); diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp index 95ed2fff35..673ff0d513 100644 --- a/cmds/installd/installd.cpp +++ b/cmds/installd/installd.cpp @@ -107,7 +107,7 @@ static int initialize_directories() { DIR *dir; struct dirent *dirent; dir = opendir("/data/user"); - if (dir != NULL) { + if (dir != nullptr) { while ((dirent = readdir(dir))) { const char *name = dirent->d_name; @@ -146,10 +146,10 @@ static int initialize_directories() { closedir(dir); if (access(keychain_added_dir, F_OK) == 0) { - delete_dir_contents(keychain_added_dir, 1, 0); + delete_dir_contents(keychain_added_dir, 1, nullptr); } if (access(keychain_removed_dir, F_OK) == 0) { - delete_dir_contents(keychain_removed_dir, 1, 0); + delete_dir_contents(keychain_removed_dir, 1, nullptr); } } diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 1ff45e4845..48f9eb4c89 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -310,7 +310,7 @@ std::vector<userid_t> get_known_users(const char* volume_uuid) { std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX); DIR* dir = opendir(path.c_str()); - if (dir == NULL) { + if (dir == nullptr) { // Unable to discover other users, but at least return owner PLOG(ERROR) << "Failed to opendir " << path; return users; @@ -340,13 +340,13 @@ int calculate_tree_size(const std::string& path, int64_t* size, FTSENT *p; int64_t matchedSize = 0; char *argv[] = { (char*) path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { if (errno != ENOENT) { PLOG(ERROR) << "Failed to fts_open " << path; } return -1; } - while ((p = fts_read(fts)) != NULL) { + while ((p = fts_read(fts)) != nullptr) { switch (p->fts_info) { case FTS_D: case FTS_DEFAULT: @@ -469,7 +469,7 @@ static int _delete_dir_contents(DIR *d, continue; } subdir = fdopendir(subfd); - if (subdir == NULL) { + if (subdir == nullptr) { ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); close(subfd); result = -1; @@ -495,11 +495,11 @@ static int _delete_dir_contents(DIR *d, } int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) { - return delete_dir_contents(pathname.c_str(), 0, NULL, ignore_if_missing); + return delete_dir_contents(pathname.c_str(), 0, nullptr, ignore_if_missing); } int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) { - return delete_dir_contents(pathname.c_str(), 1, NULL, ignore_if_missing); + return delete_dir_contents(pathname.c_str(), 1, nullptr, ignore_if_missing); } int delete_dir_contents(const char *pathname, @@ -511,7 +511,7 @@ int delete_dir_contents(const char *pathname, DIR *d; d = opendir(pathname); - if (d == NULL) { + if (d == nullptr) { if (ignore_if_missing && (errno == ENOENT)) { return 0; } @@ -540,12 +540,12 @@ int delete_dir_contents_fd(int dfd, const char *name) return -1; } d = fdopendir(fd); - if (d == NULL) { + if (d == nullptr) { ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); close(fd); return -1; } - res = _delete_dir_contents(d, 0); + res = _delete_dir_contents(d, nullptr); closedir(d); return res; } @@ -573,7 +573,7 @@ static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group) } DIR *ds = fdopendir(sdfd); - if (ds == NULL) { + if (ds == nullptr) { ALOGE("Couldn't fdopendir: %s\n", strerror(errno)); return -1; } @@ -619,18 +619,18 @@ int copy_dir_files(const char *srcname, uid_t group) { int res = 0; - DIR *ds = NULL; - DIR *dd = NULL; + DIR *ds = nullptr; + DIR *dd = nullptr; ds = opendir(srcname); - if (ds == NULL) { + if (ds == nullptr) { ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno)); return -errno; } mkdir(dstname, 0600); dd = opendir(dstname); - if (dd == NULL) { + if (dd == nullptr) { ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno)); closedir(ds); return -errno; @@ -964,11 +964,11 @@ int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t ta FTS *fts; FTSENT *p; char *argv[] = { (char*) path.c_str(), nullptr }; - if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) { PLOG(ERROR) << "Failed to fts_open " << path; return -1; } - while ((p = fts_read(fts)) != NULL) { + while ((p = fts_read(fts)) != nullptr) { switch (p->fts_info) { case FTS_DP: if (chmod(p->fts_path, target_mode) != 0) { @@ -1037,7 +1037,7 @@ static bool collect_profiles(DIR* d, } DIR* subdir = fdopendir(subdir_fd); - if (subdir == NULL) { + if (subdir == nullptr) { PLOG(WARNING) << "Could not open dir path " << local_path; result = false; continue; @@ -1055,7 +1055,7 @@ static bool collect_profiles(DIR* d, bool collect_profiles(std::vector<std::string>* profiles_paths) { DIR* d = opendir(android_profiles_dir.c_str()); - if (d == NULL) { + if (d == nullptr) { return false; } else { return collect_profiles(d, android_profiles_dir, profiles_paths); diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 4140f40888..d9ff4ba59f 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -489,7 +489,7 @@ void Replayer::setCrop(SurfaceComposerClient::Transaction& t, Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(), cc.rectangle().bottom()); - t.setCrop(mLayers[id], r); + t.setCrop_legacy(mLayers[id], r); } void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, @@ -499,7 +499,7 @@ void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, fcc.rectangle().bottom()); Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), fcc.rectangle().bottom()); - t.setFinalCrop(mLayers[id], r); + t.setFinalCrop_legacy(mLayers[id], r); } void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, @@ -570,7 +570,7 @@ void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t, auto handle = mLayers[dtc.layer_id()]->getHandle(); - t.deferTransactionUntil(mLayers[id], handle, dtc.frame_number()); + t.deferTransactionUntil_legacy(mLayers[id], handle, dtc.frame_number()); } void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t, diff --git a/data/etc/android.hardware.face.xml b/data/etc/android.hardware.face.xml new file mode 100644 index 0000000000..abd23fb1c4 --- /dev/null +++ b/data/etc/android.hardware.face.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<!-- This is the standard set of features for a biometric face authentication sensor. --> +<permissions> + <feature name="android.hardware.face" /> +</permissions> diff --git a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h index b32c92eb88..67abc68d39 100644 --- a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h +++ b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h @@ -17,7 +17,7 @@ #ifndef ANDROID_IARC_VIDEO_BRIDGE_H #define ANDROID_IARC_VIDEO_BRIDGE_H -#include <arc/IArcBridgeService.h> +#include <arc/MojoBootstrapResult.h> #include <binder/IInterface.h> #include <utils/Errors.h> diff --git a/include/android/input.h b/include/android/input.h index 681090188f..cfade6c806 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -83,7 +83,7 @@ enum { }; /** - * Meta key / modifer state. + * Meta key / modifier state. */ enum { /** No meta keys are pressed. */ diff --git a/include/input/Input.h b/include/input/Input.h index cfcafabebf..7c4379eda1 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -302,12 +302,18 @@ public: inline void setSource(int32_t source) { mSource = source; } + inline int32_t getDisplayId() const { return mDisplayId; } + + inline void setDisplayId(int32_t displayId) { mDisplayId = displayId; } + + protected: - void initialize(int32_t deviceId, int32_t source); + void initialize(int32_t deviceId, int32_t source, int32_t displayId); void initialize(const InputEvent& from); int32_t mDeviceId; int32_t mSource; + int32_t mDisplayId; }; /* @@ -339,10 +345,11 @@ public: static const char* getLabel(int32_t keyCode); static int32_t getKeyCodeFromLabel(const char* label); - + void initialize( int32_t deviceId, int32_t source, + int32_t displayId, int32_t action, int32_t flags, int32_t keyCode, @@ -556,6 +563,7 @@ public: void initialize( int32_t deviceId, int32_t source, + int32_t displayId, int32_t action, int32_t actionButton, int32_t flags, diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h index 4b33a96adf..6d072a3ea5 100644 --- a/include/input/InputEventLabels.h +++ b/include/input/InputEventLabels.h @@ -326,7 +326,7 @@ static const InputEventLabel KEYCODES[] = { DEFINE_KEYCODE(ALL_APPS), DEFINE_KEYCODE(REFRESH), - { NULL, 0 } + { nullptr, 0 } }; static const InputEventLabel AXES[] = { @@ -375,7 +375,7 @@ static const InputEventLabel AXES[] = { // NOTE: If you add a new axis here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. - { NULL, 0 } + { nullptr, 0 } }; static const InputEventLabel LEDS[] = { @@ -396,7 +396,7 @@ static const InputEventLabel LEDS[] = { DEFINE_LED(CONTROLLER_4), // NOTE: If you add new LEDs here, you must also add them to Input.h - { NULL, 0 } + { nullptr, 0 } }; static const InputEventLabel FLAGS[] = { @@ -404,7 +404,7 @@ static const InputEventLabel FLAGS[] = { DEFINE_FLAG(FUNCTION), DEFINE_FLAG(GESTURE), - { NULL, 0 } + { nullptr, 0 } }; static int lookupValueByLabel(const char* literal, const InputEventLabel *list) { @@ -424,7 +424,7 @@ static const char* lookupLabelByValue(int value, const InputEventLabel* list) { } list++; } - return NULL; + return nullptr; } static inline int32_t getKeyCodeByLabel(const char* label) { @@ -435,7 +435,7 @@ static inline const char* getLabelByKeyCode(int32_t keyCode) { if (keyCode >= 0 && keyCode < static_cast<int32_t>(size(KEYCODES))) { return KEYCODES[keyCode].literal; } - return NULL; + return nullptr; } static inline uint32_t getKeyFlagByLabel(const char* label) { diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 1ea2c2cc07..e8d1345096 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -212,6 +212,7 @@ public: uint32_t seq, int32_t deviceId, int32_t source, + int32_t displayId, int32_t action, int32_t flags, int32_t keyCode, @@ -305,7 +306,7 @@ public: * Other errors probably indicate that the channel is broken. */ status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId); + nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent); /* Sends a finished signal to the publisher to inform it that the message * with the specified sequence number has finished being process and whether @@ -460,10 +461,9 @@ private: Vector<SeqChain> mSeqChains; status_t consumeBatch(InputEventFactoryInterface* factory, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId); + nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent); status_t consumeSamples(InputEventFactoryInterface* factory, - Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent, - int32_t* displayId); + Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent); void updateTouchState(InputMessage& msg); void resampleTouchState(nsecs_t frameTime, MotionEvent* event, diff --git a/include/input/VelocityTracker.h b/include/input/VelocityTracker.h index ffa1614b55..727865a933 100644 --- a/include/input/VelocityTracker.h +++ b/include/input/VelocityTracker.h @@ -63,7 +63,7 @@ public: // Creates a velocity tracker using the specified strategy. // If strategy is NULL, uses the default strategy for the platform. - VelocityTracker(const char* strategy = NULL); + VelocityTracker(const char* strategy = nullptr); ~VelocityTracker(); diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 6a30956463..786b136a79 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -107,6 +107,7 @@ cc_library_shared { "-Wall", "-Wextra", "-Werror", + "-Wzero-as-null-pointer-constant", ], product_variables: { binder32bit: { diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index b3ae09b405..87c9842de9 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -74,7 +74,7 @@ static size_t pad_size(size_t s) { } // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER -#define STRICT_MODE_PENALTY_GATHER (0x40 << 16) +#define STRICT_MODE_PENALTY_GATHER (1 << 31) // XXX This can be made public if we want to provide // support for typed data. @@ -2307,6 +2307,15 @@ status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const int fd = readFileDescriptor(); if (fd == int(BAD_TYPE)) return BAD_VALUE; + if (!ashmem_valid(fd)) { + ALOGE("invalid fd"); + return BAD_VALUE; + } + int size = ashmem_get_size_region(fd); + if (size < 0 || size_t(size) < len) { + ALOGE("request size %zu does not match fd size %d", len, size); + return BAD_VALUE; + } void* ptr = ::mmap(nullptr, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) return NO_MEMORY; diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h index c5b57c7edf..7870c7b19e 100644 --- a/libs/binder/include/binder/AppOpsManager.h +++ b/libs/binder/include/binder/AppOpsManager.h @@ -95,6 +95,20 @@ public: OP_USE_FINGERPRINT = 55, OP_BODY_SENSORS = 56, OP_AUDIO_ACCESSIBILITY_VOLUME = 64, + OP_READ_PHONE_NUMBERS = 65, + OP_REQUEST_INSTALL_PACKAGES = 66, + OP_PICTURE_IN_PICTURE = 67, + OP_INSTANT_APP_START_FOREGROUND = 68, + OP_ANSWER_PHONE_CALLS = 69, + OP_RUN_ANY_IN_BACKGROUND = 70, + OP_CHANGE_WIFI_STATE = 71, + OP_REQUEST_DELETE_PACKAGES = 72, + OP_BIND_ACCESSIBILITY_SERVICE = 73, + OP_ACCEPT_HANDOVER = 74, + OP_MANAGE_IPSEC_TUNNELS = 75, + OP_START_FOREGROUND = 76, + OP_BLUETOOTH_SCAN = 77, + OP_USE_FACE = 78, }; AppOpsManager(); diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index a998529cd8..1d39aa309d 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -86,7 +86,7 @@ status_t getService(const String16& name, sp<INTERFACE>* outService) const sp<IServiceManager> sm = defaultServiceManager(); if (sm != nullptr) { *outService = interface_cast<INTERFACE>(sm->getService(name)); - if ((*outService) != NULL) return NO_ERROR; + if ((*outService) != nullptr) return NO_ERROR; } return NAME_NOT_FOUND; } diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp index 961f1011e0..a8ef7a051d 100644 --- a/libs/graphicsenv/GraphicsEnv.cpp +++ b/libs/graphicsenv/GraphicsEnv.cpp @@ -56,7 +56,7 @@ void GraphicsEnv::setDriverPath(const std::string path) { mDriverPath = path; } -void GraphicsEnv::setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths) { +void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) { if (mLayerPaths.empty()) { mLayerPaths = layerPaths; mAppNamespace = appNamespace; @@ -66,7 +66,7 @@ void GraphicsEnv::setLayerPaths(android_namespace_t* appNamespace, const std::st } } -android_namespace_t* GraphicsEnv::getAppNamespace() { +NativeLoaderNamespace* GraphicsEnv::getAppNamespace() { return mAppNamespace; } diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h index 213580c20b..17e8f6ba47 100644 --- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h +++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h @@ -23,6 +23,8 @@ struct android_namespace_t; namespace android { +class NativeLoaderNamespace; + class GraphicsEnv { public: static GraphicsEnv& getInstance(); @@ -35,8 +37,8 @@ public: void setDriverPath(const std::string path); android_namespace_t* getDriverNamespace(); - void setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths); - android_namespace_t* getAppNamespace(); + void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths); + NativeLoaderNamespace* getAppNamespace(); const std::string getLayerPaths(); void setDebugLayers(const std::string layers); @@ -48,7 +50,7 @@ private: std::string mDebugLayers; std::string mLayerPaths; android_namespace_t* mDriverNamespace = nullptr; - android_namespace_t* mAppNamespace = nullptr; + NativeLoaderNamespace* mAppNamespace = nullptr; }; } // namespace android diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index b29c1d5157..ef3e592c09 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -123,6 +123,7 @@ cc_library_shared { "android.hardware.graphics.common@1.1", "libsync", "libbinder", + "libbufferhub", "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui. "libpdx_default_transport", "libcutils", @@ -149,6 +150,7 @@ cc_library_shared { "BufferHubProducer.cpp", ], exclude_shared_libs: [ + "libbufferhub", "libbufferhubqueue", "libpdx_default_transport", ], diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp index ae5cca2d20..06d597ccfa 100644 --- a/libs/gui/BufferHubProducer.cpp +++ b/libs/gui/BufferHubProducer.cpp @@ -18,7 +18,9 @@ #include <gui/BufferHubProducer.h> #include <inttypes.h> #include <log/log.h> +#include <private/dvr/detached_buffer.h> #include <system/window.h> +#include <ui/DetachedBufferHandle.h> namespace android { @@ -224,24 +226,224 @@ status_t BufferHubProducer::dequeueBuffer(int* out_slot, sp<Fence>* out_fence, u return ret; } -status_t BufferHubProducer::detachBuffer(int /* slot */) { - ALOGE("BufferHubProducer::detachBuffer not implemented."); - return INVALID_OPERATION; +status_t BufferHubProducer::detachBuffer(int slot) { + ALOGV("detachBuffer: slot=%d", slot); + std::unique_lock<std::mutex> lock(mutex_); + + return DetachBufferLocked(static_cast<size_t>(slot)); } -status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* /* out_buffer */, - sp<Fence>* /* out_fence */) { - ALOGE("BufferHubProducer::detachNextBuffer not implemented."); - return INVALID_OPERATION; +status_t BufferHubProducer::DetachBufferLocked(size_t slot) { + if (connected_api_ == kNoConnectedApi) { + ALOGE("detachBuffer: BufferHubProducer is not connected."); + return NO_INIT; + } + + if (slot >= static_cast<size_t>(max_buffer_count_)) { + ALOGE("detachBuffer: slot index %zu out of range [0, %d)", slot, max_buffer_count_); + return BAD_VALUE; + } else if (!buffers_[slot].mBufferState.isDequeued()) { + ALOGE("detachBuffer: slot %zu is not owned by the producer (state = %s)", slot, + buffers_[slot].mBufferState.string()); + return BAD_VALUE; + } else if (!buffers_[slot].mRequestBufferCalled) { + ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot); + return BAD_VALUE; + } + std::shared_ptr<BufferProducer> buffer_producer = queue_->GetBuffer(slot); + if (buffer_producer == nullptr || buffer_producer->buffer() == nullptr) { + ALOGE("detachBuffer: Invalid BufferProducer at slot %zu.", slot); + return BAD_VALUE; + } + sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer(); + if (graphic_buffer == nullptr) { + ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot); + return BAD_VALUE; + } + + // Remove the BufferProducer from the ProducerQueue. + status_t error = RemoveBuffer(slot); + if (error != NO_ERROR) { + ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error); + return error; + } + + // Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject + // the handle into the GraphicBuffer object at the requested slot. + auto status_or_handle = buffer_producer->Detach(); + if (!status_or_handle.ok()) { + ALOGE("detachBuffer: Failed to detach from a BufferProducer at slot %zu, error=%d.", slot, + status_or_handle.error()); + return BAD_VALUE; + } + std::unique_ptr<DetachedBufferHandle> handle = + DetachedBufferHandle::Create(status_or_handle.take()); + if (!handle->isValid()) { + ALOGE("detachBuffer: Failed to create a DetachedBufferHandle at slot %zu.", slot); + return BAD_VALUE; + } + + return graphic_buffer->setDetachedBufferHandle(std::move(handle)); } -status_t BufferHubProducer::attachBuffer(int* /* out_slot */, - const sp<GraphicBuffer>& /* buffer */) { - // With this BufferHub backed implementation, we assume (for now) all buffers - // are allocated and owned by the BufferHub. Thus the attempt of transfering - // ownership of a buffer to the buffer queue is intentionally unsupported. - LOG_ALWAYS_FATAL("BufferHubProducer::attachBuffer not supported."); - return INVALID_OPERATION; +status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) { + ALOGV("detachNextBuffer."); + + if (out_buffer == nullptr || out_fence == nullptr) { + ALOGE("detachNextBuffer: Invalid parameter: out_buffer=%p, out_fence=%p", out_buffer, + out_fence); + return BAD_VALUE; + } + + std::unique_lock<std::mutex> lock(mutex_); + + if (connected_api_ == kNoConnectedApi) { + ALOGE("detachNextBuffer: BufferHubProducer is not connected."); + return NO_INIT; + } + + // detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer, and detachBuffer in + // sequence, except for two things: + // + // 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the + // function just returns whatever BufferProducer is available from the ProducerQueue and no + // buffer allocation or re-allocation will happen. + // 2) It will not block, since if it cannot find an appropriate buffer to return, it will return + // an error instead. + size_t slot = 0; + LocalHandle fence; + + // First, dequeue a BufferProducer from the ProducerQueue with no timeout. Report error + // immediately if ProducerQueue::Dequeue() fails. + auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence); + if (!status_or_buffer.ok()) { + ALOGE("detachNextBuffer: Failed to dequeue buffer, error=%d.", status_or_buffer.error()); + return NO_MEMORY; + } + + std::shared_ptr<BufferProducer> buffer_producer = status_or_buffer.take(); + if (buffer_producer == nullptr) { + ALOGE("detachNextBuffer: Dequeued buffer is null."); + return NO_MEMORY; + } + + // With the BufferHub backed solution, slot returned from |queue_->Dequeue| is guaranteed to + // be available for producer's use. It's either in free state (if the buffer has never been used + // before) or in queued state (if the buffer has been dequeued and queued back to + // BufferHubQueue). + if (!buffers_[slot].mBufferState.isFree() && !buffers_[slot].mBufferState.isQueued()) { + ALOGE("detachNextBuffer: slot %zu is not free or queued, actual state: %s.", slot, + buffers_[slot].mBufferState.string()); + return BAD_VALUE; + } + if (buffers_[slot].mBufferProducer == nullptr) { + ALOGE("detachNextBuffer: BufferProducer at slot %zu is null.", slot); + return BAD_VALUE; + } + if (buffers_[slot].mBufferProducer->id() != buffer_producer->id()) { + ALOGE("detachNextBuffer: BufferProducer at slot %zu has mismatched id, actual: " + "%d, expected: %d.", + slot, buffers_[slot].mBufferProducer->id(), buffer_producer->id()); + return BAD_VALUE; + } + + ALOGV("detachNextBuffer: slot=%zu", slot); + buffers_[slot].mBufferState.freeQueued(); + buffers_[slot].mBufferState.dequeue(); + + // Second, request the buffer. + sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer(); + buffers_[slot].mGraphicBuffer = buffer_producer->buffer()->buffer(); + + // Finally, detach the buffer and then return. + status_t error = DetachBufferLocked(slot); + if (error == NO_ERROR) { + *out_fence = new Fence(fence.Release()); + *out_buffer = graphic_buffer; + } + return error; +} + +status_t BufferHubProducer::attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) { + // In the BufferHub design, all buffers are allocated and owned by the BufferHub. Thus only + // GraphicBuffers that are originated from BufferHub can be attached to a BufferHubProducer. + ALOGV("queueBuffer: buffer=%p", buffer.get()); + + if (out_slot == nullptr) { + ALOGE("attachBuffer: out_slot cannot be NULL."); + return BAD_VALUE; + } + if (buffer == nullptr || !buffer->isDetachedBuffer()) { + ALOGE("attachBuffer: invalid GraphicBuffer."); + return BAD_VALUE; + } + + std::unique_lock<std::mutex> lock(mutex_); + + if (connected_api_ == kNoConnectedApi) { + ALOGE("attachBuffer: BufferQueue has no connected producer"); + return NO_INIT; + } + + // Before attaching the buffer, caller is supposed to call + // IGraphicBufferProducer::setGenerationNumber to inform the + // BufferHubProducer the next generation number. + if (buffer->getGenerationNumber() != generation_number_) { + ALOGE("attachBuffer: Mismatched generation number, buffer: %u, queue: %u.", + buffer->getGenerationNumber(), generation_number_); + return BAD_VALUE; + } + + // Creates a BufferProducer from the GraphicBuffer. + std::unique_ptr<DetachedBufferHandle> detached_handle = buffer->takeDetachedBufferHandle(); + if (detached_handle == nullptr) { + ALOGE("attachBuffer: DetachedBufferHandle cannot be NULL."); + return BAD_VALUE; + } + auto detached_buffer = DetachedBuffer::Import(std::move(detached_handle->handle())); + if (detached_buffer == nullptr) { + ALOGE("attachBuffer: DetachedBuffer cannot be NULL."); + return BAD_VALUE; + } + auto status_or_handle = detached_buffer->Promote(); + if (!status_or_handle.ok()) { + ALOGE("attachBuffer: Failed to promote a DetachedBuffer into a BufferProducer, error=%d.", + status_or_handle.error()); + return BAD_VALUE; + } + std::shared_ptr<BufferProducer> buffer_producer = + BufferProducer::Import(status_or_handle.take()); + if (buffer_producer == nullptr) { + ALOGE("attachBuffer: Failed to import BufferProducer."); + return BAD_VALUE; + } + + // Adds the BufferProducer into the Queue. + auto status_or_slot = queue_->InsertBuffer(buffer_producer); + if (!status_or_slot.ok()) { + ALOGE("attachBuffer: Failed to insert buffer, error=%d.", status_or_slot.error()); + return BAD_VALUE; + } + + size_t slot = status_or_slot.get(); + ALOGV("attachBuffer: returning slot %zu.", slot); + if (slot >= static_cast<size_t>(max_buffer_count_)) { + ALOGE("attachBuffer: Invalid slot: %zu.", slot); + return BAD_VALUE; + } + + // The just attached buffer should be in dequeued state according to IGraphicBufferProducer + // interface. In BufferHub's language the buffer should be in Gained state. + buffers_[slot].mGraphicBuffer = buffer; + buffers_[slot].mBufferState.attachProducer(); + buffers_[slot].mEglFence = EGL_NO_SYNC_KHR; + buffers_[slot].mFence = Fence::NO_FENCE; + buffers_[slot].mRequestBufferCalled = true; + buffers_[slot].mAcquireCalled = false; + buffers_[slot].mNeedsReallocation = false; + + *out_slot = static_cast<int>(slot); + return NO_ERROR; } status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input, @@ -654,26 +856,28 @@ status_t BufferHubProducer::AllocateBuffer(uint32_t width, uint32_t height, uint status_t BufferHubProducer::RemoveBuffer(size_t slot) { auto status = queue_->RemoveBuffer(slot); if (!status) { - ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer: %s", - status.GetErrorMessage().c_str()); + ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer at slot: %zu, error: %s.", + slot, status.GetErrorMessage().c_str()); return INVALID_OPERATION; } // Reset in memory objects related the the buffer. buffers_[slot].mBufferProducer = nullptr; - buffers_[slot].mGraphicBuffer = nullptr; buffers_[slot].mBufferState.detachProducer(); + buffers_[slot].mFence = Fence::NO_FENCE; + buffers_[slot].mGraphicBuffer = nullptr; + buffers_[slot].mRequestBufferCalled = false; return NO_ERROR; } status_t BufferHubProducer::FreeAllBuffers() { for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) { // Reset in memory objects related the the buffer. - buffers_[slot].mGraphicBuffer = nullptr; - buffers_[slot].mBufferState.reset(); - buffers_[slot].mRequestBufferCalled = false; buffers_[slot].mBufferProducer = nullptr; + buffers_[slot].mBufferState.reset(); buffers_[slot].mFence = Fence::NO_FENCE; + buffers_[slot].mGraphicBuffer = nullptr; + buffers_[slot].mRequestBufferCalled = false; } auto status = queue_->FreeAllBuffers(); diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp index f50379b3ed..5beba02e63 100644 --- a/libs/gui/BufferItem.cpp +++ b/libs/gui/BufferItem.cpp @@ -39,8 +39,8 @@ static inline constexpr T to64(const uint32_t lo, const uint32_t hi) { } BufferItem::BufferItem() : - mGraphicBuffer(NULL), - mFence(NULL), + mGraphicBuffer(nullptr), + mFence(nullptr), mCrop(Rect::INVALID_RECT), mTransform(0), mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), @@ -91,11 +91,11 @@ size_t BufferItem::getPodSize() const { size_t BufferItem::getFlattenedSize() const { size_t size = sizeof(uint32_t); // Flags - if (mGraphicBuffer != 0) { + if (mGraphicBuffer != nullptr) { size += mGraphicBuffer->getFlattenedSize(); size = FlattenableUtils::align<4>(size); } - if (mFence != 0) { + if (mFence != nullptr) { size += mFence->getFlattenedSize(); size = FlattenableUtils::align<4>(size); } @@ -107,10 +107,10 @@ size_t BufferItem::getFlattenedSize() const { size_t BufferItem::getFdCount() const { size_t count = 0; - if (mGraphicBuffer != 0) { + if (mGraphicBuffer != nullptr) { count += mGraphicBuffer->getFdCount(); } - if (mFence != 0) { + if (mFence != nullptr) { count += mFence->getFdCount(); } return count; @@ -137,13 +137,13 @@ status_t BufferItem::flatten( FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); flags = 0; - if (mGraphicBuffer != 0) { + if (mGraphicBuffer != nullptr) { status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); if (err) return err; size -= FlattenableUtils::align<4>(buffer); flags |= 1; } - if (mFence != 0) { + if (mFence != nullptr) { status_t err = mFence->flatten(buffer, size, fds, count); if (err) return err; size -= FlattenableUtils::align<4>(buffer); diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp index 89bc0c4c2d..f50bc203e8 100644 --- a/libs/gui/BufferItemConsumer.cpp +++ b/libs/gui/BufferItemConsumer.cpp @@ -107,7 +107,7 @@ status_t BufferItemConsumer::releaseBuffer(const BufferItem &item, void BufferItemConsumer::freeBufferLocked(int slotIndex) { sp<BufferFreedListener> listener = mBufferFreedListener.promote(); - if (listener != NULL && mSlots[slotIndex].mGraphicBuffer != NULL) { + if (listener != nullptr && mSlots[slotIndex].mGraphicBuffer != nullptr) { // Fire callback if we have a listener registered and the buffer being freed is valid. BI_LOGV("actually calling onBufferFreed"); listener->onBufferFreed(mSlots[slotIndex].mGraphicBuffer); diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index a8da1347cb..5fb3f0b80f 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -38,7 +38,7 @@ BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} void BufferQueue::ProxyConsumerListener::onDisconnect() { sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onDisconnect(); } } @@ -46,7 +46,7 @@ void BufferQueue::ProxyConsumerListener::onDisconnect() { void BufferQueue::ProxyConsumerListener::onFrameAvailable( const BufferItem& item) { sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onFrameAvailable(item); } } @@ -54,21 +54,21 @@ void BufferQueue::ProxyConsumerListener::onFrameAvailable( void BufferQueue::ProxyConsumerListener::onFrameReplaced( const BufferItem& item) { sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onFrameReplaced(item); } } void BufferQueue::ProxyConsumerListener::onBuffersReleased() { sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } } void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { + if (listener != nullptr) { listener->onSidebandStreamChanged(); } } @@ -85,21 +85,21 @@ void BufferQueue::ProxyConsumerListener::addAndGetFrameTimestamps( void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger) { - LOG_ALWAYS_FATAL_IF(outProducer == NULL, + LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BufferQueue: outProducer must not be NULL"); - LOG_ALWAYS_FATAL_IF(outConsumer == NULL, + LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BufferQueue: outConsumer must not be NULL"); sp<BufferQueueCore> core(new BufferQueueCore()); - LOG_ALWAYS_FATAL_IF(core == NULL, + LOG_ALWAYS_FATAL_IF(core == nullptr, "BufferQueue: failed to create BufferQueueCore"); sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger)); - LOG_ALWAYS_FATAL_IF(producer == NULL, + LOG_ALWAYS_FATAL_IF(producer == nullptr, "BufferQueue: failed to create BufferQueueProducer"); sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); - LOG_ALWAYS_FATAL_IF(consumer == NULL, + LOG_ALWAYS_FATAL_IF(consumer == nullptr, "BufferQueue: failed to create BufferQueueConsumer"); *outProducer = producer; @@ -109,8 +109,8 @@ void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, #ifndef NO_BUFFERHUB void BufferQueue::createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer) { - LOG_ALWAYS_FATAL_IF(outProducer == NULL, "BufferQueue: outProducer must not be NULL"); - LOG_ALWAYS_FATAL_IF(outConsumer == NULL, "BufferQueue: outConsumer must not be NULL"); + LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BufferQueue: outProducer must not be NULL"); + LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BufferQueue: outConsumer must not be NULL"); sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; @@ -118,16 +118,16 @@ void BufferQueue::createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer, dvr::ProducerQueueConfigBuilder configBuilder; std::shared_ptr<dvr::ProducerQueue> producerQueue = dvr::ProducerQueue::Create(configBuilder.Build(), dvr::UsagePolicy{}); - LOG_ALWAYS_FATAL_IF(producerQueue == NULL, "BufferQueue: failed to create ProducerQueue."); + LOG_ALWAYS_FATAL_IF(producerQueue == nullptr, "BufferQueue: failed to create ProducerQueue."); std::shared_ptr<dvr::ConsumerQueue> consumerQueue = producerQueue->CreateConsumerQueue(); - LOG_ALWAYS_FATAL_IF(consumerQueue == NULL, "BufferQueue: failed to create ConsumerQueue."); + LOG_ALWAYS_FATAL_IF(consumerQueue == nullptr, "BufferQueue: failed to create ConsumerQueue."); producer = BufferHubProducer::Create(producerQueue); consumer = BufferHubConsumer::Create(consumerQueue); - LOG_ALWAYS_FATAL_IF(producer == NULL, "BufferQueue: failed to create BufferQueueProducer"); - LOG_ALWAYS_FATAL_IF(consumer == NULL, "BufferQueue: failed to create BufferQueueConsumer"); + LOG_ALWAYS_FATAL_IF(producer == nullptr, "BufferQueue: failed to create BufferQueueProducer"); + LOG_ALWAYS_FATAL_IF(consumer == nullptr, "BufferQueue: failed to create BufferQueueConsumer"); *outProducer = producer; *outConsumer = consumer; diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index d70e1422b0..3837c3e11a 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -255,7 +255,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer // on the consumer side if (outBuffer->mAcquireCalled) { - outBuffer->mGraphicBuffer = NULL; + outBuffer->mGraphicBuffer = nullptr; } mCore->mQueue.erase(front); @@ -272,7 +272,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, VALIDATE_CONSISTENCY(); } - if (listener != NULL) { + if (listener != nullptr) { for (int i = 0; i < numDroppedBuffers; ++i) { listener->onBufferReleased(); } @@ -321,10 +321,10 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot, const sp<android::GraphicBuffer>& buffer) { ATRACE_CALL(); - if (outSlot == NULL) { + if (outSlot == nullptr) { BQ_LOGE("attachBuffer: outSlot must not be NULL"); return BAD_VALUE; - } else if (buffer == NULL) { + } else if (buffer == nullptr) { BQ_LOGE("attachBuffer: cannot attach NULL buffer"); return BAD_VALUE; } @@ -413,7 +413,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, ATRACE_BUFFER_INDEX(slot); if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS || - releaseFence == NULL) { + releaseFence == nullptr) { BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot, releaseFence.get()); return BAD_VALUE; @@ -465,7 +465,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBufferReleased(); } @@ -476,7 +476,7 @@ status_t BufferQueueConsumer::connect( const sp<IConsumerListener>& consumerListener, bool controlledByApp) { ATRACE_CALL(); - if (consumerListener == NULL) { + if (consumerListener == nullptr) { BQ_LOGE("connect: consumerListener may not be NULL"); return BAD_VALUE; } @@ -504,13 +504,13 @@ status_t BufferQueueConsumer::disconnect() { Mutex::Autolock lock(mCore->mMutex); - if (mCore->mConsumerListener == NULL) { + if (mCore->mConsumerListener == nullptr) { BQ_LOGE("disconnect: no consumer is connected"); return BAD_VALUE; } mCore->mIsAbandoned = true; - mCore->mConsumerListener = NULL; + mCore->mConsumerListener = nullptr; mCore->mQueue.clear(); mCore->freeAllBuffersLocked(); mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT; @@ -521,7 +521,7 @@ status_t BufferQueueConsumer::disconnect() { status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) { ATRACE_CALL(); - if (outSlotMask == NULL) { + if (outSlotMask == nullptr) { BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL"); return BAD_VALUE; } @@ -673,7 +673,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount( } } // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -772,7 +772,7 @@ status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResul if (uid != shellUid) { #endif android_errorWriteWithInfoLog(0x534e4554, "27046057", - static_cast<int32_t>(uid), NULL, 0); + static_cast<int32_t>(uid), nullptr, 0); return PERMISSION_DENIED; } diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index bb703da3dd..960b1948c2 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -349,7 +349,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer != NULL) { + if (mSlots[slot].mGraphicBuffer != nullptr) { BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer", slot); usleep(PAUSE_TIME); @@ -371,7 +371,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer != NULL) { + if (mSlots[slot].mGraphicBuffer != nullptr) { BQ_LOGE("Slot %d is in mFreeSlots but has a buffer", slot); usleep(PAUSE_TIME); @@ -394,7 +394,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer == NULL) { + if (mSlots[slot].mGraphicBuffer == nullptr) { BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot); usleep(PAUSE_TIME); } @@ -418,7 +418,7 @@ void BufferQueueCore::validateConsistencyLocked() const { BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot); usleep(PAUSE_TIME); } - if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) { + if (mSlots[slot].mGraphicBuffer == nullptr && !mIsAllocating) { BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot); usleep(PAUSE_TIME); } diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index c96a2dd6a3..5e250a4185 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -166,7 +166,7 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount( } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -221,7 +221,7 @@ status_t BufferQueueProducer::setAsyncMode(bool async) { } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } return NO_ERROR; @@ -449,11 +449,11 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou mSlots[found].mBufferState.dequeue(); - if ((buffer == NULL) || + if ((buffer == nullptr) || buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) { mSlots[found].mAcquireCalled = false; - mSlots[found].mGraphicBuffer = NULL; + mSlots[found].mGraphicBuffer = nullptr; mSlots[found].mRequestBufferCalled = false; mSlots[found].mEglDisplay = EGL_NO_DISPLAY; mSlots[found].mEglFence = EGL_NO_SYNC_KHR; @@ -471,7 +471,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64, mCore->mBufferAge); - if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { + if (CC_UNLIKELY(mSlots[found].mFence == nullptr)) { BQ_LOGE("dequeueBuffer: about to return a NULL fence - " "slot=%d w=%d h=%d format=%u", found, buffer->width, buffer->height, buffer->format); @@ -612,7 +612,7 @@ status_t BufferQueueProducer::detachBuffer(int slot) { listener = mCore->mConsumerListener; } - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -623,10 +623,10 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) { ATRACE_CALL(); - if (outBuffer == NULL) { + if (outBuffer == nullptr) { BQ_LOGE("detachNextBuffer: outBuffer must not be NULL"); return BAD_VALUE; - } else if (outFence == NULL) { + } else if (outFence == nullptr) { BQ_LOGE("detachNextBuffer: outFence must not be NULL"); return BAD_VALUE; } @@ -670,7 +670,7 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, listener = mCore->mConsumerListener; } - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); } @@ -681,10 +681,10 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot, const sp<android::GraphicBuffer>& buffer) { ATRACE_CALL(); - if (outSlot == NULL) { + if (outSlot == nullptr) { BQ_LOGE("attachBuffer: outSlot must not be NULL"); return BAD_VALUE; - } else if (buffer == NULL) { + } else if (buffer == nullptr) { BQ_LOGE("attachBuffer: cannot attach NULL buffer"); return BAD_VALUE; } @@ -766,7 +766,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, const Region& surfaceDamage = input.getSurfaceDamage(); const HdrMetadata& hdrMetadata = input.getHdrMetadata(); - if (acquireFence == NULL) { + if (acquireFence == nullptr) { BQ_LOGE("queueBuffer: fence is NULL"); return BAD_VALUE; } @@ -972,9 +972,9 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCallbackCondition.wait(mCallbackMutex); } - if (frameAvailableListener != NULL) { + if (frameAvailableListener != nullptr) { frameAvailableListener->onFrameAvailable(item); - } else if (frameReplacedListener != NULL) { + } else if (frameReplacedListener != nullptr) { frameReplacedListener->onFrameReplaced(item); } @@ -1039,7 +1039,7 @@ status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " "(state = %s)", slot, mSlots[slot].mBufferState.string()); return BAD_VALUE; - } else if (fence == NULL) { + } else if (fence == nullptr) { BQ_LOGE("cancelBuffer: fence is NULL"); return BAD_VALUE; } @@ -1069,7 +1069,7 @@ int BufferQueueProducer::query(int what, int *outValue) { ATRACE_CALL(); Mutex::Autolock lock(mCore->mMutex); - if (outValue == NULL) { + if (outValue == nullptr) { BQ_LOGE("query: outValue was NULL"); return BAD_VALUE; } @@ -1145,12 +1145,12 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, return NO_INIT; } - if (mCore->mConsumerListener == NULL) { + if (mCore->mConsumerListener == nullptr) { BQ_LOGE("connect: BufferQueue has no consumer"); return NO_INIT; } - if (output == NULL) { + if (output == nullptr) { BQ_LOGE("connect: output was NULL"); return BAD_VALUE; } @@ -1188,10 +1188,10 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, output->nextFrameNumber = mCore->mFrameCounter + 1; output->bufferReplaced = false; - if (listener != NULL) { + if (listener != nullptr) { // Set up a death notification so that we can disconnect // automatically if the remote producer dies - if (IInterface::asBinder(listener)->remoteBinder() != NULL) { + if (IInterface::asBinder(listener)->remoteBinder() != nullptr) { status = IInterface::asBinder(listener)->linkToDeath( static_cast<IBinder::DeathRecipient*>(this)); if (status != NO_ERROR) { @@ -1268,7 +1268,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { mCore->freeAllBuffersLocked(); // Remove our death notification callback if we have one - if (mCore->mLinkedToDeath != NULL) { + if (mCore->mLinkedToDeath != nullptr) { sp<IBinder> token = IInterface::asBinder(mCore->mLinkedToDeath); // This can fail if we're here because of the death @@ -1278,8 +1278,8 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { } mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT; - mCore->mLinkedToDeath = NULL; - mCore->mConnectedProducerListener = NULL; + mCore->mLinkedToDeath = nullptr; + mCore->mConnectedProducerListener = nullptr; mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; mCore->mConnectedPid = -1; mCore->mSidebandStream.clear(); @@ -1302,7 +1302,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { } // Autolock scope // Call back without lock held - if (listener != NULL) { + if (listener != nullptr) { listener->onBuffersReleased(); listener->onDisconnect(); } @@ -1318,7 +1318,7 @@ status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) listener = mCore->mConsumerListener; } // Autolock scope - if (listener != NULL) { + if (listener != nullptr) { listener->onSidebandStreamChanged(); } return NO_ERROR; @@ -1536,7 +1536,7 @@ void BufferQueueProducer::addAndGetFrameTimestamps( Mutex::Autolock lock(mCore->mMutex); listener = mCore->mConsumerListener; } - if (listener != NULL) { + if (listener != nullptr) { listener->addAndGetFrameTimestamps(newTimestamps, outDelta); } } diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index f9e292e199..abd9921fa9 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -96,7 +96,7 @@ void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) { void ConsumerBase::freeBufferLocked(int slotIndex) { CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); - mSlots[slotIndex].mGraphicBuffer = 0; + mSlots[slotIndex].mGraphicBuffer = nullptr; mSlots[slotIndex].mFence = Fence::NO_FENCE; mSlots[slotIndex].mFrameNumber = 0; } @@ -110,7 +110,7 @@ void ConsumerBase::onFrameAvailable(const BufferItem& item) { listener = mFrameAvailableListener.promote(); } - if (listener != NULL) { + if (listener != nullptr) { CB_LOGV("actually calling onFrameAvailable"); listener->onFrameAvailable(item); } @@ -125,7 +125,7 @@ void ConsumerBase::onFrameReplaced(const BufferItem &item) { listener = mFrameAvailableListener.promote(); } - if (listener != NULL) { + if (listener != nullptr) { CB_LOGV("actually calling onFrameReplaced"); listener->onFrameReplaced(item); } @@ -352,8 +352,8 @@ status_t ConsumerBase::acquireBufferLocked(BufferItem *item, return err; } - if (item->mGraphicBuffer != NULL) { - if (mSlots[item->mSlot].mGraphicBuffer != NULL) { + if (item->mGraphicBuffer != nullptr) { + if (mSlots[item->mSlot].mGraphicBuffer != nullptr) { freeBufferLocked(item->mSlot); } mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer; @@ -468,7 +468,7 @@ bool ConsumerBase::stillTracking(int slot, if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) { return false; } - return (mSlots[slot].mGraphicBuffer != NULL && + return (mSlots[slot].mGraphicBuffer != nullptr && mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle); } diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp index 1757ec1cd3..f5cf1c4d5a 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -34,9 +34,9 @@ namespace android { DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) { sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - if (sf != NULL) { + if (sf != nullptr) { mEventConnection = sf->createDisplayEventConnection(vsyncSource); - if (mEventConnection != NULL) { + if (mEventConnection != nullptr) { mDataChannel = std::make_unique<gui::BitTube>(); mEventConnection->stealReceiveChannel(mDataChannel.get()); } @@ -47,13 +47,13 @@ DisplayEventReceiver::~DisplayEventReceiver() { } status_t DisplayEventReceiver::initCheck() const { - if (mDataChannel != NULL) + if (mDataChannel != nullptr) return NO_ERROR; return NO_INIT; } int DisplayEventReceiver::getFd() const { - if (mDataChannel == NULL) + if (mDataChannel == nullptr) return NO_INIT; return mDataChannel->getFd(); @@ -63,7 +63,7 @@ status_t DisplayEventReceiver::setVsyncRate(uint32_t count) { if (int32_t(count) < 0) return BAD_VALUE; - if (mEventConnection != NULL) { + if (mEventConnection != nullptr) { mEventConnection->setVsyncRate(count); return NO_ERROR; } @@ -71,7 +71,7 @@ status_t DisplayEventReceiver::setVsyncRate(uint32_t count) { } status_t DisplayEventReceiver::requestNextVsync() { - if (mEventConnection != NULL) { + if (mEventConnection != nullptr) { mEventConnection->requestNextVsync(); return NO_ERROR; } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 885efec9b9..5532db43ad 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -46,7 +46,6 @@ #include <utils/Trace.h> extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); -#define CROP_EXT_STR "EGL_ANDROID_image_crop" #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content" #define EGL_PROTECTED_CONTENT_EXT 0x32C0 @@ -82,26 +81,6 @@ static const mat4 mtxIdentity; Mutex GLConsumer::sStaticInitLock; sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer; -static bool hasEglAndroidImageCropImpl() { - EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS); - size_t cropExtLen = strlen(CROP_EXT_STR); - size_t extsLen = strlen(exts); - bool equal = !strcmp(CROP_EXT_STR, exts); - bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1); - bool atEnd = (cropExtLen+1) < extsLen && - !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1)); - bool inMiddle = strstr(exts, " " CROP_EXT_STR " "); - return equal || atStart || atEnd || inMiddle; -} - -static bool hasEglAndroidImageCrop() { - // Only compute whether the extension is present once the first time this - // function is called. - static bool hasIt = hasEglAndroidImageCropImpl(); - return hasIt; -} - static bool hasEglProtectedContentImpl() { EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); const char* exts = eglQueryString(dpy, EGL_EXTENSIONS); @@ -122,10 +101,6 @@ static bool hasEglProtectedContent() { return hasIt; } -static bool isEglImageCroppable(const Rect& crop) { - return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0); -} - GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t texTarget, bool useFenceSync, bool isControlledByApp) : ConsumerBase(bq, isControlledByApp), @@ -291,7 +266,7 @@ status_t GLConsumer::releaseTexImage() { return err; } - if (mReleasedTexImage == NULL) { + if (mReleasedTexImage == nullptr) { mReleasedTexImage = new EglImage(getDebugTexImageBuffer()); } @@ -321,7 +296,7 @@ status_t GLConsumer::releaseTexImage() { sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() { Mutex::Autolock _l(sStaticInitLock); - if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) { + if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) { // The first time, create the debug texture in case the application // continues to use it. sp<GraphicBuffer> buffer = new GraphicBuffer( @@ -357,7 +332,7 @@ status_t GLConsumer::acquireBufferLocked(BufferItem *item, // If item->mGraphicBuffer is not null, this buffer has not been acquired // before, so any prior EglImage created is using a stale buffer. This // replaces any old EglImage with a new one (using the new buffer). - if (item->mGraphicBuffer != NULL) { + if (item->mGraphicBuffer != nullptr) { int slot = item->mSlot; mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer); } @@ -406,7 +381,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item, // ConsumerBase. // We may have to do this even when item.mGraphicBuffer == NULL (which // means the buffer was previously acquired). - err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop); + err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay); if (err != NO_ERROR) { GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay, slot); @@ -430,8 +405,8 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item, } GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", - mCurrentTexture, mCurrentTextureImage != NULL ? - mCurrentTextureImage->graphicBufferHandle() : 0, + mCurrentTexture, mCurrentTextureImage != nullptr ? + mCurrentTextureImage->graphicBufferHandle() : nullptr, slot, mSlots[slot].mGraphicBuffer->handle); // Hang onto the pointer so that it isn't freed in the call to @@ -491,13 +466,12 @@ status_t GLConsumer::bindTextureImageLocked() { glBindTexture(mTexTarget, mTexName); if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && - mCurrentTextureImage == NULL) { + mCurrentTextureImage == nullptr) { GLC_LOGE("bindTextureImage: no currently-bound texture"); return NO_INIT; } - status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, - mCurrentCrop); + status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay); if (err != NO_ERROR) { GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay, mCurrentTexture); @@ -511,9 +485,7 @@ status_t GLConsumer::bindTextureImageLocked() { // forcing the creation of a new image. if ((error = glGetError()) != GL_NO_ERROR) { glBindTexture(mTexTarget, mTexName); - status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, - mCurrentCrop, - true); + status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, true); if (result != NO_ERROR) { GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay, mCurrentTexture); @@ -655,7 +627,7 @@ status_t GLConsumer::attachToContext(uint32_t tex) { mTexName = tex; mAttached = true; - if (mCurrentTextureImage != NULL) { + if (mCurrentTextureImage != nullptr) { // This may wait for a buffer a second time. This is likely required if // this is a different context, since otherwise the wait could be skipped // by bouncing through another context. For the same context the extra @@ -676,7 +648,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (SyncFeatures::getInstance().useNativeFenceSync()) { EGLSyncKHR sync = eglCreateSyncKHR(dpy, - EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); + EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr); if (sync == EGL_NO_SYNC_KHR) { GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError()); @@ -720,7 +692,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { // Create a fence for the outstanding accesses in the current // OpenGL ES context. - fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); + fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr); if (fence == EGL_NO_SYNC_KHR) { GLC_LOGE("syncForReleaseLocked: error creating fence: %#x", eglGetError()); @@ -752,11 +724,11 @@ void GLConsumer::setFilteringEnabled(bool enabled) { bool needsRecompute = mFilteringEnabled != enabled; mFilteringEnabled = enabled; - if (needsRecompute && mCurrentTextureImage==NULL) { + if (needsRecompute && mCurrentTextureImage==nullptr) { GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); } - if (needsRecompute && mCurrentTextureImage != NULL) { + if (needsRecompute && mCurrentTextureImage != nullptr) { computeCurrentTransformMatrixLocked(); } } @@ -769,8 +741,7 @@ void GLConsumer::computeCurrentTransformMatrixLocked() { GLC_LOGD("computeCurrentTransformMatrixLocked: " "mCurrentTextureImage is NULL"); } - computeTransformMatrix(mCurrentTransformMatrix, buf, - isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop, + computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop, mCurrentTransform, mFilteringEnabled); } @@ -938,7 +909,7 @@ sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const { } return (mCurrentTextureImage == nullptr) ? - NULL : mCurrentTextureImage->graphicBuffer(); + nullptr : mCurrentTextureImage->graphicBuffer(); } Rect GLConsumer::getCurrentCrop() const { @@ -1063,8 +1034,7 @@ void GLConsumer::dumpLocked(String8& result, const char* prefix) const GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) : mGraphicBuffer(graphicBuffer), mEglImage(EGL_NO_IMAGE_KHR), - mEglDisplay(EGL_NO_DISPLAY), - mCropRect(Rect::EMPTY_RECT) { + mEglDisplay(EGL_NO_DISPLAY) { } GLConsumer::EglImage::~EglImage() { @@ -1077,13 +1047,11 @@ GLConsumer::EglImage::~EglImage() { } status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, - const Rect& cropRect, bool forceCreation) { // If there's an image and it's no longer valid, destroy it. bool haveImage = mEglImage != EGL_NO_IMAGE_KHR; bool displayInvalid = mEglDisplay != eglDisplay; - bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect; - if (haveImage && (displayInvalid || cropInvalid || forceCreation)) { + if (haveImage && (displayInvalid || forceCreation)) { if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { ALOGE("createIfNeeded: eglDestroyImageKHR failed"); } @@ -1095,14 +1063,12 @@ status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, // If there's no image, create one. if (mEglImage == EGL_NO_IMAGE_KHR) { mEglDisplay = eglDisplay; - mCropRect = cropRect; - mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect); + mEglImage = createImage(mEglDisplay, mGraphicBuffer); } // Fail if we can't create a valid image. if (mEglImage == EGL_NO_IMAGE_KHR) { mEglDisplay = EGL_NO_DISPLAY; - mCropRect.makeInvalid(); const sp<GraphicBuffer>& buffer = mGraphicBuffer; ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d", buffer->getWidth(), buffer->getHeight(), buffer->getStride(), @@ -1119,38 +1085,19 @@ void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) { } EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, - const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) { + const sp<GraphicBuffer>& graphicBuffer) { EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer()); const bool createProtectedImage = (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && hasEglProtectedContent(); EGLint attrs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_IMAGE_CROP_LEFT_ANDROID, crop.left, - EGL_IMAGE_CROP_TOP_ANDROID, crop.top, - EGL_IMAGE_CROP_RIGHT_ANDROID, crop.right, - EGL_IMAGE_CROP_BOTTOM_ANDROID, crop.bottom, + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE, createProtectedImage ? EGL_TRUE : EGL_NONE, EGL_NONE, }; - if (!crop.isValid()) { - // No crop rect to set, so leave the crop out of the attrib array. Make - // sure to propagate the protected content attrs if they are set. - attrs[2] = attrs[10]; - attrs[3] = attrs[11]; - attrs[4] = EGL_NONE; - } else if (!isEglImageCroppable(crop)) { - // The crop rect is not at the origin, so we can't set the crop on the - // EGLImage because that's not allowed by the EGL_ANDROID_image_crop - // extension. In the future we can add a layered extension that - // removes this restriction if there is hardware that can support it. - attrs[2] = attrs[10]; - attrs[3] = attrs[11]; - attrs[4] = EGL_NONE; - } - eglInitialize(dpy, 0, 0); + eglInitialize(dpy, nullptr, nullptr); EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); if (image == EGL_NO_IMAGE_KHR) { diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 0b3796056d..68a6b1fe38 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -190,10 +190,10 @@ public: virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) { - if (outBuffer == NULL) { + if (outBuffer == nullptr) { ALOGE("detachNextBuffer: outBuffer must not be NULL"); return BAD_VALUE; - } else if (outFence == NULL) { + } else if (outFence == nullptr) { ALOGE("detachNextBuffer: outFence must not be NULL"); return BAD_VALUE; } @@ -301,7 +301,7 @@ public: int api, bool producerControlledByApp, QueueBufferOutput* output) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); - if (listener != NULL) { + if (listener != nullptr) { data.writeInt32(1); data.writeStrongBinder(IInterface::asBinder(listener)); } else { @@ -738,8 +738,8 @@ status_t BnGraphicBufferProducer::onTransact( int bufferIdx = data.readInt32(); sp<GraphicBuffer> buffer; int result = requestBuffer(bufferIdx, &buffer); - reply->writeInt32(buffer != 0); - if (buffer != 0) { + reply->writeInt32(buffer != nullptr); + if (buffer != nullptr) { reply->write(*buffer); } reply->writeInt32(result); @@ -797,12 +797,12 @@ status_t BnGraphicBufferProducer::onTransact( int32_t result = detachNextBuffer(&buffer, &fence); reply->writeInt32(result); if (result == NO_ERROR) { - reply->writeInt32(buffer != NULL); - if (buffer != NULL) { + reply->writeInt32(buffer != nullptr); + if (buffer != nullptr) { reply->write(*buffer); } - reply->writeInt32(fence != NULL); - if (fence != NULL) { + reply->writeInt32(fence != nullptr); + if (fence != nullptr) { reply->write(*fence); } } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index e22bc708c9..7f9668fc2c 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -116,20 +116,20 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast<int32_t>(useIdentityTransform)); data.writeInt32(static_cast<int32_t>(rotation)); - status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - - if (err != NO_ERROR) { - return err; + status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); + if (result != NO_ERROR) { + ALOGE("captureScreen failed to transact: %d", result); + return result; } - - err = reply.readInt32(); - if (err != NO_ERROR) { - return err; + result = reply.readInt32(); + if (result != NO_ERROR) { + ALOGE("captureScreen failed to readInt32: %d", result); + return result; } *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); - return err; + return result; } virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder, @@ -141,21 +141,20 @@ public: data.write(sourceCrop); data.writeFloat(frameScale); data.writeBool(childrenOnly); - status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - - if (err != NO_ERROR) { - return err; + status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + if (result != NO_ERROR) { + ALOGE("captureLayers failed to transact: %d", result); + return result; } - - err = reply.readInt32(); - if (err != NO_ERROR) { - return err; + result = reply.readInt32(); + if (result != NO_ERROR) { + ALOGE("captureLayers failed to readInt32: %d", result); + return result; } - *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); - return err; + return result; } virtual bool authenticateSurfaceTexture( @@ -344,10 +343,26 @@ public: virtual status_t setActiveConfig(const sp<IBinder>& display, int id) { Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display); - data.writeInt32(id); - remote()->transact(BnSurfaceComposer::SET_ACTIVE_CONFIG, data, &reply); + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setActiveConfig failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("setActiveConfig failed to writeStrongBinder: %d", result); + return result; + } + result = data.writeInt32(id); + if (result != NO_ERROR) { + ALOGE("setActiveConfig failed to writeInt32: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::SET_ACTIVE_CONFIG, data, &reply); + if (result != NO_ERROR) { + ALOGE("setActiveConfig failed to transact: %d", result); + return result; + } return reply.readInt32(); } @@ -429,8 +444,16 @@ public: virtual status_t clearAnimationFrameStats() { Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS, data, &reply); + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("clearAnimationFrameStats failed to writeInterfaceToken: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS, data, &reply); + if (result != NO_ERROR) { + ALOGE("clearAnimationFrameStats failed to transact: %d", result); + return result; + } return reply.readInt32(); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 01acc2de20..931c446275 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -37,19 +37,45 @@ status_t layer_state_t::write(Parcel& output) const output.writeUint32(mask); *reinterpret_cast<layer_state_t::matrix22_t *>( output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix; - output.write(crop); - output.write(finalCrop); - output.writeStrongBinder(barrierHandle); + output.write(crop_legacy); + output.write(finalCrop_legacy); + output.writeStrongBinder(barrierHandle_legacy); output.writeStrongBinder(reparentHandle); - output.writeUint64(frameNumber); + output.writeUint64(frameNumber_legacy); output.writeInt32(overrideScalingMode); - output.writeStrongBinder(IInterface::asBinder(barrierGbp)); + output.writeStrongBinder(IInterface::asBinder(barrierGbp_legacy)); output.writeStrongBinder(relativeLayerHandle); output.writeStrongBinder(parentHandleForChild); output.writeFloat(color.r); output.writeFloat(color.g); output.writeFloat(color.b); output.write(transparentRegion); + output.writeUint32(transform); + output.writeBool(transformToDisplayInverse); + output.write(crop); + if (buffer) { + output.writeBool(true); + output.write(*buffer); + } else { + output.writeBool(false); + } + if (acquireFence) { + output.writeBool(true); + output.write(*acquireFence); + } else { + output.writeBool(false); + } + output.writeUint32(static_cast<uint32_t>(dataspace)); + output.write(hdrMetadata); + output.write(surfaceDamageRegion); + output.writeInt32(api); + if (sidebandStream) { + output.writeBool(true); + output.writeNativeHandle(sidebandStream->handle()); + } else { + output.writeBool(false); + } + return NO_ERROR; } @@ -72,20 +98,38 @@ status_t layer_state_t::read(const Parcel& input) } else { return BAD_VALUE; } - input.read(crop); - input.read(finalCrop); - barrierHandle = input.readStrongBinder(); + input.read(crop_legacy); + input.read(finalCrop_legacy); + barrierHandle_legacy = input.readStrongBinder(); reparentHandle = input.readStrongBinder(); - frameNumber = input.readUint64(); + frameNumber_legacy = input.readUint64(); overrideScalingMode = input.readInt32(); - barrierGbp = - interface_cast<IGraphicBufferProducer>(input.readStrongBinder()); + barrierGbp_legacy = interface_cast<IGraphicBufferProducer>(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); parentHandleForChild = input.readStrongBinder(); color.r = input.readFloat(); color.g = input.readFloat(); color.b = input.readFloat(); input.read(transparentRegion); + transform = input.readUint32(); + transformToDisplayInverse = input.readBool(); + input.read(crop); + buffer = new GraphicBuffer(); + if (input.readBool()) { + input.read(*buffer); + } + acquireFence = new Fence(); + if (input.readBool()) { + input.read(*acquireFence); + } + dataspace = static_cast<ui::Dataspace>(input.readUint32()); + input.read(hdrMetadata); + input.read(surfaceDamageRegion); + api = input.readInt32(); + if (input.readBool()) { + sidebandStream = NativeHandle::create(input.readNativeHandle(), true); + } + return NO_ERROR; } @@ -194,19 +238,19 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eLayerStackChanged; layerStack = other.layerStack; } - if (other.what & eCropChanged) { - what |= eCropChanged; - crop = other.crop; + if (other.what & eCropChanged_legacy) { + what |= eCropChanged_legacy; + crop_legacy = other.crop_legacy; } - if (other.what & eDeferTransaction) { - what |= eDeferTransaction; - barrierHandle = other.barrierHandle; - barrierGbp = other.barrierGbp; - frameNumber = other.frameNumber; + if (other.what & eDeferTransaction_legacy) { + what |= eDeferTransaction_legacy; + barrierHandle_legacy = other.barrierHandle_legacy; + barrierGbp_legacy = other.barrierGbp_legacy; + frameNumber_legacy = other.frameNumber_legacy; } - if (other.what & eFinalCropChanged) { - what |= eFinalCropChanged; - finalCrop = other.finalCrop; + if (other.what & eFinalCropChanged_legacy) { + what |= eFinalCropChanged_legacy; + finalCrop_legacy = other.finalCrop_legacy; } if (other.what & eOverrideScalingModeChanged) { what |= eOverrideScalingModeChanged; @@ -234,6 +278,46 @@ void layer_state_t::merge(const layer_state_t& other) { if (other.what & eDestroySurface) { what |= eDestroySurface; } + if (other.what & eTransformChanged) { + what |= eTransformChanged; + transform = other.transform; + } + if (other.what & eTransformToDisplayInverseChanged) { + what |= eTransformToDisplayInverseChanged; + transformToDisplayInverse = other.transformToDisplayInverse; + } + if (other.what & eCropChanged) { + what |= eCropChanged; + crop = other.crop; + } + if (other.what & eBufferChanged) { + what |= eBufferChanged; + buffer = other.buffer; + } + if (other.what & eAcquireFenceChanged) { + what |= eAcquireFenceChanged; + acquireFence = other.acquireFence; + } + if (other.what & eDataspaceChanged) { + what |= eDataspaceChanged; + dataspace = other.dataspace; + } + if (other.what & eHdrMetadataChanged) { + what |= eHdrMetadataChanged; + hdrMetadata = other.hdrMetadata; + } + if (other.what & eSurfaceDamageRegionChanged) { + what |= eSurfaceDamageRegionChanged; + surfaceDamageRegion = other.surfaceDamageRegion; + } + if (other.what & eApiChanged) { + what |= eApiChanged; + api = other.api; + } + if (other.what & eSidebandStreamChanged) { + what |= eSidebandStreamChanged; + sidebandStream = other.sidebandStream; + } } }; // namespace android diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp index 52c906775e..2f8e104ea0 100644 --- a/libs/gui/StreamSplitter.cpp +++ b/libs/gui/StreamSplitter.cpp @@ -38,11 +38,11 @@ namespace android { status_t StreamSplitter::createSplitter( const sp<IGraphicBufferConsumer>& inputQueue, sp<StreamSplitter>* outSplitter) { - if (inputQueue == NULL) { + if (inputQueue == nullptr) { ALOGE("createSplitter: inputQueue must not be NULL"); return BAD_VALUE; } - if (outSplitter == NULL) { + if (outSplitter == nullptr) { ALOGE("createSplitter: outSplitter must not be NULL"); return BAD_VALUE; } @@ -74,7 +74,7 @@ StreamSplitter::~StreamSplitter() { status_t StreamSplitter::addOutput( const sp<IGraphicBufferProducer>& outputQueue) { - if (outputQueue == NULL) { + if (outputQueue == nullptr) { ALOGE("addOutput: outputQueue must not be NULL"); return BAD_VALUE; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 2de14c8846..b505c6fa23 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -156,7 +156,7 @@ status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) { ATRACE_CALL(); DisplayStatInfo stats; - status_t result = composerService()->getDisplayStats(NULL, &stats); + status_t result = composerService()->getDisplayStats(nullptr, &stats); if (result != NO_ERROR) { return result; } @@ -501,7 +501,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot != BufferItem::INVALID_BUFFER_SLOT) { sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer); - if (gbuf != NULL) { + if (gbuf != nullptr) { *buffer = gbuf.get(); *fenceFd = -1; return OK; @@ -541,7 +541,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { sp<GraphicBuffer>& gbuf(mSlots[buf].buffer); // this should never happen - ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); + ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) { freeAllBuffers(); @@ -619,7 +619,7 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer, int Surface::getSlotFromBufferLocked( android_native_buffer_t* buffer) const { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].buffer != NULL && + if (mSlots[i].buffer != nullptr && mSlots[i].buffer->handle == buffer->handle) { return i; } @@ -1268,7 +1268,7 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer, ATRACE_CALL(); ALOGV("Surface::detachNextBuffer"); - if (outBuffer == NULL || outFence == NULL) { + if (outBuffer == nullptr || outFence == nullptr) { return BAD_VALUE; } @@ -1277,8 +1277,8 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer, mRemovedBuffers.clear(); } - sp<GraphicBuffer> buffer(NULL); - sp<Fence> fence(NULL); + sp<GraphicBuffer> buffer(nullptr); + sp<Fence> fence(nullptr); status_t result = mGraphicBufferProducer->detachNextBuffer( &buffer, &fence); if (result != NO_ERROR) { @@ -1286,19 +1286,19 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer, } *outBuffer = buffer; - if (fence != NULL && fence->isValid()) { + if (fence != nullptr && fence->isValid()) { *outFence = fence; } else { *outFence = Fence::NO_FENCE; } for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i].buffer != NULL && + if (mSlots[i].buffer != nullptr && mSlots[i].buffer->getId() == buffer->getId()) { if (mReportRemovedBuffers) { mRemovedBuffers.push_back(mSlots[i].buffer); } - mSlots[i].buffer = NULL; + mSlots[i].buffer = nullptr; } } @@ -1349,7 +1349,7 @@ int Surface::setCrop(Rect const* rect) ATRACE_CALL(); Rect realRect(Rect::EMPTY_RECT); - if (rect == NULL || rect->isEmpty()) { + if (rect == nullptr || rect->isEmpty()) { realRect.clear(); } else { realRect = *rect; @@ -1576,7 +1576,7 @@ Dataspace Surface::getBuffersDataSpace() { void Surface::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i].buffer = 0; + mSlots[i].buffer = nullptr; } } @@ -1616,12 +1616,12 @@ static status_t copyBlt( // src and dst with, height and format must be identical. no verification // is done here. status_t err; - uint8_t* src_bits = NULL; + uint8_t* src_bits = nullptr; err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), reinterpret_cast<void**>(&src_bits)); ALOGE_IF(err, "error locking src buffer %s", strerror(-err)); - uint8_t* dst_bits = NULL; + uint8_t* dst_bits = nullptr; err = dst->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), reinterpret_cast<void**>(&dst_bits), *dstFenceFd); ALOGE_IF(err, "error locking dst buffer %s", strerror(-err)); @@ -1669,7 +1669,7 @@ static status_t copyBlt( status_t Surface::lock( ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) { - if (mLockedBuffer != 0) { + if (mLockedBuffer != nullptr) { ALOGE("Surface::lock failed, already locked"); return INVALID_OPERATION; } @@ -1701,7 +1701,7 @@ status_t Surface::lock( // figure out if we can copy the frontbuffer back const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); - const bool canCopyBack = (frontBuffer != 0 && + const bool canCopyBack = (frontBuffer != nullptr && backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && backBuffer->format == frontBuffer->format); @@ -1763,7 +1763,7 @@ status_t Surface::lock( status_t Surface::unlockAndPost() { - if (mLockedBuffer == 0) { + if (mLockedBuffer == nullptr) { ALOGE("Surface::unlockAndPost failed, no locked buffer"); return INVALID_OPERATION; } @@ -1777,7 +1777,7 @@ status_t Surface::unlockAndPost() mLockedBuffer->handle, strerror(-err)); mPostedBuffer = mLockedBuffer; - mLockedBuffer = 0; + mLockedBuffer = nullptr; return err; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 63560c4b89..17cff546e0 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -60,7 +60,7 @@ void ComposerService::connectLocked() { while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000); } - assert(mComposerService != NULL); + assert(mComposerService != nullptr); // Create the death listener. class DeathObserver : public IBinder::DeathRecipient { @@ -81,9 +81,9 @@ void ComposerService::connectLocked() { /*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() { ComposerService& instance = ComposerService::getInstance(); Mutex::Autolock _l(instance.mLock); - if (instance.mComposerService == NULL) { + if (instance.mComposerService == nullptr) { ComposerService::getInstance().connectLocked(); - assert(instance.mComposerService != NULL); + assert(instance.mComposerService != nullptr); ALOGD("ComposerService reconnected"); } return instance.mComposerService; @@ -92,8 +92,8 @@ void ComposerService::connectLocked() { void ComposerService::composerServiceDied() { Mutex::Autolock _l(mLock); - mComposerService = NULL; - mDeathObserver = NULL; + mComposerService = nullptr; + mDeathObserver = nullptr; } // --------------------------------------------------------------------------- @@ -344,54 +344,57 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatri return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop_legacy( const sp<SurfaceControl>& sc, const Rect& crop) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eCropChanged; - s->crop = crop; + s->what |= layer_state_t::eCropChanged_legacy; + s->crop_legacy = crop; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop) { +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop_legacy( + const sp<SurfaceControl>& sc, const Rect& crop) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eFinalCropChanged; - s->finalCrop = crop; + s->what |= layer_state_t::eFinalCropChanged_legacy; + s->finalCrop_legacy = crop; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( - const sp<SurfaceControl>& sc, - const sp<IBinder>& handle, uint64_t frameNumber) { +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp<SurfaceControl>& sc, + const sp<IBinder>& handle, + uint64_t frameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eDeferTransaction; - s->barrierHandle = handle; - s->frameNumber = frameNumber; + s->what |= layer_state_t::eDeferTransaction_legacy; + s->barrierHandle_legacy = handle; + s->frameNumber_legacy = frameNumber; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( - const sp<SurfaceControl>& sc, - const sp<Surface>& barrierSurface, uint64_t frameNumber) { +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp<SurfaceControl>& sc, + const sp<Surface>& barrierSurface, + uint64_t frameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eDeferTransaction; - s->barrierGbp = barrierSurface->getIGraphicBufferProducer(); - s->frameNumber = frameNumber; + s->what |= layer_state_t::eDeferTransaction_legacy; + s->barrierGbp_legacy = barrierSurface->getIGraphicBufferProducer(); + s->frameNumber_legacy = frameNumber; return *this; } @@ -434,6 +437,127 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransform( + const sp<SurfaceControl>& sc, uint32_t transform) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eTransformChanged; + s->transform = transform; + return *this; +} + +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp<SurfaceControl>& sc, + bool transformToDisplayInverse) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eTransformToDisplayInverseChanged; + s->transformToDisplayInverse = transformToDisplayInverse; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( + const sp<SurfaceControl>& sc, const Rect& crop) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eCropChanged; + s->crop = crop; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( + const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eBufferChanged; + s->buffer = buffer; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence( + const sp<SurfaceControl>& sc, const sp<Fence>& fence) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eAcquireFenceChanged; + s->acquireFence = fence; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace( + const sp<SurfaceControl>& sc, ui::Dataspace dataspace) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eDataspaceChanged; + s->dataspace = dataspace; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setHdrMetadata( + const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eHdrMetadataChanged; + s->hdrMetadata = hdrMetadata; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSurfaceDamageRegion( + const sp<SurfaceControl>& sc, const Region& surfaceDamageRegion) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eSurfaceDamageRegionChanged; + s->surfaceDamageRegion = surfaceDamageRegion; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApi( + const sp<SurfaceControl>& sc, int32_t api) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eApiChanged; + s->api = api; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSidebandStream( + const sp<SurfaceControl>& sc, const sp<NativeHandle>& sidebandStream) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eSidebandStreamChanged; + s->sidebandStream = sidebandStream; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); @@ -571,12 +695,12 @@ SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& c void SurfaceComposerClient::onFirstRef() { sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - if (sf != 0 && mStatus == NO_INIT) { + if (sf != nullptr && mStatus == NO_INIT) { auto rootProducer = mParent.promote(); sp<ISurfaceComposerClient> conn; conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) : sf->createConnection(); - if (conn != 0) { + if (conn != nullptr) { mClient = conn; mStatus = NO_ERROR; } @@ -606,7 +730,7 @@ void SurfaceComposerClient::dispose() { // this can be called more than once. sp<ISurfaceComposerClient> client; Mutex::Autolock _lm(mLock); - if (mClient != 0) { + if (mClient != nullptr) { client = mClient; // hold ref while lock is held mClient.clear(); } @@ -766,7 +890,7 @@ status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, bool useIdentityTransform, uint32_t rotation, sp<GraphicBuffer>* outBuffer) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; + if (s == nullptr) return NO_INIT; status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, static_cast<ISurfaceComposer::Rotation>(rotation)); @@ -779,7 +903,7 @@ status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float frameScale, sp<GraphicBuffer>* outBuffer) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; + if (s == nullptr) return NO_INIT; status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, false /* childrenOnly */); return ret; @@ -788,7 +912,7 @@ status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect so status_t ScreenshotClient::captureChildLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float frameScale, sp<GraphicBuffer>* outBuffer) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; + if (s == nullptr) return NO_INIT; status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, true /* childrenOnly */); return ret; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 5eafbb3555..19ad31b8c7 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -86,7 +86,7 @@ void SurfaceControl::clear() } void SurfaceControl::disconnect() { - if (mGraphicBufferProducer != NULL) { + if (mGraphicBufferProducer != nullptr) { mGraphicBufferProducer->disconnect( BufferQueueCore::CURRENTLY_CONNECTED_API); } @@ -95,7 +95,7 @@ void SurfaceControl::disconnect() { bool SurfaceControl::isSameSurface( const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) { - if (lhs == 0 || rhs == 0) + if (lhs == nullptr || rhs == nullptr) return false; return lhs->mHandle == rhs->mHandle; } @@ -116,7 +116,7 @@ status_t SurfaceControl::getLayerFrameStats(FrameStats* outStats) const { status_t SurfaceControl::validate() const { - if (mHandle==0 || mClient==0) { + if (mHandle==nullptr || mClient==nullptr) { ALOGE("invalid handle (%p) or client (%p)", mHandle.get(), mClient.get()); return NO_INIT; @@ -128,7 +128,7 @@ status_t SurfaceControl::writeSurfaceToParcel( const sp<SurfaceControl>& control, Parcel* parcel) { sp<IGraphicBufferProducer> bp; - if (control != NULL) { + if (control != nullptr) { bp = control->mGraphicBufferProducer; } return parcel->writeStrongBinder(IInterface::asBinder(bp)); @@ -146,7 +146,7 @@ sp<Surface> SurfaceControl::generateSurfaceLocked() const sp<Surface> SurfaceControl::getSurface() const { Mutex::Autolock _l(mLock); - if (mSurfaceData == 0) { + if (mSurfaceData == nullptr) { return generateSurfaceLocked(); } return mSurfaceData; diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp index afa15c5cda..fcae05c8ad 100644 --- a/libs/gui/SyncFeatures.cpp +++ b/libs/gui/SyncFeatures.cpp @@ -41,7 +41,7 @@ SyncFeatures::SyncFeatures() : Singleton<SyncFeatures>(), // This can only be called after EGL has been initialized; otherwise the // check below will abort. const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS); - LOG_ALWAYS_FATAL_IF(exts == NULL, "eglQueryStringImplementationANDROID failed"); + LOG_ALWAYS_FATAL_IF(exts == nullptr, "eglQueryStringImplementationANDROID failed"); if (strstr(exts, "EGL_ANDROID_native_fence_sync")) { // This makes GLConsumer use the EGL_ANDROID_native_fence_sync // extension to create Android native fences to signal when all diff --git a/libs/gui/include/gui/BufferHubProducer.h b/libs/gui/include/gui/BufferHubProducer.h index 23c9909826..f7af19b20e 100644 --- a/libs/gui/include/gui/BufferHubProducer.h +++ b/libs/gui/include/gui/BufferHubProducer.h @@ -165,6 +165,10 @@ private: // buffers are acquired by the consumer, we can't . status_t FreeAllBuffers(); + // Helper function that implements the detachBuffer() call, but assuming |mutex_| has been + // locked already. + status_t DetachBufferLocked(size_t slot); + // Concreate implementation backed by BufferHubBuffer. std::shared_ptr<dvr::ProducerQueue> queue_; diff --git a/libs/gui/include/gui/CpuConsumer.h b/libs/gui/include/gui/CpuConsumer.h index d375611e5b..806fbe8aa0 100644 --- a/libs/gui/include/gui/CpuConsumer.h +++ b/libs/gui/include/gui/CpuConsumer.h @@ -70,7 +70,7 @@ class CpuConsumer : public ConsumerBase uint32_t chromaStep; LockedBuffer() : - data(NULL), + data(nullptr), width(0), height(0), format(PIXEL_FORMAT_NONE), @@ -82,8 +82,8 @@ class CpuConsumer : public ConsumerBase dataSpace(HAL_DATASPACE_UNKNOWN), frameNumber(0), flexFormat(PIXEL_FORMAT_NONE), - dataCb(NULL), - dataCr(NULL), + dataCb(nullptr), + dataCr(nullptr), chromaStride(0), chromaStep(0) {} diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h index 71ed3bf239..46a99e124c 100644 --- a/libs/gui/include/gui/GLConsumer.h +++ b/libs/gui/include/gui/GLConsumer.h @@ -140,7 +140,8 @@ public: // Scale the crop down horizontally or vertically such that it has the // same aspect ratio as the buffer does. - static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight); + static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth, + uint32_t bufferHeight); // getTimestamp retrieves the timestamp associated with the texture image // set by the most recent call to updateTexImage. @@ -305,7 +306,6 @@ private: // createIfNeeded creates an EGLImage if required (we haven't created // one yet, or the EGLDisplay or crop-rect has changed). status_t createIfNeeded(EGLDisplay display, - const Rect& cropRect, bool forceCreate = false); // This calls glEGLImageTargetTexture2DOES to bind the image to the @@ -314,7 +314,7 @@ private: const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; } const native_handle* graphicBufferHandle() { - return mGraphicBuffer == NULL ? NULL : mGraphicBuffer->handle; + return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle; } private: @@ -324,7 +324,7 @@ private: // createImage creates a new EGLImage from a GraphicBuffer. EGLImageKHR createImage(EGLDisplay dpy, - const sp<GraphicBuffer>& graphicBuffer, const Rect& crop); + const sp<GraphicBuffer>& graphicBuffer); // Disallow copying EglImage(const EglImage& rhs); diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 887654e05b..8ff8d81cf6 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -345,7 +345,7 @@ public: *outScalingMode = scalingMode; *outTransform = transform; *outFence = fence; - if (outStickyTransform != NULL) { + if (outStickyTransform != nullptr) { *outStickyTransform = stickyTransform; } if (outGetFrameTimestamps) { diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 8dfc99a4b7..11261c307c 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -40,8 +40,9 @@ public: eProtectedByDRM = 0x00001000, eCursorWindow = 0x00002000, - eFXSurfaceNormal = 0x00000000, + eFXSurfaceBufferQueue = 0x00000000, eFXSurfaceColor = 0x00020000, + eFXSurfaceBufferState = 0x00040000, eFXSurfaceMask = 0x000F0000, }; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 788962e490..098179864a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -22,10 +22,11 @@ #include <utils/Errors.h> -#include <ui/Region.h> -#include <ui/Rect.h> #include <gui/IGraphicBufferProducer.h> #include <math/vec3.h> +#include <ui/GraphicTypes.h> +#include <ui/Rect.h> +#include <ui/Region.h> namespace android { @@ -36,113 +37,146 @@ class ISurfaceComposerClient; * Used to communicate layer information between SurfaceFlinger and its clients. */ struct layer_state_t { - - enum { - eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java - eLayerOpaque = 0x02, // SURFACE_OPAQUE - eLayerSecure = 0x80, // SECURE + eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java + eLayerOpaque = 0x02, // SURFACE_OPAQUE + eLayerSecure = 0x80, // SECURE }; enum { - ePositionChanged = 0x00000001, - eLayerChanged = 0x00000002, - eSizeChanged = 0x00000004, - eAlphaChanged = 0x00000008, - eMatrixChanged = 0x00000010, - eTransparentRegionChanged = 0x00000020, - eFlagsChanged = 0x00000040, - eLayerStackChanged = 0x00000080, - eCropChanged = 0x00000100, - eDeferTransaction = 0x00000200, - eFinalCropChanged = 0x00000400, + ePositionChanged = 0x00000001, + eLayerChanged = 0x00000002, + eSizeChanged = 0x00000004, + eAlphaChanged = 0x00000008, + eMatrixChanged = 0x00000010, + eTransparentRegionChanged = 0x00000020, + eFlagsChanged = 0x00000040, + eLayerStackChanged = 0x00000080, + eCropChanged_legacy = 0x00000100, + eDeferTransaction_legacy = 0x00000200, + eFinalCropChanged_legacy = 0x00000400, eOverrideScalingModeChanged = 0x00000800, - eGeometryAppliesWithResize = 0x00001000, - eReparentChildren = 0x00002000, - eDetachChildren = 0x00004000, - eRelativeLayerChanged = 0x00008000, - eReparent = 0x00010000, - eColorChanged = 0x00020000, - eDestroySurface = 0x00040000 + eGeometryAppliesWithResize = 0x00001000, + eReparentChildren = 0x00002000, + eDetachChildren = 0x00004000, + eRelativeLayerChanged = 0x00008000, + eReparent = 0x00010000, + eColorChanged = 0x00020000, + eDestroySurface = 0x00040000, + eTransformChanged = 0x00100000, + eTransformToDisplayInverseChanged = 0x00200000, + eCropChanged = 0x00400000, + eBufferChanged = 0x00800000, + eAcquireFenceChanged = 0x01000000, + eDataspaceChanged = 0x02000000, + eHdrMetadataChanged = 0x04000000, + eSurfaceDamageRegionChanged = 0x08000000, + eApiChanged = 0x10000000, + eSidebandStreamChanged = 0x20000000, }; layer_state_t() - : what(0), - x(0), y(0), z(0), w(0), h(0), layerStack(0), - alpha(0), flags(0), mask(0), - reserved(0), crop(Rect::INVALID_RECT), - finalCrop(Rect::INVALID_RECT), frameNumber(0), - overrideScalingMode(-1) - { + : what(0), + x(0), + y(0), + z(0), + w(0), + h(0), + layerStack(0), + alpha(0), + flags(0), + mask(0), + reserved(0), + crop_legacy(Rect::INVALID_RECT), + finalCrop_legacy(Rect::INVALID_RECT), + frameNumber_legacy(0), + overrideScalingMode(-1), + transform(0), + transformToDisplayInverse(false), + crop(Rect::INVALID_RECT), + dataspace(ui::Dataspace::UNKNOWN), + surfaceDamageRegion(), + api(-1) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; + hdrMetadata.validTypes = 0; } void merge(const layer_state_t& other); - status_t write(Parcel& output) const; - status_t read(const Parcel& input); - - struct matrix22_t { - float dsdx{0}; - float dtdx{0}; - float dtdy{0}; - float dsdy{0}; - }; - sp<IBinder> surface; - uint32_t what; - float x; - float y; - int32_t z; - uint32_t w; - uint32_t h; - uint32_t layerStack; - float alpha; - uint8_t flags; - uint8_t mask; - uint8_t reserved; - matrix22_t matrix; - Rect crop; - Rect finalCrop; - sp<IBinder> barrierHandle; - sp<IBinder> reparentHandle; - uint64_t frameNumber; - int32_t overrideScalingMode; - - sp<IGraphicBufferProducer> barrierGbp; - - sp<IBinder> relativeLayerHandle; - - sp<IBinder> parentHandleForChild; - - half3 color; - - // non POD must be last. see write/read - Region transparentRegion; + status_t write(Parcel& output) const; + status_t read(const Parcel& input); + + struct matrix22_t { + float dsdx{0}; + float dtdx{0}; + float dtdy{0}; + float dsdy{0}; + }; + sp<IBinder> surface; + uint32_t what; + float x; + float y; + int32_t z; + uint32_t w; + uint32_t h; + uint32_t layerStack; + float alpha; + uint8_t flags; + uint8_t mask; + uint8_t reserved; + matrix22_t matrix; + Rect crop_legacy; + Rect finalCrop_legacy; + sp<IBinder> barrierHandle_legacy; + sp<IBinder> reparentHandle; + uint64_t frameNumber_legacy; + int32_t overrideScalingMode; + + sp<IGraphicBufferProducer> barrierGbp_legacy; + + sp<IBinder> relativeLayerHandle; + + sp<IBinder> parentHandleForChild; + + half3 color; + + // non POD must be last. see write/read + Region transparentRegion; + + uint32_t transform; + bool transformToDisplayInverse; + Rect crop; + sp<GraphicBuffer> buffer; + sp<Fence> acquireFence; + ui::Dataspace dataspace; + HdrMetadata hdrMetadata; + Region surfaceDamageRegion; + int32_t api; + sp<NativeHandle> sidebandStream; }; struct ComposerState { sp<ISurfaceComposerClient> client; layer_state_t state; - status_t write(Parcel& output) const; - status_t read(const Parcel& input); + status_t write(Parcel& output) const; + status_t read(const Parcel& input); }; struct DisplayState { - enum { - eOrientationDefault = 0, - eOrientation90 = 1, - eOrientation180 = 2, - eOrientation270 = 3, - eOrientationUnchanged = 4, - eOrientationSwapMask = 0x01 + eOrientationDefault = 0, + eOrientation90 = 1, + eOrientation180 = 2, + eOrientation270 = 3, + eOrientationUnchanged = 4, + eOrientationSwapMask = 0x01 }; enum { - eSurfaceChanged = 0x01, - eLayerStackChanged = 0x02, - eDisplayProjectionChanged = 0x04, - eDisplaySizeChanged = 0x08 + eSurfaceChanged = 0x01, + eLayerStackChanged = 0x02, + eDisplayProjectionChanged = 0x04, + eDisplaySizeChanged = 0x08 }; DisplayState(); @@ -160,21 +194,18 @@ struct DisplayState { status_t read(const Parcel& input); }; -static inline -int compare_type(const ComposerState& lhs, const ComposerState& rhs) { +static inline int compare_type(const ComposerState& lhs, const ComposerState& rhs) { if (lhs.client < rhs.client) return -1; if (lhs.client > rhs.client) return 1; - if (lhs.state.surface < rhs.state.surface) return -1; - if (lhs.state.surface > rhs.state.surface) return 1; + if (lhs.state.surface < rhs.state.surface) return -1; + if (lhs.state.surface > rhs.state.surface) return 1; return 0; } -static inline -int compare_type(const DisplayState& lhs, const DisplayState& rhs) { +static inline int compare_type(const DisplayState& lhs, const DisplayState& rhs) { return compare_type(lhs.token, rhs.token); } }; // namespace android #endif // ANDROID_SF_LAYER_STATE_H - diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 9aeafae198..32ee595d45 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -80,7 +80,7 @@ public: /* convenience function to check that the given surface is non NULL as * well as its IGraphicBufferProducer */ static bool isValid(const sp<Surface>& surface) { - return surface != NULL && surface->getIGraphicBufferProducer() != NULL; + return surface != nullptr && surface->getIGraphicBufferProducer() != nullptr; } /* Attaches a sideband buffer stream to the Surface's IGraphicBufferProducer. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 377fe68c41..4907866d0f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -69,7 +69,7 @@ public: // callback when the composer is dies status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& recipient, - void* cookie = NULL, uint32_t flags = 0); + void* cookie = nullptr, uint32_t flags = 0); // Get a list of supported configurations for a given display static status_t getDisplayConfigs(const sp<IBinder>& display, @@ -200,22 +200,21 @@ public: float alpha); Transaction& setMatrix(const sp<SurfaceControl>& sc, float dsdx, float dtdx, float dtdy, float dsdy); - Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop); - Transaction& setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop); + Transaction& setCrop_legacy(const sp<SurfaceControl>& sc, const Rect& crop); + Transaction& setFinalCrop_legacy(const sp<SurfaceControl>& sc, const Rect& crop); Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack); // Defers applying any changes made in this transaction until the Layer // identified by handle reaches the given frameNumber. If the Layer identified // by handle is removed, then we will apply this transaction regardless of // what frame number has been reached. - Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc, - const sp<IBinder>& handle, - uint64_t frameNumber); - // A variant of deferTransactionUntil which identifies the Layer we wait for by + Transaction& deferTransactionUntil_legacy(const sp<SurfaceControl>& sc, + const sp<IBinder>& handle, uint64_t frameNumber); + // A variant of deferTransactionUntil_legacy which identifies the Layer we wait for by // Surface instead of Handle. Useful for clients which may not have the // SurfaceControl for some of their Surfaces. Otherwise behaves identically. - Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc, - const sp<Surface>& barrierSurface, - uint64_t frameNumber); + Transaction& deferTransactionUntil_legacy(const sp<SurfaceControl>& sc, + const sp<Surface>& barrierSurface, + uint64_t frameNumber); // Reparents all children of this layer to the new parent handle. Transaction& reparentChildren(const sp<SurfaceControl>& sc, const sp<IBinder>& newParentHandle); @@ -228,6 +227,20 @@ public: Transaction& setColor(const sp<SurfaceControl>& sc, const half3& color); + Transaction& setTransform(const sp<SurfaceControl>& sc, uint32_t transform); + Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc, + bool transformToDisplayInverse); + Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop); + Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer); + Transaction& setAcquireFence(const sp<SurfaceControl>& sc, const sp<Fence>& fence); + Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace); + Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata); + Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc, + const Region& surfaceDamageRegion); + Transaction& setApi(const sp<SurfaceControl>& sc, int32_t api); + Transaction& setSidebandStream(const sp<SurfaceControl>& sc, + const sp<NativeHandle>& sidebandStream); + // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. // The child SurfaceControls will not throw exceptions or return errors, diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index bd987dd638..ccb30fa8e7 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -48,11 +48,11 @@ public: void writeToParcel(Parcel* parcel); static bool isValid(const sp<SurfaceControl>& surface) { - return (surface != 0) && surface->isValid(); + return (surface != nullptr) && surface->isValid(); } bool isValid() { - return mHandle!=0 && mClient!=0; + return mHandle!=nullptr && mClient!=nullptr; } static bool isSameSurface( diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index 01e90e0eb8..02064c6cef 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -50,9 +50,12 @@ cc_test { ], } -// Build a separate binary for each source file to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) +// Build a separate binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) +// This test has a main method, and requires a separate binary to be built. +// To add move tests like this, just add additional cc_test statements, +// as opposed to adding more source files to this one. cc_test { - name: "libgui_separate_binary_test", + name: "SurfaceParcelable_test", test_suites: ["device-tests"], clang: true, @@ -61,7 +64,6 @@ cc_test { "-Werror", ], - test_per_src: true, srcs: [ "SurfaceParcelable_test.cpp", ], diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 9a208593ab..119e888edb 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -61,7 +61,7 @@ protected: } void GetMinUndequeuedBufferCount(int* bufferCount) { - ASSERT_TRUE(bufferCount != NULL); + ASSERT_TRUE(bufferCount != nullptr); ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, bufferCount)); ASSERT_GE(*bufferCount, 0); @@ -82,7 +82,7 @@ protected: sp<Fence> fence; input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, - &scalingMode, &transform, &fence, NULL); + &scalingMode, &transform, &fence, nullptr); ASSERT_EQ(timestamp, item.mTimestamp); ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp); ASSERT_EQ(dataSpace, item.mDataSpace); @@ -128,17 +128,17 @@ TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) { sp<IBinder> binderProducer = serviceManager->getService(PRODUCER_NAME); mProducer = interface_cast<IGraphicBufferProducer>(binderProducer); - EXPECT_TRUE(mProducer != NULL); + EXPECT_TRUE(mProducer != nullptr); sp<IBinder> binderConsumer = serviceManager->getService(CONSUMER_NAME); mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer); - EXPECT_TRUE(mConsumer != NULL); + EXPECT_TRUE(mConsumer != nullptr); sp<DummyConsumer> dc(new DummyConsumer); ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); IGraphicBufferProducer::QueueBufferOutput output; ASSERT_EQ(OK, - mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output)); + mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output)); int slot; sp<Fence> fence; @@ -353,8 +353,8 @@ TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) { ASSERT_EQ(OK, buffer->unlock()); int newSlot; - ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(NULL, safeToClobberBuffer)); - ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL)); + ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer)); + ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr)); ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer)); IGraphicBufferProducer::QueueBufferInput input(0, false, @@ -412,8 +412,8 @@ TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { int newSlot; sp<GraphicBuffer> safeToClobberBuffer; - ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer)); - ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL)); + ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer)); + ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr)); ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer)); ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY, diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp index 36be7d9368..00e32d9124 100644 --- a/libs/gui/tests/CpuConsumer_test.cpp +++ b/libs/gui/tests/CpuConsumer_test.cpp @@ -484,12 +484,12 @@ void produceOneFrame(const sp<ANativeWindow>& anw, err = native_window_dequeue_buffer_and_wait(anw.get(), &anb); ASSERT_NO_ERROR(err, "dequeueBuffer error: "); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); *stride = buf->getStride(); - uint8_t* img = NULL; + uint8_t* img = nullptr; ALOGVV("Lock buffer from %p for write", anw.get()); err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); @@ -554,7 +554,7 @@ TEST_P(CpuConsumerTest, FromCpuSingle) { err = mCC->lockNextBuffer(&b); ASSERT_NO_ERROR(err, "getNextBuffer error: "); - ASSERT_TRUE(b.data != NULL); + ASSERT_TRUE(b.data != nullptr); EXPECT_EQ(params.width, b.width); EXPECT_EQ(params.height, b.height); EXPECT_EQ(params.format, b.format); @@ -595,7 +595,7 @@ TEST_P(CpuConsumerTest, FromCpuManyInQueue) { err = mCC->lockNextBuffer(&b); ASSERT_NO_ERROR(err, "getNextBuffer error: "); - ASSERT_TRUE(b.data != NULL); + ASSERT_TRUE(b.data != nullptr); EXPECT_EQ(params.width, b.width); EXPECT_EQ(params.height, b.height); EXPECT_EQ(params.format, b.format); @@ -637,7 +637,7 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { err = mCC->lockNextBuffer(&b[i]); ASSERT_NO_ERROR(err, "getNextBuffer error: "); - ASSERT_TRUE(b[i].data != NULL); + ASSERT_TRUE(b[i].data != nullptr); EXPECT_EQ(params.width, b[i].width); EXPECT_EQ(params.height, b[i].height); EXPECT_EQ(params.format, b[i].format); @@ -660,7 +660,7 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { err = mCC->lockNextBuffer(&bTooMuch); ASSERT_NO_ERROR(err, "Did not allow new lock after unlock"); - ASSERT_TRUE(bTooMuch.data != NULL); + ASSERT_TRUE(bTooMuch.data != nullptr); EXPECT_EQ(params.width, bTooMuch.width); EXPECT_EQ(params.height, bTooMuch.height); EXPECT_EQ(params.format, bTooMuch.format); diff --git a/libs/gui/tests/FillBuffer.cpp b/libs/gui/tests/FillBuffer.cpp index ccd674fcb8..b60995a624 100644 --- a/libs/gui/tests/FillBuffer.cpp +++ b/libs/gui/tests/FillBuffer.cpp @@ -93,11 +93,11 @@ void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) { android_native_buffer_t* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); - uint8_t* img = NULL; + uint8_t* img = nullptr; ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img))); fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride()); diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp index a91552f7fe..a1405fcb11 100644 --- a/libs/gui/tests/GLTest.cpp +++ b/libs/gui/tests/GLTest.cpp @@ -50,7 +50,7 @@ void GLTest::SetUp() { ASSERT_EQ(EGL_SUCCESS, eglGetError()); char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS"); - if (displaySecsEnv != NULL) { + if (displaySecsEnv != nullptr) { mDisplaySecs = atoi(displaySecsEnv); if (mDisplaySecs < 0) { mDisplaySecs = 0; @@ -67,7 +67,7 @@ void GLTest::SetUp() { String8("Test Surface"), getSurfaceWidth(), getSurfaceHeight(), PIXEL_FORMAT_RGB_888, 0); - ASSERT_TRUE(mSurfaceControl != NULL); + ASSERT_TRUE(mSurfaceControl != nullptr); ASSERT_TRUE(mSurfaceControl->isValid()); Transaction t; @@ -117,7 +117,7 @@ void GLTest::TearDown() { sleep(mDisplaySecs); } - if (mComposerClient != NULL) { + if (mComposerClient != nullptr) { mComposerClient->dispose(); } if (mEglContext != EGL_NO_CONTEXT) { @@ -171,7 +171,7 @@ EGLint GLTest::getSurfaceHeight() { EGLSurface GLTest::createWindowSurface(EGLDisplay display, EGLConfig config, sp<ANativeWindow>& window) const { - return eglCreateWindowSurface(display, config, window.get(), NULL); + return eglCreateWindowSurface(display, config, window.get(), nullptr); } ::testing::AssertionResult GLTest::checkPixel(int x, int y, @@ -256,7 +256,7 @@ void GLTest::loadShader(GLenum shaderType, const char* pSource, GLuint shader = glCreateShader(shaderType); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); if (shader) { - glShaderSource(shader, 1, &pSource, NULL); + glShaderSource(shader, 1, &pSource, nullptr); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); glCompileShader(shader); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); @@ -270,7 +270,7 @@ void GLTest::loadShader(GLenum shaderType, const char* pSource, if (infoLen) { char* buf = (char*) malloc(infoLen); if (buf) { - glGetShaderInfoLog(shader, infoLen, NULL, buf); + glGetShaderInfoLog(shader, infoLen, nullptr, buf); printf("Shader compile log:\n%s\n", buf); free(buf); FAIL(); @@ -278,7 +278,7 @@ void GLTest::loadShader(GLenum shaderType, const char* pSource, } else { char* buf = (char*) malloc(0x1000); if (buf) { - glGetShaderInfoLog(shader, 0x1000, NULL, buf); + glGetShaderInfoLog(shader, 0x1000, nullptr, buf); printf("Shader compile log:\n%s\n", buf); free(buf); FAIL(); @@ -322,7 +322,7 @@ void GLTest::createProgram(const char* pVertexSource, if (bufLength) { char* buf = (char*) malloc(bufLength); if (buf) { - glGetProgramInfoLog(program, bufLength, NULL, buf); + glGetProgramInfoLog(program, bufLength, nullptr, buf); printf("Program link log:\n%s\n", buf); free(buf); FAIL(); diff --git a/libs/gui/tests/GLTest.h b/libs/gui/tests/GLTest.h index f0d27a8a34..f290b3c68d 100644 --- a/libs/gui/tests/GLTest.h +++ b/libs/gui/tests/GLTest.h @@ -39,7 +39,7 @@ protected: mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT), - mGlConfig(NULL) { + mGlConfig(nullptr) { } virtual void SetUp(); diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp index a35cf11174..6d03374810 100644 --- a/libs/gui/tests/IGraphicBufferProducer_test.cpp +++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp @@ -228,9 +228,9 @@ protected: void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence, sp<GraphicBuffer> *buffer) { - ASSERT_TRUE(slot != NULL); - ASSERT_TRUE(fence != NULL); - ASSERT_TRUE(buffer != NULL); + ASSERT_TRUE(slot != nullptr); + ASSERT_TRUE(fence != nullptr); + ASSERT_TRUE(buffer != nullptr); ASSERT_NO_FATAL_FAILURE(ConnectProducer()); @@ -263,7 +263,7 @@ TEST_P(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) { EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN, TEST_API, TEST_CONTROLLED_BY_APP, - /*output*/NULL)); + /*output*/nullptr)); // Invalid API returns bad value EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN, @@ -359,7 +359,7 @@ TEST_P(IGraphicBufferProducerTest, Query_ReturnsError) { // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP // Value was NULL - EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/NULL)); + EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/nullptr)); ASSERT_OK(mConsumer->consumerDisconnect()); @@ -465,7 +465,7 @@ TEST_P(IGraphicBufferProducerTest, Queue_ReturnsError) { // Fence was NULL { - sp<Fence> nullFence = NULL; + sp<Fence> nullFence = nullptr; IGraphicBufferProducer::QueueBufferInput input = QueueBufferInputBuilder().setFence(nullFence).build(); @@ -695,10 +695,7 @@ TEST_P(IGraphicBufferProducerTest, sp<Fence> fence; sp<GraphicBuffer> buffer; - if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { - // TODO(b/38137191): Implement BufferHubProducer::detachBuffer - ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence)); - } + ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence)); } TEST_P(IGraphicBufferProducerTest, @@ -735,10 +732,7 @@ TEST_P(IGraphicBufferProducerTest, ASSERT_OK(mProducer->disconnect(TEST_API)); - if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { - // TODO(b/38137191): Implement BufferHubProducer::detachBuffer - ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot)); - } + ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot)); } TEST_P(IGraphicBufferProducerTest, @@ -778,18 +772,46 @@ TEST_P(IGraphicBufferProducerTest, sp<GraphicBuffer> buffer; setupDequeueRequestBuffer(&slot, &fence, &buffer); + ASSERT_TRUE(buffer != nullptr); - if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { - // TODO(b/38137191): Implement BufferHubProducer::detachBuffer - ASSERT_OK(mProducer->detachBuffer(slot)); + ASSERT_OK(mProducer->detachBuffer(slot)); + EXPECT_OK(buffer->initCheck()); + + if (GetParam() == USE_BUFFER_HUB_PRODUCER) { + // For a GraphicBuffer backed by BufferHub, once detached from an IGBP, it should have + // isDetachedBuffer() set. Note that this only applies to BufferHub. + EXPECT_TRUE(buffer->isDetachedBuffer()); + } else { + EXPECT_FALSE(buffer->isDetachedBuffer()); } ASSERT_OK(mProducer->disconnect(TEST_API)); - if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { - // TODO(b/69981968): Implement BufferHubProducer::attachBuffer - ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer)); + ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer)); +} + +TEST_P(IGraphicBufferProducerTest, DetachThenAttach_Succeeds) { + int slot = -1; + sp<Fence> fence; + sp<GraphicBuffer> buffer; + + setupDequeueRequestBuffer(&slot, &fence, &buffer); + ASSERT_TRUE(buffer != nullptr); + + ASSERT_OK(mProducer->detachBuffer(slot)); + EXPECT_OK(buffer->initCheck()); + + if (GetParam() == USE_BUFFER_HUB_PRODUCER) { + // For a GraphicBuffer backed by BufferHub, once detached from an IGBP, it should have + // isDetachedBuffer() set. Note that this only applies to BufferHub. + EXPECT_TRUE(buffer->isDetachedBuffer()); + } else { + EXPECT_FALSE(buffer->isDetachedBuffer()); } + + EXPECT_OK(mProducer->attachBuffer(&slot, buffer)); + EXPECT_FALSE(buffer->isDetachedBuffer()); + EXPECT_OK(buffer->initCheck()); } #if USE_BUFFER_HUB_AS_BUFFER_QUEUE diff --git a/libs/gui/tests/MultiTextureConsumer_test.cpp b/libs/gui/tests/MultiTextureConsumer_test.cpp index 3a25ac59ca..7d3d4aa412 100644 --- a/libs/gui/tests/MultiTextureConsumer_test.cpp +++ b/libs/gui/tests/MultiTextureConsumer_test.cpp @@ -47,7 +47,7 @@ protected: GLTest::TearDown(); } virtual EGLint const* getContextAttribs() { - return NULL; + return nullptr; } virtual EGLint const* getConfigAttribs() { static EGLint sDefaultConfigAttribs[] = { @@ -105,7 +105,7 @@ TEST_F(MultiTextureConsumerTest, EGLImageTargetWorks) { glClear(GL_COLOR_BUFFER_BIT); for (int i=0 ; i<8 ; i++) { - mSurface->lock(&buffer, NULL); + mSurface->lock(&buffer, nullptr); memset(buffer.bits, (i&7) * 0x20, buffer.stride * buffer.height * 4); mSurface->unlockAndPost(); diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index d5b2f004ed..65e09f2540 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -29,7 +29,6 @@ #include <utils/Thread.h> extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); -#define CROP_EXT_STR "EGL_ANDROID_image_crop" namespace android { @@ -39,7 +38,7 @@ protected: mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT), - mEglConfig(NULL) { + mEglConfig(nullptr) { } virtual void SetUp() { @@ -82,7 +81,7 @@ protected: ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_SURFACE, mEglSurface); - mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, 0); + mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_CONTEXT, mEglContext); @@ -127,7 +126,7 @@ protected: TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) { sp<IGraphicBufferProducer> ist(mSTC->getIGraphicBufferProducer()); - ASSERT_TRUE(ist != NULL); + ASSERT_TRUE(ist != nullptr); } TEST_F(SurfaceTextureClientTest, QueuesToWindowCompositorIsFalse) { @@ -155,7 +154,7 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { EXPECT_TRUE(eglInitialize(dpy, &majorVersion, &minorVersion)); ASSERT_EQ(EGL_SUCCESS, eglGetError()); - EGLConfig myConfig = {0}; + EGLConfig myConfig = {nullptr}; EGLint numConfigs = 0; EGLint configAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, @@ -172,7 +171,7 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { ASSERT_EQ(EGL_SUCCESS, eglGetError()); EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, mANW.get(), - NULL); + nullptr); EXPECT_NE(EGL_NO_SURFACE, eglSurface); EXPECT_EQ(EGL_SUCCESS, eglGetError()); @@ -185,7 +184,7 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { TEST_F(SurfaceTextureClientTest, EglSwapBuffersAbandonErrorIsEglBadSurface) { - EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, mANW.get(), NULL); + EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, mANW.get(), nullptr); EXPECT_NE(EGL_NO_SURFACE, eglSurface); EXPECT_EQ(EGL_SUCCESS, eglGetError()); @@ -638,18 +637,6 @@ TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) } TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWithCrop) { - // Query to see if the image crop extension exists - EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS); - size_t cropExtLen = strlen(CROP_EXT_STR); - size_t extsLen = strlen(exts); - bool equal = !strcmp(CROP_EXT_STR, exts); - bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1); - bool atEnd = (cropExtLen+1) < extsLen && - !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1)); - bool inMiddle = strstr(exts, " " CROP_EXT_STR " "); - bool hasEglAndroidImageCrop = equal || atStart || atEnd || inMiddle; - android_native_buffer_t* buf[3]; float mtx[16] = {}; android_native_rect_t crop; @@ -669,17 +656,15 @@ TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWi ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers mST->getTransformMatrix(mtx); - // If the egl image crop extension is not present, this accounts for the - // .5 texel shrink for each edge that's included in the transform matrix - // to avoid texturing outside the crop region. Otherwise the crop is not - // included in the transform matrix. - EXPECT_EQ(hasEglAndroidImageCrop ? 1 : 0.5, mtx[0]); + // This accounts for the .5 texel shrink for each edge that's included in + // the transform matrix to avoid texturing outside the crop region. + EXPECT_EQ(0.5f, mtx[0]); EXPECT_EQ(0.f, mtx[1]); EXPECT_EQ(0.f, mtx[2]); EXPECT_EQ(0.f, mtx[3]); EXPECT_EQ(0.f, mtx[4]); - EXPECT_EQ(hasEglAndroidImageCrop ? -1 : -0.5, mtx[5]); + EXPECT_EQ(-0.5f, mtx[5]); EXPECT_EQ(0.f, mtx[6]); EXPECT_EQ(0.f, mtx[7]); @@ -688,8 +673,8 @@ TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWi EXPECT_EQ(1.f, mtx[10]); EXPECT_EQ(0.f, mtx[11]); - EXPECT_EQ(hasEglAndroidImageCrop ? 0 : 0.0625f, mtx[12]); - EXPECT_EQ(hasEglAndroidImageCrop ? 1 : 0.5625f, mtx[13]); + EXPECT_EQ(0.0625f, mtx[12]); + EXPECT_EQ(0.5625f, mtx[13]); EXPECT_EQ(0.f, mtx[14]); EXPECT_EQ(1.f, mtx[15]); } @@ -753,7 +738,7 @@ protected: ASSERT_EQ(EGL_SUCCESS, eglGetError()); mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, - 0); + nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_CONTEXT, mEglContext); @@ -765,7 +750,7 @@ protected: GLConsumer::TEXTURE_EXTERNAL, true, false)); sp<Surface> stc(new Surface(producer)); mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig, - static_cast<ANativeWindow*>(stc.get()), NULL); + static_cast<ANativeWindow*>(stc.get()), nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_SURFACE, mEglSurfaces[i]); } diff --git a/libs/gui/tests/SurfaceTextureFBO.h b/libs/gui/tests/SurfaceTextureFBO.h index 7f1ae84c48..70f988de11 100644 --- a/libs/gui/tests/SurfaceTextureFBO.h +++ b/libs/gui/tests/SurfaceTextureFBO.h @@ -34,7 +34,7 @@ protected: glGenTextures(1, &mFboTex); glBindTexture(GL_TEXTURE_2D, mFboTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(), - getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(GL_TEXTURE_2D, 0); ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp index 0134273a07..f34561f668 100644 --- a/libs/gui/tests/SurfaceTextureFBO_test.cpp +++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp @@ -39,12 +39,12 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { android_native_buffer_t* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); // Fill the buffer with green - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255, 0, 255); @@ -63,7 +63,7 @@ TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); buf = GraphicBuffer::from(anb); diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h index 2ce20eb2b1..03975b1261 100644 --- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h +++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h @@ -158,7 +158,7 @@ protected: } virtual void TearDown() { - if (mProducerThread != NULL) { + if (mProducerThread != nullptr) { mProducerThread->requestExitAndWait(); } mProducerThread.clear(); @@ -167,7 +167,7 @@ protected: } void runProducerThread(const sp<ProducerThread> producerThread) { - ASSERT_TRUE(mProducerThread == NULL); + ASSERT_TRUE(mProducerThread == nullptr); mProducerThread = producerThread; producerThread->setEglObjects(mEglDisplay, mProducerEglSurface, mProducerEglContext); diff --git a/libs/gui/tests/SurfaceTextureGLToGL.h b/libs/gui/tests/SurfaceTextureGLToGL.h index 5d43a48898..3a87c12cf6 100644 --- a/libs/gui/tests/SurfaceTextureGLToGL.h +++ b/libs/gui/tests/SurfaceTextureGLToGL.h @@ -38,7 +38,7 @@ protected: void SetUpWindowAndContext() { mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, - mANW.get(), NULL); + mANW.get(), nullptr); ASSERT_EQ(EGL_SUCCESS, eglGetError()); ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface); diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp index 56392867ea..e2b4f3d035 100644 --- a/libs/gui/tests/SurfaceTextureGL_test.cpp +++ b/libs/gui/tests/SurfaceTextureGL_test.cpp @@ -40,12 +40,12 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { ANativeWindowBuffer* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); // Fill the buffer with the a checkerboard pattern - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); buf->unlock(); @@ -90,12 +90,12 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) { ANativeWindowBuffer* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); // Fill the buffer with the a checkerboard pattern - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); buf->unlock(); @@ -155,11 +155,11 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { ANativeWindowBuffer* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); - ASSERT_TRUE(anb != NULL); + ASSERT_TRUE(anb != nullptr); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop); buf->unlock(); @@ -234,7 +234,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } @@ -248,7 +248,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2; int yuvTexStrideU = yuvTexStrideV; - uint8_t* img = NULL; + uint8_t* img = nullptr; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); // Gray out all the test pixels first, so we're more likely to @@ -457,7 +457,7 @@ TEST_F(SurfaceTextureGLTest, DisconnectStressTest) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } if (mANW->queueBuffer(mANW.get(), anb, -1) @@ -641,7 +641,7 @@ TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } if (mANW->queueBuffer(mANW.get(), anb, -1) @@ -654,7 +654,7 @@ TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { &anb) != NO_ERROR) { return false; } - if (anb == NULL) { + if (anb == nullptr) { return false; } if (mANW->queueBuffer(mANW.get(), anb, -1) diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 2c02ba657d..3542aba83f 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -72,7 +72,7 @@ protected: mSurfaceControl = mComposerClient->createSurface( String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(mSurfaceControl != NULL); + ASSERT_TRUE(mSurfaceControl != nullptr); ASSERT_TRUE(mSurfaceControl->isValid()); Transaction t; @@ -81,7 +81,7 @@ protected: .apply()); mSurface = mSurfaceControl->getSurface(); - ASSERT_TRUE(mSurface != NULL); + ASSERT_TRUE(mSurface != nullptr); } virtual void TearDown() { @@ -145,7 +145,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), GRALLOC_USAGE_PROTECTED)); ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); - ANativeWindowBuffer* buf = 0; + ANativeWindowBuffer* buf = nullptr; status_t err = native_window_dequeue_buffer_and_wait(anw.get(), &buf); if (err) { diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index a6246636a3..8a15e2f40f 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -31,14 +31,16 @@ namespace android { // --- InputEvent --- -void InputEvent::initialize(int32_t deviceId, int32_t source) { +void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId) { mDeviceId = deviceId; mSource = source; + mDisplayId = displayId; } void InputEvent::initialize(const InputEvent& from) { mDeviceId = from.mDeviceId; mSource = from.mSource; + mDisplayId = from.mDisplayId; } // --- KeyEvent --- @@ -54,6 +56,7 @@ int32_t KeyEvent::getKeyCodeFromLabel(const char* label) { void KeyEvent::initialize( int32_t deviceId, int32_t source, + int32_t displayId, int32_t action, int32_t flags, int32_t keyCode, @@ -62,7 +65,7 @@ void KeyEvent::initialize( int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime) { - InputEvent::initialize(deviceId, source); + InputEvent::initialize(deviceId, source, displayId); mAction = action; mFlags = flags; mKeyCode = keyCode; @@ -215,6 +218,7 @@ void PointerProperties::copyFrom(const PointerProperties& other) { void MotionEvent::initialize( int32_t deviceId, int32_t source, + int32_t displayId, int32_t action, int32_t actionButton, int32_t flags, @@ -230,7 +234,7 @@ void MotionEvent::initialize( size_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) { - InputEvent::initialize(deviceId, source); + InputEvent::initialize(deviceId, source, displayId); mAction = action; mActionButton = actionButton; mFlags = flags; @@ -250,7 +254,7 @@ void MotionEvent::initialize( } void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { - InputEvent::initialize(other->mDeviceId, other->mSource); + InputEvent::initialize(other->mDeviceId, other->mSource, other->mDisplayId); mAction = other->mAction; mActionButton = other->mActionButton; mFlags = other->mFlags; @@ -431,6 +435,7 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) { mDeviceId = parcel->readInt32(); mSource = parcel->readInt32(); + mDisplayId = parcel->readInt32(); mAction = parcel->readInt32(); mActionButton = parcel->readInt32(); mFlags = parcel->readInt32(); @@ -480,6 +485,7 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { parcel->writeInt32(mDeviceId); parcel->writeInt32(mSource); + parcel->writeInt32(mDisplayId); parcel->writeInt32(mAction); parcel->writeInt32(mActionButton); parcel->writeInt32(mFlags); diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 4287abeb7d..5d27bf687d 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -175,7 +175,7 @@ const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( return ⦥ } } - return NULL; + return nullptr; } void InputDeviceInfo::addSource(uint32_t source) { diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index aa0bf17ca3..770d48397e 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -226,7 +226,7 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { sp<InputChannel> InputChannel::dup() const { int fd = ::dup(getFd()); - return fd >= 0 ? new InputChannel(getName(), fd) : NULL; + return fd >= 0 ? new InputChannel(getName(), fd) : nullptr; } @@ -243,6 +243,7 @@ status_t InputPublisher::publishKeyEvent( uint32_t seq, int32_t deviceId, int32_t source, + int32_t displayId, int32_t action, int32_t flags, int32_t keyCode, @@ -270,6 +271,7 @@ status_t InputPublisher::publishKeyEvent( msg.body.key.seq = seq; msg.body.key.deviceId = deviceId; msg.body.key.source = source; + msg.body.key.displayId = displayId; msg.body.key.action = action; msg.body.key.flags = flags; msg.body.key.keyCode = keyCode; @@ -303,13 +305,15 @@ status_t InputPublisher::publishMotionEvent( const PointerCoords* pointerCoords) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, " + "displayId=%" PRId32 ", " "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, " "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, " "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", " "pointerCount=%" PRIu32, mChannel->getName().c_str(), seq, - deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState, - xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount); + deviceId, source, displayId, action, actionButton, flags, edgeFlags, metaState, + buttonState, xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, + pointerCount); #endif if (!seq) { @@ -384,7 +388,7 @@ InputConsumer::~InputConsumer() { bool InputConsumer::isTouchResamplingEnabled() { char value[PROPERTY_VALUE_MAX]; - int length = property_get("ro.input.noresample", value, NULL); + int length = property_get("ro.input.noresample", value, nullptr); if (length > 0) { if (!strcmp("1", value)) { return false; @@ -398,16 +402,14 @@ bool InputConsumer::isTouchResamplingEnabled() { } status_t InputConsumer::consume(InputEventFactoryInterface* factory, - bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, - int32_t* displayId) { + bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64, mChannel->getName().c_str(), consumeBatches ? "true" : "false", frameTime); #endif *outSeq = 0; - *outEvent = NULL; - *displayId = -1; // Invalid display. + *outEvent = nullptr; // Fetch the next input message. // Loop until an event can be returned or no additional events are received. @@ -422,7 +424,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, if (result) { // Consume the next batched event unless batches are being held for later. if (consumeBatches || result != WOULD_BLOCK) { - result = consumeBatch(factory, frameTime, outSeq, outEvent, displayId); + result = consumeBatch(factory, frameTime, outSeq, outEvent); if (*outEvent) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u", @@ -466,7 +468,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, // the previous batch right now and defer the new message until later. mMsgDeferred = true; status_t result = consumeSamples(factory, - batch, batch.samples.size(), outSeq, outEvent, displayId); + batch, batch.samples.size(), outSeq, outEvent); mBatches.removeAt(batchIndex); if (result) { return result; @@ -500,7 +502,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, initializeMotionEvent(motionEvent, &mMsg); *outSeq = mMsg.body.motion.seq; *outEvent = motionEvent; - *displayId = mMsg.body.motion.displayId; + #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u", mChannel->getName().c_str(), *outSeq); @@ -518,14 +520,13 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, } status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) { + nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) { status_t result; for (size_t i = mBatches.size(); i > 0; ) { i--; Batch& batch = mBatches.editItemAt(i); if (frameTime < 0) { - result = consumeSamples(factory, batch, batch.samples.size(), - outSeq, outEvent, displayId); + result = consumeSamples(factory, batch, batch.samples.size(), outSeq, outEvent); mBatches.removeAt(i); return result; } @@ -539,11 +540,11 @@ status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory, continue; } - result = consumeSamples(factory, batch, split + 1, outSeq, outEvent, displayId); + result = consumeSamples(factory, batch, split + 1, outSeq, outEvent); const InputMessage* next; if (batch.samples.isEmpty()) { mBatches.removeAt(i); - next = NULL; + next = nullptr; } else { next = &batch.samples.itemAt(0); } @@ -557,7 +558,7 @@ status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory, } status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory, - Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) { + Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) { MotionEvent* motionEvent = factory->createMotionEvent(); if (! motionEvent) return NO_MEMORY; @@ -572,7 +573,6 @@ status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory, mSeqChains.push(seqChain); addSample(motionEvent, &msg); } else { - *displayId = msg.body.motion.displayId; initializeMotionEvent(motionEvent, &msg); } chain = msg.body.motion.seq; @@ -928,6 +928,7 @@ void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) event->initialize( msg->body.key.deviceId, msg->body.key.source, + msg->body.key.displayId, msg->body.key.action, msg->body.key.flags, msg->body.key.keyCode, @@ -950,6 +951,7 @@ void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage event->initialize( msg->body.motion.deviceId, msg->body.motion.source, + msg->body.motion.displayId, msg->body.motion.action, msg->body.motion.actionButton, msg->body.motion.flags, diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index cba1111606..26747bdbbc 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -164,10 +164,10 @@ status_t KeyCharacterMap::load(Tokenizer* tokenizer, sp<KeyCharacterMap> KeyCharacterMap::combine(const sp<KeyCharacterMap>& base, const sp<KeyCharacterMap>& overlay) { - if (overlay == NULL) { + if (overlay == nullptr) { return base; } - if (base == NULL) { + if (base == nullptr) { return overlay; } @@ -468,7 +468,7 @@ bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMeta // Try to find the most general behavior that maps to this character. // For example, the base key behavior will usually be last in the list. - const Behavior* found = NULL; + const Behavior* found = nullptr; for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) { if (behavior->character == ch) { found = behavior; @@ -487,7 +487,7 @@ void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents, int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) { outEvents.push(); KeyEvent& event = outEvents.editTop(); - event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, + event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode, 0, metaState, 0, time, time); } @@ -605,11 +605,11 @@ sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { map->mType = parcel->readInt32(); size_t numKeys = parcel->readInt32(); if (parcel->errorCheck()) { - return NULL; + return nullptr; } if (numKeys > MAX_KEYS) { ALOGE("Too many keys in KeyCharacterMap (%zu > %d)", numKeys, MAX_KEYS); - return NULL; + return nullptr; } for (size_t i = 0; i < numKeys; i++) { @@ -617,7 +617,7 @@ sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { char16_t label = parcel->readInt32(); char16_t number = parcel->readInt32(); if (parcel->errorCheck()) { - return NULL; + return nullptr; } Key* key = new Key(); @@ -625,14 +625,14 @@ sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { key->number = number; map->mKeys.add(keyCode, key); - Behavior* lastBehavior = NULL; + Behavior* lastBehavior = nullptr; while (parcel->readInt32()) { int32_t metaState = parcel->readInt32(); char16_t character = parcel->readInt32(); int32_t fallbackKeyCode = parcel->readInt32(); int32_t replacementKeyCode = parcel->readInt32(); if (parcel->errorCheck()) { - return NULL; + return nullptr; } Behavior* behavior = new Behavior(); @@ -649,7 +649,7 @@ sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { } if (parcel->errorCheck()) { - return NULL; + return nullptr; } } return map; @@ -666,7 +666,7 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const { parcel->writeInt32(keyCode); parcel->writeInt32(key->label); parcel->writeInt32(key->number); - for (const Behavior* behavior = key->firstBehavior; behavior != NULL; + for (const Behavior* behavior = key->firstBehavior; behavior != nullptr; behavior = behavior->next) { parcel->writeInt32(1); parcel->writeInt32(behavior->metaState); @@ -683,12 +683,12 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const { // --- KeyCharacterMap::Key --- KeyCharacterMap::Key::Key() : - label(0), number(0), firstBehavior(NULL) { + label(0), number(0), firstBehavior(nullptr) { } KeyCharacterMap::Key::Key(const Key& other) : label(other.label), number(other.number), - firstBehavior(other.firstBehavior ? new Behavior(*other.firstBehavior) : NULL) { + firstBehavior(other.firstBehavior ? new Behavior(*other.firstBehavior) : nullptr) { } KeyCharacterMap::Key::~Key() { @@ -704,11 +704,11 @@ KeyCharacterMap::Key::~Key() { // --- KeyCharacterMap::Behavior --- KeyCharacterMap::Behavior::Behavior() : - next(NULL), metaState(0), character(0), fallbackKeyCode(0), replacementKeyCode(0) { + next(nullptr), metaState(0), character(0), fallbackKeyCode(0), replacementKeyCode(0) { } KeyCharacterMap::Behavior::Behavior(const Behavior& other) : - next(other.next ? new Behavior(*other.next) : NULL), + next(other.next ? new Behavior(*other.next) : nullptr), metaState(other.metaState), character(other.character), fallbackKeyCode(other.fallbackKeyCode), replacementKeyCode(other.replacementKeyCode) { diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index 2b2f13e4c7..c440078666 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -117,7 +117,7 @@ const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCod return &mKeysByScanCode.valueAt(index); } } - return NULL; + return nullptr; } status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const { diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp index c07a81245a..118f3aacd9 100644 --- a/libs/input/VelocityTracker.cpp +++ b/libs/input/VelocityTracker.cpp @@ -115,7 +115,7 @@ VelocityTracker::VelocityTracker(const char* strategy) : // Allow the default strategy to be overridden using a system property for debugging. if (!strategy) { - int length = property_get("debug.velocitytracker.strategy", value, NULL); + int length = property_get("persist.input.velocitytracker.strategy", value, nullptr); if (length > 0) { strategy = value; } else { @@ -139,7 +139,7 @@ VelocityTracker::~VelocityTracker() { bool VelocityTracker::configureStrategy(const char* strategy) { mStrategy = createStrategy(strategy); - return mStrategy != NULL; + return mStrategy != nullptr; } VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) { @@ -204,7 +204,7 @@ VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) { // time to adjust to changes in direction. return new LegacyVelocityTrackerStrategy(); } - return NULL; + return nullptr; } void VelocityTracker::clear() { diff --git a/libs/input/VirtualKeyMap.cpp b/libs/input/VirtualKeyMap.cpp index 28ea7177cf..993297319e 100644 --- a/libs/input/VirtualKeyMap.cpp +++ b/libs/input/VirtualKeyMap.cpp @@ -47,7 +47,7 @@ VirtualKeyMap::~VirtualKeyMap() { } status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) { - *outMap = NULL; + *outMap = nullptr; Tokenizer* tokenizer; status_t status = Tokenizer::open(filename, &tokenizer); diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index aca9521c76..f06119f3f7 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -1,7 +1,6 @@ // Build the unit tests. cc_test { name: "libinput_tests", - test_per_src: true, srcs: [ "InputChannel_test.cpp", "InputEvent_test.cpp", diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index fd3b7c8ee4..99f83ba7db 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -22,6 +22,9 @@ namespace android { +// Default display id. +static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT; + class BaseTest : public testing::Test { protected: virtual void SetUp() { } @@ -178,13 +181,14 @@ TEST_F(KeyEventTest, Properties) { // Initialize and get properties. const nsecs_t ARBITRARY_DOWN_TIME = 1; const nsecs_t ARBITRARY_EVENT_TIME = 2; - event.initialize(2, AINPUT_SOURCE_GAMEPAD, AKEY_EVENT_ACTION_DOWN, + event.initialize(2, AINPUT_SOURCE_GAMEPAD, DISPLAY_ID, AKEY_EVENT_ACTION_DOWN, AKEY_EVENT_FLAG_FROM_SYSTEM, AKEYCODE_BUTTON_X, 121, AMETA_ALT_ON, 1, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME); ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType()); ASSERT_EQ(2, event.getDeviceId()); ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_GAMEPAD), event.getSource()); + ASSERT_EQ(DISPLAY_ID, event.getDisplayId()); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction()); ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags()); ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode()); @@ -197,6 +201,11 @@ TEST_F(KeyEventTest, Properties) { // Set source. event.setSource(AINPUT_SOURCE_JOYSTICK); ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource()); + + // Set display id. + constexpr int32_t newDisplayId = 2; + event.setDisplayId(newDisplayId); + ASSERT_EQ(newDisplayId, event.getDisplayId()); } @@ -248,7 +257,7 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28); - event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, 0, + event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, X_OFFSET, Y_OFFSET, 2.0f, 2.1f, @@ -301,6 +310,7 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()); ASSERT_EQ(2, event->getDeviceId()); ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_TOUCHSCREEN), event->getSource()); + ASSERT_EQ(DISPLAY_ID, event->getDisplayId()); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags()); ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags()); @@ -434,6 +444,11 @@ TEST_F(MotionEventTest, Properties) { event.setSource(AINPUT_SOURCE_JOYSTICK); ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource()); + // Set displayId. + constexpr int32_t newDisplayId = 2; + event.setDisplayId(newDisplayId); + ASSERT_EQ(newDisplayId, event.getDisplayId()); + // Set action. event.setAction(AMOTION_EVENT_ACTION_CANCEL); ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction()); @@ -557,7 +572,7 @@ TEST_F(MotionEventTest, Transform) { pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle); } MotionEvent event; - event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0, + event.initialize(0, 0, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords); float originalRawX = 0 + 3; float originalRawY = -RADIUS + 2; diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index c5322414fd..0788c89b2a 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -46,12 +46,12 @@ protected: virtual void TearDown() { if (mPublisher) { delete mPublisher; - mPublisher = NULL; + mPublisher = nullptr; } if (mConsumer) { delete mConsumer; - mConsumer = NULL; + mConsumer = nullptr; } serverChannel.clear(); @@ -70,32 +70,31 @@ TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) { void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { status_t status; - const uint32_t seq = 15; - const int32_t deviceId = 1; - const int32_t source = AINPUT_SOURCE_KEYBOARD; - const int32_t action = AKEY_EVENT_ACTION_DOWN; - const int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM; - const int32_t keyCode = AKEYCODE_ENTER; - const int32_t scanCode = 13; - const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; - const int32_t repeatCount = 1; - const nsecs_t downTime = 3; - const nsecs_t eventTime = 4; - - status = mPublisher->publishKeyEvent(seq, deviceId, source, action, flags, + constexpr uint32_t seq = 15; + constexpr int32_t deviceId = 1; + constexpr int32_t source = AINPUT_SOURCE_KEYBOARD; + constexpr int32_t displayId = ADISPLAY_ID_DEFAULT; + constexpr int32_t action = AKEY_EVENT_ACTION_DOWN; + constexpr int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM; + constexpr int32_t keyCode = AKEYCODE_ENTER; + constexpr int32_t scanCode = 13; + constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; + constexpr int32_t repeatCount = 1; + constexpr nsecs_t downTime = 3; + constexpr nsecs_t eventTime = 4; + + status = mPublisher->publishKeyEvent(seq, deviceId, source, displayId, action, flags, keyCode, scanCode, metaState, repeatCount, downTime, eventTime); ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK"; uint32_t consumeSeq; InputEvent* event; - int32_t displayId; - status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event, - &displayId); + status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event); ASSERT_EQ(OK, status) << "consumer consume should return OK"; - ASSERT_TRUE(event != NULL) + ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event->getType()) << "consumer should have returned a key event"; @@ -104,6 +103,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { EXPECT_EQ(seq, consumeSeq); EXPECT_EQ(deviceId, keyEvent->getDeviceId()); EXPECT_EQ(source, keyEvent->getSource()); + EXPECT_EQ(displayId, keyEvent->getDisplayId()); EXPECT_EQ(action, keyEvent->getAction()); EXPECT_EQ(flags, keyEvent->getFlags()); EXPECT_EQ(keyCode, keyEvent->getKeyCode()); @@ -131,23 +131,23 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { status_t status; - const uint32_t seq = 15; - const int32_t deviceId = 1; - const int32_t source = AINPUT_SOURCE_TOUCHSCREEN; - int32_t displayId = 0; - const int32_t action = AMOTION_EVENT_ACTION_MOVE; - const int32_t actionButton = 0; - const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; - const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP; - const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; - const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY; - const float xOffset = -10; - const float yOffset = -20; - const float xPrecision = 0.25; - const float yPrecision = 0.5; - const nsecs_t downTime = 3; - const size_t pointerCount = 3; - const nsecs_t eventTime = 4; + constexpr uint32_t seq = 15; + constexpr int32_t deviceId = 1; + constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN; + constexpr int32_t displayId = ADISPLAY_ID_DEFAULT; + constexpr int32_t action = AMOTION_EVENT_ACTION_MOVE; + constexpr int32_t actionButton = 0; + constexpr int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; + constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP; + constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; + constexpr int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY; + constexpr float xOffset = -10; + constexpr float yOffset = -20; + constexpr float xPrecision = 0.25; + constexpr float yPrecision = 0.5; + constexpr nsecs_t downTime = 3; + constexpr size_t pointerCount = 3; + constexpr nsecs_t eventTime = 4; PointerProperties pointerProperties[pointerCount]; PointerCoords pointerCoords[pointerCount]; for (size_t i = 0; i < pointerCount; i++) { @@ -176,12 +176,11 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { uint32_t consumeSeq; InputEvent* event; - status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event, - &displayId); + status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event); ASSERT_EQ(OK, status) << "consumer consume should return OK"; - ASSERT_TRUE(event != NULL) + ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) << "consumer should have returned a motion event"; @@ -190,6 +189,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { EXPECT_EQ(seq, consumeSeq); EXPECT_EQ(deviceId, motionEvent->getDeviceId()); EXPECT_EQ(source, motionEvent->getSource()); + EXPECT_EQ(displayId, motionEvent->getDisplayId()); EXPECT_EQ(action, motionEvent->getAction()); EXPECT_EQ(flags, motionEvent->getFlags()); EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags()); diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp index 43b6012e0d..5242a1899f 100644 --- a/libs/input/tests/VelocityTracker_test.cpp +++ b/libs/input/tests/VelocityTracker_test.cpp @@ -26,6 +26,8 @@ using android::base::StringPrintf; namespace android { +constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT; // default display id + constexpr int32_t DEFAULT_POINTER_ID = 0; // pointer ID used for manually defined tests // velocity must be in the range (1-tol)*EV <= velocity <= (1+tol)*EV @@ -89,7 +91,7 @@ MotionEvent* createSimpleMotionEvent(const Position* positions, size_t numSample // First sample added separately with initialize coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[0].x); coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[0].y); - event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, + event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, positions[0].time, 1, properties, &coords); for (size_t i = 1; i < numSamples; i++) { diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp index a0e368c7e4..d9a986ed00 100644 --- a/libs/sensor/Sensor.cpp +++ b/libs/sensor/Sensor.cpp @@ -318,7 +318,7 @@ Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersi // If the sensor is protected by a permission we need to know if it is // a runtime one to determine whether we can use the permission cache. sp<IBinder> binder = defaultServiceManager()->getService(String16("permission")); - if (binder != 0) { + if (binder != nullptr) { sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder); mRequiredPermissionRuntime = permCtrl->isRuntimePermission( String16(mRequiredPermission)); diff --git a/libs/sensor/SensorEventQueue.cpp b/libs/sensor/SensorEventQueue.cpp index 6f68fb5f7b..46ba7c6250 100644 --- a/libs/sensor/SensorEventQueue.cpp +++ b/libs/sensor/SensorEventQueue.cpp @@ -37,7 +37,7 @@ namespace android { // ---------------------------------------------------------------------------- SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection) - : mSensorEventConnection(connection), mRecBuffer(NULL), mAvailable(0), mConsumed(0), + : mSensorEventConnection(connection), mRecBuffer(nullptr), mAvailable(0), mConsumed(0), mNumAcksToSend(0) { mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT]; } @@ -82,9 +82,9 @@ ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) { sp<Looper> SensorEventQueue::getLooper() const { Mutex::Autolock _l(mLock); - if (mLooper == 0) { + if (mLooper == nullptr) { mLooper = new Looper(true); - mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL); + mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, nullptr, nullptr); } return mLooper; } @@ -97,7 +97,7 @@ status_t SensorEventQueue::waitForEvent() const int events; int32_t result; do { - result = looper->pollOnce(-1, NULL, &events, NULL); + result = looper->pollOnce(-1, nullptr, &events, nullptr); if (result == ALOOPER_POLL_ERROR) { ALOGE("SensorEventQueue::waitForEvent error (errno=%d)", errno); result = -EPIPE; // unknown error, so we make up one diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp index b9ae524ee8..5840d51079 100644 --- a/libs/sensor/SensorManager.cpp +++ b/libs/sensor/SensorManager.cpp @@ -62,7 +62,7 @@ SensorManager& SensorManager::getInstanceForPackage(const String16& packageName) // to the wrong package and stats based on app ops may be slightly off. if (opPackageName.size() <= 0) { sp<IBinder> binder = defaultServiceManager()->getService(String16("permission")); - if (binder != 0) { + if (binder != nullptr) { const uid_t uid = IPCThreadState::self()->getCallingUid(); Vector<String16> packages; interface_cast<IPermissionController>(binder)->getPackagesForUid(uid, packages); @@ -93,7 +93,7 @@ SensorManager& SensorManager::getInstanceForPackage(const String16& packageName) } SensorManager::SensorManager(const String16& opPackageName) - : mSensorList(0), mOpPackageName(opPackageName), mDirectConnectionHandle(1) { + : mSensorList(nullptr), mOpPackageName(opPackageName), mDirectConnectionHandle(1) { // okay we're not locked here, but it's not needed during construction assertStateLocked(); } @@ -128,13 +128,13 @@ void SensorManager::sensorManagerDied() { Mutex::Autolock _l(mLock); mSensorServer.clear(); free(mSensorList); - mSensorList = NULL; + mSensorList = nullptr; mSensors.clear(); } status_t SensorManager::assertStateLocked() { bool initSensorManager = false; - if (mSensorServer == NULL) { + if (mSensorServer == nullptr) { initSensorManager = true; } else { // Ping binder to check if sensorservice is alive. @@ -164,7 +164,7 @@ status_t SensorManager::assertStateLocked() { size_t count = mSensors.size(); mSensorList = static_cast<Sensor const**>(malloc(count * sizeof(Sensor*))); - LOG_ALWAYS_FATAL_IF(mSensorList == NULL, "mSensorList NULL"); + LOG_ALWAYS_FATAL_IF(mSensorList == nullptr, "mSensorList NULL"); for (size_t i=0 ; i<count ; i++) { mSensorList[i] = mSensors.array() + i; @@ -222,7 +222,7 @@ Sensor const* SensorManager::getDefaultSensor(int type) } } } - return NULL; + return nullptr; } sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) { @@ -232,10 +232,10 @@ sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mo while (assertStateLocked() == NO_ERROR) { sp<ISensorEventConnection> connection = mSensorServer->createSensorEventConnection(packageName, mode, mOpPackageName); - if (connection == NULL) { + if (connection == nullptr) { // SensorService just died or the app doesn't have required permissions. ALOGE("createEventQueue: connection is NULL."); - return NULL; + return nullptr; } queue = new SensorEventQueue(connection); break; diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp index e24739845d..2a962b5cea 100644 --- a/libs/vr/libbufferhub/buffer_hub-test.cpp +++ b/libs/vr/libbufferhub/buffer_hub-test.cpp @@ -945,3 +945,35 @@ TEST_F(LibBufferHubTest, TestDetachThenPromote) { EXPECT_EQ(b1_id, p2_id); EXPECT_TRUE(IsBufferGained(p2->buffer_state())); } + +TEST_F(LibBufferHubTest, TestDuplicateDetachedBuffer) { + auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, + kUsage, kUserMetadataSize); + int b1_id = b1->id(); + EXPECT_TRUE(b1->IsValid()); + + auto status_or_handle = b1->Duplicate(); + EXPECT_TRUE(status_or_handle); + + // The detached buffer should still be valid. + EXPECT_TRUE(b1->IsConnected()); + EXPECT_TRUE(b1->IsValid()); + + // Gets the channel handle for the duplicated buffer. + LocalChannelHandle h2 = status_or_handle.take(); + EXPECT_TRUE(h2.valid()); + + std::unique_ptr<DetachedBuffer> b2 = DetachedBuffer::Import(std::move(h2)); + EXPECT_FALSE(h2.valid()); + ASSERT_TRUE(b2 != nullptr); + int b2_id = b2->id(); + + // The duplicated buffer should inherit the same buffer id. + EXPECT_EQ(b1_id, b2_id); + + // Promote the detached buffer should fail as b1 is no longer the exclusive + // owner of the buffer.. + status_or_handle = b1->Promote(); + EXPECT_FALSE(status_or_handle.ok()); + EXPECT_EQ(status_or_handle.error(), EINVAL); +} diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp index 159f2bd1b3..577cba9572 100644 --- a/libs/vr/libbufferhub/buffer_hub_client.cpp +++ b/libs/vr/libbufferhub/buffer_hub_client.cpp @@ -42,11 +42,13 @@ LocalChannelHandle BufferHubClient::TakeChannelHandle() { BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle) : Client{pdx::default_transport::ClientChannel::Create( std::move(channel_handle))}, - id_(-1) {} + id_(-1), + cid_(-1) {} BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path) : Client{pdx::default_transport::ClientChannelFactory::Create( endpoint_path)}, - id_(-1) {} + id_(-1), + cid_(-1) {} BufferHubBuffer::~BufferHubBuffer() { if (metadata_header_ != nullptr) { @@ -136,6 +138,7 @@ int BufferHubBuffer::ImportBuffer() { } id_ = new_id; + cid_ = buffer_desc.buffer_cid(); buffer_state_bit_ = buffer_desc.buffer_state_bit(); // Note that here the buffer state is mapped from shared memory as an atomic diff --git a/libs/vr/libbufferhub/detached_buffer.cpp b/libs/vr/libbufferhub/detached_buffer.cpp index 6fae16d265..60f11e24a2 100644 --- a/libs/vr/libbufferhub/detached_buffer.cpp +++ b/libs/vr/libbufferhub/detached_buffer.cpp @@ -104,6 +104,20 @@ Status<LocalChannelHandle> DetachedBuffer::Promote() { return status_or_handle; } +Status<LocalChannelHandle> DetachedBuffer::Duplicate() { + ATRACE_NAME("DetachedBuffer::Duplicate"); + ALOGD_IF(TRACE, "DetachedBuffer::Duplicate: id=%d.", id_); + + auto status_or_handle = + client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>(); + + if (!status_or_handle.ok()) { + ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.", + id_, status_or_handle.GetErrorMessage().c_str()); + } + return status_or_handle; +} + sp<GraphicBuffer> DetachedBuffer::TakeGraphicBuffer() { if (!client_.IsValid() || !buffer_.buffer()) { ALOGE("DetachedBuffer::TakeGraphicBuffer: Invalid buffer."); diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h index 0ea77c85fb..b71f5dcba6 100644 --- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h +++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h @@ -107,8 +107,14 @@ class BufferHubBuffer : public pdx::Client { IonBuffer* buffer() { return &buffer_; } const IonBuffer* buffer() const { return &buffer_; } + // Gets ID of the buffer client. All BufferHubBuffer clients derived from the + // same buffer in bufferhubd share the same buffer id. int id() const { return id_; } + // Gets the channel id of the buffer client. Each BufferHubBuffer client has + // its system unique channel id. + int cid() const { return cid_; } + // Returns the buffer buffer state. uint64_t buffer_state() { return buffer_state_->load(); }; @@ -170,6 +176,7 @@ class BufferHubBuffer : public pdx::Client { // for logging and debugging purposes only and should not be used for lookup // or any other functional purpose as a security precaution. int id_; + int cid_; uint64_t buffer_state_bit_{0ULL}; IonBuffer buffer_; IonBuffer metadata_buffer_; diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h new file mode 100644 index 0000000000..8b2bf91d87 --- /dev/null +++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h @@ -0,0 +1,89 @@ +#ifndef ANDROID_DVR_BUFFER_HUB_DEFS_H_ +#define ANDROID_DVR_BUFFER_HUB_DEFS_H_ + +#include <dvr/dvr_api.h> +#include <hardware/gralloc.h> + +#include <atomic> + +namespace android { +namespace dvr { + +namespace BufferHubDefs { + +static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB; +static constexpr uint32_t kMetadataUsage = + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; + +// Single producuer multiple (up to 63) consumers ownership signal. +// 64-bit atomic unsigned int. +// +// MSB LSB +// | | +// v v +// [P|C62|...|C1|C0] +// Gain'ed state: [0|..|0|0] -> Exclusively Writable. +// Post'ed state: [1|..|0|0] +// Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits +// Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits +static constexpr uint64_t kProducerStateBit = 1ULL << 63; +static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1; + +static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state, + uint64_t clear_mask, uint64_t set_mask) { + uint64_t old_state; + uint64_t new_state; + do { + old_state = buffer_state->load(); + new_state = (old_state & ~clear_mask) | set_mask; + } while (!buffer_state->compare_exchange_weak(old_state, new_state)); +} + +static inline bool IsBufferGained(uint64_t state) { return state == 0; } + +static inline bool IsBufferPosted(uint64_t state, + uint64_t consumer_bit = kConsumerStateMask) { + return (state & kProducerStateBit) && !(state & consumer_bit); +} + +static inline bool IsBufferAcquired(uint64_t state) { + return (state & kProducerStateBit) && (state & kConsumerStateMask); +} + +static inline bool IsBufferReleased(uint64_t state) { + return !(state & kProducerStateBit) && (state & kConsumerStateMask); +} + +static inline uint64_t FindNextClearedBit(uint64_t bits) { + return ~bits - (~bits & (~bits - 1)); +} + +static inline uint64_t FindFirstClearedBit() { + return FindNextClearedBit(kProducerStateBit); +} + +struct __attribute__((packed, aligned(8))) MetadataHeader { + // Internal data format, which can be updated as long as the size, padding and + // field alignment of the struct is consistent within the same ABI. As this + // part is subject for future updates, it's not stable cross Android version, + // so don't have it visible from outside of the Android platform (include Apps + // and vendor HAL). + std::atomic<uint64_t> buffer_state; + std::atomic<uint64_t> fence_state; + uint64_t queue_index; + + // Public data format, which should be updated with caution. See more details + // in dvr_api.h + DvrNativeBufferMetadata metadata; +}; + +static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size"); +static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader); + +} // namespace BufferHubDefs + +} // namespace dvr +} // namespace android + + +#endif // ANDROID_DVR_BUFFER_HUB_DEFS_H_ diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h index f4918c497e..e163216c33 100644 --- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h +++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h @@ -1,11 +1,11 @@ #ifndef ANDROID_DVR_BUFFERHUB_RPC_H_ #define ANDROID_DVR_BUFFERHUB_RPC_H_ +#include "buffer_hub_defs.h" + #include <cutils/native_handle.h> -#include <sys/types.h> #include <ui/BufferQueueDefs.h> -#include <dvr/dvr_api.h> #include <pdx/channel_handle.h> #include <pdx/file_handle.h> #include <pdx/rpc/remote_method.h> @@ -15,71 +15,6 @@ namespace android { namespace dvr { -namespace BufferHubDefs { - -static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB; -static constexpr uint32_t kMetadataUsage = - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; - -// Single producuer multiple (up to 63) consumers ownership signal. -// 64-bit atomic unsigned int. -// -// MSB LSB -// | | -// v v -// [P|C62|...|C1|C0] -// Gain'ed state: [0|..|0|0] -> Exclusively Writable. -// Post'ed state: [1|..|0|0] -// Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits -// Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits -static constexpr uint64_t kProducerStateBit = 1ULL << 63; -static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1; - -static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state, - uint64_t clear_mask, uint64_t set_mask) { - uint64_t old_state; - uint64_t new_state; - do { - old_state = buffer_state->load(); - new_state = (old_state & ~clear_mask) | set_mask; - } while (!buffer_state->compare_exchange_weak(old_state, new_state)); -} - -static inline bool IsBufferGained(uint64_t state) { return state == 0; } - -static inline bool IsBufferPosted(uint64_t state, - uint64_t consumer_bit = kConsumerStateMask) { - return (state & kProducerStateBit) && !(state & consumer_bit); -} - -static inline bool IsBufferAcquired(uint64_t state) { - return (state & kProducerStateBit) && (state & kConsumerStateMask); -} - -static inline bool IsBufferReleased(uint64_t state) { - return !(state & kProducerStateBit) && (state & kConsumerStateMask); -} - -struct __attribute__((packed, aligned(8))) MetadataHeader { - // Internal data format, which can be updated as long as the size, padding and - // field alignment of the struct is consistent within the same ABI. As this - // part is subject for future updates, it's not stable cross Android version, - // so don't have it visible from outside of the Android platform (include Apps - // and vendor HAL). - std::atomic<uint64_t> buffer_state; - std::atomic<uint64_t> fence_state; - uint64_t queue_index; - - // Public data format, which should be updated with caution. See more details - // in dvr_api.h - DvrNativeBufferMetadata metadata; -}; - -static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size"); -static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader); - -} // namespace BufferHubDefs - template <typename FileHandleType> class NativeBufferHandle { public: @@ -164,10 +99,11 @@ class BufferDescription { public: BufferDescription() = default; BufferDescription(const IonBuffer& buffer, const IonBuffer& metadata, int id, - uint64_t buffer_state_bit, + int buffer_cid, uint64_t buffer_state_bit, const FileHandleType& acquire_fence_fd, const FileHandleType& release_fence_fd) : id_(id), + buffer_cid_(buffer_cid), buffer_state_bit_(buffer_state_bit), buffer_(buffer, id), metadata_(metadata, id), @@ -180,6 +116,9 @@ class BufferDescription { // ID of the buffer client. All BufferHubBuffer clients derived from the same // buffer in bufferhubd share the same buffer id. int id() const { return id_; } + // Channel ID of the buffer client. Each BufferHubBuffer client has its system + // unique channel id. + int buffer_cid() const { return buffer_cid_; } // State mask of the buffer client. Each BufferHubBuffer client backed by the // same buffer channel has uniqued state bit among its siblings. For a // producer buffer the bit must be kProducerStateBit; for a consumer the bit @@ -193,6 +132,7 @@ class BufferDescription { private: int id_{-1}; + int buffer_cid_{-1}; uint64_t buffer_state_bit_{0}; // Two IonBuffers: one for the graphic buffer and one for metadata. NativeBufferHandle<FileHandleType> buffer_; @@ -202,7 +142,7 @@ class BufferDescription { FileHandleType acquire_fence_fd_; FileHandleType release_fence_fd_; - PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_, + PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_, buffer_cid_, buffer_state_bit_, buffer_, metadata_, acquire_fence_fd_, release_fence_fd_); @@ -381,6 +321,7 @@ struct BufferHubRPC { kOpCreateConsumerQueue, kOpGetQueueInfo, kOpProducerQueueAllocateBuffers, + kOpProducerQueueInsertBuffer, kOpProducerQueueRemoveBuffer, kOpConsumerQueueImportBuffers, // TODO(b/77153033): Separate all those RPC operations into subclasses. @@ -430,6 +371,8 @@ struct BufferHubRPC { std::vector<std::pair<LocalChannelHandle, size_t>>( uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format, uint64_t usage, size_t buffer_count)); + PDX_REMOTE_METHOD(ProducerQueueInsertBuffer, kOpProducerQueueInsertBuffer, + size_t(int buffer_cid)); PDX_REMOTE_METHOD(ProducerQueueRemoveBuffer, kOpProducerQueueRemoveBuffer, void(size_t slot)); PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers, @@ -442,6 +385,7 @@ struct DetachedBufferRPC final : public BufferHubRPC { kOpCreate = kOpDetachedBufferBase, kOpImport, kOpPromote, + kOpDuplicate, }; public: @@ -451,8 +395,9 @@ struct DetachedBufferRPC final : public BufferHubRPC { size_t user_metadata_size)); PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(Void)); PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void)); + PDX_REMOTE_METHOD(Duplicate, kOpDuplicate, LocalChannelHandle(Void)); - PDX_REMOTE_API(API, Create, Promote); + PDX_REMOTE_API(API, Create, Import, Promote, Duplicate); }; } // namespace dvr diff --git a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h index 6d0b502271..376b53ec8c 100644 --- a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h +++ b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h @@ -57,6 +57,9 @@ class DetachedBuffer { // return. Further IPCs towards this channel will return error. pdx::Status<pdx::LocalChannelHandle> Promote(); + // Creates a DetachedBuffer from an existing one. + pdx::Status<pdx::LocalChannelHandle> Duplicate(); + // Takes the underlying graphic buffer out of this DetachedBuffer. This call // immediately invalidates this DetachedBuffer object and transfers the // underlying pdx::LocalChannelHandle into the GraphicBuffer. diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp index 8feb1cd803..1f2c51765d 100644 --- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp +++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp @@ -524,6 +524,40 @@ Status<void> ProducerQueue::AddBuffer( return BufferHubQueue::Enqueue({buffer, slot, 0ULL}); } +Status<size_t> ProducerQueue::InsertBuffer( + const std::shared_ptr<BufferProducer>& buffer) { + if (buffer == nullptr || + !BufferHubDefs::IsBufferGained(buffer->buffer_state())) { + ALOGE( + "ProducerQueue::InsertBuffer: Can only insert a buffer when it's in " + "gained state."); + return ErrorStatus(EINVAL); + } + + auto status_or_slot = + InvokeRemoteMethod<BufferHubRPC::ProducerQueueInsertBuffer>( + buffer->cid()); + if (!status_or_slot) { + ALOGE( + "ProducerQueue::InsertBuffer: Failed to insert producer buffer: " + "buffer_cid=%d, error: %s.", + buffer->cid(), status_or_slot.GetErrorMessage().c_str()); + return status_or_slot.error_status(); + } + + size_t slot = status_or_slot.get(); + + // Note that we are calling AddBuffer() from the base class to explicitly + // avoid Enqueue() the BufferProducer. + auto status = BufferHubQueue::AddBuffer(buffer, slot); + if (!status) { + ALOGE("ProducerQueue::InsertBuffer: Failed to add buffer: %s.", + status.GetErrorMessage().c_str()); + return status.error_status(); + } + return {slot}; +} + Status<void> ProducerQueue::RemoveBuffer(size_t slot) { auto status = InvokeRemoteMethod<BufferHubRPC::ProducerQueueRemoveBuffer>(slot); diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h index 60e1c4b8a9..df500b493e 100644 --- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h +++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h @@ -331,6 +331,13 @@ class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> { pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer, size_t slot); + // Inserts a ProducerBuffer into the queue. On success, the method returns the + // |slot| number where the new buffer gets inserted. Note that the buffer + // being inserted should be in Gain'ed state prior to the call and it's + // considered as already Dequeued when the function returns. + pdx::Status<size_t> InsertBuffer( + const std::shared_ptr<BufferProducer>& buffer); + // Remove producer buffer from the queue. pdx::Status<void> RemoveBuffer(size_t slot) override; diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp index 47a27344bd..2975f56928 100644 --- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp +++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp @@ -181,6 +181,40 @@ TEST_F(BufferHubQueueTest, TestProducerConsumer) { } } +TEST_F(BufferHubQueueTest, TestInsertBuffer) { + ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{})); + + consumer_queue_ = producer_queue_->CreateConsumerQueue(); + ASSERT_TRUE(consumer_queue_ != nullptr); + EXPECT_EQ(producer_queue_->capacity(), 0); + EXPECT_EQ(consumer_queue_->capacity(), 0); + + std::shared_ptr<BufferProducer> p1 = BufferProducer::Create( + kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage, 0); + ASSERT_TRUE(p1 != nullptr); + + // Inserting a posted buffer will fail. + DvrNativeBufferMetadata meta; + EXPECT_EQ(p1->PostAsync(&meta, LocalHandle()), 0); + auto status_or_slot = producer_queue_->InsertBuffer(p1); + EXPECT_FALSE(status_or_slot.ok()); + EXPECT_EQ(status_or_slot.error(), EINVAL); + + // Inserting a gained buffer will succeed. + std::shared_ptr<BufferProducer> p2 = BufferProducer::Create( + kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage); + ASSERT_TRUE(p2 != nullptr); + status_or_slot = producer_queue_->InsertBuffer(p2); + EXPECT_TRUE(status_or_slot.ok()); + // This is the first buffer inserted, should take slot 0. + size_t slot = status_or_slot.get(); + EXPECT_EQ(slot, 0); + + // Wait and expect the consumer to kick up the newly inserted buffer. + WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs); + EXPECT_EQ(consumer_queue_->capacity(), 1ULL); +} + TEST_F(BufferHubQueueTest, TestRemoveBuffer) { ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{})); DvrNativeBufferMetadata mo; diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp index 9c678815cd..8c354fbc18 100644 --- a/libs/vr/libdisplay/Android.bp +++ b/libs/vr/libdisplay/Android.bp @@ -16,8 +16,8 @@ sourceFiles = [ "display_client.cpp", "display_manager_client.cpp", "display_protocol.cpp", - "vsync_client.cpp", "shared_buffer_helpers.cpp", + "vsync_service.cpp", ] localIncludeFiles = [ diff --git a/libs/vr/libdisplay/include/private/dvr/vsync_client.h b/libs/vr/libdisplay/include/private/dvr/vsync_client.h deleted file mode 100644 index 1eeb80e09d..0000000000 --- a/libs/vr/libdisplay/include/private/dvr/vsync_client.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef ANDROID_DVR_VSYNC_CLIENT_H_ -#define ANDROID_DVR_VSYNC_CLIENT_H_ - -#include <stdint.h> - -#include <pdx/client.h> - -struct dvr_vsync_client {}; - -namespace android { -namespace dvr { - -/* - * VSyncClient is a remote interface to the vsync service in displayd. - * This class is used to wait for and retrieve information about the - * display vsync. - */ -class VSyncClient : public pdx::ClientBase<VSyncClient>, - public dvr_vsync_client { - public: - /* - * Wait for the next vsync signal. - * The timestamp (in ns) is written into *ts when ts is non-NULL. - */ - int Wait(int64_t* timestamp_ns); - - /* - * Returns the file descriptor used to communicate with the vsync system - * service or -1 on error. - */ - int GetFd(); - - /* - * Clears the select/poll/epoll event so that subsequent calls to - * these will not signal until the next vsync. - */ - int Acknowledge(); - - /* - * Get the timestamp of the last vsync event in ns. This call has - * the same side effect on events as Acknowledge(), which saves - * an IPC message. - */ - int GetLastTimestamp(int64_t* timestamp_ns); - - /* - * Get vsync scheduling info. - * Get the estimated timestamp of the next GPU lens warp preemption event in - * ns. Also returns the corresponding vsync count that the next lens warp - * operation will target. This call has the same side effect on events as - * Acknowledge(), which saves an IPC message. - */ - int GetSchedInfo(int64_t* vsync_period_ns, int64_t* next_timestamp_ns, - uint32_t* next_vsync_count); - - private: - friend BASE; - - VSyncClient(); - explicit VSyncClient(long timeout_ms); - - VSyncClient(const VSyncClient&) = delete; - void operator=(const VSyncClient&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_VSYNC_CLIENT_H_ diff --git a/libs/vr/libdisplay/include/private/dvr/vsync_service.h b/libs/vr/libdisplay/include/private/dvr/vsync_service.h new file mode 100644 index 0000000000..152464abd1 --- /dev/null +++ b/libs/vr/libdisplay/include/private/dvr/vsync_service.h @@ -0,0 +1,65 @@ +#ifndef ANDROID_DVR_VSYNC_SERVICE_H_ +#define ANDROID_DVR_VSYNC_SERVICE_H_ + +#include <binder/IInterface.h> + +namespace android { +namespace dvr { + +class IVsyncCallback : public IInterface { + public: + DECLARE_META_INTERFACE(VsyncCallback) + + enum { + ON_VSYNC = IBinder::FIRST_CALL_TRANSACTION + }; + + virtual status_t onVsync(int64_t vsync_timestamp) = 0; +}; + +class BnVsyncCallback : public BnInterface<IVsyncCallback> { + public: + virtual status_t onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags = 0); +}; + +// Register a callback with IVsyncService to be notified of vsync events and +// timestamps. There's also a shared memory vsync buffer defined in +// dvr_shared_buffers.h. IVsyncService has advantages over the vsync shared +// memory buffer that make it preferable in certain situations: +// +// 1. The shared memory buffer lifetime is controlled by VrCore. IVsyncService +// is always available as long as surface flinger is running. +// +// 2. IVsyncService will make a binder callback when a vsync event occurs. This +// allows the client to not write code to implement periodic "get the latest +// vsync" calls, which is necessary with the vsync shared memory buffer. +// +// 3. The IVsyncService provides the real vsync timestamp reported by hardware +// composer, whereas the vsync shared memory buffer only has predicted vsync +// times. +class IVsyncService : public IInterface { +public: + DECLARE_META_INTERFACE(VsyncService) + + static const char* GetServiceName() { return "vrflinger_vsync"; } + + enum { + REGISTER_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, + UNREGISTER_CALLBACK + }; + + virtual status_t registerCallback(const sp<IVsyncCallback> callback) = 0; + virtual status_t unregisterCallback(const sp<IVsyncCallback> callback) = 0; +}; + +class BnVsyncService : public BnInterface<IVsyncService> { + public: + virtual status_t onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags = 0); +}; + +} // namespace dvr +} // namespace android + +#endif // ANDROID_DVR_VSYNC_SERVICE_H_ diff --git a/libs/vr/libdisplay/vsync_client.cpp b/libs/vr/libdisplay/vsync_client.cpp deleted file mode 100644 index bc6cf6cabe..0000000000 --- a/libs/vr/libdisplay/vsync_client.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "include/private/dvr/vsync_client.h" - -#include <log/log.h> - -#include <pdx/default_transport/client_channel_factory.h> -#include <private/dvr/display_protocol.h> - -using android::dvr::display::VSyncProtocol; -using android::pdx::Transaction; - -namespace android { -namespace dvr { - -VSyncClient::VSyncClient(long timeout_ms) - : BASE(pdx::default_transport::ClientChannelFactory::Create( - VSyncProtocol::kClientPath), - timeout_ms) {} - -VSyncClient::VSyncClient() - : BASE(pdx::default_transport::ClientChannelFactory::Create( - VSyncProtocol::kClientPath)) {} - -int VSyncClient::Wait(int64_t* timestamp_ns) { - auto status = InvokeRemoteMethod<VSyncProtocol::Wait>(); - if (!status) { - ALOGE("VSyncClient::Wait: Failed to wait for vsync: %s", - status.GetErrorMessage().c_str()); - return -status.error(); - } - - if (timestamp_ns != nullptr) { - *timestamp_ns = status.get(); - } - return 0; -} - -int VSyncClient::GetFd() { return event_fd(); } - -int VSyncClient::GetLastTimestamp(int64_t* timestamp_ns) { - auto status = InvokeRemoteMethod<VSyncProtocol::GetLastTimestamp>(); - if (!status) { - ALOGE("VSyncClient::GetLastTimestamp: Failed to get vsync timestamp: %s", - status.GetErrorMessage().c_str()); - return -status.error(); - } - *timestamp_ns = status.get(); - return 0; -} - -int VSyncClient::GetSchedInfo(int64_t* vsync_period_ns, int64_t* timestamp_ns, - uint32_t* next_vsync_count) { - if (!vsync_period_ns || !timestamp_ns || !next_vsync_count) - return -EINVAL; - - auto status = InvokeRemoteMethod<VSyncProtocol::GetSchedInfo>(); - if (!status) { - ALOGE("VSyncClient::GetSchedInfo:: Failed to get warp timestamp: %s", - status.GetErrorMessage().c_str()); - return -status.error(); - } - - *vsync_period_ns = status.get().vsync_period_ns; - *timestamp_ns = status.get().timestamp_ns; - *next_vsync_count = status.get().next_vsync_count; - return 0; -} - -int VSyncClient::Acknowledge() { - auto status = InvokeRemoteMethod<VSyncProtocol::Acknowledge>(); - ALOGE_IF(!status, "VSuncClient::Acknowledge: Failed to ack vsync because: %s", - status.GetErrorMessage().c_str()); - return ReturnStatusOrError(status); -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libdisplay/vsync_service.cpp b/libs/vr/libdisplay/vsync_service.cpp new file mode 100644 index 0000000000..43b1196fb3 --- /dev/null +++ b/libs/vr/libdisplay/vsync_service.cpp @@ -0,0 +1,146 @@ +#include "include/private/dvr/vsync_service.h" + +#include <binder/Parcel.h> +#include <log/log.h> + +namespace android { +namespace dvr { + +status_t BnVsyncCallback::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + switch (code) { + case ON_VSYNC: { + CHECK_INTERFACE(IVsyncCallback, data, reply); + int64_t vsync_timestamp = 0; + status_t result = data.readInt64(&vsync_timestamp); + if (result != NO_ERROR) { + ALOGE("onVsync failed to readInt64: %d", result); + return result; + } + onVsync(vsync_timestamp); + return NO_ERROR; + } + default: { + return BBinder::onTransact(code, data, reply, flags); + } + } +} + +class BpVsyncCallback : public BpInterface<IVsyncCallback> { +public: + explicit BpVsyncCallback(const sp<IBinder>& impl) + : BpInterface<IVsyncCallback>(impl) {} + virtual ~BpVsyncCallback() {} + + virtual status_t onVsync(int64_t vsync_timestamp) { + Parcel data, reply; + status_t result = data.writeInterfaceToken( + IVsyncCallback::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("onVsync failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeInt64(vsync_timestamp); + if (result != NO_ERROR) { + ALOGE("onVsync failed to writeInt64: %d", result); + return result; + } + result = remote()->transact( + BnVsyncCallback::ON_VSYNC, data, &reply, TF_ONE_WAY); + if (result != NO_ERROR) { + ALOGE("onVsync failed to transact: %d", result); + return result; + } + return result; + } +}; + +IMPLEMENT_META_INTERFACE(VsyncCallback, "android.dvr.IVsyncCallback"); + + +status_t BnVsyncService::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + switch (code) { + case REGISTER_CALLBACK: { + CHECK_INTERFACE(IVsyncService, data, reply); + sp<IBinder> callback; + status_t result = data.readStrongBinder(&callback); + if (result != NO_ERROR) { + ALOGE("registerCallback failed to readStrongBinder: %d", result); + return result; + } + registerCallback(interface_cast<IVsyncCallback>(callback)); + return NO_ERROR; + } + case UNREGISTER_CALLBACK: { + CHECK_INTERFACE(IVsyncService, data, reply); + sp<IBinder> callback; + status_t result = data.readStrongBinder(&callback); + if (result != NO_ERROR) { + ALOGE("unregisterCallback failed to readStrongBinder: %d", result); + return result; + } + unregisterCallback(interface_cast<IVsyncCallback>(callback)); + return NO_ERROR; + } + default: { + return BBinder::onTransact(code, data, reply, flags); + } + } +} + +class BpVsyncService : public BpInterface<IVsyncService> { +public: + explicit BpVsyncService(const sp<IBinder>& impl) + : BpInterface<IVsyncService>(impl) {} + virtual ~BpVsyncService() {} + + virtual status_t registerCallback(const sp<IVsyncCallback> callback) { + Parcel data, reply; + status_t result = data.writeInterfaceToken( + IVsyncService::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("registerCallback failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(IInterface::asBinder(callback)); + if (result != NO_ERROR) { + ALOGE("registerCallback failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact( + BnVsyncService::REGISTER_CALLBACK, data, &reply); + if (result != NO_ERROR) { + ALOGE("registerCallback failed to transact: %d", result); + return result; + } + return result; + } + + virtual status_t unregisterCallback(const sp<IVsyncCallback> callback) { + Parcel data, reply; + status_t result = data.writeInterfaceToken( + IVsyncService::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("unregisterCallback failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(IInterface::asBinder(callback)); + if (result != NO_ERROR) { + ALOGE("unregisterCallback failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact( + BnVsyncService::UNREGISTER_CALLBACK, data, &reply); + if (result != NO_ERROR) { + ALOGE("unregisterCallback failed to transact: %d", result); + return result; + } + return result; + } +}; + +IMPLEMENT_META_INTERFACE(VsyncService, "android.dvr.IVsyncService"); + +} // namespace dvr +} // namespace android diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp index 16906f57cd..38299512fe 100644 --- a/libs/vr/libdvr/Android.bp +++ b/libs/vr/libdvr/Android.bp @@ -19,7 +19,14 @@ cc_library_headers { vendor_available: true, } +cc_library_headers { + name: "libdvr_private_headers", + export_include_dirs: ["."], + vendor_available: false, +} + cflags = [ + "-DDVR_TRACKING_IMPLEMENTED=0", "-DLOG_TAG=\"libdvr\"", "-DTRACE=0", "-Wall", @@ -36,7 +43,7 @@ srcs = [ "dvr_performance.cpp", "dvr_pose.cpp", "dvr_surface.cpp", - "dvr_vsync.cpp", + "dvr_tracking.cpp", ] static_libs = [ diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp index d14f040f12..e099f6a699 100644 --- a/libs/vr/libdvr/dvr_api.cpp +++ b/libs/vr/libdvr/dvr_api.cpp @@ -12,6 +12,7 @@ #include <dvr/dvr_display_manager.h> #include <dvr/dvr_performance.h> #include <dvr/dvr_surface.h> +#include <dvr/dvr_tracking.h> #include <dvr/dvr_vsync.h> // Headers not yet moved into libdvr. diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp index 74cee3fa1f..571558a5bd 100644 --- a/libs/vr/libdvr/dvr_buffer_queue.cpp +++ b/libs/vr/libdvr/dvr_buffer_queue.cpp @@ -171,12 +171,12 @@ int DvrWriteBufferQueue::GainBuffer(int timeout, int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer, const DvrNativeBufferMetadata* meta, int ready_fence_fd) { + // Some basic sanity checks before we put the buffer back into a slot. + size_t slot = static_cast<size_t>(write_buffer->slot); LOG_FATAL_IF( (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()), "DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot); - // Some basic sanity checks before we put the buffer back into a slot. - size_t slot = static_cast<size_t>(write_buffer->slot); if (write_buffers_[slot] != nullptr) { ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot); return -EINVAL; @@ -374,12 +374,12 @@ int DvrReadBufferQueue::AcquireBuffer(int timeout, int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer, const DvrNativeBufferMetadata* meta, int release_fence_fd) { + // Some basic sanity checks before we put the buffer back into a slot. + size_t slot = static_cast<size_t>(read_buffer->slot); LOG_FATAL_IF( (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()), "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot); - // Some basic sanity checks before we put the buffer back into a slot. - size_t slot = static_cast<size_t>(read_buffer->slot); if (read_buffers_[slot] != nullptr) { ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot); return -EINVAL; diff --git a/libs/vr/libdvr/dvr_tracking.cpp b/libs/vr/libdvr/dvr_tracking.cpp new file mode 100644 index 0000000000..73addc9a0c --- /dev/null +++ b/libs/vr/libdvr/dvr_tracking.cpp @@ -0,0 +1,82 @@ +#include "include/dvr/dvr_tracking.h" + +#include <utils/Errors.h> +#include <utils/Log.h> + +#if !DVR_TRACKING_IMPLEMENTED + +extern "C" { + +// This file provides the stub implementation of dvrTrackingXXX APIs. On +// platforms that implement these APIs, set -DDVR_TRACKING_IMPLEMENTED=1 in the +// build file. +int dvrTrackingCameraCreate(DvrTrackingCamera**) { + ALOGE("dvrTrackingCameraCreate is not implemented."); + return -ENOSYS; +} + +void dvrTrackingCameraDestroy(DvrTrackingCamera*) { + ALOGE("dvrTrackingCameraDestroy is not implemented."); +} + +int dvrTrackingCameraStart(DvrTrackingCamera*, DvrWriteBufferQueue*) { + ALOGE("dvrTrackingCameraCreate is not implemented."); + return -ENOSYS; +} + +int dvrTrackingCameraStop(DvrTrackingCamera*) { + ALOGE("dvrTrackingCameraCreate is not implemented."); + return -ENOSYS; +} + +int dvrTrackingFeatureExtractorCreate(DvrTrackingFeatureExtractor**) { + ALOGE("dvrTrackingFeatureExtractorCreate is not implemented."); + return -ENOSYS; +} + +void dvrTrackingFeatureExtractorDestroy(DvrTrackingFeatureExtractor*) { + ALOGE("dvrTrackingFeatureExtractorDestroy is not implemented."); +} + +int dvrTrackingFeatureExtractorStart(DvrTrackingFeatureExtractor*, + DvrTrackingFeatureCallback, void*) { + ALOGE("dvrTrackingFeatureExtractorCreate is not implemented."); + return -ENOSYS; +} + +int dvrTrackingFeatureExtractorStop(DvrTrackingFeatureExtractor*) { + ALOGE("dvrTrackingFeatureExtractorCreate is not implemented."); + return -ENOSYS; +} + +int dvrTrackingFeatureExtractorProcessBuffer(DvrTrackingFeatureExtractor*, + DvrReadBuffer*, + const DvrTrackingBufferMetadata*, + bool*) { + ALOGE("dvrTrackingFeatureExtractorProcessBuffer is not implemented."); + return -ENOSYS; +} + +int dvrTrackingSensorsCreate(DvrTrackingSensors**, const char*) { + ALOGE("dvrTrackingSensorsCreate is not implemented."); + return -ENOSYS; +} + +void dvrTrackingSensorsDestroy(DvrTrackingSensors*) { + ALOGE("dvrTrackingSensorsDestroy is not implemented."); +} + +int dvrTrackingSensorsStart(DvrTrackingSensors*, DvrTrackingSensorEventCallback, + void*) { + ALOGE("dvrTrackingStart is not implemented."); + return -ENOSYS; +} + +int dvrTrackingSensorsStop(DvrTrackingSensors*) { + ALOGE("dvrTrackingStop is not implemented."); + return -ENOSYS; +} + +} // extern "C" + +#endif // DVR_TRACKING_IMPLEMENTED diff --git a/libs/vr/libdvr/dvr_vsync.cpp b/libs/vr/libdvr/dvr_vsync.cpp deleted file mode 100644 index 099240e53a..0000000000 --- a/libs/vr/libdvr/dvr_vsync.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "include/dvr/dvr_vsync.h" - -#include <utils/Log.h> - -#include <private/dvr/vsync_client.h> - -extern "C" { - -struct DvrVSyncClient { - std::unique_ptr<android::dvr::VSyncClient> client; -}; - -int dvrVSyncClientCreate(DvrVSyncClient** client_out) { - auto client = android::dvr::VSyncClient::Create(); - if (!client) { - ALOGE("dvrVSyncClientCreate: Failed to create vsync client!"); - return -EIO; - } - - *client_out = new DvrVSyncClient{std::move(client)}; - return 0; -} - -void dvrVSyncClientDestroy(DvrVSyncClient* client) { delete client; } - -int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns, - int64_t* next_timestamp_ns, - uint32_t* next_vsync_count) { - return client->client->GetSchedInfo(vsync_period_ns, next_timestamp_ns, - next_vsync_count); -} - -} // extern "C" diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h index 80ffc82920..fef8512266 100644 --- a/libs/vr/libdvr/include/dvr/dvr_api.h +++ b/libs/vr/libdvr/include/dvr/dvr_api.h @@ -10,6 +10,7 @@ #include <dvr/dvr_display_types.h> #include <dvr/dvr_hardware_composer_types.h> #include <dvr/dvr_pose.h> +#include <dvr/dvr_tracking_types.h> #ifdef __cplusplus extern "C" { @@ -50,6 +51,12 @@ typedef int32_t DvrGlobalBufferKey; typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue; typedef struct DvrSurfaceAttribute DvrSurfaceAttribute; +typedef struct DvrReadBuffer DvrReadBuffer; +typedef struct DvrTrackingCamera DvrTrackingCamera; +typedef struct DvrTrackingFeatureExtractor DvrTrackingFeatureExtractor; +typedef struct DvrTrackingSensors DvrTrackingSensors; +typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; + // Note: To avoid breaking others during active development, only modify this // struct by appending elements to the end. // If you do feel we should to re-arrange or remove elements, please make a @@ -367,6 +374,38 @@ typedef DvrHwcRecti (*DvrHwcFrameGetLayerDamagedRegionPtr)(DvrHwcFrame* frame, typedef int (*DvrPerformanceSetSchedulerPolicyPtr)( pid_t task_id, const char* scheduler_policy); +// dvr_tracking.h +typedef int (*DvrTrackingCameraCreatePtr)(DvrTrackingCamera** out_camera); +typedef void (*DvrTrackingCameraDestroyPtr)(DvrTrackingCamera* camera); +typedef int (*DvrTrackingCameraStartPtr)(DvrTrackingCamera* camera, + DvrWriteBufferQueue* write_queue); +typedef int (*DvrTrackingCameraStopPtr)(DvrTrackingCamera* camera); + +typedef int (*DvrTrackingFeatureExtractorCreatePtr)( + DvrTrackingFeatureExtractor** out_extractor); +typedef void (*DvrTrackingFeatureExtractorDestroyPtr)( + DvrTrackingFeatureExtractor* extractor); +typedef void (*DvrTrackingFeatureCallback)(void* context, + const DvrTrackingFeatures* event); +typedef int (*DvrTrackingFeatureExtractorStartPtr)( + DvrTrackingFeatureExtractor* extractor, + DvrTrackingFeatureCallback callback, void* context); +typedef int (*DvrTrackingFeatureExtractorStopPtr)( + DvrTrackingFeatureExtractor* extractor); +typedef int (*DvrTrackingFeatureExtractorProcessBufferPtr)( + DvrTrackingFeatureExtractor* extractor, DvrReadBuffer* buffer, + const DvrTrackingBufferMetadata* metadata, bool* out_skipped); + +typedef void (*DvrTrackingSensorEventCallback)(void* context, + DvrTrackingSensorEvent* event); +typedef int (*DvrTrackingSensorsCreatePtr)(DvrTrackingSensors** out_sensors, + const char* mode); +typedef void (*DvrTrackingSensorsDestroyPtr)(DvrTrackingSensors* sensors); +typedef int (*DvrTrackingSensorsStartPtr)( + DvrTrackingSensors* sensors, DvrTrackingSensorEventCallback callback, + void* context); +typedef int (*DvrTrackingSensorsStopPtr)(DvrTrackingSensors* sensors); + // The buffer metadata that an Android Surface (a.k.a. ANativeWindow) // will populate. A DvrWriteBufferQueue must be created with this metadata iff // ANativeWindow access is needed. Please do not remove, modify, or reorder diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h index f0d8ec6d24..3006b61b81 100644 --- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h +++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h @@ -85,9 +85,9 @@ DVR_V1_API_ENTRY(ReadBufferQueueSetBufferRemovedCallback); DVR_V1_API_ENTRY(ReadBufferQueueHandleEvents); // V-Sync client -DVR_V1_API_ENTRY(VSyncClientCreate); -DVR_V1_API_ENTRY(VSyncClientDestroy); -DVR_V1_API_ENTRY(VSyncClientGetSchedInfo); +DVR_V1_API_ENTRY_DEPRECATED(VSyncClientCreate); +DVR_V1_API_ENTRY_DEPRECATED(VSyncClientDestroy); +DVR_V1_API_ENTRY_DEPRECATED(VSyncClientGetSchedInfo); // Display surface DVR_V1_API_ENTRY(SurfaceCreate); @@ -181,3 +181,20 @@ DVR_V1_API_ENTRY(ReadBufferQueueReleaseBuffer); DVR_V1_API_ENTRY(PoseClientGetDataReader); DVR_V1_API_ENTRY(PoseClientDataCapture); DVR_V1_API_ENTRY(PoseClientDataReaderDestroy); + +// Tracking +DVR_V1_API_ENTRY(TrackingCameraCreate); +DVR_V1_API_ENTRY(TrackingCameraDestroy); +DVR_V1_API_ENTRY(TrackingCameraStart); +DVR_V1_API_ENTRY(TrackingCameraStop); + +DVR_V1_API_ENTRY(TrackingFeatureExtractorCreate); +DVR_V1_API_ENTRY(TrackingFeatureExtractorDestroy); +DVR_V1_API_ENTRY(TrackingFeatureExtractorStart); +DVR_V1_API_ENTRY(TrackingFeatureExtractorStop); +DVR_V1_API_ENTRY(TrackingFeatureExtractorProcessBuffer); + +DVR_V1_API_ENTRY(TrackingSensorsCreate); +DVR_V1_API_ENTRY(TrackingSensorsDestroy); +DVR_V1_API_ENTRY(TrackingSensorsStart); +DVR_V1_API_ENTRY(TrackingSensorsStop); diff --git a/libs/vr/libdvr/include/dvr/dvr_deleter.h b/libs/vr/libdvr/include/dvr/dvr_deleter.h index 943384f802..fe59d1ffba 100644 --- a/libs/vr/libdvr/include/dvr/dvr_deleter.h +++ b/libs/vr/libdvr/include/dvr/dvr_deleter.h @@ -20,7 +20,6 @@ typedef struct DvrSurfaceState DvrSurfaceState; typedef struct DvrSurface DvrSurface; typedef struct DvrHwcClient DvrHwcClient; typedef struct DvrHwcFrame DvrHwcFrame; -typedef struct DvrVSyncClient DvrVSyncClient; void dvrBufferDestroy(DvrBuffer* buffer); void dvrReadBufferDestroy(DvrReadBuffer* read_buffer); @@ -32,7 +31,6 @@ void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state); void dvrSurfaceDestroy(DvrSurface* surface); void dvrHwcClientDestroy(DvrHwcClient* client); void dvrHwcFrameDestroy(DvrHwcFrame* frame); -void dvrVSyncClientDestroy(DvrVSyncClient* client); __END_DECLS @@ -55,7 +53,6 @@ struct DvrObjectDeleter { void operator()(DvrSurface* p) { dvrSurfaceDestroy(p); } void operator()(DvrHwcClient* p) { dvrHwcClientDestroy(p); } void operator()(DvrHwcFrame* p) { dvrHwcFrameDestroy(p); } - void operator()(DvrVSyncClient* p) { dvrVSyncClientDestroy(p); } }; // Helper to define unique pointers for DVR object types. @@ -73,7 +70,6 @@ using UniqueDvrSurfaceState = MakeUniqueDvrPointer<DvrSurfaceState>; using UniqueDvrSurface = MakeUniqueDvrPointer<DvrSurface>; using UniqueDvrHwcClient = MakeUniqueDvrPointer<DvrHwcClient>; using UniqueDvrHwcFrame = MakeUniqueDvrPointer<DvrHwcFrame>; -using UniqueDvrVSyncClient = MakeUniqueDvrPointer<DvrVSyncClient>; // TODO(eieio): Add an adapter for std::shared_ptr that injects the deleter into // the relevant constructors. diff --git a/libs/vr/libdvr/include/dvr/dvr_tracking.h b/libs/vr/libdvr/include/dvr/dvr_tracking.h new file mode 100644 index 0000000000..5e388f391a --- /dev/null +++ b/libs/vr/libdvr/include/dvr/dvr_tracking.h @@ -0,0 +1,185 @@ +#ifndef ANDROID_DVR_TRACKING_H_ +#define ANDROID_DVR_TRACKING_H_ + +#include <stdint.h> +#include <sys/cdefs.h> + +#include <dvr/dvr_tracking_types.h> + +__BEGIN_DECLS + +typedef struct DvrReadBuffer DvrReadBuffer; +typedef struct DvrTrackingCamera DvrTrackingCamera; +typedef struct DvrTrackingFeatureExtractor DvrTrackingFeatureExtractor; +typedef struct DvrTrackingSensors DvrTrackingSensors; +typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; + +// The callback for DvrTrackingFeatureExtractor that will deliver the feature +// events. This callback is passed to dvrTrackingFeatureExtractorStart. +typedef void (*DvrTrackingFeatureCallback)(void* context, + const DvrTrackingFeatures* event); + +// The callback for DvrTrackingSensors session that will deliver the events. +// This callback is passed to dvrTrackingSensorsStart. +typedef void (*DvrTrackingSensorEventCallback)(void* context, + DvrTrackingSensorEvent* event); + +// Creates a DvrTrackingCamera session. +// +// On creation, the session is not in operating mode. Client code must call +// dvrTrackingCameraStart to bootstrap the underlying camera stack. +// +// There is no plan to expose camera configuration through this API. All camera +// parameters are determined by the system optimized for better tracking +// results. See b/78662281 for detailed deprecation plan of this API and the +// Stage 2 of VR tracking data source refactoring. +// +// @param out_camera The pointer of a DvrTrackingCamera will be filled here if +// the method call succeeds. +// @return Zero on success, or negative error code. +int dvrTrackingCameraCreate(DvrTrackingCamera** out_camera); + +// Destroys a DvrTrackingCamera handle. +// +// @param camera The DvrTrackingCamera of interest. +void dvrTrackingCameraDestroy(DvrTrackingCamera* camera); + +// Starts the DvrTrackingCamera. +// +// On successful return, all DvrReadBufferQueue's associated with the given +// write_queue will start to receive buffers from the camera stack. Note that +// clients of this API should not assume the buffer dimension, format, and/or +// usage of the outcoming buffers, as they are governed by the underlying camera +// logic. Also note that it's the client's responsibility to consume buffers +// from DvrReadBufferQueue on time and return them back to the producer; +// otherwise the camera stack might be blocked. +// +// @param camera The DvrTrackingCamera of interest. +// @param write_queue A DvrWriteBufferQueue that the camera stack can use to +// populate the buffer into. The queue must be empty and the camera stack +// will request buffer allocation with proper buffer dimension, format, and +// usage. Note that the write queue must be created with user_metadata_size +// set to sizeof(DvrTrackingBufferMetadata). On success, the write_queue +// handle will become invalid and the ownership of the queue handle will be +// transferred into the camera; otherwise, the write_queue handle will keep +// untouched and the caller still has the ownership. +// @return Zero on success, or negative error code. +int dvrTrackingCameraStart(DvrTrackingCamera* camera, + DvrWriteBufferQueue* write_queue); + +// Stops the DvrTrackingCamera. +// +// On successful return, the DvrWriteBufferQueue set during +// dvrTrackingCameraStart will stop getting new buffers from the camera stack. +// +// @param camera The DvrTrackingCamera of interest. +// @return Zero on success, or negative error code. +int dvrTrackingCameraStop(DvrTrackingCamera* camera); + +// Creates a DvrTrackingSensors session. +// +// This will initialize but not start device sensors (gyro / accel). Upon +// successfull creation, the clients can call dvrTrackingSensorsStart to start +// receiving sensor events. +// +// @param out_sensors The pointer of a DvrTrackingSensors will be filled here if +// the method call succeeds. +// @param mode The sensor mode. +// mode="ndk": Use the Android NDK. +// mode="direct": Use direct mode sensors (lower latency). +// @return Zero on success, or negative error code. +int dvrTrackingSensorsCreate(DvrTrackingSensors** out_sensors, + const char* mode); + +// Destroys a DvrTrackingSensors session. +// +// @param sensors The DvrTrackingSensors struct to destroy. +void dvrTrackingSensorsDestroy(DvrTrackingSensors* sensors); + +// Starts the tracking sensor session. +// +// This will start the device sensors and start pumping the feature and sensor +// events as they arrive. +// +// @param client A tracking client created by dvrTrackingSensorsCreate. +// @param context A client supplied pointer that will be passed to the callback. +// @param callback A callback that will receive the sensor events on an +// arbitrary thread. +// @return Zero on success, or negative error code. +int dvrTrackingSensorsStart(DvrTrackingSensors* sensors, + DvrTrackingSensorEventCallback callback, + void* context); + +// Stops a DvrTrackingSensors session. +// +// This will stop the device sensors. dvrTrackingSensorsStart can be called to +// restart them again. +// +// @param client A tracking client created by dvrTrackingClientCreate. +// @return Zero on success, or negative error code. +int dvrTrackingSensorsStop(DvrTrackingSensors* sensors); + +// Creates a tracking feature extractor. +// +// This will initialize but not start the feature extraction session. Upon +// successful creation, the client can call dvrTrackingFeatureExtractorStart to +// start receiving features. +// +// @param out_extractor The pointer of a DvrTrackingFeatureExtractor will be +// filled here if the method call succeeds. +int dvrTrackingFeatureExtractorCreate( + DvrTrackingFeatureExtractor** out_extractor); + +// Destroys a tracking feature extractor. +// +// @param extractor The DvrTrackingFeatureExtractor to destroy. +void dvrTrackingFeatureExtractorDestroy(DvrTrackingFeatureExtractor* extractor); + +// Starts the tracking feature extractor. +// +// This will start the extractor and start pumping the output feature events to +// the registered callback. Note that this method will create one or more +// threads to handle feature processing. +// +// @param extractor The DvrTrackingFeatureExtractor to destroy. +int dvrTrackingFeatureExtractorStart(DvrTrackingFeatureExtractor* extractor, + DvrTrackingFeatureCallback callback, + void* context); + +// Stops the tracking feature extractor. +// +// This will stop the extractor session and clean up all internal resourcse +// related to this extractor. On succssful return, all internal therad started +// by dvrTrackingFeatureExtractorStart should be stopped. +// +// @param extractor The DvrTrackingFeatureExtractor to destroy. +int dvrTrackingFeatureExtractorStop(DvrTrackingFeatureExtractor* extractor); + +// Processes one buffer to extract features from. +// +// The buffer will be sent over to DSP for feature extraction. Once the process +// is done, the processing thread will invoke DvrTrackingFeatureCallback with +// newly extracted features. Note that not all buffers will be processed, as the +// underlying DSP can only process buffers at a certain framerate. If a buffer +// needs to be skipped, out_skipped filed will be set to true. Also note that +// for successfully processed stereo buffer, two callbacks (one for each eye) +// will be fired. +// +// @param extractor The DvrTrackingFeatureExtractor to destroy. +// @param buffer The buffer to extract features from. Note that the buffer must +// be in acquired state for the buffer to be processed. Also note that the +// buffer will be released back to its producer on successful return of the +// method. +// @param metadata The metadata associated with the buffer. Should be populated +// by DvrTrackingCamera session as user defined metadata. +// @param out_skipped On successful return, the field will be set to true iff +// the buffer was skipped; and false iff the buffer was processed. This +// field is optional and nullptr can be passed here to ignore the field. +// @return Zero on success, or negative error code. +int dvrTrackingFeatureExtractorProcessBuffer( + DvrTrackingFeatureExtractor* extractor, DvrReadBuffer* buffer, + const DvrTrackingBufferMetadata* metadata, bool* out_skipped); + +__END_DECLS + +#endif // ANDROID_DVR_TRACKING_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_tracking_types.h b/libs/vr/libdvr/include/dvr/dvr_tracking_types.h new file mode 100644 index 0000000000..81310d2303 --- /dev/null +++ b/libs/vr/libdvr/include/dvr/dvr_tracking_types.h @@ -0,0 +1,104 @@ +#ifndef ANDROID_DVR_TRACKING_TYPES_H_ +#define ANDROID_DVR_TRACKING_TYPES_H_ + +#include <stdint.h> +#include <sys/cdefs.h> + +__BEGIN_DECLS + +typedef struct DvrTrackingBufferMetadata { + // Specifies the source of this image. + uint32_t camera_mask; + // Specifies the memory format of this image. + uint32_t format; + /// The width of the image data. + uint32_t width; + /// The height of the image data. + uint32_t height; + /// The number of bytes per scanline of image data. + uint32_t stride; + /// The frame number of this image. + int32_t frame_number; + /// The timestamp of this image in nanoseconds. Taken in the middle of the + /// exposure interval. + int64_t timestamp_ns; + // This is the timestamp for recording when the system using the HAL + // received the callback. It will not be populated by the HAL. + int64_t callback_timestamp_ns; + /// The exposure duration of this image in nanoseconds. + int64_t exposure_duration_ns; +} DvrTrackingBufferMetadata; + +// Represents a set of features extracted from a camera frame. Note that this +// should be in sync with TangoHalCallbacks defined in tango-hal.h. +typedef struct DvrTrackingFeatures { + // Specifies the source of the features. + uint32_t camera_mask; + + // This is unused. + uint32_t unused; + + // The timestamp in nanoseconds from the image that generated the features. + // Taken in the middle of the exposure interval. + int64_t timestamp_ns; + + // This is the timestamp for recording when the system using the HAL + // received the callback. It will not be populated by the HAL. + int64_t callback_timestamp_ns; + + // The frame number from the image that generated the features. + int64_t frame_number; + + // The number of features. + int count; + + // An array of 2D image points for each feature in the current image. + // This is sub-pixel refined extremum location at the fine resolution. + float (*positions)[2]; + + // The id of these measurements. + int32_t* ids; + + // The feature descriptors. + uint64_t (*descriptors)[8]; + + // Laplacian scores for each feature. + float* scores; + + // Is this feature a minimum or maximum in the Laplacian image. + // 0 if the feature is a maximum, 1 if it is a minimum. + int32_t* is_minimum; + + // This corresponds to the sub-pixel index of the laplacian image + // that the extremum was found. + float* scales; + + // Computed orientation of keypoint as part of FREAK extraction, except + // it's represented in radians and measured anti-clockwise. + float* angles; + + // Edge scores for each feature. + float* edge_scores; +} DvrTrackingFeatures; + +// Represents a sensor event. +typedef struct DvrTrackingSensorEvent { + // The sensor type. + int32_t sensor; + + // Event type. + int32_t type; + + // This is the timestamp recorded from the device. Taken in the middle + // of the integration interval and adjusted for any low pass filtering. + int64_t timestamp_ns; + + // The event data. + float x; + float y; + float z; +} DvrTrackingSensorEvent; + +__END_DECLS + +#endif // ANDROID_DVR_TRACKING_TYPES_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h index 87fdf31b2b..498bb5cc6e 100644 --- a/libs/vr/libdvr/include/dvr/dvr_vsync.h +++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h @@ -6,8 +6,6 @@ __BEGIN_DECLS -typedef struct DvrVSyncClient DvrVSyncClient; - // Represents a vsync sample. The size of this struct is 32 bytes. typedef struct __attribute__((packed, aligned(16))) DvrVsync { // The timestamp for the last vsync in nanoseconds. @@ -29,19 +27,6 @@ typedef struct __attribute__((packed, aligned(16))) DvrVsync { uint8_t padding[8]; } DvrVsync; -// Creates a new client to the system vsync service. -int dvrVSyncClientCreate(DvrVSyncClient** client_out); - -// Destroys the vsync client. -void dvrVSyncClientDestroy(DvrVSyncClient* client); - -// Get the estimated timestamp of the next GPU lens warp preemption event in/ -// ns. Also returns the corresponding vsync count that the next lens warp -// operation will target. -int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns, - int64_t* next_timestamp_ns, - uint32_t* next_vsync_count); - __END_DECLS #endif // ANDROID_DVR_VSYNC_H_ diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp index 1ae75fbe04..b23a0fa30f 100644 --- a/libs/vr/libdvr/tests/Android.bp +++ b/libs/vr/libdvr/tests/Android.bp @@ -12,38 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -shared_libraries = [ - "libbase", - "libbinder", - "libbufferhubqueue", - "libcutils", - "libgui", - "liblog", - "libhardware", - "libui", - "libutils", - "libnativewindow", - "libpdx_default_transport", -] - -static_libraries = [ - "libdvr_static", - "libchrome", - "libdvrcommon", - "libdisplay", - "libbroadcastring", -] - cc_test { srcs: [ "dvr_display_manager-test.cpp", "dvr_named_buffer-test.cpp", + "dvr_tracking-test.cpp", ], header_libs: ["libdvr_headers"], - static_libs: static_libraries, - shared_libs: shared_libraries, + static_libs: [ + "libdvr_static", + "libchrome", + "libdvrcommon", + "libdisplay", + "libbroadcastring", + ], + shared_libs: [ + "libbase", + "libbinder", + "libbufferhubqueue", + "libcutils", + "libgui", + "liblog", + "libhardware", + "libui", + "libutils", + "libnativewindow", + "libpdx_default_transport", + ], cflags: [ + "-DDVR_TRACKING_IMPLEMENTED=0", "-DLOG_TAG=\"dvr_api-test\"", "-DTRACE=0", "-Wno-missing-field-initializers", @@ -52,3 +50,55 @@ cc_test { ], name: "dvr_api-test", } + +cc_test { + name: "dvr_buffer_queue-test", + + // Includes the dvr_api.h header. Tests should only include "dvr_api.h", + // and shall only get access to |dvrGetApi|, as other symbols are hidden + // from the library. + include_dirs: ["frameworks/native/libs/vr/libdvr/include"], + + srcs: ["dvr_buffer_queue-test.cpp"], + + shared_libs: [ + "libandroid", + "liblog", + ], + + cflags: [ + "-DTRACE=0", + "-O2", + "-g", + ], + + // DTS Should only link to NDK libraries. + sdk_version: "26", + stl: "c++_static", +} + +cc_test { + name: "dvr_display-test", + + include_dirs: [ + "frameworks/native/libs/vr/libdvr/include", + "frameworks/native/libs/nativewindow/include", + ], + + srcs: ["dvr_display-test.cpp"], + + shared_libs: [ + "libandroid", + "liblog", + ], + + cflags: [ + "-DTRACE=0", + "-O2", + "-g", + ], + + // DTS Should only link to NDK libraries. + sdk_version: "26", + stl: "c++_static", +} diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk deleted file mode 100644 index 0f3840d52c..0000000000 --- a/libs/vr/libdvr/tests/Android.mk +++ /dev/null @@ -1,73 +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. - -LOCAL_PATH:= $(call my-dir) - -# TODO(b/73133405): Currently, building cc_test against NDK using Android.bp -# doesn't work well. Migrate to use Android.bp once b/73133405 gets fixed. - -include $(CLEAR_VARS) -LOCAL_MODULE:= dvr_buffer_queue-test - -# Includes the dvr_api.h header. Tests should only include "dvr_api.h", -# and shall only get access to |dvrGetApi|, as other symbols are hidden from the -# library. -LOCAL_C_INCLUDES := \ - frameworks/native/libs/vr/libdvr/include \ - -LOCAL_SANITIZE := thread - -LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp - -LOCAL_SHARED_LIBRARIES := \ - libandroid \ - liblog \ - -LOCAL_CFLAGS := \ - -DTRACE=0 \ - -O2 \ - -g \ - -# DTS Should only link to NDK libraries. -LOCAL_SDK_VERSION := 26 -LOCAL_NDK_STL_VARIANT := c++_static - -include $(BUILD_NATIVE_TEST) - - -include $(CLEAR_VARS) -LOCAL_MODULE:= dvr_display-test - -LOCAL_C_INCLUDES := \ - frameworks/native/libs/vr/libdvr/include \ - frameworks/native/libs/nativewindow/include - -LOCAL_SANITIZE := thread - -LOCAL_SRC_FILES := dvr_display-test.cpp - -LOCAL_SHARED_LIBRARIES := \ - libandroid \ - liblog - -LOCAL_CFLAGS := \ - -DTRACE=0 \ - -O2 \ - -g - -# DTS Should only link to NDK libraries. -LOCAL_SDK_VERSION := 26 -LOCAL_NDK_STL_VARIANT := c++_static - -include $(BUILD_NATIVE_TEST)
\ No newline at end of file diff --git a/libs/vr/libdvr/tests/dvr_tracking-test.cpp b/libs/vr/libdvr/tests/dvr_tracking-test.cpp new file mode 100644 index 0000000000..3b6d6e1ec4 --- /dev/null +++ b/libs/vr/libdvr/tests/dvr_tracking-test.cpp @@ -0,0 +1,103 @@ +#include <android/log.h> +#include <gtest/gtest.h> + +#include "dvr_api_test.h" + +namespace { + +class DvrTrackingTest : public DvrApiTest {}; + +#if DVR_TRACKING_IMPLEMENTED + +TEST_F(DvrTrackingTest, Implemented) { + ASSERT_TRUE(api_.TrackingCameraCreate != nullptr); + ASSERT_TRUE(api_.TrackingCameraStart != nullptr); + ASSERT_TRUE(api_.TrackingCameraStop != nullptr); + + ASSERT_TRUE(api_.TrackingFeatureExtractorCreate != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorDestroy != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorStart != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorStop != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorProcessBuffer != nullptr); +} + +TEST_F(DvrTrackingTest, CameraCreateFailsForInvalidInput) { + int ret; + ret = api_.TrackingCameraCreate(nullptr); + EXPECT_EQ(ret, -EINVAL); + + DvrTrackingCamera* camera = reinterpret_cast<DvrTrackingCamera*>(42); + ret = api_.TrackingCameraCreate(&camera); + EXPECT_EQ(ret, -EINVAL); +} + +TEST_F(DvrTrackingTest, CameraCreateDestroy) { + DvrTrackingCamera* camera = nullptr; + int ret = api_.TrackingCameraCreate(&camera); + + EXPECT_EQ(ret, 0); + ASSERT_TRUE(camera != nullptr); + + api_.TrackingCameraDestroy(camera); +} + +TEST_F(DvrTrackingTest, FeatureExtractorCreateFailsForInvalidInput) { + int ret; + ret = api_.TrackingFeatureExtractorCreate(nullptr); + EXPECT_EQ(ret, -EINVAL); + + DvrTrackingFeatureExtractor* camera = + reinterpret_cast<DvrTrackingFeatureExtractor*>(42); + ret = api_.TrackingFeatureExtractorCreate(&camera); + EXPECT_EQ(ret, -EINVAL); +} + +TEST_F(DvrTrackingTest, FeatureExtractorCreateDestroy) { + DvrTrackingFeatureExtractor* camera = nullptr; + int ret = api_.TrackingFeatureExtractorCreate(&camera); + + EXPECT_EQ(ret, 0); + ASSERT_TRUE(camera != nullptr); + + api_.TrackingFeatureExtractorDestroy(camera); +} + +#else // !DVR_TRACKING_IMPLEMENTED + +TEST_F(DvrTrackingTest, NotImplemented) { + ASSERT_TRUE(api_.TrackingCameraCreate != nullptr); + ASSERT_TRUE(api_.TrackingCameraDestroy != nullptr); + ASSERT_TRUE(api_.TrackingCameraStart != nullptr); + ASSERT_TRUE(api_.TrackingCameraStop != nullptr); + + EXPECT_EQ(api_.TrackingCameraCreate(nullptr), -ENOSYS); + EXPECT_EQ(api_.TrackingCameraStart(nullptr, nullptr), -ENOSYS); + EXPECT_EQ(api_.TrackingCameraStop(nullptr), -ENOSYS); + + ASSERT_TRUE(api_.TrackingFeatureExtractorCreate != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorDestroy != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorStart != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorStop != nullptr); + ASSERT_TRUE(api_.TrackingFeatureExtractorProcessBuffer != nullptr); + + EXPECT_EQ(api_.TrackingFeatureExtractorCreate(nullptr), -ENOSYS); + EXPECT_EQ(api_.TrackingFeatureExtractorStart(nullptr, nullptr, nullptr), + -ENOSYS); + EXPECT_EQ(api_.TrackingFeatureExtractorStop(nullptr), -ENOSYS); + EXPECT_EQ(api_.TrackingFeatureExtractorProcessBuffer(nullptr, nullptr, + nullptr, nullptr), + -ENOSYS); + + ASSERT_TRUE(api_.TrackingSensorsCreate != nullptr); + ASSERT_TRUE(api_.TrackingSensorsDestroy != nullptr); + ASSERT_TRUE(api_.TrackingSensorsStart != nullptr); + ASSERT_TRUE(api_.TrackingSensorsStop != nullptr); + + EXPECT_EQ(api_.TrackingSensorsCreate(nullptr, nullptr), -ENOSYS); + EXPECT_EQ(api_.TrackingSensorsStart(nullptr, nullptr, nullptr), -ENOSYS); + EXPECT_EQ(api_.TrackingSensorsStop(nullptr), -ENOSYS); +} + +#endif // DVR_TRACKING_IMPLEMENTED + +} // namespace diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h index 13aa3e90d7..15fa327e45 100644 --- a/libs/vr/libpdx/private/pdx/service.h +++ b/libs/vr/libpdx/private/pdx/service.h @@ -59,9 +59,18 @@ class Channel : public std::enable_shared_from_this<Channel> { virtual ~Channel() {} /* + * Accessors to the pid of the last active client. + */ + pid_t GetActiveProcessId() const { return client_pid_; } + void SetActiveProcessId(pid_t pid) { client_pid_ = pid; } + + /* * Utility to get a shared_ptr reference from the channel context pointer. */ static std::shared_ptr<Channel> GetFromMessageInfo(const MessageInfo& info); + + private: + pid_t client_pid_ = 0; }; /* diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp index 32d40e8371..ecbfdba7c4 100644 --- a/libs/vr/libpdx_uds/service_endpoint.cpp +++ b/libs/vr/libpdx_uds/service_endpoint.cpp @@ -521,6 +521,9 @@ Status<void> Endpoint::ReceiveMessageForChannel( info.flags = 0; info.service = service_; info.channel = GetChannelState(channel_id); + if (info.channel != nullptr) { + info.channel->SetActiveProcessId(request.cred.pid); + } info.send_len = request.send_len; info.recv_len = request.max_recv_len; info.fd_count = request.file_descriptors.size(); diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp index 4dc669b339..776dd8e802 100644 --- a/libs/vr/libvrflinger/Android.bp +++ b/libs/vr/libvrflinger/Android.bp @@ -20,7 +20,6 @@ sourceFiles = [ "display_surface.cpp", "hardware_composer.cpp", "vr_flinger.cpp", - "vsync_service.cpp", ] includeFiles = [ "include" ] @@ -40,6 +39,7 @@ sharedLibraries = [ "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", "libbinder", "libbase", "libbufferhubqueue", @@ -92,3 +92,7 @@ cc_library_static { header_libs: headerLibraries, name: "libvrflinger", } + +subdirs = [ + "tests", +] diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h index 3090bd1e7a..6fad58ef6f 100644 --- a/libs/vr/libvrflinger/display_service.h +++ b/libs/vr/libvrflinger/display_service.h @@ -60,11 +60,6 @@ class DisplayService : public pdx::ServiceBase<DisplayService> { void SetDisplayConfigurationUpdateNotifier( DisplayConfigurationUpdateNotifier notifier); - using VSyncCallback = HardwareComposer::VSyncCallback; - void SetVSyncCallback(VSyncCallback callback) { - hardware_composer_.SetVSyncCallback(callback); - } - void GrantDisplayOwnership() { hardware_composer_.Enable(); } void SeizeDisplayOwnership() { hardware_composer_.Disable(); } void OnBootFinished() { hardware_composer_.OnBootFinished(); } diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp index 44ce78c854..e98d592bb7 100644 --- a/libs/vr/libvrflinger/hardware_composer.cpp +++ b/libs/vr/libvrflinger/hardware_composer.cpp @@ -1,5 +1,6 @@ #include "hardware_composer.h" +#include <binder/IServiceManager.h> #include <cutils/properties.h> #include <cutils/sched_policy.h> #include <fcntl.h> @@ -52,6 +53,10 @@ const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns"; const char kUseExternalDisplayProperty[] = "persist.vr.use_external_display"; +// Surface flinger uses "VSYNC-sf" and "VSYNC-app" for its version of these +// events. Name ours similarly. +const char kVsyncTraceEventName[] = "VSYNC-vrflinger"; + // How long to wait after boot finishes before we turn the display off. constexpr int kBootFinishedDisplayOffTimeoutSec = 10; @@ -131,6 +136,7 @@ HardwareComposer::~HardwareComposer(void) { UpdatePostThreadState(PostThreadState::Quit, true); if (post_thread_.joinable()) post_thread_.join(); + composer_callback_->SetVsyncService(nullptr); } bool HardwareComposer::Initialize( @@ -147,6 +153,13 @@ bool HardwareComposer::Initialize( primary_display_ = GetDisplayParams(composer, primary_display_id, true); + vsync_service_ = new VsyncService; + sp<IServiceManager> sm(defaultServiceManager()); + auto result = sm->addService(String16(VsyncService::GetServiceName()), + vsync_service_, false); + LOG_ALWAYS_FATAL_IF(result != android::OK, + "addService(%s) failed", VsyncService::GetServiceName()); + post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); LOG_ALWAYS_FATAL_IF( !post_thread_event_fd_, @@ -223,6 +236,7 @@ void HardwareComposer::CreateComposer() { LOG_ALWAYS_FATAL_IF(!composer_callback_->GotFirstHotplug(), "Registered composer callback but didn't get hotplug for primary" " display"); + composer_callback_->SetVsyncService(vsync_service_); } void HardwareComposer::OnPostThreadResumed() { @@ -242,7 +256,10 @@ void HardwareComposer::OnPostThreadPaused() { // Standalones only create the composer client once and then use SetPowerMode // to control the screen on pause/resume. if (!is_standalone_device_) { - composer_callback_ = nullptr; + if (composer_callback_ != nullptr) { + composer_callback_->SetVsyncService(nullptr); + composer_callback_ = nullptr; + } composer_.reset(nullptr); } else { EnableDisplay(*target_display_, false); @@ -336,7 +353,6 @@ HWC::Error HardwareComposer::Present(hwc2_display_t display) { // According to the documentation, this fence is signaled at the time of // vsync/DMA for physical displays. if (error == HWC::Error::None) { - ATRACE_INT("HardwareComposer: VsyncFence", present_fence); retire_fence_fds_.emplace_back(present_fence); } else { ATRACE_INT("HardwareComposer: PresentResult", error); @@ -775,6 +791,11 @@ void HardwareComposer::PostThread() { std::unique_lock<std::mutex> lock(post_thread_mutex_); ALOGI("HardwareComposer::PostThread: Entering quiescent state."); + if (was_running) { + vsync_trace_parity_ = false; + ATRACE_INT(kVsyncTraceEventName, 0); + } + // Tear down resources. OnPostThreadPaused(); was_running = false; @@ -848,6 +869,9 @@ void HardwareComposer::PostThread() { vsync_timestamp = status.get(); } + vsync_trace_parity_ = !vsync_trace_parity_; + ATRACE_INT(kVsyncTraceEventName, vsync_trace_parity_ ? 1 : 0); + // Advance the vsync counter only if the system is keeping up with hardware // vsync to give clients an indication of the delays. if (vsync_prediction_interval_ == 1) @@ -867,11 +891,6 @@ void HardwareComposer::PostThread() { vsync_ring_->Publish(vsync); } - // Signal all of the vsync clients. Because absolute time is used for the - // wakeup time below, this can take a little time if necessary. - if (vsync_callback_) - vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_); - { // Sleep until shortly before vsync. ATRACE_NAME("sleep"); @@ -1063,8 +1082,45 @@ void HardwareComposer::UpdateLayerConfig() { layers_.size()); } -void HardwareComposer::SetVSyncCallback(VSyncCallback callback) { - vsync_callback_ = callback; +std::vector<sp<IVsyncCallback>>::const_iterator +HardwareComposer::VsyncService::FindCallback( + const sp<IVsyncCallback>& callback) const { + sp<IBinder> binder = IInterface::asBinder(callback); + return std::find_if(callbacks_.cbegin(), callbacks_.cend(), + [&](const sp<IVsyncCallback>& callback) { + return IInterface::asBinder(callback) == binder; + }); +} + +status_t HardwareComposer::VsyncService::registerCallback( + const sp<IVsyncCallback> callback) { + std::lock_guard<std::mutex> autolock(mutex_); + if (FindCallback(callback) == callbacks_.cend()) { + callbacks_.push_back(callback); + } + return NO_ERROR; +} + +status_t HardwareComposer::VsyncService::unregisterCallback( + const sp<IVsyncCallback> callback) { + std::lock_guard<std::mutex> autolock(mutex_); + auto iter = FindCallback(callback); + if (iter != callbacks_.cend()) { + callbacks_.erase(iter); + } + return NO_ERROR; +} + +void HardwareComposer::VsyncService::OnVsync(int64_t vsync_timestamp) { + ATRACE_NAME("VsyncService::OnVsync"); + std::lock_guard<std::mutex> autolock(mutex_); + for (auto iter = callbacks_.begin(); iter != callbacks_.end();) { + if ((*iter)->onVsync(vsync_timestamp) == android::DEAD_OBJECT) { + iter = callbacks_.erase(iter); + } else { + ++iter; + } + } } Return<void> HardwareComposer::ComposerCallback::onHotplug( @@ -1123,16 +1179,26 @@ Return<void> HardwareComposer::ComposerCallback::onRefresh( Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display, int64_t timestamp) { + TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|", + display, timestamp); + std::lock_guard<std::mutex> lock(mutex_); DisplayInfo* display_info = GetDisplayInfo(display); if (display_info) { - TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|", - display, timestamp); display_info->callback_vsync_timestamp = timestamp; } + if (primary_display_.id == display && vsync_service_ != nullptr) { + vsync_service_->OnVsync(timestamp); + } return Void(); } +void HardwareComposer::ComposerCallback::SetVsyncService( + const sp<VsyncService>& vsync_service) { + std::lock_guard<std::mutex> lock(mutex_); + vsync_service_ = vsync_service; +} + HardwareComposer::ComposerCallback::Displays HardwareComposer::ComposerCallback::GetDisplays() { std::lock_guard<std::mutex> lock(mutex_); @@ -1149,6 +1215,7 @@ HardwareComposer::ComposerCallback::GetDisplays() { Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime( hwc2_display_t display) { + std::lock_guard<std::mutex> autolock(mutex_); DisplayInfo* display_info = GetDisplayInfo(display); if (!display_info) { ALOGW("Attempt to get vsync time for unknown display %" PRIu64, display); @@ -1160,7 +1227,6 @@ Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime( if (!event_fd) { // Fall back to returning the last timestamp returned by the vsync // callback. - std::lock_guard<std::mutex> autolock(mutex_); return display_info->callback_vsync_timestamp; } diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h index 1d8d46354d..80fa7acf17 100644 --- a/libs/vr/libvrflinger/hardware_composer.h +++ b/libs/vr/libvrflinger/hardware_composer.h @@ -24,6 +24,7 @@ #include <pdx/rpc/variant.h> #include <private/dvr/buffer_hub_client.h> #include <private/dvr/shared_buffer_helpers.h> +#include <private/dvr/vsync_service.h> #include "acquired_buffer.h" #include "display_surface.h" @@ -300,8 +301,6 @@ class Layer { // will access the state and whether it needs to be synchronized. class HardwareComposer { public: - // Type for vsync callback. - using VSyncCallback = std::function<void(int64_t, int64_t, uint32_t)>; using RequestDisplayCallback = std::function<void(bool)>; HardwareComposer(); @@ -325,8 +324,6 @@ class HardwareComposer { std::string Dump(); - void SetVSyncCallback(VSyncCallback callback); - const DisplayParams& GetPrimaryDisplayParams() const { return primary_display_; } @@ -350,6 +347,18 @@ class HardwareComposer { // on/off. Returns true on success, false on failure. bool EnableDisplay(const DisplayParams& display, bool enabled); + class VsyncService : public BnVsyncService { + public: + status_t registerCallback(const sp<IVsyncCallback> callback) override; + status_t unregisterCallback(const sp<IVsyncCallback> callback) override; + void OnVsync(int64_t vsync_timestamp); + private: + std::vector<sp<IVsyncCallback>>::const_iterator FindCallback( + const sp<IVsyncCallback>& callback) const; + std::mutex mutex_; + std::vector<sp<IVsyncCallback>> callbacks_; + }; + class ComposerCallback : public Hwc2::IComposerCallback { public: ComposerCallback() = default; @@ -360,6 +369,7 @@ class HardwareComposer { int64_t timestamp) override; bool GotFirstHotplug() { return got_first_hotplug_; } + void SetVsyncService(const sp<VsyncService>& vsync_service); struct Displays { hwc2_display_t primary_display = 0; @@ -385,6 +395,7 @@ class HardwareComposer { DisplayInfo primary_display_; std::optional<DisplayInfo> external_display_; bool external_display_was_hotplugged_ = false; + sp<VsyncService> vsync_service_; }; HWC::Error Validate(hwc2_display_t display); @@ -484,9 +495,6 @@ class HardwareComposer { // vector must be sorted by surface_id in ascending order. std::vector<Layer> layers_; - // Handler to hook vsync events outside of this class. - VSyncCallback vsync_callback_; - // The layer posting thread. This thread wakes up a short time before vsync to // hand buffers to hardware composer. std::thread post_thread_; @@ -534,6 +542,9 @@ class HardwareComposer { DvrConfig post_thread_config_; std::mutex shared_config_mutex_; + bool vsync_trace_parity_ = false; + sp<VsyncService> vsync_service_; + static constexpr int kPostThreadInterrupted = 1; HardwareComposer(const HardwareComposer&) = delete; diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp new file mode 100644 index 0000000000..d500278b1c --- /dev/null +++ b/libs/vr/libvrflinger/tests/Android.bp @@ -0,0 +1,37 @@ +shared_libs = [ + "android.hardware.configstore-utils", + "android.hardware.configstore@1.0", + "libbinder", + "libbufferhubqueue", + "libcutils", + "libgui", + "libhidlbase", + "liblog", + "libui", + "libutils", + "libnativewindow", + "libpdx_default_transport", +] + +static_libs = [ + "libdisplay", +] + +cc_test { + srcs: ["vrflinger_test.cpp"], + // See go/apct-presubmit for documentation on how this .filter file is used + // by Android's automated testing infrastructure for test filtering. + data: ["vrflinger_test.filter"], + static_libs: static_libs, + shared_libs: shared_libs, + cflags: [ + "-DLOG_TAG=\"VrFlingerTest\"", + "-DTRACE=0", + "-O0", + "-g", + "-Wall", + "-Werror", + ], + cppflags: ["-std=c++1z"], + name: "vrflinger_test", +} diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.cpp b/libs/vr/libvrflinger/tests/vrflinger_test.cpp new file mode 100644 index 0000000000..e1c7adbb11 --- /dev/null +++ b/libs/vr/libvrflinger/tests/vrflinger_test.cpp @@ -0,0 +1,264 @@ +#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> +#include <android/hardware/configstore/1.1/types.h> +#include <android/hardware_buffer.h> +#include <binder/IServiceManager.h> +#include <binder/Parcel.h> +#include <binder/ProcessState.h> +#include <configstore/Utils.h> +#include <cutils/properties.h> +#include <gtest/gtest.h> +#include <gui/ISurfaceComposer.h> +#include <log/log.h> +#include <utils/StrongPointer.h> + +#include <chrono> +#include <memory> +#include <mutex> +#include <optional> +#include <thread> + +#include <private/dvr/display_client.h> + +using namespace android::hardware::configstore; +using namespace android::hardware::configstore::V1_0; +using android::dvr::display::DisplayClient; +using android::dvr::display::Surface; +using android::dvr::display::SurfaceAttribute; +using android::dvr::display::SurfaceAttributeValue; + +namespace android { +namespace dvr { + +// The transaction code for asking surface flinger if vr flinger is active. This +// is done as a hidden api since it's only used for tests. See the "case 1028" +// block in SurfaceFlinger::onTransact() in SurfaceFlinger.cpp. +constexpr uint32_t kIsVrFlingerActiveTransactionCode = 1028; + +// The maximum amount of time to give vr flinger to activate/deactivate. If the +// switch hasn't completed in this amount of time, the test will fail. +constexpr auto kVrFlingerSwitchMaxTime = std::chrono::seconds(1); + +// How long to wait between each check to see if the vr flinger switch +// completed. +constexpr auto kVrFlingerSwitchPollInterval = std::chrono::milliseconds(50); + +// How long to wait for a device that boots to VR to have vr flinger ready. +constexpr auto kBootVrFlingerWaitTimeout = std::chrono::seconds(30); + +// A Binder connection to surface flinger. +class SurfaceFlingerConnection { + public: + static std::unique_ptr<SurfaceFlingerConnection> Create() { + sp<ISurfaceComposer> surface_flinger = interface_cast<ISurfaceComposer>( + defaultServiceManager()->getService(String16("SurfaceFlinger"))); + if (surface_flinger == nullptr) { + return nullptr; + } + + return std::unique_ptr<SurfaceFlingerConnection>( + new SurfaceFlingerConnection(surface_flinger)); + } + + // Returns true if the surface flinger process is still running. We use this + // to detect if surface flinger has crashed. + bool IsAlive() { + IInterface::asBinder(surface_flinger_)->pingBinder(); + return IInterface::asBinder(surface_flinger_)->isBinderAlive(); + } + + // Return true if vr flinger is currently active, false otherwise. If there's + // an error communicating with surface flinger, std::nullopt is returned. + std::optional<bool> IsVrFlingerActive() { + Parcel data, reply; + status_t result = + data.writeInterfaceToken(surface_flinger_->getInterfaceDescriptor()); + if (result != NO_ERROR) { + return std::nullopt; + } + result = IInterface::asBinder(surface_flinger_) + ->transact(kIsVrFlingerActiveTransactionCode, data, &reply); + if (result != NO_ERROR) { + return std::nullopt; + } + bool vr_flinger_active; + result = reply.readBool(&vr_flinger_active); + if (result != NO_ERROR) { + return std::nullopt; + } + return vr_flinger_active; + } + + enum class VrFlingerSwitchResult : int8_t { + kSuccess, + kTimedOut, + kCommunicationError, + kSurfaceFlingerDied + }; + + // Wait for vr flinger to become active or inactive. + VrFlingerSwitchResult WaitForVrFlinger(bool wait_active) { + return WaitForVrFlingerTimed(wait_active, kVrFlingerSwitchPollInterval, + kVrFlingerSwitchMaxTime); + } + + // Wait for vr flinger to become active or inactive, specifying custom timeouts. + VrFlingerSwitchResult WaitForVrFlingerTimed(bool wait_active, + std::chrono::milliseconds pollInterval, std::chrono::seconds timeout) { + auto start_time = std::chrono::steady_clock::now(); + while (1) { + std::this_thread::sleep_for(pollInterval); + if (!IsAlive()) { + return VrFlingerSwitchResult::kSurfaceFlingerDied; + } + std::optional<bool> vr_flinger_active = IsVrFlingerActive(); + if (!vr_flinger_active.has_value()) { + return VrFlingerSwitchResult::kCommunicationError; + } + if (vr_flinger_active.value() == wait_active) { + return VrFlingerSwitchResult::kSuccess; + } else if (std::chrono::steady_clock::now() - start_time > timeout) { + return VrFlingerSwitchResult::kTimedOut; + } + } + } + + private: + SurfaceFlingerConnection(sp<ISurfaceComposer> surface_flinger) + : surface_flinger_(surface_flinger) {} + + sp<ISurfaceComposer> surface_flinger_ = nullptr; +}; + +// This test activates vr flinger by creating a vr flinger surface, then +// deactivates vr flinger by destroying the surface. We verify that vr flinger +// is activated and deactivated as expected, and that surface flinger doesn't +// crash. +// +// If the device doesn't support vr flinger (as repoted by ConfigStore), the +// test does nothing. +// +// If the device is a standalone vr device, the test also does nothing, since +// this test verifies the behavior of display handoff from surface flinger to vr +// flinger and back, and standalone devices never hand control of the display +// back to surface flinger. +TEST(VrFlingerTest, ActivateDeactivate) { + android::ProcessState::self()->startThreadPool(); + + // Exit immediately if the device doesn't support vr flinger. This ConfigStore + // check is the same mechanism used by surface flinger to decide if it should + // initialize vr flinger. + bool vr_flinger_enabled = + getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::useVrFlinger>( + false); + if (!vr_flinger_enabled) { + return; + } + + // This test doesn't apply to standalone vr devices. + if (property_get_bool("ro.boot.vr", false)) { + return; + } + + auto surface_flinger_connection = SurfaceFlingerConnection::Create(); + ASSERT_NE(surface_flinger_connection, nullptr); + + // Verify we start off with vr flinger disabled. + ASSERT_TRUE(surface_flinger_connection->IsAlive()); + auto vr_flinger_active = surface_flinger_connection->IsVrFlingerActive(); + ASSERT_TRUE(vr_flinger_active.has_value()); + ASSERT_FALSE(vr_flinger_active.value()); + + // Create a vr flinger surface, and verify vr flinger becomes active. + // Introduce a scope so that, at the end of the scope, the vr flinger surface + // is destroyed, and vr flinger deactivates. + { + auto display_client = DisplayClient::Create(); + ASSERT_NE(display_client, nullptr); + auto metrics = display_client->GetDisplayMetrics(); + ASSERT_TRUE(metrics.ok()); + + auto surface = Surface::CreateSurface({ + {SurfaceAttribute::Direct, SurfaceAttributeValue(true)}, + {SurfaceAttribute::Visible, SurfaceAttributeValue(true)}, + }); + ASSERT_TRUE(surface.ok()); + ASSERT_TRUE(surface.get() != nullptr); + + auto queue = surface.get()->CreateQueue( + metrics.get().display_width, metrics.get().display_height, + /*layer_count=*/1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, + AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | + AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | + AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, + /*capacity=*/1, + /*metadata_size=*/0); + ASSERT_TRUE(queue.ok()); + ASSERT_TRUE(queue.get() != nullptr); + + size_t slot; + pdx::LocalHandle release_fence; + auto buffer = queue.get()->Dequeue(/*timeout=*/0, &slot, &release_fence); + ASSERT_TRUE(buffer.ok()); + ASSERT_TRUE(buffer.get() != nullptr); + + ASSERT_EQ(buffer.get()->width(), metrics.get().display_width); + ASSERT_EQ(buffer.get()->height(), metrics.get().display_height); + + void* raw_buf = nullptr; + ASSERT_GE(buffer.get()->Lock(AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, + /*x=*/0, /*y=*/0, buffer.get()->width(), + buffer.get()->height(), &raw_buf), + 0); + ASSERT_NE(raw_buf, nullptr); + uint32_t* pixels = static_cast<uint32_t*>(raw_buf); + + for (int i = 0; i < buffer.get()->stride() * buffer.get()->height(); ++i) { + pixels[i] = 0x0000ff00; + } + + ASSERT_GE(buffer.get()->Unlock(), 0); + + ASSERT_GE(buffer.get()->Post(/*ready_fence=*/pdx::LocalHandle(), + /*meta=*/nullptr, + /*user_metadata_size=*/0), + 0); + + ASSERT_EQ( + surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/true), + SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess); + } + + // Now that the vr flinger surface is destroyed, vr flinger should deactivate. + ASSERT_EQ( + surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/false), + SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess); +} + +// This test runs only on devices that boot to vr. Such a device should boot to +// a state where vr flinger is running, and the test verifies this after a +// delay. +TEST(BootVrFlingerTest, BootsToVrFlinger) { + // Exit if we are not running on a device that boots to vr. + if (!property_get_bool("ro.boot.vr", false)) { + return; + } + + auto surface_flinger_connection = SurfaceFlingerConnection::Create(); + ASSERT_NE(surface_flinger_connection, nullptr); + + // Verify that vr flinger is enabled. + ASSERT_TRUE(surface_flinger_connection->IsAlive()); + auto vr_flinger_active = surface_flinger_connection->IsVrFlingerActive(); + ASSERT_TRUE(vr_flinger_active.has_value()); + + bool active_value = vr_flinger_active.value(); + if (!active_value) { + // Try again, but delay up to 30 seconds. + ASSERT_EQ(surface_flinger_connection->WaitForVrFlingerTimed(true, + kVrFlingerSwitchPollInterval, kBootVrFlingerWaitTimeout), + SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess); + } +} + +} // namespace dvr +} // namespace android diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.filter b/libs/vr/libvrflinger/tests/vrflinger_test.filter new file mode 100644 index 0000000000..030bb7b67c --- /dev/null +++ b/libs/vr/libvrflinger/tests/vrflinger_test.filter @@ -0,0 +1,5 @@ +{ + "presubmit": { + "filter": "BootVrFlingerTest.*" + } +} diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp index 26aed4f25f..b57383ad44 100644 --- a/libs/vr/libvrflinger/vr_flinger.cpp +++ b/libs/vr/libvrflinger/vr_flinger.cpp @@ -23,7 +23,6 @@ #include "DisplayHardware/ComposerHal.h" #include "display_manager_service.h" #include "display_service.h" -#include "vsync_service.h" namespace android { namespace dvr { @@ -85,16 +84,6 @@ bool VrFlinger::Init(Hwc2::Composer* hidl, CHECK_ERROR(!service, error, "Failed to create display manager service."); dispatcher_->AddService(service); - service = android::dvr::VSyncService::Create(); - CHECK_ERROR(!service, error, "Failed to create vsync service."); - dispatcher_->AddService(service); - - display_service_->SetVSyncCallback( - std::bind(&android::dvr::VSyncService::VSyncEvent, - std::static_pointer_cast<android::dvr::VSyncService>(service), - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3)); - dispatcher_thread_ = std::thread([this]() { prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0); ALOGI("Entering message loop."); diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp deleted file mode 100644 index b8d8b08b5f..0000000000 --- a/libs/vr/libvrflinger/vsync_service.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include "vsync_service.h" - -#include <hardware/hwcomposer.h> -#include <log/log.h> -#include <poll.h> -#include <sys/prctl.h> -#include <time.h> -#include <utils/Trace.h> - -#include <dvr/dvr_display_types.h> -#include <pdx/default_transport/service_endpoint.h> -#include <private/dvr/clock_ns.h> -#include <private/dvr/display_protocol.h> - -using android::dvr::display::VSyncProtocol; -using android::dvr::display::VSyncSchedInfo; -using android::pdx::Channel; -using android::pdx::Message; -using android::pdx::MessageInfo; -using android::pdx::default_transport::Endpoint; -using android::pdx::rpc::DispatchRemoteMethod; - -namespace android { -namespace dvr { - -VSyncService::VSyncService() - : BASE("VSyncService", Endpoint::Create(VSyncProtocol::kClientPath)), - last_vsync_(0), - current_vsync_(0), - compositor_time_ns_(0), - current_vsync_count_(0) {} - -VSyncService::~VSyncService() {} - -void VSyncService::VSyncEvent(int64_t timestamp_ns, - int64_t compositor_time_ns, - uint32_t vsync_count) { - ATRACE_NAME("VSyncService::VSyncEvent"); - std::lock_guard<std::mutex> autolock(mutex_); - - last_vsync_ = current_vsync_; - current_vsync_ = timestamp_ns; - compositor_time_ns_ = compositor_time_ns; - current_vsync_count_ = vsync_count; - - NotifyWaiters(); - UpdateClients(); -} - -std::shared_ptr<Channel> VSyncService::OnChannelOpen(pdx::Message& message) { - const MessageInfo& info = message.GetInfo(); - - auto client = std::make_shared<VSyncChannel>(*this, info.pid, info.cid); - AddClient(client); - - return client; -} - -void VSyncService::OnChannelClose(pdx::Message& /*message*/, - const std::shared_ptr<Channel>& channel) { - auto client = std::static_pointer_cast<VSyncChannel>(channel); - if (!client) { - ALOGW("WARNING: VSyncChannel was NULL!!!\n"); - return; - } - - RemoveClient(client); -} - -void VSyncService::AddWaiter(pdx::Message& message) { - std::lock_guard<std::mutex> autolock(mutex_); - std::unique_ptr<VSyncWaiter> waiter(new VSyncWaiter(message)); - waiters_.push_back(std::move(waiter)); -} - -void VSyncService::AddClient(const std::shared_ptr<VSyncChannel>& client) { - std::lock_guard<std::mutex> autolock(mutex_); - clients_.push_back(client); -} - -void VSyncService::RemoveClient(const std::shared_ptr<VSyncChannel>& client) { - std::lock_guard<std::mutex> autolock(mutex_); - clients_.remove(client); -} - -// Private. Assumes mutex is held. -void VSyncService::NotifyWaiters() { - ATRACE_NAME("VSyncService::NotifyWaiters"); - auto first = waiters_.begin(); - auto last = waiters_.end(); - - while (first != last) { - (*first)->Notify(current_vsync_); - waiters_.erase(first++); - } -} - -// Private. Assumes mutex is held. -void VSyncService::UpdateClients() { - ATRACE_NAME("VSyncService::UpdateClients"); - auto first = clients_.begin(); - auto last = clients_.end(); - - while (first != last) { - (*first)->Signal(); - first++; - } -} - -pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) { - ATRACE_NAME("VSyncService::HandleMessage"); - switch (message.GetOp()) { - case VSyncProtocol::Wait::Opcode: - AddWaiter(message); - return {}; - - case VSyncProtocol::GetLastTimestamp::Opcode: - DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>( - *this, &VSyncService::OnGetLastTimestamp, message); - return {}; - - case VSyncProtocol::GetSchedInfo::Opcode: - DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>( - *this, &VSyncService::OnGetSchedInfo, message); - return {}; - - case VSyncProtocol::Acknowledge::Opcode: - DispatchRemoteMethod<VSyncProtocol::Acknowledge>( - *this, &VSyncService::OnAcknowledge, message); - return {}; - - default: - return Service::HandleMessage(message); - } -} - -pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) { - auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel()); - std::lock_guard<std::mutex> autolock(mutex_); - - // Getting the timestamp has the side effect of ACKing. - client->Ack(); - return {current_vsync_}; -} - -pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo( - pdx::Message& message) { - auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel()); - std::lock_guard<std::mutex> autolock(mutex_); - - // Getting the timestamp has the side effect of ACKing. - client->Ack(); - - uint32_t next_vsync_count = current_vsync_count_ + 1; - int64_t current_time = GetSystemClockNs(); - int64_t vsync_period_ns = 0; - int64_t next_warp; - if (current_vsync_ == 0 || last_vsync_ == 0) { - // Handle startup when current_vsync_ or last_vsync_ are 0. - // Normally should not happen because vsync_service is running before - // applications, but in case it does a sane time prevents applications - // from malfunctioning. - vsync_period_ns = 20000000; - next_warp = current_time; - } else { - // TODO(jbates) When we have an accurate reading of the true vsync - // period, use that instead of this estimated value. - vsync_period_ns = current_vsync_ - last_vsync_; - // Clamp the period, because when there are no surfaces the last_vsync_ - // value will get stale. Note this is temporary and goes away as soon - // as we have an accurate vsync period reported by the system. - vsync_period_ns = std::min(vsync_period_ns, INT64_C(20000000)); - next_warp = current_vsync_ + vsync_period_ns - compositor_time_ns_; - // If the request missed the present window, move up to the next vsync. - if (current_time > next_warp) { - next_warp += vsync_period_ns; - ++next_vsync_count; - } - } - - return {{vsync_period_ns, next_warp, next_vsync_count}}; -} - -pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) { - auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel()); - std::lock_guard<std::mutex> autolock(mutex_); - client->Ack(); - return {}; -} - -void VSyncWaiter::Notify(int64_t timestamp) { - timestamp_ = timestamp; - DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait, - message_); -} - -pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) { - return {timestamp_}; -} - -void VSyncChannel::Ack() { - ALOGD_IF(TRACE > 1, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_); - service_.ModifyChannelEvents(cid_, POLLPRI, 0); -} - -void VSyncChannel::Signal() { - ALOGD_IF(TRACE > 1, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_); - service_.ModifyChannelEvents(cid_, 0, POLLPRI); -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h deleted file mode 100644 index 822f02b266..0000000000 --- a/libs/vr/libvrflinger/vsync_service.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef ANDROID_DVR_SERVICES_DISPLAYD_VSYNC_SERVICE_H_ -#define ANDROID_DVR_SERVICES_DISPLAYD_VSYNC_SERVICE_H_ - -#include <pdx/service.h> - -#include <list> -#include <memory> -#include <mutex> -#include <thread> - -#include "display_service.h" - -namespace android { -namespace dvr { - -// VSyncWaiter encapsulates a client blocked waiting for the next vsync. -// It is used to enqueue the Message to reply to when the next vsync event -// occurs. -class VSyncWaiter { - public: - explicit VSyncWaiter(pdx::Message& message) : message_(std::move(message)) {} - - void Notify(int64_t timestamp); - - private: - pdx::Status<int64_t> OnWait(pdx::Message& message); - - pdx::Message message_; - int64_t timestamp_ = 0; - - VSyncWaiter(const VSyncWaiter&) = delete; - void operator=(const VSyncWaiter&) = delete; -}; - -// VSyncChannel manages the service-side per-client context for each client -// using the service. -class VSyncChannel : public pdx::Channel { - public: - VSyncChannel(pdx::Service& service, int pid, int cid) - : service_(service), pid_(pid), cid_(cid) {} - - void Ack(); - void Signal(); - - private: - pdx::Service& service_; - pid_t pid_; - int cid_; - - VSyncChannel(const VSyncChannel&) = delete; - void operator=(const VSyncChannel&) = delete; -}; - -// VSyncService implements the displayd vsync service over ServiceFS. -class VSyncService : public pdx::ServiceBase<VSyncService> { - public: - ~VSyncService() override; - - pdx::Status<void> HandleMessage(pdx::Message& message) override; - - std::shared_ptr<pdx::Channel> OnChannelOpen(pdx::Message& message) override; - void OnChannelClose(pdx::Message& message, - const std::shared_ptr<pdx::Channel>& channel) override; - - // Called by the hardware composer HAL, or similar, whenever a vsync event - // occurs on the primary display. |compositor_time_ns| is the number of ns - // before the next vsync when the compositor will preempt the GPU to do EDS - // and lens warp. - void VSyncEvent(int64_t timestamp_ns, int64_t compositor_time_ns, - uint32_t vsync_count); - - private: - friend BASE; - - VSyncService(); - - pdx::Status<int64_t> OnGetLastTimestamp(pdx::Message& message); - pdx::Status<display::VSyncSchedInfo> OnGetSchedInfo(pdx::Message& message); - pdx::Status<void> OnAcknowledge(pdx::Message& message); - - void NotifierThreadFunction(); - - void AddWaiter(pdx::Message& message); - void NotifyWaiters(); - void UpdateClients(); - - void AddClient(const std::shared_ptr<VSyncChannel>& client); - void RemoveClient(const std::shared_ptr<VSyncChannel>& client); - - int64_t last_vsync_; - int64_t current_vsync_; - int64_t compositor_time_ns_; - uint32_t current_vsync_count_; - - std::mutex mutex_; - - std::list<std::unique_ptr<VSyncWaiter>> waiters_; - std::list<std::shared_ptr<VSyncChannel>> clients_; - - VSyncService(const VSyncService&) = delete; - void operator=(VSyncService&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SERVICES_DISPLAYD_VSYNC_SERVICE_H_ diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 44f4dbc929..0fd91eb262 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -1285,17 +1285,6 @@ EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void); #define EGL_NATIVE_SURFACE_TIZEN 0x32A1 #endif /* EGL_TIZEN_image_native_surface */ -/* This is a private Android extension that does not exist in the EGL registry, - * formerly used to work around a hardware issue on Nexus 4. It is deprecated - * and unimplemented. It has been added to this header manually. */ -#ifndef EGL_ANDROID_image_crop -#define EGL_ANDROID_image_crop 1 -#define EGL_IMAGE_CROP_LEFT_ANDROID 0x3148 -#define EGL_IMAGE_CROP_TOP_ANDROID 0x3149 -#define EGL_IMAGE_CROP_RIGHT_ANDROID 0x314A -#define EGL_IMAGE_CROP_BOTTOM_ANDROID 0x314B -#endif - #ifdef __cplusplus } #endif diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp index b3752f5bcc..74c4d7d07a 100644 --- a/opengl/libs/EGL/BlobCache.cpp +++ b/opengl/libs/EGL/BlobCache.cpp @@ -79,7 +79,7 @@ void BlobCache::set(const void* key, size_t keySize, const void* value, } std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false)); - CacheEntry dummyEntry(dummyKey, NULL); + CacheEntry dummyEntry(dummyKey, nullptr); while (true) { auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry); @@ -139,7 +139,7 @@ size_t BlobCache::get(const void* key, size_t keySize, void* value, return 0; } std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false)); - CacheEntry dummyEntry(dummyKey, NULL); + CacheEntry dummyEntry(dummyKey, nullptr); auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry); if (index == mCacheEntries.end() || dummyEntry < *index) { ALOGV("get: no cache entry found for key of size %zu", keySize); @@ -308,7 +308,7 @@ BlobCache::Blob::Blob(const void* data, size_t size, bool copyData) : mData(copyData ? malloc(size) : data), mSize(size), mOwnsData(copyData) { - if (data != NULL && copyData) { + if (data != nullptr && copyData) { memcpy(const_cast<void*>(mData), data, size); } } diff --git a/opengl/libs/EGL/BlobCache_test.cpp b/opengl/libs/EGL/BlobCache_test.cpp index edbaaf090d..cf67cf443b 100644 --- a/opengl/libs/EGL/BlobCache_test.cpp +++ b/opengl/libs/EGL/BlobCache_test.cpp @@ -97,7 +97,7 @@ TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) { TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) { mBC->set("abcd", 4, "efgh", 4); - ASSERT_EQ(size_t(4), mBC->get("abcd", 4, NULL, 0)); + ASSERT_EQ(size_t(4), mBC->get("abcd", 4, nullptr, 0)); } TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) { @@ -169,7 +169,7 @@ TEST_F(BlobCacheTest, DoesntCacheIfKeyValuePairIsTooBig) { } mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE); - ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, NULL, 0)); + ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, nullptr, 0)); } TEST_F(BlobCacheTest, CacheMaxKeySizeSucceeds) { @@ -219,7 +219,7 @@ TEST_F(BlobCacheTest, CacheMaxKeyValuePairSizeSucceeds) { } mBC->set(key, MAX_KEY_SIZE, buf, bufSize); - ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, NULL, 0)); + ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, nullptr, 0)); } TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) { @@ -237,7 +237,7 @@ TEST_F(BlobCacheTest, CacheSizeDoesntExceedTotalLimit) { int numCached = 0; for (int i = 0; i < 256; i++) { uint8_t k = i; - if (mBC->get(&k, 1, NULL, 0) == 1) { + if (mBC->get(&k, 1, nullptr, 0) == 1) { numCached++; } } @@ -260,7 +260,7 @@ TEST_F(BlobCacheTest, ExceedingTotalLimitHalvesCacheSize) { int numCached = 0; for (int i = 0; i < maxEntries+1; i++) { uint8_t k = i; - if (mBC->get(&k, 1, NULL, 0) == 1) { + if (mBC->get(&k, 1, nullptr, 0) == 1) { numCached++; } } diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp index 79237159bf..cc42ac7fef 100644 --- a/opengl/libs/EGL/FileBlobCache.cpp +++ b/opengl/libs/EGL/FileBlobCache.cpp @@ -77,7 +77,7 @@ FileBlobCache::FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxT return; } - uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize, + uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(nullptr, fileSize, PROT_READ, MAP_PRIVATE, fd, 0)); if (buf == MAP_FAILED) { ALOGE("error mmaping cache file: %s (%d)", strerror(errno), diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index 91a34558aa..e954b4f3f8 100644 --- a/opengl/libs/EGL/Loader.cpp +++ b/opengl/libs/EGL/Loader.cpp @@ -129,7 +129,7 @@ Loader::driver_t::driver_t(void* gles) { dso[0] = gles; for (size_t i=1 ; i<NELEM(dso) ; i++) - dso[i] = 0; + dso[i] = nullptr; } Loader::driver_t::~driver_t() @@ -137,7 +137,7 @@ Loader::driver_t::~driver_t() for (size_t i=0 ; i<NELEM(dso) ; i++) { if (dso[i]) { dlclose(dso[i]); - dso[i] = 0; + dso[i] = nullptr; } } } @@ -163,7 +163,7 @@ int Loader::driver_t::set(void* hnd, int32_t api) // ---------------------------------------------------------------------------- Loader::Loader() - : getProcAddress(NULL) + : getProcAddress(nullptr) { } @@ -221,7 +221,7 @@ void* Loader::open(egl_connection_t* cnx) ATRACE_CALL(); void* dso; - driver_t* hnd = 0; + driver_t* hnd = nullptr; setEmulatorGlesValue(); @@ -272,11 +272,11 @@ void Loader::init_api(void* dso, char const * name = *api; __eglMustCastToProperFunctionPointerType f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { + if (f == nullptr) { // couldn't find the entry-point, use eglGetProcAddress() f = getProcAddress(name); } - if (f == NULL) { + if (f == nullptr) { // Try without the OES postfix ssize_t index = ssize_t(strlen(name)) - 3; if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) { @@ -286,7 +286,7 @@ void Loader::init_api(void* dso, //ALOGD_IF(f, "found <%s> instead", scrap); } } - if (f == NULL) { + if (f == nullptr) { // Try with the OES postfix ssize_t index = ssize_t(strlen(name)) - 3; if (index>0 && strcmp(name+index, "OES")) { @@ -295,7 +295,7 @@ void Loader::init_api(void* dso, //ALOGD_IF(f, "found <%s> instead", scrap); } } - if (f == NULL) { + if (f == nullptr) { //ALOGD("%s", name); f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; @@ -406,9 +406,9 @@ static void* load_system_driver(const char* kind) { } DIR* d = opendir(search); - if (d != NULL) { + if (d != nullptr) { struct dirent* e; - while ((e = readdir(d)) != NULL) { + while ((e = readdir(d)) != nullptr) { if (e->d_type == DT_DIR) { continue; } @@ -434,7 +434,7 @@ static void* load_system_driver(const char* kind) { std::string absolutePath = MatchFile::find(kind); if (absolutePath.empty()) { // this happens often, we don't want to log an error - return 0; + return nullptr; } const char* const driver_absolute_path = absolutePath.c_str(); @@ -444,10 +444,10 @@ static void* load_system_driver(const char* kind) { // sphal namespace. void* dso = do_android_load_sphal_library(driver_absolute_path, RTLD_NOW | RTLD_LOCAL); - if (dso == 0) { + if (dso == nullptr) { const char* err = dlerror(); ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown"); - return 0; + return nullptr; } ALOGD("loaded %s", driver_absolute_path); @@ -495,7 +495,7 @@ void *Loader::load_driver(const char* kind, if (!dso) { dso = load_system_driver(kind); if (!dso) - return NULL; + return nullptr; } if (mask & EGL) { @@ -512,11 +512,11 @@ void *Loader::load_driver(const char* kind, char const * name = *api; __eglMustCastToProperFunctionPointerType f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { + if (f == nullptr) { // couldn't find the entry-point, use eglGetProcAddress() f = getProcAddress(name); - if (f == NULL) { - f = (__eglMustCastToProperFunctionPointerType)0; + if (f == nullptr) { + f = (__eglMustCastToProperFunctionPointerType)nullptr; } } *curr++ = f; diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index f53cf3f8cc..e292b80ac5 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -89,22 +89,22 @@ static int sEarlyInitState = pthread_once(&once_control, &early_egl_init); egl_display_ptr validate_display(EGLDisplay dpy) { egl_display_ptr dp = get_display(dpy); if (!dp) - return setError(EGL_BAD_DISPLAY, egl_display_ptr(NULL)); + return setError(EGL_BAD_DISPLAY, egl_display_ptr(nullptr)); if (!dp->isReady()) - return setError(EGL_NOT_INITIALIZED, egl_display_ptr(NULL)); + return setError(EGL_NOT_INITIALIZED, egl_display_ptr(nullptr)); return dp; } egl_display_ptr validate_display_connection(EGLDisplay dpy, egl_connection_t*& cnx) { - cnx = NULL; + cnx = nullptr; egl_display_ptr dp = validate_display(dpy); if (!dp) return dp; cnx = &gEGLImpl; - if (cnx->dso == 0) { - return setError(EGL_BAD_CONFIG, egl_display_ptr(NULL)); + if (cnx->dso == nullptr) { + return setError(EGL_BAD_CONFIG, egl_display_ptr(nullptr)); } return dp; } @@ -117,14 +117,14 @@ const GLubyte * egl_get_string_for_current_context(GLenum name) { EGLContext context = egl_tls_t::getContext(); if (context == EGL_NO_CONTEXT) - return NULL; + return nullptr; egl_context_t const * const c = get_context(context); - if (c == NULL) // this should never happen, by construction - return NULL; + if (c == nullptr) // this should never happen, by construction + return nullptr; if (name != GL_EXTENSIONS) - return NULL; + return nullptr; return (const GLubyte *)c->gl_extensions.c_str(); } @@ -135,19 +135,19 @@ const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index) { EGLContext context = egl_tls_t::getContext(); if (context == EGL_NO_CONTEXT) - return NULL; + return nullptr; egl_context_t const * const c = get_context(context); - if (c == NULL) // this should never happen, by construction - return NULL; + if (c == nullptr) // this should never happen, by construction + return nullptr; if (name != GL_EXTENSIONS) - return NULL; + return nullptr; // if index is out of bounds, assume it will be in the default // implementation too, so we don't have to generate a GL error here if (index >= c->tokenized_gl_extensions.size()) - return NULL; + return nullptr; return (const GLubyte *)c->tokenized_gl_extensions[index].c_str(); } @@ -161,7 +161,7 @@ GLint egl_get_num_extensions_for_current_context() { return -1; egl_context_t const * const c = get_context(context); - if (c == NULL) // this should never happen, by construction + if (c == nullptr) // this should never happen, by construction return -1; return (GLint)c->tokenized_gl_extensions.size(); @@ -184,7 +184,7 @@ static EGLBoolean egl_init_drivers_locked() { // dynamically load our EGL implementation egl_connection_t* cnx = &gEGLImpl; - if (cnx->dso == 0) { + if (cnx->dso == nullptr) { cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX]; cnx->hooks[egl_connection_t::GLESv2_INDEX] = @@ -249,12 +249,12 @@ void setGlThreadSpecific(gl_hooks_t const *value) { char const * const gl_names[] = { #include "../entries.in" - NULL + nullptr }; char const * const egl_names[] = { #include "egl_entries.in" - NULL + nullptr }; #undef GL_ENTRY diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 3312b031a0..c361ab004b 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -136,7 +136,6 @@ char const * const gExtensionString = // "EGL_IMG_hibernate_process " // optional // "EGL_ANDROID_native_fence_sync " // strongly recommended // "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 -// "EGL_ANDROID_image_crop " // optional /* * EGL Extensions entry-points exposed to 3rd party applications @@ -258,7 +257,7 @@ static void(*findProcAddress(const char* name, return map[i].address; } } - return NULL; + return nullptr; } // ---------------------------------------------------------------------------- @@ -341,7 +340,7 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy, const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - if (num_config==0) { + if (num_config==nullptr) { return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); } @@ -366,7 +365,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; - if (num_config==0) { + if (num_config==nullptr) { return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); } @@ -385,8 +384,8 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, // Only enable MSAA if the context is OpenGL ES 2.0 and // if no caveat is requested - const EGLint *attribRendererable = NULL; - const EGLint *attribCaveat = NULL; + const EGLint *attribRendererable = nullptr; + const EGLint *attribCaveat = nullptr; // Count the number of attributes and look for // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT @@ -441,7 +440,7 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, { clearError(); - egl_connection_t* cnx = NULL; + egl_connection_t* cnx = nullptr; const egl_display_ptr dp = validate_display_connection(dpy, cnx); if (!dp) return EGL_FALSE; @@ -456,7 +455,7 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, // Translates EGL color spaces to Android data spaces. static android_dataspace dataSpaceFromEGLColorSpace(EGLint colorspace) { if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { - return HAL_DATASPACE_SRGB_LINEAR; + return HAL_DATASPACE_UNKNOWN; } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { return HAL_DATASPACE_SRGB; } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) { @@ -699,7 +698,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, const EGLint *origAttribList = attrib_list; clearError(); - egl_connection_t* cnx = NULL; + egl_connection_t* cnx = nullptr; egl_display_ptr dp = validate_display_connection(dpy, cnx); if (dp) { if (!window) { @@ -782,7 +781,7 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, { clearError(); - egl_connection_t* cnx = NULL; + egl_connection_t* cnx = nullptr; egl_display_ptr dp = validate_display_connection(dpy, cnx); if (dp) { EGLDisplay iDpy = dp->disp.dpy; @@ -803,7 +802,7 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, dp->disp.dpy, config, pixmap, attrib_list); if (surface != EGL_NO_SURFACE) { egl_surface_t* s = - new egl_surface_t(dp.get(), config, NULL, surface, + new egl_surface_t(dp.get(), config, nullptr, surface, getReportedColorSpace(colorSpace), cnx); return s; } @@ -816,7 +815,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, { clearError(); - egl_connection_t* cnx = NULL; + egl_connection_t* cnx = nullptr; egl_display_ptr dp = validate_display_connection(dpy, cnx); if (dp) { EGLDisplay iDpy = dp->disp.dpy; @@ -837,7 +836,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, dp->disp.dpy, config, attrib_list); if (surface != EGL_NO_SURFACE) { egl_surface_t* s = - new egl_surface_t(dp.get(), config, NULL, surface, + new egl_surface_t(dp.get(), config, nullptr, surface, getReportedColorSpace(colorSpace), cnx); return s; } @@ -911,7 +910,7 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, { clearError(); - egl_connection_t* cnx = NULL; + egl_connection_t* cnx = nullptr; const egl_display_ptr dp = validate_display_connection(dpy, cnx); if (dp) { if (share_list != EGL_NO_CONTEXT) { @@ -1000,9 +999,9 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, EGLSurface impl_read = EGL_NO_SURFACE; // these are our objects structs passed in - egl_context_t * c = NULL; - egl_surface_t const * d = NULL; - egl_surface_t const * r = NULL; + egl_context_t * c = nullptr; + egl_surface_t const * d = nullptr; + egl_surface_t const * r = nullptr; // these are the current objects structs egl_context_t * cur_c = get_context(getContext()); @@ -1016,7 +1015,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE); } - if (cur_c == NULL) { + if (cur_c == nullptr) { // no current context // not an error, there is just no current context. return EGL_TRUE; @@ -1164,7 +1163,7 @@ EGLint eglGetError(void) static __eglMustCastToProperFunctionPointerType findBuiltinWrapper( const char* procname) { const egl_connection_t* cnx = &gEGLImpl; - void* proc = NULL; + void* proc = nullptr; proc = dlsym(cnx->libEgl, procname); if (proc) return (__eglMustCastToProperFunctionPointerType)proc; @@ -1175,7 +1174,7 @@ static __eglMustCastToProperFunctionPointerType findBuiltinWrapper( proc = dlsym(cnx->libGles1, procname); if (proc) return (__eglMustCastToProperFunctionPointerType)proc; - return NULL; + return nullptr; } __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) @@ -1188,11 +1187,11 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) if (egl_init_drivers() == EGL_FALSE) { setError(EGL_BAD_PARAMETER, NULL); - return NULL; + return nullptr; } if (FILTER_EXTENSIONS(procname)) { - return NULL; + return nullptr; } __eglMustCastToProperFunctionPointerType addr; @@ -1347,7 +1346,7 @@ EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, egl_surface_t* const s = get_surface(draw); if (CC_UNLIKELY(dp->traceGpuCompletion)) { - EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); + EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr); if (sync != EGL_NO_SYNC_KHR) { FrameCompletionThread::queueSync(sync); } @@ -1398,7 +1397,7 @@ EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { - return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0); + return eglSwapBuffersWithDamageKHR(dpy, surface, nullptr, 0); } EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, @@ -1429,10 +1428,10 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name) // If we want to support EGL_EXT_client_extensions later, we can return // the client extension string here instead. if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) - return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0); + return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)nullptr); const egl_display_ptr dp = validate_display(dpy); - if (!dp) return (const char *) NULL; + if (!dp) return (const char *) nullptr; switch (name) { case EGL_VENDOR: @@ -1446,7 +1445,7 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name) default: break; } - return setError(EGL_BAD_PARAMETER, (const char *)0); + return setError(EGL_BAD_PARAMETER, (const char *)nullptr); } extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) @@ -1454,7 +1453,7 @@ extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy clearError(); const egl_display_ptr dp = validate_display(dpy); - if (!dp) return (const char *) NULL; + if (!dp) return (const char *) nullptr; switch (name) { case EGL_VENDOR: @@ -1468,7 +1467,7 @@ extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy default: break; } - return setError(EGL_BAD_PARAMETER, (const char *)0); + return setError(EGL_BAD_PARAMETER, (const char *)nullptr); } // ---------------------------------------------------------------------------- @@ -1650,7 +1649,7 @@ EGLSurface eglCreatePbufferFromClientBuffer( { clearError(); - egl_connection_t* cnx = NULL; + egl_connection_t* cnx = nullptr; const egl_display_ptr dp = validate_display_connection(dpy, cnx); if (!dp) return EGL_FALSE; if (cnx->egl.eglCreatePbufferFromClientBuffer) { @@ -1713,31 +1712,13 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, ContextRef _c(dp.get(), ctx); egl_context_t * const c = _c.get(); - // Temporary hack: eglImageCreateKHR should accept EGL_GL_COLORSPACE_LINEAR_KHR, - // EGL_GL_COLORSPACE_SRGB_KHR and EGL_GL_COLORSPACE_DEFAULT_EXT if - // EGL_EXT_image_gl_colorspace is supported, but some drivers don't like - // the DEFAULT value and generate an error. - std::vector<EGLint> strippedAttribList; - for (const EGLint *attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) { - if (attr[0] == EGL_GL_COLORSPACE_KHR && - dp->haveExtension("EGL_EXT_image_gl_colorspace")) { - if (attr[1] != EGL_GL_COLORSPACE_LINEAR_KHR && - attr[1] != EGL_GL_COLORSPACE_SRGB_KHR) { - continue; - } - } - strippedAttribList.push_back(attr[0]); - strippedAttribList.push_back(attr[1]); - } - strippedAttribList.push_back(EGL_NONE); - EGLImageKHR result = EGL_NO_IMAGE_KHR; egl_connection_t* const cnx = &gEGLImpl; if (cnx->dso && cnx->egl.eglCreateImageKHR) { result = cnx->egl.eglCreateImageKHR( dp->disp.dpy, c ? c->context : EGL_NO_CONTEXT, - target, buffer, strippedAttribList.data()); + target, buffer, attrib_list); } return result; } @@ -1954,7 +1935,7 @@ EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR( dp->disp.dpy, config, stream, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, + egl_surface_t* s = new egl_surface_t(dp.get(), config, nullptr, surface, EGL_GL_COLORSPACE_LINEAR_KHR, cnx); return s; } @@ -2110,10 +2091,10 @@ EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) { // this function cannot be implemented when this libEGL is built for // vendors. #ifndef __ANDROID_VNDK__ - if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); + if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer) nullptr); return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer)); #else - return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); + return setError(EGL_BAD_PARAMETER, (EGLClientBuffer) nullptr); #endif } diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp index ec548f3121..bcf496164b 100644 --- a/opengl/libs/EGL/egl_cache.cpp +++ b/opengl/libs/EGL/egl_cache.cpp @@ -95,7 +95,7 @@ void egl_cache_t::initialize(egl_display_t *display) { reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>( cnx->egl.eglGetProcAddress( "eglSetBlobCacheFuncsANDROID")); - if (eglSetBlobCacheFuncsANDROID == NULL) { + if (eglSetBlobCacheFuncsANDROID == nullptr) { ALOGE("EGL_ANDROID_blob_cache advertised, " "but unable to get eglSetBlobCacheFuncsANDROID"); return; @@ -119,7 +119,7 @@ void egl_cache_t::terminate() { if (mBlobCache) { mBlobCache->writeToFile(); } - mBlobCache = NULL; + mBlobCache = nullptr; } void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 2aec249aa5..d16d33a771 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -116,7 +116,7 @@ bool egl_display_t::getObject(egl_object_t* object) const { EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) { if (uintptr_t(disp) >= NUM_DISPLAYS) - return NULL; + return nullptr; return sDisplay[uintptr_t(disp)].getDisplay(disp); } @@ -135,7 +135,7 @@ EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) { disp.dpy = dpy; if (dpy == EGL_NO_DISPLAY) { loader.close(cnx->dso); - cnx->dso = NULL; + cnx->dso = nullptr; } } @@ -148,9 +148,9 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { std::unique_lock<std::mutex> _l(refLock); refs++; if (refs > 1) { - if (major != NULL) + if (major != nullptr) *major = VERSION_MAJOR; - if (minor != NULL) + if (minor != nullptr) *minor = VERSION_MINOR; while(!eglIsInitialized) { refCond.wait(_l); @@ -240,12 +240,6 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { if (len) { // NOTE: we could avoid the copy if we had strnstr. const std::string ext(start, len); - // Temporary hack: Adreno 530 driver exposes this extension under the draft - // KHR name, but during Khronos review it was decided to demote it to EXT. - if (ext == "EGL_EXT_image_gl_colorspace" && - findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) { - mExtensionString.append("EGL_EXT_image_gl_colorspace "); - } if (findExtension(disp.queryString.extensions, ext.c_str(), len)) { mExtensionString.append(ext + " "); } @@ -268,9 +262,9 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { traceGpuCompletion = true; } - if (major != NULL) + if (major != nullptr) *major = VERSION_MAJOR; - if (minor != NULL) + if (minor != nullptr) *minor = VERSION_MINOR; } @@ -361,8 +355,8 @@ void egl_display_t::loseCurrentImpl(egl_context_t * cur_c) // by construction, these are either 0 or valid (possibly terminated) // it should be impossible for these to be invalid ContextRef _cur_c(cur_c); - SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL); - SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL); + SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr); + SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr); { // scope for the lock std::lock_guard<std::mutex> _l(lock); @@ -387,8 +381,8 @@ EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c, // by construction, these are either 0 or valid (possibly terminated) // it should be impossible for these to be invalid ContextRef _cur_c(cur_c); - SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL); - SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL); + SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr); + SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr); { // scope for the lock std::lock_guard<std::mutex> _l(lock); diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h index 79a9f082a6..f7640287e4 100644 --- a/opengl/libs/EGL/egl_display.h +++ b/opengl/libs/EGL/egl_display.h @@ -160,7 +160,7 @@ public: const egl_display_t* get() const { return mDpy; } egl_display_t* get() { return mDpy; } - operator bool() const { return mDpy != NULL; } + operator bool() const { return mDpy != nullptr; } private: egl_display_t* mDpy; diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp index f879254f76..ff4fe2dd9c 100644 --- a/opengl/libs/EGL/egl_object.cpp +++ b/opengl/libs/EGL/egl_object.cpp @@ -81,14 +81,14 @@ egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWind } egl_surface_t::~egl_surface_t() { - if (win != NULL) { + if (win != nullptr) { disconnect(); win->decStrong(this); } } void egl_surface_t::disconnect() { - if (win != NULL && connected) { + if (win != nullptr && connected) { native_window_set_buffers_format(win, 0); if (native_window_api_disconnect(win, NATIVE_WINDOW_API_EGL)) { ALOGW("EGLNativeWindowType %p disconnect failed", win); @@ -281,12 +281,12 @@ void egl_surface_t::terminate() { egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config, egl_connection_t const* cnx, int version) : egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context), - config(config), read(0), draw(0), cnx(cnx), version(version) { + config(config), read(nullptr), draw(nullptr), cnx(cnx), version(version) { } void egl_context_t::onLooseCurrent() { - read = NULL; - draw = NULL; + read = nullptr; + draw = nullptr; } void egl_context_t::onMakeCurrent(EGLSurface draw, EGLSurface read) { diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h index 4e1de5cec4..fb2bdf4c51 100644 --- a/opengl/libs/EGL/egl_object.h +++ b/opengl/libs/EGL/egl_object.h @@ -67,7 +67,7 @@ public: public: ~LocalRef(); explicit LocalRef(egl_object_t* rhs); - explicit LocalRef(egl_display_t const* display, T o) : ref(0) { + explicit LocalRef(egl_display_t const* display, T o) : ref(nullptr) { egl_object_t* native = reinterpret_cast<N*>(o); if (o && egl_object_t::get(display, native)) { ref = native; diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp index 8508c5fe9d..b57c357990 100644 --- a/opengl/libs/EGL/egl_tls.cpp +++ b/opengl/libs/EGL/egl_tls.cpp @@ -28,7 +28,7 @@ pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED; pthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT; egl_tls_t::egl_tls_t() - : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(true) { + : error(EGL_SUCCESS), ctx(nullptr), logCallWithNoContext(true) { } const char *egl_tls_t::egl_strerror(EGLint err) { @@ -55,13 +55,38 @@ const char *egl_tls_t::egl_strerror(EGLint err) { void egl_tls_t::validateTLSKey() { struct TlsKeyInitializer { - static void create() { - pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread); - } + static void create() { pthread_key_create(&sKey, destructTLSData); } }; pthread_once(&sOnceKey, TlsKeyInitializer::create); } +void egl_tls_t::destructTLSData(void* data) { + egl_tls_t* tls = static_cast<egl_tls_t*>(data); + if (!tls) return; + + // Several things in the call tree of eglReleaseThread expect to be able to get the current + // thread state directly from TLS. That's a problem because Bionic has already cleared our + // TLS pointer before calling this function (pthread_getspecific(sKey) will return nullptr). + // Instead the data is passed as our parameter. + // + // Ideally we'd refactor this so we have thin wrappers that retrieve thread state from TLS and + // then pass it as a parameter (or 'this' pointer) to functions that do the real work without + // touching TLS. Then from here we could just call those implementation functions with the the + // TLS data we just received as a parameter. + // + // But that's a fairly invasive refactoring, so to do this robustly in the short term we just + // put the data *back* in TLS and call the top-level eglReleaseThread. It and it's call tree + // will retrieve the value from TLS, and then finally clear the TLS data. Bionic explicitly + // tolerates re-setting the value that it's currently trying to destruct (see + // pthread_key_clean_all()). Even if we forgot to clear the restored TLS data, bionic would + // call the destructor again, but eventually gives up and just leaks the data rather than + // enter an infinite loop. + pthread_setspecific(sKey, tls); + eglReleaseThread(); + ALOGE_IF(pthread_getspecific(sKey) != nullptr, + "EGL TLS data still exists after eglReleaseThread"); +} + void egl_tls_t::setErrorEtcImpl( const char* caller, int line, EGLint error, bool quiet) { validateTLSKey(); @@ -92,7 +117,7 @@ bool egl_tls_t::logNoContextCall() { egl_tls_t* egl_tls_t::getTLS() { egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); - if (tls == 0) { + if (tls == nullptr) { tls = new egl_tls_t; pthread_setspecific(sKey, tls); } @@ -103,7 +128,7 @@ void egl_tls_t::clearTLS() { if (sKey != TLS_KEY_NOT_INITIALIZED) { egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); if (tls) { - pthread_setspecific(sKey, 0); + pthread_setspecific(sKey, nullptr); delete tls; } } diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h index 9feae681bd..86a375c002 100644 --- a/opengl/libs/EGL/egl_tls.h +++ b/opengl/libs/EGL/egl_tls.h @@ -38,6 +38,7 @@ class egl_tls_t { egl_tls_t(); static void validateTLSKey(); + static void destructTLSData(void* data); static void setErrorEtcImpl( const char* caller, int line, EGLint error, bool quiet); diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h index 985827655a..299d8f71ad 100644 --- a/opengl/libs/EGL/egldefs.h +++ b/opengl/libs/EGL/egldefs.h @@ -37,7 +37,7 @@ struct egl_connection_t { GLESv2_INDEX = 1 }; - inline egl_connection_t() : dso(0) { } + inline egl_connection_t() : dso(nullptr) { } void * dso; gl_hooks_t * hooks[2]; EGLint major; diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles deleted file mode 100755 index feef3186a8..0000000000 --- a/opengl/libs/tools/genfiles +++ /dev/null @@ -1,50 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2008 Google Inc. -# -# 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. - -# Force a specific locale for sorting to avoid irrelevant differences -# in the generated files that could hide real differences. -export LC_ALL=POSIX - -./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in -./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in -./glapigen ../../include/GLES3/gl3.h > ../GLES2/gl2_api.in -./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in - -./glentrygen ../../include/GLES/gl.h > /tmp/gl_entries.in -./glentrygen ../../include/GLES/glext.h > /tmp/glext_entries.in -./glentrygen ../../include/GLES3/gl3.h > /tmp/gl2_entries.in -./glentrygen ../../include/GLES2/gl2ext.h > /tmp/gl2ext_entries.in - -# The awk command removes lines with the same function name as an earlier -# line, even if the rest of the line differs. Although signatures of -# functions with the same name should be the same, the different versions -# have some irrelevant whitespace and parameter name differences. -cat /tmp/gl_entries.in \ - /tmp/glext_entries.in \ - /tmp/gl2_entries.in \ - /tmp/gl2ext_entries.in \ - | sort -t, -k2 \ - | awk -F, '!_[$2]++' \ - > ../entries.in - -cat ../../include/GLES/gl.h \ - ../../include/GLES/glext.h \ - ../../include/GLES2/gl2ext.h \ - ../../include/GLES3/gl3.h \ - | ./glenumsgen \ - | sort \ - > ../enums.in - diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen deleted file mode 100755 index 4d8334f90f..0000000000 --- a/opengl/libs/tools/glapigen +++ /dev/null @@ -1,76 +0,0 @@ -#! /usr/bin/perl -# -# Copyright (C) 2008 Google Inc. -# -# 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. - -use strict; - -sub rtrim($) -{ - my $string = shift; - $string =~ s/\s+$//; - return $string; -} - -while (my $line = <>) { - next if $line =~ /^\//; - next if $line =~ /^#/; - next if $line =~ /^\s*$/; - if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { - next; - } - my $type = rtrim($2); - my $name = $3; - my $args = $4; - - #printf("%s", $line); - - my $prefix = ""; - if ($name eq "glGetString") { - $prefix = "__"; - } - - printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args); - - printf(" {\n"); - if ($type eq "void") { - printf(" CALL_GL_API(%s", $name); - } else { - printf(" CALL_GL_API_RETURN(%s", $name); - } - my @args = split ',', $args; - my $len = scalar(@args); - for (my $num = 0; $num < $len; $num++) { - if ($args[$num] ne "void") { - print ", "; - # - # extract the name from the parameter - # type name - # const type *name - # type *name - # type name[4] - # - if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) { - printf("%s", $2); - } - } - } - printf(");\n"); - printf("}\n"); -} - - - - - diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen deleted file mode 100755 index 170f04131a..0000000000 --- a/opengl/libs/tools/glentrygen +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/perl -# -# Copyright (C) 2008 Google Inc. -# -# 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. - -use strict; - -sub rtrim($) -{ - my $string = shift; - $string =~ s/\s+$//; - return $string; -} - -while (my $line = <>) { - next if $line =~ /^\//; - next if $line =~ /^#/; - next if $line =~ /^\s*$/; - if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { - next; - } - my $type = rtrim($2); - my $name = $3; - my $args = $4; - - printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args); -} diff --git a/opengl/libs/tools/glenumsgen b/opengl/libs/tools/glenumsgen deleted file mode 100755 index 2ae5fbfa25..0000000000 --- a/opengl/libs/tools/glenumsgen +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/perl -# -# Copyright (C) 2010 Google Inc. -# -# 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. - -use strict; - -my %enumHash = (); - -while (my $line = <STDIN>) { - next if $line =~ /^\//; - # Skip bitfield definitions. - next if $line =~ /_BIT(\d+_|\s+)/; - if ($line !~ /^#define\s+(\S+)\s+(0x\S+)/) { - next; - } - my $enumName = $1; - my $enumValue = $2; - next if exists($enumHash { $enumValue }); - $enumHash { $enumValue } = $enumName; - printf("GL_ENUM(%s,%s)\n", $enumValue, $enumName); -} - - - - - diff --git a/opengl/specs/README b/opengl/specs/README index fdafb1bffb..6d597d5519 100644 --- a/opengl/specs/README +++ b/opengl/specs/README @@ -19,10 +19,7 @@ Khronos. 0x3145 EGL_SYNC_NATIVE_FENCE_FD_ANDROID (EGL_ANDROID_native_fence_sync) 0x3146 EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID (EGL_ANDROID_native_fence_sync) 0x3147 EGL_FRAMEBUFFER_TARGET_ANDROID (EGL_ANDROID_framebuffer_target) -0x3148 EGL_IMAGE_CROP_LEFT_ANDROID (EGL_ANDROID_image_crop) -0x3149 EGL_IMAGE_CROP_TOP_ANDROID (EGL_ANDROID_image_crop) -0x314A EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop) -0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop) +0x3148 - 0x314B previously used by the undocumented, deprecated extension EGL_ANDROID_image_crop 0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh) 0x314D EGL_GL_COLORSPACE_DEFAULT_EXT (EGL_EXT_image_gl_colorspace) 0x314E - 0x314F (unused) diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp index 2b76279801..b06422a98c 100644 --- a/opengl/tests/lib/WindowSurface.cpp +++ b/opengl/tests/lib/WindowSurface.cpp @@ -57,7 +57,7 @@ WindowSurface::WindowSurface() { sp<SurfaceControl> sc = surfaceComposerClient->createSurface( String8("Benchmark"), width, height, PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque); - if (sc == NULL || !sc->isValid()) { + if (sc == nullptr || !sc->isValid()) { fprintf(stderr, "Failed to create SurfaceControl\n"); return; } diff --git a/opengl/tests/lib/glTestLib.cpp b/opengl/tests/lib/glTestLib.cpp index 213dffd50f..290d7a0de2 100644 --- a/opengl/tests/lib/glTestLib.cpp +++ b/opengl/tests/lib/glTestLib.cpp @@ -37,7 +37,7 @@ void glTestPrintGLString(const char *name, GLenum s) { const char *v = (const char *) glGetString(s); - if (v == NULL) { + if (v == nullptr) { testPrintI("GL %s unknown", name); } else { testPrintI("GL %s = %s", name, v); diff --git a/opengl/tests/lib/include/EGLUtils.h b/opengl/tests/lib/include/EGLUtils.h index 9dc6bcf56a..eb9571d478 100644 --- a/opengl/tests/lib/include/EGLUtils.h +++ b/opengl/tests/lib/include/EGLUtils.h @@ -100,11 +100,11 @@ status_t EGLUtils::selectConfigForPixelFormat( if (!attrs) return BAD_VALUE; - if (outConfig == NULL) + if (outConfig == nullptr) return BAD_VALUE; // Get all the "potential match" configs... - if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE) + if (eglGetConfigs(dpy, nullptr, 0, &numConfigs) == EGL_FALSE) return BAD_VALUE; std::vector<EGLConfig> configs(numConfigs); @@ -113,7 +113,7 @@ status_t EGLUtils::selectConfigForPixelFormat( } int i; - EGLConfig config = NULL; + EGLConfig config = nullptr; for (i=0 ; i<n ; i++) { EGLint nativeVisualId = 0; eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId); @@ -243,7 +243,7 @@ String8 EGLUtils::printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { bool EGLUtils::printEGLConfigurations(EGLDisplay dpy, String8& msg) { EGLint numConfig = 0; - EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig); + EGLint returnVal = eglGetConfigs(dpy, nullptr, 0, &numConfig); msg.append(checkEglError("eglGetConfigs", returnVal)); if (!returnVal) { return false; diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index a9e5a4339c..45efb9fc08 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -15,6 +15,8 @@ cc_library_shared { name: "libinputflinger", + cpp_std: "c++17", + srcs: [ "EventHub.cpp", "InputApplication.cpp", diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp index 4d9a2a0254..77a474fa82 100644 --- a/services/inputflinger/EventHub.cpp +++ b/services/inputflinger/EventHub.cpp @@ -143,9 +143,9 @@ uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) { EventHub::Device::Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier) : - next(NULL), + next(nullptr), fd(fd), id(id), path(path), identifier(identifier), - classes(0), configuration(NULL), virtualKeyMap(NULL), + classes(0), configuration(nullptr), virtualKeyMap(nullptr), ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0), timestampOverrideSec(0), timestampOverrideUsec(0), enabled(true), isVirtual(fd < 0) { @@ -200,7 +200,7 @@ const int EventHub::EPOLL_MAX_EVENTS; EventHub::EventHub(void) : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(), - mOpeningDevices(0), mClosingDevices(0), + mOpeningDevices(nullptr), mClosingDevices(nullptr), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { @@ -267,21 +267,21 @@ EventHub::~EventHub(void) { InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device == NULL) return InputDeviceIdentifier(); + if (device == nullptr) return InputDeviceIdentifier(); return device->identifier; } uint32_t EventHub::getDeviceClasses(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device == NULL) return 0; + if (device == nullptr) return 0; return device->classes; } int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device == NULL) return 0; + if (device == nullptr) return 0; return device->controllerNumber; } @@ -465,7 +465,7 @@ status_t EventHub::mapKey(int32_t deviceId, if (device) { // Check the key character map first. sp<KeyCharacterMap> kcm = device->getKeyCharacterMap(); - if (kcm != NULL) { + if (kcm != nullptr) { if (!kcm->mapKey(scanCode, usageCode, outKeycode)) { *outFlags = 0; status = NO_ERROR; @@ -481,7 +481,7 @@ status_t EventHub::mapKey(int32_t deviceId, } if (status == NO_ERROR) { - if (kcm != NULL) { + if (kcm != nullptr) { kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState); } else { *outMetaState = metaState; @@ -581,7 +581,7 @@ sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { if (device) { return device->getKeyCharacterMap(); } - return NULL; + return nullptr; } bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, @@ -641,7 +641,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) { if (identifier.uniqueId.isEmpty()) { // If it didn't have a unique id check for conflicts and enforce // uniqueness if necessary. - while(getDeviceByDescriptorLocked(identifier.descriptor) != NULL) { + while(getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) { identifier.nonce++; rawDescriptor = generateDescriptor(identifier); } @@ -714,7 +714,7 @@ EventHub::Device* EventHub::getDeviceByDescriptorLocked(String8& descriptor) con return device; } } - return NULL; + return nullptr; } EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const { @@ -732,7 +732,7 @@ EventHub::Device* EventHub::getDeviceByPathLocked(const char* devicePath) const return device; } } - return NULL; + return nullptr; } size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { @@ -782,7 +782,7 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz mNeedToSendFinishedDeviceScan = true; } - while (mOpeningDevices != NULL) { + while (mOpeningDevices != nullptr) { Device* device = mOpeningDevices; ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.string()); @@ -1099,7 +1099,7 @@ status_t EventHub::registerDeviceForEpollLocked(Device* device) { status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) { if (device->hasValidFd()) { - if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) { + if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, nullptr)) { ALOGW("Could not remove device fd from epoll instance. errno=%d", errno); return -errno; } @@ -1423,7 +1423,7 @@ void EventHub::configureFd(Device* device) { bool EventHub::isDeviceEnabled(int32_t deviceId) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device == NULL) { + if (device == nullptr) { ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__); return false; } @@ -1433,7 +1433,7 @@ bool EventHub::isDeviceEnabled(int32_t deviceId) { status_t EventHub::enableDevice(int32_t deviceId) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device == NULL) { + if (device == nullptr) { ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__); return BAD_VALUE; } @@ -1455,7 +1455,7 @@ status_t EventHub::enableDevice(int32_t deviceId) { status_t EventHub::disableDevice(int32_t deviceId) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device == NULL) { + if (device == nullptr) { ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__); return BAD_VALUE; } @@ -1634,9 +1634,9 @@ void EventHub::closeDeviceLocked(Device* device) { device->close(); // Unlink for opening devices list if it is present. - Device* pred = NULL; + Device* pred = nullptr; bool found = false; - for (Device* entry = mOpeningDevices; entry != NULL; ) { + for (Device* entry = mOpeningDevices; entry != nullptr; ) { if (entry == device) { found = true; break; @@ -1712,7 +1712,7 @@ status_t EventHub::scanDirLocked(const char *dirname) DIR *dir; struct dirent *de; dir = opendir(dirname); - if(dir == NULL) + if(dir == nullptr) return -1; strcpy(devname, dirname); filename = devname + strlen(devname); @@ -1773,7 +1773,7 @@ void EventHub::dump(std::string& dump) { dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n", device->configurationFile.string()); dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n", - toString(device->overlayKeyMap != NULL)); + toString(device->overlayKeyMap != nullptr)); } } // release lock } diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h index 66bc29456b..dfe3defc73 100644 --- a/services/inputflinger/EventHub.h +++ b/services/inputflinger/EventHub.h @@ -385,7 +385,7 @@ private: const bool isVirtual; // set if fd < 0 is passed to constructor const sp<KeyCharacterMap>& getKeyCharacterMap() const { - if (combinedKeyMap != NULL) { + if (combinedKeyMap != nullptr) { return combinedKeyMap; } return keyMap.keyCharacterMap; diff --git a/services/inputflinger/InputApplication.cpp b/services/inputflinger/InputApplication.cpp index 9e90631840..c56dfe6879 100644 --- a/services/inputflinger/InputApplication.cpp +++ b/services/inputflinger/InputApplication.cpp @@ -25,7 +25,7 @@ namespace android { // --- InputApplicationHandle --- InputApplicationHandle::InputApplicationHandle() : - mInfo(NULL) { + mInfo(nullptr) { } InputApplicationHandle::~InputApplicationHandle() { @@ -35,7 +35,7 @@ InputApplicationHandle::~InputApplicationHandle() { void InputApplicationHandle::releaseInfo() { if (mInfo) { delete mInfo; - mInfo = NULL; + mInfo = nullptr; } } diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp index 9a449fa6d1..c805805252 100644 --- a/services/inputflinger/InputDispatcher.cpp +++ b/services/inputflinger/InputDispatcher.cpp @@ -240,14 +240,14 @@ static void dumpRegion(std::string& dump, const Region& region) { InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) : mPolicy(policy), - mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED), + mPendingEvent(nullptr), mLastDropReason(DROP_REASON_NOT_DROPPED), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX), - mNextUnblockedEvent(NULL), + mNextUnblockedEvent(nullptr), mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false), mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) { mLooper = new Looper(false); - mKeyRepeatState.lastKeyEntry = NULL; + mKeyRepeatState.lastKeyEntry = nullptr; policy->getDispatcherConfiguration(&mConfig); } @@ -360,7 +360,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { // Now we have an event to dispatch. // All events are eventually dequeued and processed this way, even if we intend to drop them. - ALOG_ASSERT(mPendingEvent != NULL); + ALOG_ASSERT(mPendingEvent != nullptr); bool done = false; DropReason dropReason = DROP_REASON_NOT_DROPPED; if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) { @@ -370,7 +370,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } if (mNextUnblockedEvent == mPendingEvent) { - mNextUnblockedEvent = NULL; + mNextUnblockedEvent = nullptr; } switch (mPendingEvent->type) { @@ -481,14 +481,14 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY - && mInputTargetWaitApplicationHandle != NULL) { + && mInputTargetWaitApplicationHandle != nullptr) { int32_t displayId = motionEntry->displayId; int32_t x = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(motionEntry->pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_Y)); sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); - if (touchedWindowHandle != NULL + if (touchedWindowHandle != nullptr && touchedWindowHandle->inputApplicationHandle != mInputTargetWaitApplicationHandle) { // User touched a different application than the one we are waiting on. @@ -534,7 +534,7 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display } } } - return NULL; + return nullptr; } void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) { @@ -663,7 +663,7 @@ void InputDispatcher::releasePendingEventLocked() { if (mPendingEvent) { resetANRTimeoutsLocked(); releaseInboundEventLocked(mPendingEvent); - mPendingEvent = NULL; + mPendingEvent = nullptr; } } @@ -676,7 +676,7 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) { setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); } if (entry == mNextUnblockedEvent) { - mNextUnblockedEvent = NULL; + mNextUnblockedEvent = nullptr; } addRecentEventLocked(entry); entry->release(); @@ -685,7 +685,7 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) { void InputDispatcher::resetKeyRepeatLocked() { if (mKeyRepeatState.lastKeyEntry) { mKeyRepeatState.lastKeyEntry->release(); - mKeyRepeatState.lastKeyEntry = NULL; + mKeyRepeatState.lastKeyEntry = nullptr; } } @@ -702,7 +702,7 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t cu entry->repeatCount += 1; } else { KeyEntry* newEntry = new KeyEntry(currentTime, - entry->deviceId, entry->source, policyFlags, + entry->deviceId, entry->source, entry->displayId, policyFlags, entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount + 1, entry->downTime); @@ -807,7 +807,7 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { CommandEntry* commandEntry = postCommandLocked( & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible); - if (mFocusedWindowHandle != NULL) { + if (mFocusedWindowHandle != nullptr) { commandEntry->inputWindowHandle = mFocusedWindowHandle; } commandEntry->keyEntry = entry; @@ -851,11 +851,11 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) { #if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, " - "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, " - "repeatCount=%d, downTime=%" PRId64, + ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ", " + "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, " + "metaState=0x%x, repeatCount=%d, downTime=%" PRId64, prefix, - entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, + entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags, entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount, entry->downTime); #endif @@ -924,12 +924,13 @@ bool InputDispatcher::dispatchMotionLocked( void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) { #if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, " + ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 + ", policyFlags=0x%x, " "action=0x%x, actionButton=0x%x, flags=0x%x, " "metaState=0x%x, buttonState=0x%x," "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64, prefix, - entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, + entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags, entry->action, entry->actionButton, entry->flags, entry->metaState, entry->buttonState, entry->edgeFlags, entry->xPrecision, entry->yPrecision, @@ -987,7 +988,7 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle, const sp<InputWindowHandle>& windowHandle, nsecs_t* nextWakeupTime, const char* reason) { - if (applicationHandle == NULL && windowHandle == NULL) { + if (applicationHandle == nullptr && windowHandle == nullptr) { if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) { #if DEBUG_FOCUS ALOGD("Waiting for system to become ready for input. Reason: %s", reason); @@ -1006,9 +1007,9 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, reason); #endif nsecs_t timeout; - if (windowHandle != NULL) { + if (windowHandle != nullptr) { timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT); - } else if (applicationHandle != NULL) { + } else if (applicationHandle != nullptr) { timeout = applicationHandle->getDispatchingTimeout( DEFAULT_INPUT_DISPATCHING_TIMEOUT); } else { @@ -1021,10 +1022,10 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, mInputTargetWaitTimeoutExpired = false; mInputTargetWaitApplicationHandle.clear(); - if (windowHandle != NULL) { + if (windowHandle != nullptr) { mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle; } - if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) { + if (mInputTargetWaitApplicationHandle == nullptr && applicationHandle != nullptr) { mInputTargetWaitApplicationHandle = applicationHandle; } } @@ -1067,7 +1068,7 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); sp<InputWindowHandle> windowHandle = connection->inputWindowHandle; - if (windowHandle != NULL) { + if (windowHandle != nullptr) { const InputWindowInfo* info = windowHandle->getInfo(); if (info) { ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(info->displayId); @@ -1113,10 +1114,10 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, // If there is no currently focused window and no focused application // then drop the event. - if (mFocusedWindowHandle == NULL) { - if (mFocusedApplicationHandle != NULL) { + if (mFocusedWindowHandle == nullptr) { + if (mFocusedApplicationHandle != nullptr) { injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplicationHandle, NULL, nextWakeupTime, + mFocusedApplicationHandle, nullptr, nextWakeupTime, "Waiting because no window has focus but there is a " "focused application that may eventually add a window " "when it finishes starting up."); @@ -1186,7 +1187,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // Copy current touch state into mTempTouchState. // This state is always reset at the end of this function, so if we don't find state // for the specified display then our initial state will be empty. - const TouchState* oldState = NULL; + const TouchState* oldState = nullptr; ssize_t oldStateIndex = mTouchStatesByDisplay.indexOfKey(displayId); if (oldStateIndex >= 0) { oldState = &mTouchStatesByDisplay.valueAt(oldStateIndex); @@ -1274,21 +1275,21 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } // Figure out whether splitting will be allowed for this window. - if (newTouchedWindowHandle != NULL + if (newTouchedWindowHandle != nullptr && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) { // New window supports splitting. isSplit = true; } else if (isSplit) { // New window does not support splitting but we have already split events. // Ignore the new window. - newTouchedWindowHandle = NULL; + newTouchedWindowHandle = nullptr; } // Handle the case where we did not find a window. - if (newTouchedWindowHandle == NULL) { + if (newTouchedWindowHandle == nullptr) { // Try to assign the pointer to the first foreground window we find, if there is one. newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle(); - if (newTouchedWindowHandle == NULL) { + if (newTouchedWindowHandle == nullptr) { ALOGI("Dropping event because there is no touchable window at (%d, %d).", x, y); injectionResult = INPUT_EVENT_INJECTION_FAILED; goto Failed; @@ -1345,7 +1346,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (oldTouchedWindowHandle != newTouchedWindowHandle - && newTouchedWindowHandle != NULL) { + && newTouchedWindowHandle != nullptr) { #if DEBUG_FOCUS ALOGD("Touch is slipping out of window %s into window %s.", oldTouchedWindowHandle->getName().c_str(), @@ -1380,7 +1381,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, if (newHoverWindowHandle != mLastHoverWindowHandle) { // Let the previous window know that the hover sequence is over. - if (mLastHoverWindowHandle != NULL) { + if (mLastHoverWindowHandle != nullptr) { #if DEBUG_HOVER ALOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->getName().c_str()); @@ -1390,7 +1391,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } // Let the new window know that the hover sequence is starting. - if (newHoverWindowHandle != NULL) { + if (newHoverWindowHandle != nullptr) { #if DEBUG_HOVER ALOGD("Sending hover enter event to window %s.", newHoverWindowHandle->getName().c_str()); @@ -1455,7 +1456,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, touchedWindow.windowHandle, entry, "touched"); if (!reason.empty()) { injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - NULL, touchedWindow.windowHandle, nextWakeupTime, reason.c_str()); + nullptr, touchedWindow.windowHandle, nextWakeupTime, reason.c_str()); goto Unresponsive; } } @@ -1503,7 +1504,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, Failed: // Check injection permission once and for all. if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) { - if (checkInjectionPermission(NULL, entry->injectionState)) { + if (checkInjectionPermission(nullptr, entry->injectionState)) { injectionPermission = INJECTION_PERMISSION_GRANTED; } else { injectionPermission = INJECTION_PERMISSION_DENIED; @@ -1636,10 +1637,10 @@ void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTarge bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, const InjectionState* injectionState) { if (injectionState - && (windowHandle == NULL + && (windowHandle == nullptr || windowHandle->getInfo()->ownerUid != injectionState->injectorUid) && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) { - if (windowHandle != NULL) { + if (windowHandle != nullptr) { ALOGW("Permission denied: injecting event from pid %d uid %d to window %s " "owned by uid %d", injectionState->injectorPid, injectionState->injectorUid, @@ -1778,8 +1779,8 @@ std::string InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentT std::string InputDispatcher::getApplicationWindowLabelLocked( const sp<InputApplicationHandle>& applicationHandle, const sp<InputWindowHandle>& windowHandle) { - if (applicationHandle != NULL) { - if (windowHandle != NULL) { + if (applicationHandle != nullptr) { + if (windowHandle != nullptr) { std::string label(applicationHandle->getName()); label += " - "; label += windowHandle->getName(); @@ -1787,7 +1788,7 @@ std::string InputDispatcher::getApplicationWindowLabelLocked( } else { return applicationHandle->getName(); } - } else if (windowHandle != NULL) { + } else if (windowHandle != nullptr) { return windowHandle->getName(); } else { return "<unknown application or window>"; @@ -1795,7 +1796,7 @@ std::string InputDispatcher::getApplicationWindowLabelLocked( } void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) { - if (mFocusedWindowHandle != NULL) { + if (mFocusedWindowHandle != nullptr) { const InputWindowInfo* info = mFocusedWindowHandle->getInfo(); if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) { #if DEBUG_DISPATCH_CYCLE @@ -2017,7 +2018,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, // Publish the key event. status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq, - keyEntry->deviceId, keyEntry->source, + keyEntry->deviceId, keyEntry->source, keyEntry->displayId, dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, keyEntry->keyCode, keyEntry->scanCode, keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime, @@ -2291,7 +2292,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( InputTarget target; sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel); - if (windowHandle != NULL) { + if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); target.xOffset = -windowInfo->frameLeft; target.yOffset = -windowInfo->frameTop; @@ -2349,7 +2350,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet "we expected there to be %d pointers. This probably means we received " "a broken sequence of pointer ids from the input device.", splitPointerCount, pointerIds.count()); - return NULL; + return nullptr; } int32_t action = originalMotionEntry->action; @@ -2384,6 +2385,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet originalMotionEntry->eventTime, originalMotionEntry->deviceId, originalMotionEntry->source, + originalMotionEntry->displayId, originalMotionEntry->policyFlags, action, originalMotionEntry->actionButton, @@ -2394,7 +2396,6 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet originalMotionEntry->xPrecision, originalMotionEntry->yPrecision, originalMotionEntry->downTime, - originalMotionEntry->displayId, splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0); if (originalMotionEntry->injectionState) { @@ -2423,12 +2424,49 @@ void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChange } } +/** + * If one of the meta shortcuts is detected, process them here: + * Meta + Backspace -> generate BACK + * Meta + Enter -> generate HOME + * This will potentially overwrite keyCode and metaState. + */ +void InputDispatcher::accelerateMetaShortcuts(const int32_t deviceId, const int32_t action, + int32_t& keyCode, int32_t& metaState) { + if (metaState & AMETA_META_ON && action == AKEY_EVENT_ACTION_DOWN) { + int32_t newKeyCode = AKEYCODE_UNKNOWN; + if (keyCode == AKEYCODE_DEL) { + newKeyCode = AKEYCODE_BACK; + } else if (keyCode == AKEYCODE_ENTER) { + newKeyCode = AKEYCODE_HOME; + } + if (newKeyCode != AKEYCODE_UNKNOWN) { + AutoMutex _l(mLock); + struct KeyReplacement replacement = {keyCode, deviceId}; + mReplacedKeys.add(replacement, newKeyCode); + keyCode = newKeyCode; + metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON); + } + } else if (action == AKEY_EVENT_ACTION_UP) { + // In order to maintain a consistent stream of up and down events, check to see if the key + // going up is one we've replaced in a down event and haven't yet replaced in an up event, + // even if the modifier was released between the down and the up events. + AutoMutex _l(mLock); + struct KeyReplacement replacement = {keyCode, deviceId}; + ssize_t index = mReplacedKeys.indexOfKey(replacement); + if (index >= 0) { + keyCode = mReplacedKeys.valueAt(index); + mReplacedKeys.removeItemsAt(index); + metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON); + } + } +} + void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifyKey - eventTime=%" PRId64 - ", deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, " + ", deviceId=%d, source=0x%x, displayId=%" PRId32 "policyFlags=0x%x, action=0x%x, " "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64, - args->eventTime, args->deviceId, args->source, args->policyFlags, + args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags, args->action, args->flags, args->keyCode, args->scanCode, args->metaState, args->downTime); #endif @@ -2450,36 +2488,10 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { policyFlags |= POLICY_FLAG_TRUSTED; int32_t keyCode = args->keyCode; - if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) { - int32_t newKeyCode = AKEYCODE_UNKNOWN; - if (keyCode == AKEYCODE_DEL) { - newKeyCode = AKEYCODE_BACK; - } else if (keyCode == AKEYCODE_ENTER) { - newKeyCode = AKEYCODE_HOME; - } - if (newKeyCode != AKEYCODE_UNKNOWN) { - AutoMutex _l(mLock); - struct KeyReplacement replacement = {keyCode, args->deviceId}; - mReplacedKeys.add(replacement, newKeyCode); - keyCode = newKeyCode; - metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON); - } - } else if (args->action == AKEY_EVENT_ACTION_UP) { - // In order to maintain a consistent stream of up and down events, check to see if the key - // going up is one we've replaced in a down event and haven't yet replaced in an up event, - // even if the modifier was released between the down and the up events. - AutoMutex _l(mLock); - struct KeyReplacement replacement = {keyCode, args->deviceId}; - ssize_t index = mReplacedKeys.indexOfKey(replacement); - if (index >= 0) { - keyCode = mReplacedKeys.valueAt(index); - mReplacedKeys.removeItemsAt(index); - metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON); - } - } + accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState); KeyEvent event; - event.initialize(args->deviceId, args->source, args->action, + event.initialize(args->deviceId, args->source, args->displayId, args->action, flags, keyCode, args->scanCode, metaState, 0, args->downTime, args->eventTime); @@ -2507,7 +2519,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { int32_t repeatCount = 0; KeyEntry* newEntry = new KeyEntry(args->eventTime, - args->deviceId, args->source, policyFlags, + args->deviceId, args->source, args->displayId, policyFlags, args->action, flags, keyCode, args->scanCode, metaState, repeatCount, args->downTime); @@ -2526,10 +2538,11 @@ bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS - ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, " + ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 + ", policyFlags=0x%x, " "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x," "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64, - args->eventTime, args->deviceId, args->source, args->policyFlags, + 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, args->downTime); for (uint32_t i = 0; i < args->pointerCount; i++) { @@ -2573,7 +2586,8 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { mLock.unlock(); MotionEvent event; - event.initialize(args->deviceId, args->source, args->action, args->actionButton, + event.initialize(args->deviceId, args->source, args->displayId, + args->action, args->actionButton, args->flags, args->edgeFlags, args->metaState, args->buttonState, 0, 0, args->xPrecision, args->yPrecision, args->downTime, args->eventTime, @@ -2589,11 +2603,10 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { // Just enqueue a new motion event. MotionEntry* newEntry = new MotionEntry(args->eventTime, - args->deviceId, args->source, policyFlags, + args->deviceId, args->source, args->displayId, policyFlags, args->action, args->actionButton, args->flags, args->metaState, args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, - args->displayId, args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0); needWake = enqueueInboundEventLocked(newEntry); @@ -2642,14 +2655,13 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { } } -int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displayId, +int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, " - "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x, displayId=%d", - event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags, - displayId); + "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x", + event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags); #endif nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis); @@ -2663,20 +2675,29 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displ EventEntry* lastInjectedEntry; switch (event->getType()) { case AINPUT_EVENT_TYPE_KEY: { - const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event); - int32_t action = keyEvent->getAction(); + KeyEvent keyEvent; + keyEvent.initialize(*static_cast<const KeyEvent*>(event)); + int32_t action = keyEvent.getAction(); if (! validateKeyEvent(action)) { return INPUT_EVENT_INJECTION_FAILED; } - int32_t flags = keyEvent->getFlags(); + int32_t flags = keyEvent.getFlags(); + int32_t keyCode = keyEvent.getKeyCode(); + int32_t metaState = keyEvent.getMetaState(); + accelerateMetaShortcuts(keyEvent.getDeviceId(), action, + /*byref*/ keyCode, /*byref*/ metaState); + keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(), + action, flags, keyCode, keyEvent.getScanCode(), metaState, 0, + keyEvent.getDownTime(), keyEvent.getEventTime()); + if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) { policyFlags |= POLICY_FLAG_VIRTUAL; } if (!(policyFlags & POLICY_FLAG_FILTERED)) { android::base::Timer t; - mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags); + mPolicy->interceptKeyBeforeQueueing(&keyEvent, /*byref*/ policyFlags); if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) { ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms", std::to_string(t.duration().count()).c_str()); @@ -2684,11 +2705,11 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displ } mLock.lock(); - firstInjectedEntry = new KeyEntry(keyEvent->getEventTime(), - keyEvent->getDeviceId(), keyEvent->getSource(), + firstInjectedEntry = new KeyEntry(keyEvent.getEventTime(), + keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(), policyFlags, action, flags, - keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), - keyEvent->getRepeatCount(), keyEvent->getDownTime()); + keyEvent.getKeyCode(), keyEvent.getScanCode(), keyEvent.getMetaState(), + keyEvent.getRepeatCount(), keyEvent.getDownTime()); lastInjectedEntry = firstInjectedEntry; break; } @@ -2717,12 +2738,13 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displ const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes(); const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords(); firstInjectedEntry = new MotionEntry(*sampleEventTimes, - motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, + motionEvent->getDeviceId(), motionEvent->getSource(), motionEvent->getDisplayId(), + policyFlags, action, actionButton, motionEvent->getFlags(), motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), displayId, + motionEvent->getDownTime(), uint32_t(pointerCount), pointerProperties, samplePointerCoords, motionEvent->getXOffset(), motionEvent->getYOffset()); lastInjectedEntry = firstInjectedEntry; @@ -2730,12 +2752,13 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displ sampleEventTimes += 1; samplePointerCoords += pointerCount; MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes, - motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, + motionEvent->getDeviceId(), motionEvent->getSource(), + motionEvent->getDisplayId(), policyFlags, action, actionButton, motionEvent->getFlags(), motionEvent->getMetaState(), motionEvent->getButtonState(), motionEvent->getEdgeFlags(), motionEvent->getXPrecision(), motionEvent->getYPrecision(), - motionEvent->getDownTime(), displayId, + motionEvent->getDownTime(), uint32_t(pointerCount), pointerProperties, samplePointerCoords, motionEvent->getXOffset(), motionEvent->getYOffset()); lastInjectedEntry->next = nextInjectedEntry; @@ -2758,7 +2781,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displ lastInjectedEntry->injectionState = injectionState; bool needWake = false; - for (EventEntry* entry = firstInjectedEntry; entry != NULL; ) { + for (EventEntry* entry = firstInjectedEntry; entry != nullptr; ) { EventEntry* nextEntry = entry->next; needWake |= enqueueInboundEventLocked(entry); entry = nextEntry; @@ -2895,7 +2918,7 @@ sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked( return windowHandle; } } - return NULL; + return nullptr; } bool InputDispatcher::hasWindowHandleLocked( @@ -2923,7 +2946,7 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu bool foundHoveredWindow = false; for (size_t i = 0; i < mWindowHandles.size(); i++) { const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); - if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) { + if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) { mWindowHandles.removeAt(i--); continue; } @@ -2936,24 +2959,24 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu } if (!foundHoveredWindow) { - mLastHoverWindowHandle = NULL; + mLastHoverWindowHandle = nullptr; } if (mFocusedWindowHandle != newFocusedWindowHandle) { - if (mFocusedWindowHandle != NULL) { + if (mFocusedWindowHandle != nullptr) { #if DEBUG_FOCUS ALOGD("Focus left window: %s", mFocusedWindowHandle->getName().c_str()); #endif sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel(); - if (focusedInputChannel != NULL) { + if (focusedInputChannel != nullptr) { CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, "focus left window"); synthesizeCancelationEventsForInputChannelLocked( focusedInputChannel, options); } } - if (newFocusedWindowHandle != NULL) { + if (newFocusedWindowHandle != nullptr) { #if DEBUG_FOCUS ALOGD("Focus entered window: %s", newFocusedWindowHandle->getName().c_str()); @@ -2973,7 +2996,7 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu #endif sp<InputChannel> touchedInputChannel = touchedWindow.windowHandle->getInputChannel(); - if (touchedInputChannel != NULL) { + if (touchedInputChannel != nullptr) { CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "touched window was removed"); synthesizeCancelationEventsForInputChannelLocked( @@ -3013,15 +3036,15 @@ void InputDispatcher::setFocusedApplication( { // acquire lock AutoMutex _l(mLock); - if (inputApplicationHandle != NULL && inputApplicationHandle->updateInfo()) { + if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) { if (mFocusedApplicationHandle != inputApplicationHandle) { - if (mFocusedApplicationHandle != NULL) { + if (mFocusedApplicationHandle != nullptr) { resetANRTimeoutsLocked(); mFocusedApplicationHandle->releaseInfo(); } mFocusedApplicationHandle = inputApplicationHandle; } - } else if (mFocusedApplicationHandle != NULL) { + } else if (mFocusedApplicationHandle != nullptr) { resetANRTimeoutsLocked(); mFocusedApplicationHandle->releaseInfo(); mFocusedApplicationHandle.clear(); @@ -3103,7 +3126,7 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel); sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel); - if (fromWindowHandle == NULL || toWindowHandle == NULL) { + if (fromWindowHandle == nullptr || toWindowHandle == nullptr) { #if DEBUG_FOCUS ALOGD("Cannot transfer focus because from or to window not found."); #endif @@ -3208,7 +3231,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += StringPrintf(INDENT "DispatchEnabled: %d\n", mDispatchEnabled); dump += StringPrintf(INDENT "DispatchFrozen: %d\n", mDispatchFrozen); - if (mFocusedApplicationHandle != NULL) { + if (mFocusedApplicationHandle != nullptr) { dump += StringPrintf(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n", mFocusedApplicationHandle->getName().c_str(), mFocusedApplicationHandle->getDispatchingTimeout( @@ -3217,7 +3240,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += StringPrintf(INDENT "FocusedApplication: <null>\n"); } dump += StringPrintf(INDENT "FocusedWindow: name='%s'\n", - mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().c_str() : "<null>"); + mFocusedWindowHandle != nullptr ? mFocusedWindowHandle->getName().c_str() : "<null>"); if (!mTouchStatesByDisplay.isEmpty()) { dump += StringPrintf(INDENT "TouchStatesByDisplay:\n"); @@ -3528,7 +3551,7 @@ void InputDispatcher::onANRLocked( dispatchLatency, waitDuration, reason); // Capture a record of the InputDispatcher state at the time of the ANR. - time_t t = time(NULL); + time_t t = time(nullptr); struct tm tm; localtime_r(&t, &tm); char timestr[64]; @@ -3583,8 +3606,8 @@ void InputDispatcher::doNotifyANRLockedInterruptible( mLock.lock(); resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, - commandEntry->inputWindowHandle != NULL - ? commandEntry->inputWindowHandle->getInputChannel() : NULL); + commandEntry->inputWindowHandle != nullptr + ? commandEntry->inputWindowHandle->getInputChannel() : nullptr); } void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( @@ -3817,6 +3840,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con keyEntry->eventTime = event.getEventTime(); keyEntry->deviceId = event.getDeviceId(); keyEntry->source = event.getSource(); + keyEntry->displayId = event.getDisplayId(); keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK; keyEntry->keyCode = fallbackKeyCode; keyEntry->scanCode = event.getScanCode(); @@ -3855,7 +3879,7 @@ void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* comman } void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) { - event->initialize(entry->deviceId, entry->source, entry->action, entry->flags, + event->initialize(entry->deviceId, entry->source, entry->displayId, entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount, entry->downTime, entry->eventTime); } @@ -3934,7 +3958,7 @@ void InputDispatcher::InjectionState::release() { InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) : refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags), - injectionState(NULL), dispatchInProgress(false) { + injectionState(nullptr), dispatchInProgress(false) { } InputDispatcher::EventEntry::~EventEntry() { @@ -3953,7 +3977,7 @@ void InputDispatcher::EventEntry::release() { void InputDispatcher::EventEntry::releaseInjectionState() { if (injectionState) { injectionState->release(); - injectionState = NULL; + injectionState = nullptr; } } @@ -3991,11 +4015,11 @@ void InputDispatcher::DeviceResetEntry::appendDescription(std::string& msg) cons // --- InputDispatcher::KeyEntry --- InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, + int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime) : EventEntry(TYPE_KEY, eventTime, policyFlags), - deviceId(deviceId), source(source), action(action), flags(flags), + deviceId(deviceId), source(source), displayId(displayId), action(action), flags(flags), keyCode(keyCode), scanCode(scanCode), metaState(metaState), repeatCount(repeatCount), downTime(downTime), syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN), @@ -4006,10 +4030,10 @@ InputDispatcher::KeyEntry::~KeyEntry() { } void InputDispatcher::KeyEntry::appendDescription(std::string& msg) const { - msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, action=%s, " + msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, " "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, " "repeatCount=%d), policyFlags=0x%08x", - deviceId, source, keyActionToString(action).c_str(), flags, keyCode, + deviceId, source, displayId, keyActionToString(action).c_str(), flags, keyCode, scanCode, metaState, repeatCount, policyFlags); } @@ -4026,18 +4050,19 @@ void InputDispatcher::KeyEntry::recycle() { // --- InputDispatcher::MotionEntry --- InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t deviceId, - uint32_t source, uint32_t policyFlags, int32_t action, int32_t actionButton, + uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action, + int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime, - int32_t displayId, uint32_t pointerCount, + uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xOffset, float yOffset) : EventEntry(TYPE_MOTION, eventTime, policyFlags), eventTime(eventTime), - deviceId(deviceId), source(source), action(action), actionButton(actionButton), - flags(flags), metaState(metaState), buttonState(buttonState), + deviceId(deviceId), source(source), displayId(displayId), action(action), + actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags), xPrecision(xPrecision), yPrecision(yPrecision), - downTime(downTime), displayId(displayId), pointerCount(pointerCount) { + downTime(downTime), pointerCount(pointerCount) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); this->pointerCoords[i].copyFrom(pointerCoords[i]); @@ -4051,11 +4076,12 @@ InputDispatcher::MotionEntry::~MotionEntry() { } void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const { - msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, action=%s, actionButton=0x%08x, " - "flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, " - "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[", - deviceId, source, motionActionToString(action).c_str(), actionButton, flags, metaState, - buttonState, edgeFlags, xPrecision, yPrecision, displayId); + msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 + ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, " + "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, pointers=[", + deviceId, source, displayId, motionActionToString(action).c_str(), actionButton, flags, + metaState, buttonState, edgeFlags, xPrecision, yPrecision); + for (uint32_t i = 0; i < pointerCount; i++) { if (i) { msg += ", "; @@ -4184,8 +4210,8 @@ bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry, } #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, " - "actionMasked=%d", - entry->deviceId, entry->source, actionMasked); + "displayId=%" PRId32 ", actionMasked=%d", + entry->deviceId, entry->source, entry->displayId, actionMasked); #endif return false; } @@ -4237,8 +4263,8 @@ bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry, } #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Dropping inconsistent motion pointer up/down or move event: " - "deviceId=%d, source=%08x, actionMasked=%d", - entry->deviceId, entry->source, actionMasked); + "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d", + entry->deviceId, entry->source, entry->displayId, actionMasked); #endif return false; } @@ -4250,8 +4276,9 @@ bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry, return true; } #if DEBUG_OUTBOUND_EVENT_DETAILS - ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x", - entry->deviceId, entry->source); + ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, " + "displayId=%" PRId32, + entry->deviceId, entry->source, entry->displayId); #endif return false; } @@ -4276,6 +4303,7 @@ ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const const KeyMemento& memento = mKeyMementos.itemAt(i); if (memento.deviceId == entry->deviceId && memento.source == entry->source + && memento.displayId == entry->displayId && memento.keyCode == entry->keyCode && memento.scanCode == entry->scanCode) { return i; @@ -4303,6 +4331,7 @@ void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t f KeyMemento& memento = mKeyMementos.editTop(); memento.deviceId = entry->deviceId; memento.source = entry->source; + memento.displayId = entry->displayId; memento.keyCode = entry->keyCode; memento.scanCode = entry->scanCode; memento.metaState = entry->metaState; @@ -4317,11 +4346,11 @@ void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, MotionMemento& memento = mMotionMementos.editTop(); memento.deviceId = entry->deviceId; memento.source = entry->source; + memento.displayId = entry->displayId; memento.flags = flags; memento.xPrecision = entry->xPrecision; memento.yPrecision = entry->yPrecision; memento.downTime = entry->downTime; - memento.displayId = entry->displayId; memento.setPointers(entry); memento.hovering = hovering; memento.policyFlags = entry->policyFlags; @@ -4341,7 +4370,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim const KeyMemento& memento = mKeyMementos.itemAt(i); if (shouldCancelKey(memento, options)) { outEvents.push(new KeyEntry(currentTime, - memento.deviceId, memento.source, memento.policyFlags, + memento.deviceId, memento.source, memento.displayId, memento.policyFlags, AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime)); } @@ -4351,13 +4380,12 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim const MotionMemento& memento = mMotionMementos.itemAt(i); if (shouldCancelMotion(memento, options)) { outEvents.push(new MotionEntry(currentTime, - memento.deviceId, memento.source, memento.policyFlags, + memento.deviceId, memento.source, memento.displayId, memento.policyFlags, memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL, memento.flags, 0, 0, 0, 0, memento.xPrecision, memento.yPrecision, memento.downTime, - memento.displayId, memento.pointerCount, memento.pointerProperties, memento.pointerCoords, 0, 0)); } @@ -4461,7 +4489,7 @@ InputDispatcher::Connection::~Connection() { } const std::string InputDispatcher::Connection::getWindowName() const { - if (inputWindowHandle != NULL) { + if (inputWindowHandle != nullptr) { return inputWindowHandle->getName(); } if (monitor) { @@ -4487,19 +4515,19 @@ const char* InputDispatcher::Connection::getStatusLabel() const { } InputDispatcher::DispatchEntry* InputDispatcher::Connection::findWaitQueueEntry(uint32_t seq) { - for (DispatchEntry* entry = waitQueue.head; entry != NULL; entry = entry->next) { + for (DispatchEntry* entry = waitQueue.head; entry != nullptr; entry = entry->next) { if (entry->seq == seq) { return entry; } } - return NULL; + return nullptr; } // --- InputDispatcher::CommandEntry --- InputDispatcher::CommandEntry::CommandEntry(Command command) : - command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0), + command(command), eventTime(0), keyEntry(nullptr), userActivityEventType(0), seq(0), handled(false) { } @@ -4510,7 +4538,7 @@ InputDispatcher::CommandEntry::~CommandEntry() { // --- InputDispatcher::TouchState --- InputDispatcher::TouchState::TouchState() : - down(false), split(false), deviceId(-1), source(0), displayId(-1) { + down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) { } InputDispatcher::TouchState::~TouchState() { @@ -4521,7 +4549,7 @@ void InputDispatcher::TouchState::reset() { split = false; deviceId = -1; source = 0; - displayId = -1; + displayId = ADISPLAY_ID_NONE; windows.clear(); } @@ -4590,7 +4618,7 @@ sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandl return window.windowHandle; } } - return NULL; + return nullptr; } bool InputDispatcher::TouchState::isSlippery() const { diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h index 8da8450380..31ab339421 100644 --- a/services/inputflinger/InputDispatcher.h +++ b/services/inputflinger/InputDispatcher.h @@ -299,7 +299,7 @@ public: * * This method may be called on any thread (usually by the input manager). */ - virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId, + virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags) = 0; @@ -383,7 +383,7 @@ public: virtual void notifySwitch(const NotifySwitchArgs* args); virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args); - virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId, + virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags); @@ -406,7 +406,7 @@ private: T* prev; protected: - inline Link() : next(NULL), prev(NULL) { } + inline Link() : next(nullptr), prev(nullptr) { } }; struct InjectionState { @@ -441,7 +441,7 @@ private: bool dispatchInProgress; // initially false, set to true while dispatching - inline bool isInjected() const { return injectionState != NULL; } + inline bool isInjected() const { return injectionState != nullptr; } void release(); @@ -474,6 +474,7 @@ private: struct KeyEntry : EventEntry { int32_t deviceId; uint32_t source; + int32_t displayId; int32_t action; int32_t flags; int32_t keyCode; @@ -494,8 +495,8 @@ private: nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER KeyEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, - int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, + int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, + int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime); virtual void appendDescription(std::string& msg) const; void recycle(); @@ -508,6 +509,7 @@ private: nsecs_t eventTime; int32_t deviceId; uint32_t source; + int32_t displayId; int32_t action; int32_t actionButton; int32_t flags; @@ -517,17 +519,15 @@ private: float xPrecision; float yPrecision; nsecs_t downTime; - int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; MotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, + int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, - float xPrecision, float yPrecision, nsecs_t downTime, - int32_t displayId, uint32_t pointerCount, + float xPrecision, float yPrecision, nsecs_t downTime, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xOffset, float yOffset); virtual void appendDescription(std::string& msg) const; @@ -614,7 +614,7 @@ private: T* tail; uint32_t entryCount; - inline Queue() : head(NULL), tail(NULL), entryCount(0) { + inline Queue() : head(nullptr), tail(nullptr), entryCount(0) { } inline bool isEmpty() const { @@ -629,7 +629,7 @@ private: } else { head = entry; } - entry->next = NULL; + entry->next = nullptr; tail = entry; } @@ -641,7 +641,7 @@ private: } else { tail = entry; } - entry->prev = NULL; + entry->prev = nullptr; head = entry; } @@ -664,9 +664,9 @@ private: T* entry = head; head = entry->next; if (head) { - head->prev = NULL; + head->prev = nullptr; } else { - tail = NULL; + tail = nullptr; } return entry; } @@ -754,6 +754,7 @@ private: struct KeyMemento { int32_t deviceId; uint32_t source; + int32_t displayId; int32_t keyCode; int32_t scanCode; int32_t metaState; @@ -765,11 +766,11 @@ private: struct MotionMemento { int32_t deviceId; uint32_t source; + int32_t displayId; int32_t flags; float xPrecision; float yPrecision; nsecs_t downTime; - int32_t displayId; uint32_t pointerCount; PointerProperties pointerProperties[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; @@ -932,6 +933,9 @@ private: }; // Maps the key code replaced, device id tuple to the key code it was replaced with KeyedVector<KeyReplacement, int32_t> mReplacedKeys; + // Process certain Meta + Key combinations + void accelerateMetaShortcuts(const int32_t deviceId, const int32_t action, + int32_t& keyCode, int32_t& metaState); // Deferred command processing. bool haveCommandsLocked() const; diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index 520fea4c95..25a39a8274 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -43,17 +43,18 @@ void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& li // --- NotifyKeyArgs --- NotifyKeyArgs::NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, - uint32_t policyFlags, + int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) : - eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags), + eventTime(eventTime), deviceId(deviceId), source(source), displayId(displayId), + policyFlags(policyFlags), action(action), flags(flags), keyCode(keyCode), scanCode(scanCode), metaState(metaState), downTime(downTime) { } NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) : eventTime(other.eventTime), deviceId(other.deviceId), source(other.source), - policyFlags(other.policyFlags), + displayId(other.displayId), policyFlags(other.policyFlags), action(other.action), flags(other.flags), keyCode(other.keyCode), scanCode(other.scanCode), metaState(other.metaState), downTime(other.downTime) { @@ -67,16 +68,17 @@ void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const { // --- NotifyMotionArgs --- NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, - uint32_t policyFlags, + int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags, int32_t metaState, - int32_t buttonState, int32_t edgeFlags, int32_t displayId, uint32_t deviceTimestamp, + int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime) : - eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags), + eventTime(eventTime), deviceId(deviceId), source(source), displayId(displayId), + policyFlags(policyFlags), action(action), actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState), - edgeFlags(edgeFlags), displayId(displayId), deviceTimestamp(deviceTimestamp), + edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp), pointerCount(pointerCount), xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) { for (uint32_t i = 0; i < pointerCount; i++) { @@ -87,10 +89,10 @@ NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) : eventTime(other.eventTime), deviceId(other.deviceId), source(other.source), - policyFlags(other.policyFlags), + displayId(other.displayId), policyFlags(other.policyFlags), action(other.action), actionButton(other.actionButton), flags(other.flags), metaState(other.metaState), buttonState(other.buttonState), - edgeFlags(other.edgeFlags), displayId(other.displayId), + edgeFlags(other.edgeFlags), deviceTimestamp(other.deviceTimestamp), pointerCount(other.pointerCount), xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) { for (uint32_t i = 0; i < pointerCount; i++) { diff --git a/services/inputflinger/InputListener.h b/services/inputflinger/InputListener.h index 77afb344c2..a3d919bf5a 100644 --- a/services/inputflinger/InputListener.h +++ b/services/inputflinger/InputListener.h @@ -55,6 +55,7 @@ struct NotifyKeyArgs : public NotifyArgs { nsecs_t eventTime; int32_t deviceId; uint32_t source; + int32_t displayId; uint32_t policyFlags; int32_t action; int32_t flags; @@ -65,8 +66,8 @@ struct NotifyKeyArgs : public NotifyArgs { inline NotifyKeyArgs() { } - NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, - int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, + NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId, + uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime); NotifyKeyArgs(const NotifyKeyArgs& other); @@ -82,6 +83,7 @@ struct NotifyMotionArgs : public NotifyArgs { nsecs_t eventTime; int32_t deviceId; uint32_t source; + int32_t displayId; uint32_t policyFlags; int32_t action; int32_t actionButton; @@ -89,7 +91,6 @@ struct NotifyMotionArgs : public NotifyArgs { int32_t metaState; int32_t buttonState; int32_t edgeFlags; - int32_t displayId; /** * A timestamp in the input device's time base, not the platform's. * The units are microseconds since the last reset. @@ -106,10 +107,11 @@ struct NotifyMotionArgs : public NotifyArgs { inline NotifyMotionArgs() { } - NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, + NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId, + uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, int32_t displayId, uint32_t deviceTimestamp, uint32_t pointerCount, + int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, nsecs_t downTime); diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index e0cd8a005a..5adb75ce1b 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -226,7 +226,7 @@ static float calculateCommonVector(float a, float b) { } static void synthesizeButtonKey(InputReaderContext* context, int32_t action, - nsecs_t when, int32_t deviceId, uint32_t source, + nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState, int32_t buttonState, int32_t keyCode) { if ( @@ -236,19 +236,19 @@ static void synthesizeButtonKey(InputReaderContext* context, int32_t action, || (action == AKEY_EVENT_ACTION_UP && (lastButtonState & buttonState) && !(currentButtonState & buttonState))) { - NotifyKeyArgs args(when, deviceId, source, policyFlags, + NotifyKeyArgs args(when, deviceId, source, displayId, policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when); context->getListener()->notifyKey(&args); } } static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, - nsecs_t when, int32_t deviceId, uint32_t source, + nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) { - synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, + synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags, lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK); - synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, + synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags, lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD); } @@ -258,8 +258,8 @@ static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType, const String8* uniqueDisplayId, DisplayViewport* outViewport) const { - const DisplayViewport* viewport = NULL; - if (viewportType == ViewportType::VIEWPORT_VIRTUAL && uniqueDisplayId != NULL) { + const DisplayViewport* viewport = nullptr; + if (viewportType == ViewportType::VIEWPORT_VIRTUAL && uniqueDisplayId != nullptr) { for (const DisplayViewport& currentViewport : mVirtualDisplays) { if (currentViewport.uniqueId == *uniqueDisplayId) { viewport = ¤tViewport; @@ -272,7 +272,7 @@ bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType, viewport = &mInternalDisplay; } - if (viewport != NULL && viewport->displayId >= 0) { + if (viewport != nullptr && viewport->displayId >= 0) { *outViewport = *viewport; return true; } @@ -488,7 +488,7 @@ void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) { } void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) { - InputDevice* device = NULL; + InputDevice* device = nullptr; ssize_t deviceIndex = mDevices.indexOfKey(deviceId); if (deviceIndex < 0) { ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId); @@ -1786,7 +1786,7 @@ void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) { // --- MultiTouchMotionAccumulator --- MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() : - mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false), + mCurrentSlot(-1), mSlots(nullptr), mSlotCount(0), mUsingSlotsProtocol(false), mHaveStylus(false), mDeviceTimestamp(0) { } @@ -2240,8 +2240,7 @@ void VibratorInputMapper::dump(std::string& dump) { KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType) : - InputMapper(device), mSource(source), - mKeyboardType(keyboardType) { + InputMapper(device), mSource(source), mKeyboardType(keyboardType) { } KeyboardInputMapper::~KeyboardInputMapper() { @@ -2251,6 +2250,20 @@ uint32_t KeyboardInputMapper::getSources() { return mSource; } +int32_t KeyboardInputMapper::getOrientation() { + if (mViewport) { + return mViewport->orientation; + } + return DISPLAY_ORIENTATION_0; +} + +int32_t KeyboardInputMapper::getDisplayId() { + if (mViewport) { + return mViewport->displayId; + } + return ADISPLAY_ID_NONE; +} + void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { InputMapper::populateDeviceInfo(info); @@ -2262,7 +2275,7 @@ void KeyboardInputMapper::dump(std::string& dump) { dump += INDENT2 "Keyboard Input Mapper:\n"; dumpParameters(dump); dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType); - dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation); + dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation()); dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size()); dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState); dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime); @@ -2279,15 +2292,10 @@ void KeyboardInputMapper::configure(nsecs_t when, } if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { - DisplayViewport v; - if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) { - mOrientation = v.orientation; - } else { - mOrientation = DISPLAY_ORIENTATION_0; - } - } else { - mOrientation = DISPLAY_ORIENTATION_0; + if (mParameters.orientationAware) { + DisplayViewport dvp; + config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &dvp); + mViewport = dvp; } } } @@ -2310,10 +2318,7 @@ void KeyboardInputMapper::configureParameters() { config.tryGetProperty(String8("keyboard.orientationAware"), mParameters.orientationAware); - mParameters.hasAssociatedDisplay = false; if (mParameters.orientationAware) { - mParameters.hasAssociatedDisplay = true; - mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary"); mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1"); mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2"); @@ -2327,8 +2332,6 @@ void KeyboardInputMapper::configureParameters() { void KeyboardInputMapper::dumpParameters(std::string& dump) { dump += INDENT3 "Parameters:\n"; - dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n", - toString(mParameters.hasAssociatedDisplay)); dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", @@ -2423,8 +2426,8 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, if (down) { // Rotate key codes according to orientation if needed. - if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { - keyCode = rotateKeyCode(keyCode, mOrientation); + if (mParameters.orientationAware) { + keyCode = rotateKeyCode(keyCode, getOrientation()); } // Add key down. @@ -2489,7 +2492,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; } - NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyKeyArgs args(when, getDeviceId(), mSource, getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime); getListener()->notifyKey(&args); @@ -2699,15 +2702,12 @@ void CursorInputMapper::configure(nsecs_t when, } if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { + mOrientation = DISPLAY_ORIENTATION_0; if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { DisplayViewport v; - if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) { + if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &v)) { mOrientation = v.orientation; - } else { - mOrientation = DISPLAY_ORIENTATION_0; } - } else { - mOrientation = DISPLAY_ORIENTATION_0; } bumpGeneration(); } @@ -2826,8 +2826,8 @@ void CursorInputMapper::sync(nsecs_t when) { float hscroll = mCursorScrollAccumulator.getRelativeHWheel(); bool scrolled = vscroll != 0 || hscroll != 0; - mWheelYVelocityControl.move(when, NULL, &vscroll); - mWheelXVelocityControl.move(when, &hscroll, NULL); + mWheelYVelocityControl.move(when, nullptr, &vscroll); + mWheelXVelocityControl.move(when, &hscroll, nullptr); mPointerVelocityControl.move(when, &deltaX, &deltaY); @@ -2874,7 +2874,7 @@ void CursorInputMapper::sync(nsecs_t when) { // Synthesize key down from buttons if needed. synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, - policyFlags, lastButtonState, currentButtonState); + displayId, policyFlags, lastButtonState, currentButtonState); // Send motion event. if (downChanged || moved || scrolled || buttonsChanged) { @@ -2894,19 +2894,19 @@ void CursorInputMapper::sync(nsecs_t when) { while (!released.isEmpty()) { int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit()); buttonState &= ~actionButton; - NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&releaseArgs); } } - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&args); @@ -2915,10 +2915,10 @@ void CursorInputMapper::sync(nsecs_t when) { while (!pressed.isEmpty()) { int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit()); buttonState |= actionButton; - NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&pressArgs); } @@ -2929,10 +2929,10 @@ void CursorInputMapper::sync(nsecs_t when) { // Send hover move after UP to tell the application that the mouse is hovering now. if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) { - NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&hoverArgs); } @@ -2942,10 +2942,10 @@ void CursorInputMapper::sync(nsecs_t when) { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime); getListener()->notifyMotion(&scrollArgs); } @@ -2953,7 +2953,7 @@ void CursorInputMapper::sync(nsecs_t when) { // Synthesize key up from buttons if needed. synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, - policyFlags, lastButtonState, currentButtonState); + displayId, policyFlags, lastButtonState, currentButtonState); mCursorMotionAccumulator.finishSync(); mCursorScrollAccumulator.finishSync(); @@ -2968,7 +2968,7 @@ int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCod } void CursorInputMapper::fadePointer() { - if (mPointerController != NULL) { + if (mPointerController != nullptr) { mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); } } @@ -3020,7 +3020,7 @@ void RotaryEncoderInputMapper::configure(nsecs_t when, } if (!changes || (InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { DisplayViewport v; - if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) { + if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &v)) { mOrientation = v.orientation; } else { mOrientation = DISPLAY_ORIENTATION_0; @@ -3072,10 +3072,10 @@ void RotaryEncoderInputMapper::sync(nsecs_t when) { int32_t metaState = mContext->getGlobalMetaState(); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor); - NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0, AMOTION_EVENT_EDGE_FLAG_NONE, - displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, 0, 0, 0); getListener()->notifyMotion(&scrollArgs); } @@ -3517,7 +3517,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // Get associated display dimensions. DisplayViewport newViewport; if (mParameters.hasAssociatedDisplay) { - const String8* uniqueDisplayId = NULL; + const String8* uniqueDisplayId = nullptr; ViewportType viewportTypeToUse; if (mParameters.associatedDisplayIsExternal) { @@ -3621,7 +3621,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // Create pointer controller if needed. if (mDeviceMode == DEVICE_MODE_POINTER || (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) { - if (mPointerController == NULL) { + if (mPointerController == nullptr) { mPointerController = getPolicy()->obtainPointerController(getDeviceId()); } } else { @@ -4271,7 +4271,7 @@ void TouchInputMapper::reset(nsecs_t when) { mPointerSimple.reset(); resetExternalStylus(); - if (mPointerController != NULL) { + if (mPointerController != nullptr) { mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); mPointerController->clearSpots(); } @@ -4433,7 +4433,8 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { // Synthesize key down from raw buttons if needed. synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, - policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState); + mViewport.displayId, policyFlags, + mLastCookedState.buttonState, mCurrentCookedState.buttonState); // Dispatch the touches either directly or by translation through a pointer on screen. if (mDeviceMode == DEVICE_MODE_POINTER) { @@ -4480,7 +4481,7 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { dispatchPointerUsage(when, policyFlags, pointerUsage); } else { if (mDeviceMode == DEVICE_MODE_DIRECT - && mConfig.showTouches && mPointerController != NULL) { + && mConfig.showTouches && mPointerController != nullptr) { mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); @@ -4505,7 +4506,8 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { // Synthesize key up from raw buttons if needed. synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, - policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState); + mViewport.displayId, policyFlags, + mLastCookedState.buttonState, mCurrentCookedState.buttonState); // Clear some transient state. mCurrentRawState.rawVScroll = 0; @@ -4720,8 +4722,8 @@ void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, int32_t metaState = mContext->getGlobalMetaState(); policyFlags |= POLICY_FLAG_VIRTUAL; - NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags, - keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime); + NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, mViewport.displayId, + policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime); getListener()->notifyKey(&args); } @@ -5413,10 +5415,10 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - mViewport.displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime); getListener()->notifyMotion(&args); } @@ -5458,7 +5460,7 @@ void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) mPointerVelocityControl.reset(); // Remove any current spots. - if (mPointerController != NULL) { + if (mPointerController != nullptr) { mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); mPointerController->clearSpots(); } @@ -6321,7 +6323,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down, bool hovering) { int32_t metaState = getContext()->getGlobalMetaState(); - if (mPointerController != NULL) { + if (mPointerController != nullptr) { if (down || hovering) { mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); mPointerController->clearSpots(); @@ -6336,9 +6338,9 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.down = false; // Send up. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0, - mViewport.displayId, /* deviceTimestamp */ 0, + /* deviceTimestamp */ 0, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -6349,9 +6351,9 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.hovering = false; // Send hover exit. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0, - mViewport.displayId, /* deviceTimestamp */ 0, + /* deviceTimestamp */ 0, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -6364,9 +6366,9 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.downTime = when; // Send down. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0, - mViewport.displayId, /* deviceTimestamp */ 0, + /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -6374,9 +6376,9 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, } // Send move. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0, - mViewport.displayId, /* deviceTimestamp */ 0, + /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -6388,10 +6390,10 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.hovering = true; // Send hover enter. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState, mCurrentRawState.buttonState, 0, - mViewport.displayId, /* deviceTimestamp */ 0, + /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -6399,10 +6401,10 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, } // Send hover move. - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0, - mViewport.displayId, /* deviceTimestamp */ 0, + /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -6412,8 +6414,8 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) { float vscroll = mCurrentRawState.rawVScroll; float hscroll = mCurrentRawState.rawHScroll; - mWheelYVelocityControl.move(when, NULL, &vscroll); - mWheelXVelocityControl.move(when, &hscroll, NULL); + mWheelYVelocityControl.move(when, nullptr, &vscroll); + mWheelXVelocityControl.move(when, &hscroll, nullptr); // Send scroll. PointerCoords pointerCoords; @@ -6421,9 +6423,9 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0, - mViewport.displayId, /* deviceTimestamp */ 0, + /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties, &pointerCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); @@ -6484,9 +6486,9 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 } } - NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), source, mViewport.displayId, policyFlags, action, actionButton, flags, metaState, buttonState, edgeFlags, - mViewport.displayId, deviceTimestamp, pointerCount, pointerProperties, pointerCoords, + deviceTimestamp, pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime); getListener()->notifyMotion(&args); } @@ -6520,7 +6522,7 @@ bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties } void TouchInputMapper::fadePointer() { - if (mPointerController != NULL) { + if (mPointerController != nullptr) { mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); } } @@ -6555,7 +6557,7 @@ const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit( } } - return NULL; + return nullptr; } void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) { @@ -7404,9 +7406,10 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { // TODO: Use the input device configuration to control this behavior more finely. uint32_t policyFlags = 0; - NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, + NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, + policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - ADISPLAY_ID_NONE, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, + /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, 0, 0, 0); getListener()->notifyMotion(&args); } diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index cef3212684..89290a82e3 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -35,6 +35,7 @@ #include <utils/BitSet.h> #include <utils/SortedVector.h> +#include <optional> #include <stddef.h> #include <unistd.h> @@ -1094,6 +1095,9 @@ public: virtual void updateMetaState(int32_t keyCode); private: + // The current viewport. + std::optional<DisplayViewport> mViewport; + struct KeyDown { int32_t keyCode; int32_t scanCode; @@ -1102,8 +1106,6 @@ private: uint32_t mSource; int32_t mKeyboardType; - int32_t mOrientation; // orientation for dpad keys - Vector<KeyDown> mKeyDowns; // keys that are down int32_t mMetaState; nsecs_t mDownTime; // time of most recent key down @@ -1120,7 +1122,6 @@ private: // Immutable configuration parameters. struct Parameters { - bool hasAssociatedDisplay; bool orientationAware; bool handlesKeyRepeat; } mParameters; @@ -1128,6 +1129,9 @@ private: void configureParameters(); void dumpParameters(std::string& dump); + int32_t getOrientation(); + int32_t getDisplayId(); + bool isKeyboardOrGamepadKey(int32_t scanCode); bool isMediaKey(int32_t keyCode); diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp index 3ae7972779..0d1dfddb07 100644 --- a/services/inputflinger/InputWindow.cpp +++ b/services/inputflinger/InputWindow.cpp @@ -66,7 +66,7 @@ bool InputWindowInfo::overlaps(const InputWindowInfo* other) const { // --- InputWindowHandle --- InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) : - inputApplicationHandle(inputApplicationHandle), mInfo(NULL) { + inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) { } InputWindowHandle::~InputWindowHandle() { @@ -76,7 +76,7 @@ InputWindowHandle::~InputWindowHandle() { void InputWindowHandle::releaseInfo() { if (mInfo) { delete mInfo; - mInfo = NULL; + mInfo = nullptr; } } diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h index 5a48375910..c481853e2c 100644 --- a/services/inputflinger/InputWindow.h +++ b/services/inputflinger/InputWindow.h @@ -169,7 +169,7 @@ public: } inline sp<InputChannel> getInputChannel() const { - return mInfo ? mInfo->inputChannel : NULL; + return mInfo ? mInfo->inputChannel : nullptr; } inline std::string getName() const { diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index dd19800057..517e63945d 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -2,11 +2,11 @@ cc_test { name: "inputflinger_tests", + cpp_std: "c++17", srcs: [ "InputReader_test.cpp", "InputDispatcher_test.cpp", ], - test_per_src: true, cflags: [ "-Wall", "-Werror", diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index aa6df244e2..0e26d4a9ce 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -28,7 +28,7 @@ static const nsecs_t ARBITRARY_TIME = 1234; static const int32_t DEVICE_ID = 1; // An arbitrary display id. -static const int32_t DISPLAY_ID = 0; +static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT; // An arbitrary injector pid / uid pair that has permission to inject events. static const int32_t INJECTOR_PID = 999; @@ -120,20 +120,20 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) { KeyEvent event; // Rejects undefined key actions. - event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, + event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject key events with undefined action."; // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API. - event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, + event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject key events with ACTION_MULTIPLE."; } @@ -149,106 +149,106 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { } // Rejects undefined motion actions. - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, /*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with undefined action."; // Rejects pointer down with invalid index. - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer down index too large."; - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer down index too small."; // Rejects pointer up with invalid index. - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer up index too large."; - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer up index too small."; // Rejects motion events with invalid number of pointers. - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with 0 pointers."; - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with more than MAX_POINTERS pointers."; // Rejects motion events with invalid pointer ids. pointerProperties[0].id = -1; - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer ids less than 0."; pointerProperties[0].id = MAX_POINTER_ID + 1; - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer ids greater than MAX_POINTER_ID."; // Rejects motion events with duplicate pointer ids. pointerProperties[0].id = 1; pointerProperties[1].id = 1; - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, + event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( - &event, DISPLAY_ID, + &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with duplicate pointer ids."; } diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 22f15a05fe..286cf880f1 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -236,7 +236,7 @@ private: } virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier&) { - return NULL; + return nullptr; } virtual String8 getDeviceAlias(const InputDeviceIdentifier&) { @@ -263,7 +263,7 @@ public: } void assertNotifyConfigurationChangedWasCalled( - NotifyConfigurationChangedArgs* outEventArgs = NULL) { + NotifyConfigurationChangedArgs* outEventArgs = nullptr) { ASSERT_FALSE(mNotifyConfigurationChangedArgsQueue.empty()) << "Expected notifyConfigurationChanged() to have been called."; if (outEventArgs) { @@ -278,7 +278,7 @@ public: } void assertNotifyDeviceResetWasCalled( - NotifyDeviceResetArgs* outEventArgs = NULL) { + NotifyDeviceResetArgs* outEventArgs = nullptr) { ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty()) << "Expected notifyDeviceReset() to have been called."; if (outEventArgs) { @@ -292,7 +292,7 @@ public: << "Expected notifyDeviceReset() to not have been called."; } - void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = NULL) { + void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = nullptr) { ASSERT_FALSE(mNotifyKeyArgsQueue.empty()) << "Expected notifyKey() to have been called."; if (outEventArgs) { @@ -306,7 +306,7 @@ public: << "Expected notifyKey() to not have been called."; } - void assertNotifyMotionWasCalled(NotifyMotionArgs* outEventArgs = NULL) { + void assertNotifyMotionWasCalled(NotifyMotionArgs* outEventArgs = nullptr) { ASSERT_FALSE(mNotifyMotionArgsQueue.empty()) << "Expected notifyMotion() to have been called."; if (outEventArgs) { @@ -320,7 +320,7 @@ public: << "Expected notifyMotion() to not have been called."; } - void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = NULL) { + void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = nullptr) { ASSERT_FALSE(mNotifySwitchArgsQueue.empty()) << "Expected notifySwitch() to have been called."; if (outEventArgs) { @@ -422,7 +422,7 @@ public: bool isDeviceEnabled(int32_t deviceId) { Device* device = getDevice(deviceId); - if (device == NULL) { + if (device == nullptr) { ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__); return false; } @@ -432,7 +432,7 @@ public: status_t enableDevice(int32_t deviceId) { status_t result; Device* device = getDevice(deviceId); - if (device == NULL) { + if (device == nullptr) { ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__); return BAD_VALUE; } @@ -446,7 +446,7 @@ public: status_t disableDevice(int32_t deviceId) { Device* device = getDevice(deviceId); - if (device == NULL) { + if (device == nullptr) { ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__); return BAD_VALUE; } @@ -651,7 +651,7 @@ private: return &device->keysByScanCode.valueAt(index); } } - return NULL; + return nullptr; } virtual status_t mapAxis(int32_t, int32_t, AxisInfo*) const { @@ -781,7 +781,7 @@ private: } virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t) const { - return NULL; + return nullptr; } virtual bool setKeyboardLayoutOverlay(int32_t, const sp<KeyCharacterMap>&) { @@ -940,7 +940,7 @@ public: mResetWasCalled = false; } - void assertProcessWasCalled(RawEvent* outLastEvent = NULL) { + void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) { ASSERT_TRUE(mProcessWasCalled) << "Expected process() to have been called."; if (outLastEvent) { @@ -1039,7 +1039,7 @@ public: const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) : InputReader(eventHub, policy, listener), - mNextDevice(NULL) { + mNextDevice(nullptr) { } virtual ~InstrumentedInputReader() { @@ -1066,7 +1066,7 @@ protected: const InputDeviceIdentifier& identifier, uint32_t classes) { if (mNextDevice) { InputDevice* device = mNextDevice; - mNextDevice = NULL; + mNextDevice = nullptr; return device; } return InputReader::createDeviceLocked(deviceId, controllerNumber, identifier, classes); @@ -1142,9 +1142,9 @@ protected: TEST_F(InputReaderTest, GetInputDevices) { ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"), - INPUT_DEVICE_CLASS_KEYBOARD, NULL)); + INPUT_DEVICE_CLASS_KEYBOARD, nullptr)); ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("ignored"), - 0, NULL)); // no classes so device will be ignored + 0, nullptr)); // no classes so device will be ignored Vector<InputDeviceInfo> inputDevices; mReader->getInputDevices(inputDevices); @@ -1174,9 +1174,9 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); mReader->setNextDevice(device); - addDevice(deviceId, String8("fake"), deviceClass, NULL); + addDevice(deviceId, String8("fake"), deviceClass, nullptr); - ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(NULL)); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr)); NotifyDeviceResetArgs resetArgs; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); @@ -1207,9 +1207,9 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { } TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) { - FakeInputMapper* mapper = NULL; + FakeInputMapper* mapper = nullptr; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr)); mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN); ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0, @@ -1234,9 +1234,9 @@ TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) { } TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) { - FakeInputMapper* mapper = NULL; + FakeInputMapper* mapper = nullptr; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr)); mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN); ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0, @@ -1261,9 +1261,9 @@ TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) { } TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) { - FakeInputMapper* mapper = NULL; + FakeInputMapper* mapper = nullptr; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr)); mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN); ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0, @@ -1288,9 +1288,9 @@ TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) { } TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) { - FakeInputMapper* mapper = NULL; + FakeInputMapper* mapper = nullptr; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr)); mapper->addSupportedKeyCode(AKEYCODE_A); mapper->addSupportedKeyCode(AKEYCODE_B); @@ -1323,7 +1323,7 @@ TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) { } TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) { - addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, NULL); + addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, nullptr); NotifyConfigurationChangedArgs args; @@ -1332,9 +1332,9 @@ TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChange } TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { - FakeInputMapper* mapper = NULL; + FakeInputMapper* mapper = nullptr; ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"), - INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); + INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr)); mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, 1); mReader->loopOnce(); @@ -1621,7 +1621,7 @@ protected: static void assertMotionRange(const InputDeviceInfo& info, int32_t axis, uint32_t source, float min, float max, float flat, float fuzz) { const InputDeviceInfo::MotionRange* range = info.getMotionRange(axis, source); - ASSERT_TRUE(range != NULL) << "Axis: " << axis << " Source: " << source; + ASSERT_TRUE(range != nullptr) << "Axis: " << axis << " Source: " << source; ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source; ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source; ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source; @@ -1996,6 +1996,64 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode); } +TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) { + // If the keyboard is not orientation aware, + // key events should not be associated with a specific display id + mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0); + + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, + AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); + addMapperAndConfigure(mapper); + NotifyKeyArgs args; + + // Display id should be ADISPLAY_ID_NONE without any display configuration. + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId); + + setDisplayInfoAndReconfigure(DISPLAY_ID, + DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId); +} + +TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) { + // If the keyboard is orientation aware, + // key events should be associated with the internal viewport + mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0); + + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, + AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); + addConfigurationProperty("keyboard.orientationAware", "1"); + addMapperAndConfigure(mapper); + NotifyKeyArgs args; + + // Display id should be ADISPLAY_ID_NONE without any display configuration. + // ^--- already checked by the previous test + + setDisplayInfoAndReconfigure(DISPLAY_ID, + DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(DISPLAY_ID, args.displayId); + + constexpr int32_t newDisplayId = 2; + setDisplayInfoAndReconfigure(newDisplayId, + DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(newDisplayId, args.displayId); +} + TEST_F(KeyboardInputMapperTest, GetKeyCodeState) { KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); @@ -2174,8 +2232,8 @@ TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeF mapper->populateDeviceInfo(&info); // Initially there may not be a valid motion range. - ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE)); - ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE)); + ASSERT_EQ(nullptr, info.getMotionRange(AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE)); + ASSERT_EQ(nullptr, info.getMotionRange(AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE)); ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f)); diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp index d8e5b290d0..14f9a12553 100644 --- a/services/sensorservice/BatteryService.cpp +++ b/services/sensorservice/BatteryService.cpp @@ -94,7 +94,7 @@ void BatteryService::cleanupImpl(uid_t uid) { bool BatteryService::checkService() { if (mBatteryStatService == nullptr) { const sp<IServiceManager> sm(defaultServiceManager()); - if (sm != NULL) { + if (sm != nullptr) { const String16 name("batterystats"); mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name)); } diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp index 7b00f4d98d..f2ea02eb00 100644 --- a/services/sensorservice/RotationVectorSensor.cpp +++ b/services/sensorservice/RotationVectorSensor.cpp @@ -94,7 +94,7 @@ const char* RotationVectorSensor::getSensorName() const { return "GeoMag Rotation Vector Sensor"; default: assert(0); - return NULL; + return nullptr; } } diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index 115a983bc4..ae3f42f7bc 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -208,7 +208,7 @@ ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { if(numHidlTransportErrors > 0) { ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors); - HidlTransportErrorLog errLog(time(NULL), numHidlTransportErrors); + HidlTransportErrorLog errLog(time(nullptr), numHidlTransportErrors); mHidlTransportErrors.add(errLog); mTotalHidlTransportErrors++; } diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp index 956844f426..0fb4ac6c11 100644 --- a/services/sensorservice/SensorEventConnection.cpp +++ b/services/sensorservice/SensorEventConnection.cpp @@ -31,7 +31,7 @@ SensorService::SensorEventConnection::SensorEventConnection( const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode, const String16& opPackageName, bool hasSensorAccess) : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false), - mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL), + mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr), mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false), mHasSensorAccess(hasSensorAccess) { mChannel = new BitTube(mService->mSocketBufferSize); @@ -55,8 +55,8 @@ void SensorService::SensorEventConnection::destroy() { } mService->cleanupConnection(this); - if (mEventCache != NULL) { - delete mEventCache; + if (mEventCache != nullptr) { + delete[] mEventCache; } mDestroyed = true; } @@ -200,7 +200,7 @@ void SensorService::SensorEventConnection::updateLooperRegistrationLocked( // Add the file descriptor to the Looper for receiving acknowledegments if the app has // registered for wake-up sensors OR for sending events in the cache. - int ret = looper->addFd(mChannel->getSendFd(), 0, looper_flags, this, NULL); + int ret = looper->addFd(mChannel->getSendFd(), 0, looper_flags, this, nullptr); if (ret == 1) { ALOGD_IF(DEBUG_CONNECTIONS, "%p addFd fd=%d", this, mChannel->getSendFd()); mHasLooperCallbacks = true; @@ -224,7 +224,7 @@ status_t SensorService::SensorEventConnection::sendEvents( wp<const SensorEventConnection> const * mapFlushEventsToConnections) { // filter out events not for this connection - sensors_event_t* sanitizedBuffer = nullptr; + std::unique_ptr<sensors_event_t[]> sanitizedBuffer; int count = 0; Mutex::Autolock _l(mConnectionLock); @@ -293,7 +293,8 @@ status_t SensorService::SensorEventConnection::sendEvents( scratch = const_cast<sensors_event_t *>(buffer); count = numEvents; } else { - scratch = sanitizedBuffer = new sensors_event_t[numEvents]; + sanitizedBuffer.reset(new sensors_event_t[numEvents]); + scratch = sanitizedBuffer.get(); for (size_t i = 0; i < numEvents; i++) { if (buffer[i].type == SENSOR_TYPE_META_DATA) { scratch[count++] = buffer[i++]; @@ -305,7 +306,6 @@ status_t SensorService::SensorEventConnection::sendEvents( sendPendingFlushEventsLocked(); // Early return if there are no events for this connection. if (count == 0) { - delete sanitizedBuffer; return status_t(NO_ERROR); } @@ -323,7 +323,6 @@ status_t SensorService::SensorEventConnection::sendEvents( // the max cache size that is desired. if (mCacheSize + count < computeMaxCacheSizeLocked()) { reAllocateCacheLocked(scratch, count); - delete sanitizedBuffer; return status_t(NO_ERROR); } // Some events need to be dropped. @@ -342,7 +341,6 @@ status_t SensorService::SensorEventConnection::sendEvents( memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize, numEventsDropped * sizeof(sensors_event_t)); } - delete sanitizedBuffer; return status_t(NO_ERROR); } @@ -373,7 +371,7 @@ status_t SensorService::SensorEventConnection::sendEvents( --mTotalAcksNeeded; #endif } - if (mEventCache == NULL) { + if (mEventCache == nullptr) { mMaxCacheSize = computeMaxCacheSizeLocked(); mEventCache = new sensors_event_t[mMaxCacheSize]; mCacheSize = 0; @@ -384,7 +382,6 @@ status_t SensorService::SensorEventConnection::sendEvents( // Add this file descriptor to the looper to get a callback when this fd is available for // writing. updateLooperRegistrationLocked(mService->getLooper()); - delete sanitizedBuffer; return size; } @@ -394,7 +391,6 @@ status_t SensorService::SensorEventConnection::sendEvents( } #endif - delete sanitizedBuffer; return size < 0 ? status_t(size) : status_t(NO_ERROR); } @@ -415,7 +411,7 @@ void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t ALOGD_IF(DEBUG_CONNECTIONS, "reAllocateCacheLocked maxCacheSize=%d %d", mMaxCacheSize, new_cache_size); - delete mEventCache; + delete[] mEventCache; mEventCache = eventCache_new; mCacheSize += count; mMaxCacheSize = new_cache_size; diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h index 032721ea39..40c21ff585 100644 --- a/services/sensorservice/SensorEventConnection.h +++ b/services/sensorservice/SensorEventConnection.h @@ -53,7 +53,7 @@ public: bool hasSensorAccess); status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch, - wp<const SensorEventConnection> const * mapFlushEventsToConnections = NULL); + wp<const SensorEventConnection> const * mapFlushEventsToConnections = nullptr); bool hasSensor(int32_t handle) const; bool hasAnySensor() const; bool hasOneShotSensors() const; diff --git a/services/sensorservice/SensorRecord.cpp b/services/sensorservice/SensorRecord.cpp index 53fb9de230..7c4c6a2046 100644 --- a/services/sensorservice/SensorRecord.cpp +++ b/services/sensorservice/SensorRecord.cpp @@ -71,7 +71,7 @@ wp<const SensorService::SensorEventConnection> if (mPendingFlushConnections.size() > 0) { return mPendingFlushConnections[0]; } - return NULL; + return nullptr; } void SensorService::SensorRecord::clearAllPendingFlushConnections() { diff --git a/services/sensorservice/SensorRegistrationInfo.h b/services/sensorservice/SensorRegistrationInfo.h index bba83727d9..5411515d49 100644 --- a/services/sensorservice/SensorRegistrationInfo.h +++ b/services/sensorservice/SensorRegistrationInfo.h @@ -47,7 +47,7 @@ public: mPid = (thread != nullptr) ? thread->getCallingPid() : -1; mUid = (thread != nullptr) ? thread->getCallingUid() : -1; - time_t rawtime = time(NULL); + time_t rawtime = time(nullptr); struct tm * timeinfo = localtime(&rawtime); mHour = static_cast<int8_t>(timeinfo->tm_hour); mMin = static_cast<int8_t>(timeinfo->tm_min); diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 8e9e7fdf7c..372b6095ba 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -250,7 +250,7 @@ void SensorService::onFirstRef() { // it to maxSystemSocketBufferSize if necessary. FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r"); char line[128]; - if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) { + if (fp != nullptr && fgets(line, sizeof(line), fp) != nullptr) { line[sizeof(line) - 1] = '\0'; size_t maxSystemSocketBufferSize; sscanf(line, "%zu", &maxSystemSocketBufferSize); @@ -295,7 +295,7 @@ void SensorService::setSensorAccess(uid_t uid, bool hasAccess) { { Mutex::Autolock _l(mLock); for (size_t i = 0 ; i < activeConnections.size(); i++) { - if (activeConnections[i] != 0 && activeConnections[i]->getUid() == uid) { + if (activeConnections[i] != nullptr && activeConnections[i]->getUid() == uid) { activeConnections[i]->setSensorAccess(hasAccess); } } @@ -475,7 +475,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) { result.appendFormat("%zd active connections\n", mActiveConnections.size()); for (size_t i=0 ; i < mActiveConnections.size() ; i++) { sp<SensorEventConnection> connection(mActiveConnections[i].promote()); - if (connection != 0) { + if (connection != nullptr) { result.appendFormat("Connection Number: %zu \n", i); connection->dump(result); } @@ -722,11 +722,11 @@ bool SensorService::threadLoop() { // on the hardware sensor. mapFlushEventsToConnections[i] will be the // SensorEventConnection mapped to the corresponding flush_complete_event in // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise). - mMapFlushEventsToConnections[i] = NULL; + mMapFlushEventsToConnections[i] = nullptr; if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) { const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor; SensorRecord* rec = mActiveSensors.valueFor(sensor_handle); - if (rec != NULL) { + if (rec != nullptr) { mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection(); rec->removeFirstPendingFlushConnection(); } @@ -770,7 +770,7 @@ bool SensorService::threadLoop() { size_t numConnections = activeConnections.size(); for (size_t i=0 ; i < numConnections; ++i) { - if (activeConnections[i] != NULL) { + if (activeConnections[i] != nullptr) { activeConnections[i]->removeSensor(handle); } } @@ -783,7 +783,7 @@ bool SensorService::threadLoop() { bool needsWakeLock = false; size_t numConnections = activeConnections.size(); for (size_t i=0 ; i < numConnections; ++i) { - if (activeConnections[i] != 0) { + if (activeConnections[i] != nullptr) { activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch, mMapFlushEventsToConnections); needsWakeLock |= activeConnections[i]->needsWakeLock(); @@ -816,7 +816,7 @@ void SensorService::resetAllWakeLockRefCounts() { { Mutex::Autolock _l(mLock); for (size_t i=0 ; i < activeConnections.size(); ++i) { - if (activeConnections[i] != 0) { + if (activeConnections[i] != nullptr) { activeConnections[i]->resetWakeLockRefCount(); } } @@ -1021,15 +1021,15 @@ sp<ISensorEventConnection> SensorService::createSensorEventConnection(const Stri int requestedMode, const String16& opPackageName) { // Only 2 modes supported for a SensorEventConnection ... NORMAL and DATA_INJECTION. if (requestedMode != NORMAL && requestedMode != DATA_INJECTION) { - return NULL; + return nullptr; } Mutex::Autolock _l(mLock); // To create a client in DATA_INJECTION mode to inject data, SensorService should already be // operating in DI mode. if (requestedMode == DATA_INJECTION) { - if (mCurrentOperatingMode != DATA_INJECTION) return NULL; - if (!isWhiteListedPackage(packageName)) return NULL; + if (mCurrentOperatingMode != DATA_INJECTION) return nullptr; + if (!isWhiteListedPackage(packageName)) return nullptr; } uid_t uid = IPCThreadState::self()->getCallingUid(); @@ -1325,7 +1325,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, } SensorRecord* rec = mActiveSensors.valueFor(handle); - if (rec == 0) { + if (rec == nullptr) { rec = new SensorRecord(connection); mActiveSensors.add(handle, rec); if (sensor->isVirtual()) { @@ -1352,7 +1352,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) { setWakeLockAcquiredLocked(true); } - connection->sendEvents(&event, 1, NULL); + connection->sendEvents(&event, 1, nullptr); if (!connection->needsWakeLock() && mWakeLockAcquired) { checkWakeLockStateLocked(); } @@ -1534,7 +1534,7 @@ status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection, status_t err_flush = sensor->flush(connection.get(), handle); if (err_flush == NO_ERROR) { SensorRecord* rec = mActiveSensors.valueFor(handle); - if (rec != NULL) rec->addPendingFlushConnection(connection); + if (rec != nullptr) rec->addPendingFlushConnection(connection); } err = (err_flush != NO_ERROR) ? err_flush : err; } @@ -1592,7 +1592,7 @@ void SensorService::checkWakeLockStateLocked() { bool releaseLock = true; for (size_t i=0 ; i<mActiveConnections.size() ; i++) { sp<SensorEventConnection> connection(mActiveConnections[i].promote()); - if (connection != 0) { + if (connection != nullptr) { if (connection->needsWakeLock()) { releaseLock = false; break; @@ -1617,7 +1617,7 @@ void SensorService::populateActiveConnections( Mutex::Autolock _l(mLock); for (size_t i=0 ; i < mActiveConnections.size(); ++i) { sp<SensorEventConnection> connection(mActiveConnections[i].promote()); - if (connection != 0) { + if (connection != nullptr) { activeConnections->add(connection); } } diff --git a/services/sensorservice/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp index ff200660c1..b781744553 100644 --- a/services/sensorservice/hidl/EventQueue.cpp +++ b/services/sensorservice/hidl/EventQueue.cpp @@ -64,7 +64,7 @@ EventQueue::EventQueue( mInternalQueue(internalQueue) { mLooper->addFd(internalQueue->getFd(), ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT, - new EventQueueLooperCallback(internalQueue, callback), NULL /* data */); + new EventQueueLooperCallback(internalQueue, callback), nullptr /* data */); } void EventQueue::onLastStrongRef(const void *id) { diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp index fee6da1e60..938060063f 100644 --- a/services/sensorservice/hidl/SensorManager.cpp +++ b/services/sensorservice/hidl/SensorManager.cpp @@ -157,7 +157,7 @@ sp<Looper> SensorManager::getLooper() { JavaVMAttachArgs args{ .version = JNI_VERSION_1_2, .name = POLL_THREAD_NAME, - .group = NULL + .group = nullptr }; JNIEnv* env; if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) { diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 320e11f7eb..3fa1311ce9 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -26,6 +26,7 @@ cc_defaults { "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", "android.hardware.power@1.0", "android.hardware.power@1.3", "libbase", @@ -70,6 +71,7 @@ cc_defaults { "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", "android.hardware.power@1.3", "libhidlbase", "libhidltransport", @@ -89,11 +91,14 @@ filegroup { srcs: [ "BufferLayer.cpp", "BufferLayerConsumer.cpp", + "BufferQueueLayer.cpp", + "BufferStateLayer.cpp", "Client.cpp", "ColorLayer.cpp", "ContainerLayer.cpp", "DisplayDevice.cpp", "DisplayHardware/ComposerHal.cpp", + "DisplayHardware/DisplayIdentification.cpp", "DisplayHardware/FramebufferSurface.cpp", "DisplayHardware/HWC2.cpp", "DisplayHardware/HWComposer.cpp", @@ -108,6 +113,7 @@ filegroup { "FrameTracker.cpp", "GpuService.cpp", "Layer.cpp", + "LayerBE.cpp", "LayerProtoHelper.cpp", "LayerRejecter.cpp", "LayerStats.cpp", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 12267adbc0..e7246665dd 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -53,22 +53,18 @@ namespace android { BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags) : Layer(flinger, client, name, w, h, flags), - mConsumer(nullptr), - mTextureName(UINT32_MAX), - mFormat(PIXEL_FORMAT_NONE), + mTextureName(mFlinger->getNewTexture()), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mBufferLatched(false), - mPreviousFrameNumber(0), - mUpdateTexImageFailed(false), mRefreshPending(false) { ALOGV("Creating Layer %s", name.string()); - mTextureName = mFlinger->getNewTexture(); mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); - if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; + mPremultipliedAlpha = !(flags & ISurfaceComposerClient::eNonPremultiplied); - mCurrentState.requested = mCurrentState.active; + mPotentialCursor = flags & ISurfaceComposerClient::eCursorWindow; + mProtectedByApp = flags & ISurfaceComposerClient::eProtectedByApp; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -89,7 +85,7 @@ void BufferLayer::useSurfaceDamage() { if (mFlinger->mForceFullDamage) { surfaceDamageRegion = Region::INVALID_REGION; } else { - surfaceDamageRegion = mConsumer->getSurfaceDamage(); + surfaceDamageRegion = getDrawingSurfaceDamage(); } } @@ -97,46 +93,27 @@ void BufferLayer::useEmptyDamage() { surfaceDamageRegion.clear(); } -bool BufferLayer::isProtected() const { - const sp<GraphicBuffer>& buffer(getBE().compositionInfo.mBuffer); - return (buffer != 0) && - (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); +bool BufferLayer::isOpaque(const Layer::State& s) const { + // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the + // layer's opaque flag. + if ((getBE().compositionInfo.hwc.sidebandStream == nullptr) && (mActiveBuffer == nullptr)) { + return false; + } + + // if the layer has the opaque flag, then we're always opaque, + // otherwise we use the current buffer's format. + return ((s.flags & layer_state_t::eLayerOpaque) != 0) || getOpacityForFormat(getPixelFormat()); } bool BufferLayer::isVisible() const { return !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (getBE().compositionInfo.mBuffer != nullptr || - getBE().compositionInfo.hwc.sidebandStream != nullptr); + (mActiveBuffer != nullptr || getBE().compositionInfo.hwc.sidebandStream != nullptr); } bool BufferLayer::isFixedSize() const { return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE; } -status_t BufferLayer::setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - uint32_t const maxSurfaceDims = - min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); - - // never allow a surface larger than what our underlying GL implementation - // can handle. - if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) { - ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); - return BAD_VALUE; - } - - mFormat = format; - - mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false; - mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; - mCurrentOpacity = getOpacityForFormat(format); - - mConsumer->setDefaultBufferSize(w, h); - mConsumer->setDefaultBufferFormat(format); - mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - - return NO_ERROR; -} - static constexpr mat4 inverseOrientation(uint32_t transform) { const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1); const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1); @@ -159,10 +136,12 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { * onDraw will draw the current layer onto the presentable buffer */ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const { + bool useIdentityTransform) { ATRACE_CALL(); - if (CC_UNLIKELY(getBE().compositionInfo.mBuffer == 0)) { + CompositionInfo& compositionInfo = getBE().compositionInfo; + + if (CC_UNLIKELY(mActiveBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client @@ -191,7 +170,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, // Bind the current buffer to the GL texture, and wait for it to be // ready for us to draw into. - status_t err = mConsumer->bindTextureImage(); + status_t err = bindTextureImage(); if (err != NO_ERROR) { ALOGW("onDraw: bindTextureImage failed (err=%d)", err); // Go ahead and draw the buffer anyway; no matter what we do the screen @@ -208,8 +187,8 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, // Query the texture matrix given our current filtering mode. float textureMatrix[16]; - mConsumer->setFilteringEnabled(useFiltering); - mConsumer->getTransformMatrix(textureMatrix); + setFilteringEnabled(useFiltering); + getDrawingTransformMatrix(textureMatrix); if (getTransformToDisplayInverse()) { /* @@ -240,10 +219,10 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, } // Set things up for texturing. - mTexture.setDimensions(getBE().compositionInfo.mBuffer->getWidth(), - getBE().compositionInfo.mBuffer->getHeight()); + mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); mTexture.setFiltering(useFiltering); mTexture.setMatrix(textureMatrix); + compositionInfo.re.texture = mTexture; engine.setupLayerTexturing(mTexture); } else { @@ -253,51 +232,106 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, engine.disableTexturing(); } -void BufferLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { - mConsumer->setReleaseFence(releaseFence); +void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) { + CompositionInfo& compositionInfo = getBE().compositionInfo; + auto& engine(mFlinger->getRenderEngine()); + + draw(renderArea, useIdentityTransform); + + engine.setupLayerTexturing(compositionInfo.re.texture); + engine.setupLayerBlending(compositionInfo.re.preMultipliedAlpha, compositionInfo.re.opaque, + false, compositionInfo.re.color); + engine.setSourceDataSpace(compositionInfo.hwc.dataspace); + engine.setSourceY410BT2020(compositionInfo.re.Y410BT2020); + engine.drawMesh(getBE().getMesh()); + engine.disableBlending(); + engine.disableTexturing(); + engine.setSourceY410BT2020(false); } -void BufferLayer::abandon() { - mConsumer->abandon(); +bool BufferLayer::isHdrY410() const { + // pixel format is HDR Y410 masquerading as RGBA_1010102 + return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && + getDrawingApi() == NATIVE_WINDOW_API_MEDIA && + getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } -bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const { - if (mSidebandStreamChanged || mAutoRefresh) { - return true; +void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& display) { + // Apply this display's projection's viewport to the visible region + // before giving it to the HWC HAL. + const Transform& tr = display->getTransform(); + const auto& viewport = display->getViewport(); + Region visible = tr.transform(visibleRegion.intersect(viewport)); + const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + auto error = hwcLayer->setVisibleRegion(visible); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast<int32_t>(error)); + visible.dump(LOG_TAG); } - Mutex::Autolock lock(mQueueItemLock); - if (mQueueItems.empty()) { - return false; + error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast<int32_t>(error)); + surfaceDamageRegion.dump(LOG_TAG); } - auto timestamp = mQueueItems[0].mTimestamp; - nsecs_t expectedPresent = mConsumer->computeExpectedPresent(dispSync); - // Ignore timestamps more than a second in the future - bool isPlausible = timestamp < (expectedPresent + s2ns(1)); - ALOGW_IF(!isPlausible, - "[%s] Timestamp %" PRId64 " seems implausible " - "relative to expectedPresent %" PRId64, - mName.string(), timestamp, expectedPresent); + // Sideband layers + if (getBE().compositionInfo.hwc.sidebandStream.get()) { + setCompositionType(displayId, HWC2::Composition::Sideband); + ALOGV("[%s] Requesting Sideband composition", mName.string()); + error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), + getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), + static_cast<int32_t>(error)); + } + return; + } - bool isDue = timestamp < expectedPresent; - return isDue || !isPlausible; -} + // Device or Cursor layers + if (mPotentialCursor) { + ALOGV("[%s] Requesting Cursor composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Cursor); + } else { + ALOGV("[%s] Requesting Device composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Device); + } -void BufferLayer::setTransformHint(uint32_t orientation) const { - mConsumer->setTransformHint(orientation); + ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, + to_string(error).c_str(), static_cast<int32_t>(error)); + } + + const HdrMetadata& metadata = getDrawingHdrMetadata(); + error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); + if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { + ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast<int32_t>(error)); + } + + setHwcLayerBuffer(display); } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { if (mBufferLatched) { Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPreComposition(mCurrentFrameNumber, - refreshStartTime); + mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); } mRefreshPending = false; - return mQueuedFrames > 0 || mSidebandStreamChanged || - mAutoRefresh; + return hasReadyFrame(); } + bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, const CompositorTiming& compositorTiming) { @@ -308,18 +342,18 @@ bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFenc // Update mFrameEventHistory. { Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, - presentFence, compositorTiming); + mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence, + compositorTiming); } // Update mFrameTracker. - nsecs_t desiredPresentTime = mConsumer->getTimestamp(); + nsecs_t desiredPresentTime = getDesiredPresentTime(); mFrameTracker.setDesiredPresentTime(desiredPresentTime); const std::string layerName(getName().c_str()); mTimeStats.setDesiredTime(layerName, mCurrentFrameNumber, desiredPresentTime); - std::shared_ptr<FenceTime> frameReadyFence = mConsumer->getCurrentFenceTime(); + std::shared_ptr<FenceTime> frameReadyFence = getCurrentFenceTime(); if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); } else { @@ -331,7 +365,7 @@ bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFenc if (presentFence->isValid()) { mTimeStats.setPresentFence(layerName, mCurrentFrameNumber, presentFence); mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); - } else { + } else if (mFlinger->getHwComposer().isConnected(HWC_DISPLAY_PRIMARY)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = @@ -345,58 +379,19 @@ bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFenc return true; } -std::vector<OccupancyTracker::Segment> BufferLayer::getOccupancyHistory(bool forceFlush) { - std::vector<OccupancyTracker::Segment> history; - status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); - if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); - return {}; - } - return history; -} - -bool BufferLayer::getTransformToDisplayInverse() const { - return mConsumer->getTransformToDisplayInverse(); -} - -void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { - if (!mConsumer->releasePendingBuffer()) { - return; - } - - auto releaseFenceTime = - std::make_shared<FenceTime>(mConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - - Mutex::Autolock lock(mFrameEventHistoryMutex); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, - std::move(releaseFenceTime)); - } -} - Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { ATRACE_CALL(); - if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was true - mSidebandStream = mConsumer->getSidebandStream(); - // replicated in LayerBE until FE/BE is ready to be synchronized - getBE().compositionInfo.hwc.sidebandStream = mSidebandStream; - if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { - setTransactionFlags(eTransactionNeeded); - mFlinger->setTransactionFlags(eTraversalNeeded); - } - recomputeVisibleRegions = true; + std::optional<Region> sidebandStreamDirtyRegion = latchSidebandStream(recomputeVisibleRegions); - const State& s(getDrawingState()); - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + if (sidebandStreamDirtyRegion) { + return *sidebandStreamDirtyRegion; } - Region outDirtyRegion; - if (mQueuedFrames <= 0 && !mAutoRefresh) { - return outDirtyRegion; + Region dirtyRegion; + + if (!hasReadyFrame()) { + return dirtyRegion; } // if we've already called updateTexImage() without going through @@ -405,119 +400,41 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // compositionComplete() call. // we'll trigger an update in onPreComposition(). if (mRefreshPending) { - return outDirtyRegion; + return dirtyRegion; } // If the head buffer's acquire fence hasn't signaled yet, return and // try again later - if (!headFenceHasSignaled()) { + if (!fenceHasSignaled()) { mFlinger->signalLayerUpdate(); - return outDirtyRegion; + return dirtyRegion; } // Capture the old state of the layer for comparisons later const State& s(getDrawingState()); const bool oldOpacity = isOpaque(s); - sp<GraphicBuffer> oldBuffer = getBE().compositionInfo.mBuffer; + sp<GraphicBuffer> oldBuffer = mActiveBuffer; if (!allTransactionsSignaled()) { mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } - - // This boolean is used to make sure that SurfaceFlinger's shadow copy - // of the buffer queue isn't modified when the buffer queue is returning - // BufferItem's that weren't actually queued. This can happen in shared - // buffer mode. - bool queuedBuffer = false; - LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName.string(), - mOverrideScalingMode, mFreezeGeometryUpdates); - status_t updateResult = - mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync, - &mAutoRefresh, &queuedBuffer, - mLastFrameNumberReceived); - if (updateResult == BufferQueue::PRESENT_LATER) { - // Producer doesn't want buffer to be displayed yet. Signal a - // layer update so we check again at the next opportunity. - mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) { - // If the buffer has been rejected, remove it from the shadow queue - // and return early - if (queuedBuffer) { - Mutex::Autolock lock(mQueueItemLock); - mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); - } - return outDirtyRegion; - } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { - // This can occur if something goes wrong when trying to create the - // EGLImage for this buffer. If this happens, the buffer has already - // been released, so we need to clean up the queue and bug out - // early. - if (queuedBuffer) { - Mutex::Autolock lock(mQueueItemLock); - mQueueItems.clear(); - android_atomic_and(0, &mQueuedFrames); - mTimeStats.clearLayerRecord(getName().c_str()); - } - - // Once we have hit this state, the shadow queue may no longer - // correctly reflect the incoming BufferQueue's contents, so even if - // updateTexImage starts working, the only safe course of action is - // to continue to ignore updates. - mUpdateTexImageFailed = true; - - return outDirtyRegion; - } - - if (queuedBuffer) { - // Autolock scope - auto currentFrameNumber = mConsumer->getFrameNumber(); - - Mutex::Autolock lock(mQueueItemLock); - - // Remove any stale buffers that have been dropped during - // updateTexImage - while (mQueueItems[0].mFrameNumber != currentFrameNumber) { - mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); - } - - const std::string layerName(getName().c_str()); - mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime); - mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime); - - mQueueItems.removeAt(0); + return dirtyRegion; } - // Decrement the queued-frames count. Signal another event if we - // have more frames pending. - if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || - mAutoRefresh) { - mFlinger->signalLayerUpdate(); + status_t err = updateTexImage(recomputeVisibleRegions, latchTime); + if (err != NO_ERROR) { + return dirtyRegion; } - // update the active buffer - getBE().compositionInfo.mBuffer = - mConsumer->getCurrentBuffer(&getBE().compositionInfo.mBufferSlot); - // replicated in LayerBE until FE/BE is ready to be synchronized - mActiveBuffer = getBE().compositionInfo.mBuffer; - if (getBE().compositionInfo.mBuffer == nullptr) { - // this can only happen if the very first buffer was rejected. - return outDirtyRegion; + err = updateActiveBuffer(); + if (err != NO_ERROR) { + return dirtyRegion; } mBufferLatched = true; - mPreviousFrameNumber = mCurrentFrameNumber; - mCurrentFrameNumber = mConsumer->getFrameNumber(); - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); + err = updateFrameNumber(latchTime); + if (err != NO_ERROR) { + return dirtyRegion; } mRefreshPending = true; @@ -528,7 +445,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime recomputeVisibleRegions = true; } - ui::Dataspace dataSpace = mConsumer->getCurrentDataSpace(); + ui::Dataspace dataSpace = getDrawingDataSpace(); // treat modern dataspaces as legacy dataspaces whenever possible, until // we can trust the buffer producers switch (dataSpace) { @@ -555,11 +472,10 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } mCurrentDataSpace = dataSpace; - Rect crop(mConsumer->getCurrentCrop()); - const uint32_t transform(mConsumer->getCurrentTransform()); - const uint32_t scalingMode(mConsumer->getCurrentScalingMode()); - if ((crop != mCurrentCrop) || - (transform != mCurrentTransform) || + Rect crop(getDrawingCrop()); + const uint32_t transform(getDrawingTransform()); + const uint32_t scalingMode(getDrawingScalingMode()); + if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || (scalingMode != mCurrentScalingMode)) { mCurrentCrop = crop; mCurrentTransform = transform; @@ -568,15 +484,13 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } if (oldBuffer != nullptr) { - uint32_t bufWidth = getBE().compositionInfo.mBuffer->getWidth(); - uint32_t bufHeight = getBE().compositionInfo.mBuffer->getHeight(); - if (bufWidth != uint32_t(oldBuffer->width) || - bufHeight != uint32_t(oldBuffer->height)) { + uint32_t bufWidth = mActiveBuffer->getWidth(); + uint32_t bufHeight = mActiveBuffer->getHeight(); + if (bufWidth != uint32_t(oldBuffer->width) || bufHeight != uint32_t(oldBuffer->height)) { recomputeVisibleRegions = true; } } - mCurrentOpacity = getOpacityForFormat(getBE().compositionInfo.mBuffer->format); if (oldOpacity != isOpaque(s)) { recomputeVisibleRegions = true; } @@ -603,198 +517,78 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } // FIXME: postedRegion should be dirty & bounds - Region dirtyRegion(Rect(s.active.w, s.active.h)); - // transform the dirty region to window-manager space - outDirtyRegion = (getTransform().transform(dirtyRegion)); - - return outDirtyRegion; -} - -void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) { - mConsumer->setDefaultBufferSize(w, h); + return getTransform().transform(Region(Rect(getActiveWidth(s), getActiveHeight(s)))); } -void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) { - // Apply this display's projection's viewport to the visible region - // before giving it to the HWC HAL. - const Transform& tr = displayDevice->getTransform(); - const auto& viewport = displayDevice->getViewport(); - Region visible = tr.transform(visibleRegion.intersect(viewport)); - auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = getBE().mHwcLayers[hwcId]; - auto& hwcLayer = hwcInfo.layer; - auto error = hwcLayer->setVisibleRegion(visible); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast<int32_t>(error)); - visible.dump(LOG_TAG); - } - - error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast<int32_t>(error)); - surfaceDamageRegion.dump(LOG_TAG); - } - - // Sideband layers - if (getBE().compositionInfo.hwc.sidebandStream.get()) { - setCompositionType(hwcId, HWC2::Composition::Sideband); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast<int32_t>(error)); +// transaction +void BufferLayer::notifyAvailableFrames() { + auto headFrameNumber = getHeadFrameNumber(); + bool headFenceSignaled = fenceHasSignaled(); + Mutex::Autolock lock(mLocalSyncPointMutex); + for (auto& point : mLocalSyncPoints) { + if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) { + point->setFrameAvailable(); } - return; - } - - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Cursor); - } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Device); - } - - ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); - error = hwcLayer->setDataspace(mCurrentDataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, - to_string(error).c_str(), static_cast<int32_t>(error)); - } - - const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(displayDevice->getSupportedPerFrameMetadata(), metadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast<int32_t>(error)); - } - - uint32_t hwcSlot = 0; - sp<GraphicBuffer> hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(getBE().compositionInfo.mBufferSlot, - getBE().compositionInfo.mBuffer, &hwcSlot, &hwcBuffer); - - auto acquireFence = mConsumer->getCurrentFence(); - error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), - getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), - static_cast<int32_t>(error)); } } -bool BufferLayer::isOpaque(const Layer::State& s) const { - // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the - // layer's opaque flag. - if ((getBE().compositionInfo.hwc.sidebandStream == nullptr) && (getBE().compositionInfo.mBuffer == nullptr)) { - return false; - } - - // if the layer has the opaque flag, then we're always opaque, - // otherwise we use the current buffer's format. - return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity; +bool BufferLayer::hasReadyFrame() const { + return hasDrawingBuffer() || getSidebandStreamChanged() || getAutoRefresh(); } -void BufferLayer::onFirstRef() { - // Creates a custom BufferQueue for SurfaceFlingerConsumer to use - sp<IGraphicBufferProducer> producer; - sp<IGraphicBufferConsumer> consumer; - BufferQueue::createBufferQueue(&producer, &consumer, true); - mProducer = new MonitoredProducer(producer, mFlinger, this); - { - // Grab the SF state lock during this since it's the only safe way to access RenderEngine - Mutex::Autolock lock(mFlinger->mStateLock); - mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, - this); - } - mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - mConsumer->setContentsChangedListener(this); - mConsumer->setName(mName); - - if (mFlinger->isLayerTripleBufferingDisabled()) { - mProducer->setMaxDequeuedBufferCount(2); +uint32_t BufferLayer::getEffectiveScalingMode() const { + if (mOverrideScalingMode >= 0) { + return mOverrideScalingMode; } - const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); - updateTransformHint(hw); + return mCurrentScalingMode; } -// --------------------------------------------------------------------------- -// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener -// --------------------------------------------------------------------------- - -void BufferLayer::onFrameAvailable(const BufferItem& item) { - // Add this buffer from our internal queue tracker - { // Autolock scope - Mutex::Autolock lock(mQueueItemLock); - mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), - item.mGraphicBuffer->getHeight(), - item.mFrameNumber); - // Reset the frame number tracker when we receive the first buffer after - // a frame number reset - if (item.mFrameNumber == 1) { - mLastFrameNumberReceived = 0; - } - - // Ensure that callbacks are handled in order - while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, - ms2ns(500)); - if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); - } - } - - mQueueItems.push_back(item); - android_atomic_inc(&mQueuedFrames); +bool BufferLayer::isProtected() const { + const sp<GraphicBuffer>& buffer(mActiveBuffer); + return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); +} - // Wake up any pending callbacks - mLastFrameNumberReceived = item.mFrameNumber; - mQueueItemCondition.broadcast(); +bool BufferLayer::latchUnsignaledBuffers() { + static bool propertyLoaded = false; + static bool latch = false; + static std::mutex mutex; + std::lock_guard<std::mutex> lock(mutex); + if (!propertyLoaded) { + char value[PROPERTY_VALUE_MAX] = {}; + property_get("debug.sf.latch_unsignaled", value, "0"); + latch = atoi(value); + propertyLoaded = true; } - - mFlinger->signalLayerUpdate(); + return latch; } -void BufferLayer::onFrameReplaced(const BufferItem& item) { - { // Autolock scope - Mutex::Autolock lock(mQueueItemLock); +// h/w composer set-up +bool BufferLayer::allTransactionsSignaled() { + auto headFrameNumber = getHeadFrameNumber(); + bool matchingFramesFound = false; + bool allTransactionsApplied = true; + Mutex::Autolock lock(mLocalSyncPointMutex); - // Ensure that callbacks are handled in order - while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, - ms2ns(500)); - if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); - } + for (auto& point : mLocalSyncPoints) { + if (point->getFrameNumber() > headFrameNumber) { + break; } + matchingFramesFound = true; - if (mQueueItems.empty()) { - ALOGE("Can't replace a frame on an empty queue"); - return; + if (!point->frameIsAvailable()) { + // We haven't notified the remote layer that the frame for + // this point is available yet. Notify it now, and then + // abort this attempt to latch. + point->setFrameAvailable(); + allTransactionsApplied = false; + break; } - mQueueItems.editItemAt(mQueueItems.size() - 1) = item; - // Wake up any pending callbacks - mLastFrameNumberReceived = item.mFrameNumber; - mQueueItemCondition.broadcast(); - } -} - -void BufferLayer::onSidebandStreamChanged() { - if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was false - mFlinger->signalLayerUpdate(); + allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied(); } -} - -bool BufferLayer::needsFiltering(const RenderArea& renderArea) const { - return mNeedsFiltering || renderArea.needsFiltering(); + return !matchingFramesFound || allTransactionsApplied; } // As documented in libhardware header, formats in the range @@ -819,11 +613,8 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { return true; } -bool BufferLayer::isHdrY410() const { - // pixel format is HDR Y410 masquerading as RGBA_1010102 - return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && - mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && - getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); +bool BufferLayer::needsFiltering(const RenderArea& renderArea) const { + return mNeedsFiltering || renderArea.needsFiltering(); } void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { @@ -850,9 +641,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT Transform t = getTransform(); Rect win = bounds; - if (!s.finalCrop.isEmpty()) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { win = t.transform(win); - if (!win.intersect(s.finalCrop, &win)) { + if (!win.intersect(finalCrop, &win)) { win.clear(); } win = t.inverse().transform(win); @@ -861,10 +653,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT } } - float left = float(win.left) / float(s.active.w); - float top = float(win.top) / float(s.active.h); - float right = float(win.right) / float(s.active.w); - float bottom = float(win.bottom) / float(s.active.h); + float left = float(win.left) / float(getActiveWidth(s)); + float top = float(win.top) / float(getActiveHeight(s)); + float right = float(win.right) / float(getActiveWidth(s)); + float bottom = float(win.bottom) / float(getActiveHeight(s)); // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices @@ -889,116 +681,14 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT engine.setSourceY410BT2020(false); } -uint32_t BufferLayer::getProducerStickyTransform() const { - int producerStickyTransform = 0; - int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform); - if (ret != OK) { - ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__, - strerror(-ret), ret); - return 0; - } - return static_cast<uint32_t>(producerStickyTransform); -} - -bool BufferLayer::latchUnsignaledBuffers() { - static bool propertyLoaded = false; - static bool latch = false; - static std::mutex mutex; - std::lock_guard<std::mutex> lock(mutex); - if (!propertyLoaded) { - char value[PROPERTY_VALUE_MAX] = {}; - property_get("debug.sf.latch_unsignaled", value, "0"); - latch = atoi(value); - propertyLoaded = true; - } - return latch; -} - uint64_t BufferLayer::getHeadFrameNumber() const { - Mutex::Autolock lock(mQueueItemLock); - if (!mQueueItems.empty()) { - return mQueueItems[0].mFrameNumber; + if (hasDrawingBuffer()) { + return getFrameNumber(); } else { return mCurrentFrameNumber; } } -bool BufferLayer::headFenceHasSignaled() const { - if (latchUnsignaledBuffers()) { - return true; - } - - Mutex::Autolock lock(mQueueItemLock); - if (mQueueItems.empty()) { - return true; - } - if (mQueueItems[0].mIsDroppable) { - // Even though this buffer's fence may not have signaled yet, it could - // be replaced by another buffer before it has a chance to, which means - // that it's possible to get into a situation where a buffer is never - // able to be latched. To avoid this, grab this buffer anyway. - return true; - } - return mQueueItems[0].mFenceTime->getSignalTime() != - Fence::SIGNAL_TIME_PENDING; -} - -uint32_t BufferLayer::getEffectiveScalingMode() const { - if (mOverrideScalingMode >= 0) { - return mOverrideScalingMode; - } - return mCurrentScalingMode; -} - -// ---------------------------------------------------------------------------- -// transaction -// ---------------------------------------------------------------------------- - -void BufferLayer::notifyAvailableFrames() { - auto headFrameNumber = getHeadFrameNumber(); - bool headFenceSignaled = headFenceHasSignaled(); - Mutex::Autolock lock(mLocalSyncPointMutex); - for (auto& point : mLocalSyncPoints) { - if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) { - point->setFrameAvailable(); - } - } -} - -sp<IGraphicBufferProducer> BufferLayer::getProducer() const { - return mProducer; -} - -// --------------------------------------------------------------------------- -// h/w composer set-up -// --------------------------------------------------------------------------- - -bool BufferLayer::allTransactionsSignaled() { - auto headFrameNumber = getHeadFrameNumber(); - bool matchingFramesFound = false; - bool allTransactionsApplied = true; - Mutex::Autolock lock(mLocalSyncPointMutex); - - for (auto& point : mLocalSyncPoints) { - if (point->getFrameNumber() > headFrameNumber) { - break; - } - matchingFramesFound = true; - - if (!point->frameIsAvailable()) { - // We haven't notified the remote layer that the frame for - // this point is available yet. Notify it now, and then - // abort this attempt to latch. - point->setFrameAvailable(); - allTransactionsApplied = false; - break; - } - - allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied(); - } - return !matchingFramesFound || allTransactionsApplied; -} - } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index bf0ca69253..13f4e83b44 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -47,151 +47,142 @@ namespace android { -/* - * A new BufferQueue and a new BufferLayerConsumer are created when the - * BufferLayer is first referenced. - * - * This also implements onFrameAvailable(), which notifies SurfaceFlinger - * that new data has arrived. - */ -class BufferLayer : public Layer, public BufferLayerConsumer::ContentsChangedListener { +class BufferLayer : public Layer { public: BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); ~BufferLayer() override; - // If we have received a new buffer this frame, we will pass its surface - // damage down to hardware composer. Otherwise, we must send a region with - // one empty rect. - void useSurfaceDamage(); - void useEmptyDamage(); - // ----------------------------------------------------------------------- // Overriden from Layer // ----------------------------------------------------------------------- +public: + // If we have received a new buffer this frame, we will pass its surface + // damage down to hardware composer. Otherwise, we must send a region with + // one empty rect. + void useSurfaceDamage() override; + void useEmptyDamage() override; - /* - * getTypeId - Provide unique string for each class type in the Layer - * hierarchy - */ + // getTypeId - Provide unique string for each class type in the Layer + // hierarchy const char* getTypeId() const override { return "BufferLayer"; } - /* - * isProtected - true if the layer may contain protected content in the - * GRALLOC_USAGE_PROTECTED sense. - */ - bool isProtected() const; + bool isOpaque(const Layer::State& s) const override; - /* - * isVisible - true if this layer is visible, false otherwise - */ + // isVisible - true if this layer is visible, false otherwise bool isVisible() const override; - /* - * isFixedSize - true if content has a fixed size - */ + // isFixedSize - true if content has a fixed size bool isFixedSize() const override; - // the this layer's size and format - status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - - /* - * onDraw - draws the surface. - */ + // onDraw - draws the surface. void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const override; + bool useIdentityTransform) override; + void drawNow(const RenderArea& renderArea, bool useIdentityTransform); + + bool isHdrY410() const override; - void onLayerDisplayed(const sp<Fence>& releaseFence) override; + void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override; - void abandon() override; - bool shouldPresentNow(const DispSync& dispSync) const override; - void setTransformHint(uint32_t orientation) const override; + bool onPreComposition(nsecs_t refreshStartTime) override; bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, const CompositorTiming& compositorTiming) override; - std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override; - bool getTransformToDisplayInverse() const override; - -public: - bool onPreComposition(nsecs_t refreshStartTime) override; - - // If a buffer was replaced this frame, release the former buffer - void releasePendingBuffer(nsecs_t dequeueReadyTime); - /* - * latchBuffer - called each time the screen is redrawn and returns whether - * the visible regions need to be recomputed (this is a fairly heavy - * operation, so this should be set only if needed). Typically this is used - * to figure out if the content or size of a surface has changed. - */ + // latchBuffer - called each time the screen is redrawn and returns whether + // the visible regions need to be recomputed (this is a fairly heavy + // operation, so this should be set only if needed). Typically this is used + // to figure out if the content or size of a surface has changed. Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + bool isBufferLatched() const override { return mRefreshPending; } - void setDefaultBufferSize(uint32_t w, uint32_t h) override; - bool isHdrY410() const override; + void notifyAvailableFrames() override; - void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override; + bool hasReadyFrame() const override; - bool isOpaque(const Layer::State& s) const override; + // Returns the current scaling mode, unless mOverrideScalingMode + // is set, in which case, it returns mOverrideScalingMode + uint32_t getEffectiveScalingMode() const override; + // ----------------------------------------------------------------------- + // ----------------------------------------------------------------------- + // Functions that must be implemented by derived classes + // ----------------------------------------------------------------------- private: - void onFirstRef() override; + virtual bool fenceHasSignaled() const = 0; - // Interface implementation for - // BufferLayerConsumer::ContentsChangedListener - void onFrameAvailable(const BufferItem& item) override; - void onFrameReplaced(const BufferItem& item) override; - void onSidebandStreamChanged() override; + virtual nsecs_t getDesiredPresentTime() = 0; + virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0; - // needsLinearFiltering - true if this surface's state requires filtering - bool needsFiltering(const RenderArea& renderArea) const; + virtual void getDrawingTransformMatrix(float *matrix) = 0; + virtual uint32_t getDrawingTransform() const = 0; + virtual ui::Dataspace getDrawingDataSpace() const = 0; + virtual Rect getDrawingCrop() const = 0; + virtual uint32_t getDrawingScalingMode() const = 0; + virtual Region getDrawingSurfaceDamage() const = 0; + virtual const HdrMetadata& getDrawingHdrMetadata() const = 0; + virtual int getDrawingApi() const = 0; + virtual PixelFormat getPixelFormat() const = 0; - static bool getOpacityForFormat(uint32_t format); + virtual uint64_t getFrameNumber() const = 0; - // drawing - void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const; + virtual bool getAutoRefresh() const = 0; + virtual bool getSidebandStreamChanged() const = 0; - // Temporary - Used only for LEGACY camera mode. - uint32_t getProducerStickyTransform() const; + virtual std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) = 0; - // Loads the corresponding system property once per process - static bool latchUnsignaledBuffers(); + virtual bool hasDrawingBuffer() const = 0; - uint64_t getHeadFrameNumber() const; - bool headFenceHasSignaled() const; + virtual void setFilteringEnabled(bool enabled) = 0; - // Returns the current scaling mode, unless mOverrideScalingMode - // is set, in which case, it returns mOverrideScalingMode - uint32_t getEffectiveScalingMode() const override; + virtual status_t bindTextureImage() const = 0; + virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; -public: - void notifyAvailableFrames() override; + virtual status_t updateActiveBuffer() = 0; + virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; - PixelFormat getPixelFormat() const override { return mFormat; } - sp<IGraphicBufferProducer> getProducer() const; + virtual void setHwcLayerBuffer(const sp<const DisplayDevice>& display) = 0; -private: - sp<BufferLayerConsumer> mConsumer; + // ----------------------------------------------------------------------- + +public: + // isProtected - true if the layer may contain protected content in the + // GRALLOC_USAGE_PROTECTED sense. + bool isProtected() const; + +protected: + // Loads the corresponding system property once per process + static bool latchUnsignaledBuffers(); // Check all of the local sync points to ensure that all transactions // which need to have been applied prior to the frame which is about to // be latched have signaled bool allTransactionsSignaled(); - sp<IGraphicBufferProducer> mProducer; - // constants - uint32_t mTextureName; // from GLES - PixelFormat mFormat; + static bool getOpacityForFormat(uint32_t format); + + // from GLES + const uint32_t mTextureName; + +private: + // needsLinearFiltering - true if this surface's state requires filtering + bool needsFiltering(const RenderArea& renderArea) const; + + // drawing + void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const; + + uint64_t getHeadFrameNumber() const; - // main thread uint32_t mCurrentScalingMode; - bool mBufferLatched = false; // TODO: Use mActiveBuffer? - uint64_t mPreviousFrameNumber; // Only accessed on the main thread. + + // main thread. + bool mBufferLatched; // TODO: Use mActiveBuffer? + // The texture used to draw the layer in GLES composition mode mutable Texture mTexture; - bool mUpdateTexImageFailed; // This is only accessed on the main thread. bool mRefreshPending; }; diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 87333d0ffd..8788d47451 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -40,7 +40,6 @@ #include <gui/SurfaceComposerClient.h> #include <private/gui/ComposerService.h> -#include <private/gui/SyncFeatures.h> #include <utils/Log.h> #include <utils/String8.h> @@ -206,7 +205,7 @@ status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const Dis return err; } - if (!SyncFeatures::getInstance().useNativeFenceSync()) { + if (mRE.useNativeFenceSync()) { // Bind the new buffer to the GL texture. // // Older devices require the "implicit" synchronization provided @@ -280,14 +279,6 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres return NO_ERROR; } -bool BufferLayerConsumer::canUseImageCrop(const Rect& crop) const { - // If the crop rect is not at the origin, we can't set the crop on the - // EGLImage because that's not allowed by the EGL_ANDROID_image_crop - // extension. In the future we can add a layered extension that - // removes this restriction if there is hardware that can support it. - return mRE.supportsImageCrop() && crop.left == 0 && crop.top == 0; -} - status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease) { status_t err = NO_ERROR; @@ -365,8 +356,7 @@ status_t BufferLayerConsumer::bindTextureImageLocked() { return NO_INIT; } - const Rect& imageCrop = canUseImageCrop(mCurrentCrop) ? mCurrentCrop : Rect::EMPTY_RECT; - status_t err = mCurrentTextureImage->createIfNeeded(imageCrop); + status_t err = mCurrentTextureImage->createIfNeeded(); if (err != NO_ERROR) { BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture); mRE.bindExternalTextureImage(mTexName, *mRE.createImage()); @@ -383,7 +373,7 @@ status_t BufferLayerConsumer::syncForReleaseLocked() { BLC_LOGV("syncForReleaseLocked"); if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { - if (SyncFeatures::getInstance().useNativeFenceSync()) { + if (mRE.useNativeFenceSync()) { base::unique_fd fenceFd = mRE.flush(); if (fenceFd == -1) { BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine"); @@ -435,9 +425,8 @@ void BufferLayerConsumer::computeCurrentTransformMatrixLocked() { BLC_LOGD("computeCurrentTransformMatrixLocked: " "mCurrentTextureImage is nullptr"); } - const Rect& cropRect = canUseImageCrop(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop; - GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf, cropRect, mCurrentTransform, - mFilteringEnabled); + GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop, + mCurrentTransform, mFilteringEnabled); } nsecs_t BufferLayerConsumer::getTimestamp() { @@ -522,7 +511,7 @@ status_t BufferLayerConsumer::doFenceWaitLocked() const { } if (mCurrentFence->isValid()) { - if (SyncFeatures::getInstance().useWaitSync()) { + if (mRE.useWaitSync()) { base::unique_fd fenceFd(mCurrentFence->dup()); if (fenceFd == -1) { BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno); @@ -615,23 +604,12 @@ BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEng BufferLayerConsumer::Image::~Image() = default; -status_t BufferLayerConsumer::Image::createIfNeeded(const Rect& imageCrop) { - const int32_t cropWidth = imageCrop.width(); - const int32_t cropHeight = imageCrop.height(); - if (mCreated && mCropWidth == cropWidth && mCropHeight == cropHeight) { - return OK; - } +status_t BufferLayerConsumer::Image::createIfNeeded() { + if (mCreated) return OK; mCreated = mImage->setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(), - mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED, - cropWidth, cropHeight); - if (mCreated) { - mCropWidth = cropWidth; - mCropHeight = cropHeight; - } else { - mCropWidth = 0; - mCropHeight = 0; - + mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); + if (!mCreated) { const sp<GraphicBuffer>& buffer = mGraphicBuffer; ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d", buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(), diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index f81cdb1d91..943b8a8103 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -228,9 +228,8 @@ private: Image(const Image& rhs) = delete; Image& operator=(const Image& rhs) = delete; - // createIfNeeded creates an RE::Image if required (we haven't created - // one yet, or the crop-rect has changed). - status_t createIfNeeded(const Rect& imageCrop); + // createIfNeeded creates an RE::Image if we haven't created one yet. + status_t createIfNeeded(); const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; } const native_handle* graphicBufferHandle() { diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp new file mode 100644 index 0000000000..6c339b78a9 --- /dev/null +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -0,0 +1,485 @@ +/* + * 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 "BufferQueueLayer.h" +#include "LayerRejecter.h" +#include "clz.h" + +#include <system/window.h> + +namespace android { + +BufferQueueLayer::BufferQueueLayer(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : BufferLayer(flinger, client, name, w, h, flags), + mConsumer(nullptr), + mProducer(nullptr), + mFormat(PIXEL_FORMAT_NONE), + mPreviousFrameNumber(0), + mUpdateTexImageFailed(false), + mQueueItemLock(), + mQueueItemCondition(), + mQueueItems(), + mLastFrameNumberReceived(0), + mAutoRefresh(false), + mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), + mQueuedFrames(0), + mSidebandStreamChanged(false) { + mCurrentState.requested_legacy = mCurrentState.active_legacy; +} + +// ----------------------------------------------------------------------- +// Interface implementation for Layer +// ----------------------------------------------------------------------- + +void BufferQueueLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { + mConsumer->setReleaseFence(releaseFence); +} + +void BufferQueueLayer::abandon() { + mConsumer->abandon(); +} + +void BufferQueueLayer::setTransformHint(uint32_t orientation) const { + mConsumer->setTransformHint(orientation); +} + +std::vector<OccupancyTracker::Segment> BufferQueueLayer::getOccupancyHistory(bool forceFlush) { + std::vector<OccupancyTracker::Segment> history; + status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); + if (result != NO_ERROR) { + ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); + return {}; + } + return history; +} + +bool BufferQueueLayer::getTransformToDisplayInverse() const { + return mConsumer->getTransformToDisplayInverse(); +} + +void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { + if (!mConsumer->releasePendingBuffer()) { + return; + } + + auto releaseFenceTime = std::make_shared<FenceTime>(mConsumer->getPrevFinalReleaseFence()); + mReleaseTimeline.updateSignalTimes(); + mReleaseTimeline.push(releaseFenceTime); + + Mutex::Autolock lock(mFrameEventHistoryMutex); + if (mPreviousFrameNumber != 0) { + mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, + std::move(releaseFenceTime)); + } +} + +void BufferQueueLayer::setDefaultBufferSize(uint32_t w, uint32_t h) { + mConsumer->setDefaultBufferSize(w, h); +} + +int32_t BufferQueueLayer::getQueuedFrameCount() const { + return mQueuedFrames; +} + +bool BufferQueueLayer::shouldPresentNow(const DispSync& dispSync) const { + if (getSidebandStreamChanged() || getAutoRefresh()) { + return true; + } + + if (!hasDrawingBuffer()) { + return false; + } + + Mutex::Autolock lock(mQueueItemLock); + + const int64_t addedTime = mQueueItems[0].mTimestamp; + const nsecs_t expectedPresentTime = mConsumer->computeExpectedPresent(dispSync); + + // Ignore timestamps more than a second in the future + const bool isPlausible = addedTime < (expectedPresentTime + s2ns(1)); + ALOGW_IF(!isPlausible, + "[%s] Timestamp %" PRId64 " seems implausible " + "relative to expectedPresent %" PRId64, + mName.string(), addedTime, expectedPresentTime); + + const bool isDue = addedTime < expectedPresentTime; + return isDue || !isPlausible; +} + +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayer +// ----------------------------------------------------------------------- + +bool BufferQueueLayer::fenceHasSignaled() const { + if (latchUnsignaledBuffers()) { + return true; + } + + if (!hasDrawingBuffer()) { + return true; + } + + Mutex::Autolock lock(mQueueItemLock); + if (mQueueItems[0].mIsDroppable) { + // Even though this buffer's fence may not have signaled yet, it could + // be replaced by another buffer before it has a chance to, which means + // that it's possible to get into a situation where a buffer is never + // able to be latched. To avoid this, grab this buffer anyway. + return true; + } + return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; +} + +nsecs_t BufferQueueLayer::getDesiredPresentTime() { + return mConsumer->getTimestamp(); +} + +std::shared_ptr<FenceTime> BufferQueueLayer::getCurrentFenceTime() const { + return mConsumer->getCurrentFenceTime(); +} + +void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) { + return mConsumer->getTransformMatrix(matrix); +} + +// NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's +// These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state +// so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's +// current buffer so the consumer functions start with "getCurrent". +// +// This results in the rather confusing functions below. +uint32_t BufferQueueLayer::getDrawingTransform() const { + return mConsumer->getCurrentTransform(); +} + +ui::Dataspace BufferQueueLayer::getDrawingDataSpace() const { + return mConsumer->getCurrentDataSpace(); +} + +Rect BufferQueueLayer::getDrawingCrop() const { + return mConsumer->getCurrentCrop(); +} + +uint32_t BufferQueueLayer::getDrawingScalingMode() const { + return mConsumer->getCurrentScalingMode(); +} + +Region BufferQueueLayer::getDrawingSurfaceDamage() const { + return mConsumer->getSurfaceDamage(); +} + +const HdrMetadata& BufferQueueLayer::getDrawingHdrMetadata() const { + return mConsumer->getCurrentHdrMetadata(); +} + +int BufferQueueLayer::getDrawingApi() const { + return mConsumer->getCurrentApi(); +} + +PixelFormat BufferQueueLayer::getPixelFormat() const { + return mFormat; +} + +uint64_t BufferQueueLayer::getFrameNumber() const { + Mutex::Autolock lock(mQueueItemLock); + return mQueueItems[0].mFrameNumber; +} + +bool BufferQueueLayer::getAutoRefresh() const { + return mAutoRefresh; +} + +bool BufferQueueLayer::getSidebandStreamChanged() const { + return mSidebandStreamChanged; +} + +std::optional<Region> BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { + if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was true + // replicated in LayerBE until FE/BE is ready to be synchronized + getBE().compositionInfo.hwc.sidebandStream = mConsumer->getSidebandStream(); + if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { + setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); + } + recomputeVisibleRegions = true; + + const State& s(getDrawingState()); + return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h))); + } + return {}; +} + +bool BufferQueueLayer::hasDrawingBuffer() const { + return mQueuedFrames > 0; +} + +void BufferQueueLayer::setFilteringEnabled(bool enabled) { + return mConsumer->setFilteringEnabled(enabled); +} + +status_t BufferQueueLayer::bindTextureImage() const { + return mConsumer->bindTextureImage(); +} + +status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) { + // This boolean is used to make sure that SurfaceFlinger's shadow copy + // of the buffer queue isn't modified when the buffer queue is returning + // BufferItem's that weren't actually queued. This can happen in shared + // buffer mode. + bool queuedBuffer = false; + LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, + getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, + getTransformToDisplayInverse(), mFreezeGeometryUpdates); + status_t updateResult = + mConsumer->updateTexImage(&r, *mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer, + mLastFrameNumberReceived); + if (updateResult == BufferQueue::PRESENT_LATER) { + // Producer doesn't want buffer to be displayed yet. Signal a + // layer update so we check again at the next opportunity. + mFlinger->signalLayerUpdate(); + return BAD_VALUE; + } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) { + // If the buffer has been rejected, remove it from the shadow queue + // and return early + if (queuedBuffer) { + Mutex::Autolock lock(mQueueItemLock); + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); + mQueueItems.removeAt(0); + android_atomic_dec(&mQueuedFrames); + } + return BAD_VALUE; + } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { + // This can occur if something goes wrong when trying to create the + // EGLImage for this buffer. If this happens, the buffer has already + // been released, so we need to clean up the queue and bug out + // early. + if (queuedBuffer) { + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.clear(); + android_atomic_and(0, &mQueuedFrames); + mTimeStats.clearLayerRecord(getName().c_str()); + } + + // Once we have hit this state, the shadow queue may no longer + // correctly reflect the incoming BufferQueue's contents, so even if + // updateTexImage starts working, the only safe course of action is + // to continue to ignore updates. + mUpdateTexImageFailed = true; + + return BAD_VALUE; + } + + if (queuedBuffer) { + // Autolock scope + auto currentFrameNumber = mConsumer->getFrameNumber(); + + Mutex::Autolock lock(mQueueItemLock); + + // Remove any stale buffers that have been dropped during + // updateTexImage + while (mQueueItems[0].mFrameNumber != currentFrameNumber) { + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); + mQueueItems.removeAt(0); + android_atomic_dec(&mQueuedFrames); + } + + const std::string layerName(getName().c_str()); + mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime); + mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime); + + mQueueItems.removeAt(0); + } + + // Decrement the queued-frames count. Signal another event if we + // have more frames pending. + if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || mAutoRefresh) { + mFlinger->signalLayerUpdate(); + } + + return NO_ERROR; +} + +status_t BufferQueueLayer::updateActiveBuffer() { + // update the active buffer + mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot); + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; + + if (mActiveBuffer == nullptr) { + // this can only happen if the very first buffer was rejected. + return BAD_VALUE; + } + return NO_ERROR; +} + +status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { + mPreviousFrameNumber = mCurrentFrameNumber; + mCurrentFrameNumber = mConsumer->getFrameNumber(); + + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); + } + return NO_ERROR; +} + +void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) { + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + + uint32_t hwcSlot = 0; + sp<GraphicBuffer> hwcBuffer; + hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); + + auto acquireFence = mConsumer->getCurrentFence(); + auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), + static_cast<int32_t>(error)); + } +} + +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayerConsumer::ContentsChangedListener +// ----------------------------------------------------------------------- + +void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { + // Add this buffer from our internal queue tracker + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + // Reset the frame number tracker when we receive the first buffer after + // a frame number reset + if (item.mFrameNumber == 1) { + mLastFrameNumberReceived = 0; + } + + // Ensure that callbacks are handled in order + while (item.mFrameNumber != mLastFrameNumberReceived + 1) { + status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); + if (result != NO_ERROR) { + ALOGE("[%s] Timed out waiting on callback", mName.string()); + } + } + + mQueueItems.push_back(item); + android_atomic_inc(&mQueuedFrames); + + // Wake up any pending callbacks + mLastFrameNumberReceived = item.mFrameNumber; + mQueueItemCondition.broadcast(); + } + + mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), + item.mGraphicBuffer->getHeight(), item.mFrameNumber); + mFlinger->signalLayerUpdate(); +} + +void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + + // Ensure that callbacks are handled in order + while (item.mFrameNumber != mLastFrameNumberReceived + 1) { + status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); + if (result != NO_ERROR) { + ALOGE("[%s] Timed out waiting on callback", mName.string()); + } + } + + if (!hasDrawingBuffer()) { + ALOGE("Can't replace a frame on an empty queue"); + return; + } + mQueueItems.editItemAt(mQueueItems.size() - 1) = item; + + // Wake up any pending callbacks + mLastFrameNumberReceived = item.mFrameNumber; + mQueueItemCondition.broadcast(); + } +} + +void BufferQueueLayer::onSidebandStreamChanged() { + if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } +} + +// ----------------------------------------------------------------------- + +void BufferQueueLayer::onFirstRef() { + BufferLayer::onFirstRef(); + + // Creates a custom BufferQueue for SurfaceFlingerConsumer to use + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer, true); + mProducer = new MonitoredProducer(producer, mFlinger, this); + { + // Grab the SF state lock during this since it's the only safe way to access RenderEngine + Mutex::Autolock lock(mFlinger->mStateLock); + mConsumer = + new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); + } + mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + mConsumer->setContentsChangedListener(this); + mConsumer->setName(mName); + + if (mFlinger->isLayerTripleBufferingDisabled()) { + mProducer->setMaxDequeuedBufferCount(2); + } +} + +status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) { + uint32_t const maxSurfaceDims = + min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); + + // never allow a surface larger than what our underlying GL implementation + // can handle. + if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) { + ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); + return BAD_VALUE; + } + + mFormat = format; + + setDefaultBufferSize(w, h); + mConsumer->setDefaultBufferFormat(format); + mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + + return NO_ERROR; +} + +sp<IGraphicBufferProducer> BufferQueueLayer::getProducer() const { + return mProducer; +} + +uint32_t BufferQueueLayer::getProducerStickyTransform() const { + int producerStickyTransform = 0; + int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform); + if (ret != OK) { + ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__, + strerror(-ret), ret); + return 0; + } + return static_cast<uint32_t>(producerStickyTransform); +} + +} // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h new file mode 100644 index 0000000000..579ed81f7e --- /dev/null +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BufferLayer.h" + +#include <utils/String8.h> + +namespace android { + +/* + * A new BufferQueue and a new BufferLayerConsumer are created when the + * BufferLayer is first referenced. + * + * This also implements onFrameAvailable(), which notifies SurfaceFlinger + * that new data has arrived. + */ +class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener { +public: + BufferQueueLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags); + + // ----------------------------------------------------------------------- + // Interface implementation for Layer + // ----------------------------------------------------------------------- +public: + void onLayerDisplayed(const sp<Fence>& releaseFence) override; + + void abandon() override; + + void setTransformHint(uint32_t orientation) const override; + + std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override; + + bool getTransformToDisplayInverse() const override; + + // If a buffer was replaced this frame, release the former buffer + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; + + void setDefaultBufferSize(uint32_t w, uint32_t h) override; + + int32_t getQueuedFrameCount() const override; + + bool shouldPresentNow(const DispSync& dispSync) const override; + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayer + // ----------------------------------------------------------------------- +public: + bool fenceHasSignaled() const override; + +private: + nsecs_t getDesiredPresentTime() override; + std::shared_ptr<FenceTime> getCurrentFenceTime() const override; + + void getDrawingTransformMatrix(float *matrix) override; + uint32_t getDrawingTransform() const override; + ui::Dataspace getDrawingDataSpace() const override; + Rect getDrawingCrop() const override; + uint32_t getDrawingScalingMode() const override; + Region getDrawingSurfaceDamage() const override; + const HdrMetadata& getDrawingHdrMetadata() const override; + int getDrawingApi() const override; + PixelFormat getPixelFormat() const override; + + uint64_t getFrameNumber() const override; + + bool getAutoRefresh() const override; + bool getSidebandStreamChanged() const override; + + std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override; + + bool hasDrawingBuffer() const override; + + void setFilteringEnabled(bool enabled) override; + + status_t bindTextureImage() const override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + + status_t updateActiveBuffer() override; + status_t updateFrameNumber(nsecs_t latchTime) override; + + void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override; + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayerConsumer::ContentsChangedListener + // ----------------------------------------------------------------------- +protected: + void onFrameAvailable(const BufferItem& item) override; + void onFrameReplaced(const BufferItem& item) override; + void onSidebandStreamChanged() override; + // ----------------------------------------------------------------------- + +public: + status_t setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format); + + sp<IGraphicBufferProducer> getProducer() const; + +private: + // Temporary - Used only for LEGACY camera mode. + uint32_t getProducerStickyTransform() const; + + void onFirstRef() override; + + sp<BufferLayerConsumer> mConsumer; + sp<IGraphicBufferProducer> mProducer; + + PixelFormat mFormat; + + // Only accessed on the main thread. + uint64_t mPreviousFrameNumber; + bool mUpdateTexImageFailed; + + // Local copy of the queued contents of the incoming BufferQueue + mutable Mutex mQueueItemLock; + Condition mQueueItemCondition; + Vector<BufferItem> mQueueItems; + std::atomic<uint64_t> mLastFrameNumberReceived; + + bool mAutoRefresh; + int mActiveBufferSlot; + + // thread-safe + volatile int32_t mQueuedFrames; + volatile int32_t mSidebandStreamChanged; // used like an atomic boolean +}; + +} // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp new file mode 100644 index 0000000000..44fa760ec5 --- /dev/null +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -0,0 +1,547 @@ +/* + * Copyright (C) 2017 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 LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "BufferStateLayer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BufferStateLayer.h" +#include "RenderEngine/Image.h" +#include "clz.h" + +#include <private/gui/SyncFeatures.h> + +namespace android { + +static const std::array<float, 16> IDENTITY_MATRIX{1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + +BufferStateLayer::BufferStateLayer(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : BufferLayer(flinger, client, name, w, h, flags), + mSidebandStreamChanged(false), + mFrameNumber(0) { + mTransformMatrix = IDENTITY_MATRIX; +} + +// ----------------------------------------------------------------------- +// Interface implementation for Layer +// ----------------------------------------------------------------------- +void BufferStateLayer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) { + // TODO(marissaw): send the release fence back to buffer owner + return; +} + +void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { + // TODO(marissaw): send the transform hint to buffer owner + return; +} + +void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { + // TODO(marissaw): use this to signal the buffer owner + return; +} + +bool BufferStateLayer::shouldPresentNow(const DispSync& /*dispSync*/) const { + if (getSidebandStreamChanged() || getAutoRefresh()) { + return true; + } + + return hasDrawingBuffer(); +} + +bool BufferStateLayer::getTransformToDisplayInverse() const { + return mCurrentState.transformToDisplayInverse; +} + +void BufferStateLayer::pushPendingState() { + if (!mCurrentState.modified) { + return; + } + mPendingStates.push_back(mCurrentState); + ATRACE_INT(mTransactionName.string(), mPendingStates.size()); +} + +bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { + const bool stateUpdateAvailable = !mPendingStates.empty(); + while (!mPendingStates.empty()) { + popPendingState(stateToCommit); + } + mCurrentState.modified = false; + return stateUpdateAvailable; +} + +Rect BufferStateLayer::getCrop(const Layer::State& s) const { + return (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) + ? GLConsumer::scaleDownCrop(s.crop, s.active.w, s.active.h) + : s.crop; +} + +bool BufferStateLayer::setTransform(uint32_t transform) { + if (mCurrentState.transform == transform) return false; + mCurrentState.sequence++; + mCurrentState.transform = transform; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) { + if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false; + mCurrentState.sequence++; + mCurrentState.transformToDisplayInverse = transformToDisplayInverse; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setCrop(const Rect& crop) { + if (mCurrentState.crop == crop) return false; + mCurrentState.sequence++; + mCurrentState.crop = crop; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setBuffer(sp<GraphicBuffer> buffer) { + mCurrentState.sequence++; + mCurrentState.buffer = buffer; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) { + mCurrentState.acquireFence = fence; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) { + if (mCurrentState.dataspace == dataspace) return false; + mCurrentState.sequence++; + mCurrentState.dataspace = dataspace; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) { + if (mCurrentState.hdrMetadata == hdrMetadata) return false; + mCurrentState.sequence++; + mCurrentState.hdrMetadata = hdrMetadata; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) { + mCurrentState.sequence++; + mCurrentState.surfaceDamageRegion = surfaceDamage; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setApi(int32_t api) { + if (mCurrentState.api == api) return false; + mCurrentState.sequence++; + mCurrentState.api = api; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) { + if (mCurrentState.sidebandStream == sidebandStream) return false; + mCurrentState.sequence++; + mCurrentState.sidebandStream = sidebandStream; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + + if (!mSidebandStreamChanged.exchange(true)) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } + return true; +} + +bool BufferStateLayer::setSize(uint32_t w, uint32_t h) { + if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false; + mCurrentState.active.w = w; + mCurrentState.active.h = h; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setPosition(float x, float y, bool /*immediate*/) { + if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y) + return false; + + mCurrentState.active.transform.set(x, y); + + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { + mCurrentState.transparentRegionHint = transparent; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) { + Transform t; + t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + + if (!allowNonRectPreservingTransforms && !t.preserveRects()) { + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored"); + return false; + } + + mCurrentState.sequence++; + mCurrentState.active.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} +// ----------------------------------------------------------------------- + +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayer +// ----------------------------------------------------------------------- +bool BufferStateLayer::fenceHasSignaled() const { + if (latchUnsignaledBuffers()) { + return true; + } + + return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled; +} + +nsecs_t BufferStateLayer::getDesiredPresentTime() { + // TODO(marissaw): support an equivalent to desiredPresentTime for timestats metrics + return 0; +} + +std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const { + return std::make_shared<FenceTime>(getDrawingState().acquireFence); +} + +void BufferStateLayer::getDrawingTransformMatrix(float *matrix) { + std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix); +} + +uint32_t BufferStateLayer::getDrawingTransform() const { + return getDrawingState().transform; +} + +ui::Dataspace BufferStateLayer::getDrawingDataSpace() const { + return getDrawingState().dataspace; +} + +Rect BufferStateLayer::getDrawingCrop() const { + return Rect::INVALID_RECT; +} + +uint32_t BufferStateLayer::getDrawingScalingMode() const { + return NATIVE_WINDOW_SCALING_MODE_FREEZE; +} + +Region BufferStateLayer::getDrawingSurfaceDamage() const { + return getDrawingState().surfaceDamageRegion; +} + +const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const { + return getDrawingState().hdrMetadata; +} + +int BufferStateLayer::getDrawingApi() const { + return getDrawingState().api; +} + +PixelFormat BufferStateLayer::getPixelFormat() const { + return mActiveBuffer->format; +} + +uint64_t BufferStateLayer::getFrameNumber() const { + return mFrameNumber; +} + +bool BufferStateLayer::getAutoRefresh() const { + // TODO(marissaw): support shared buffer mode + return false; +} + +bool BufferStateLayer::getSidebandStreamChanged() const { + return mSidebandStreamChanged.load(); +} + +std::optional<Region> BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { + if (mSidebandStreamChanged.exchange(false)) { + const State& s(getDrawingState()); + // mSidebandStreamChanged was true + // replicated in LayerBE until FE/BE is ready to be synchronized + getBE().compositionInfo.hwc.sidebandStream = s.sidebandStream; + if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { + setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); + } + recomputeVisibleRegions = true; + + return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + } + return {}; +} + +bool BufferStateLayer::hasDrawingBuffer() const { + return getDrawingState().buffer != nullptr; +} + +void BufferStateLayer::setFilteringEnabled(bool enabled) { + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop, + mCurrentTransform, enabled); +} + +status_t BufferStateLayer::bindTextureImage() const { + const State& s(getDrawingState()); + auto& engine(mFlinger->getRenderEngine()); + + if (!engine.isCurrent()) { + ALOGE("RenderEngine is not current"); + return INVALID_OPERATION; + } + + engine.checkErrors(); + + if (!mTextureImage) { + ALOGE("no currently-bound texture"); + engine.bindExternalTextureImage(mTextureName, *engine.createImage()); + return NO_INIT; + } + + bool created = + mTextureImage->setNativeWindowBuffer(s.buffer->getNativeBuffer(), + s.buffer->getUsage() & GRALLOC_USAGE_PROTECTED); + if (!created) { + ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d", + s.buffer->getWidth(), s.buffer->getHeight(), s.buffer->getStride(), + s.buffer->getUsage(), s.buffer->getPixelFormat()); + engine.bindExternalTextureImage(mTextureName, *engine.createImage()); + return NO_INIT; + } + + engine.bindExternalTextureImage(mTextureName, *mTextureImage); + + // Wait for the new buffer to be ready. + if (s.acquireFence->isValid()) { + if (SyncFeatures::getInstance().useWaitSync()) { + base::unique_fd fenceFd(s.acquireFence->dup()); + if (fenceFd == -1) { + ALOGE("error dup'ing fence fd: %d", errno); + return -errno; + } + if (!engine.waitFence(std::move(fenceFd))) { + ALOGE("failed to wait on fence fd"); + return UNKNOWN_ERROR; + } + } else { + status_t err = s.acquireFence->waitForever("BufferStateLayer::bindTextureImage"); + if (err != NO_ERROR) { + ALOGE("error waiting for fence: %d", err); + return err; + } + } + } + + return NO_ERROR; +} + +status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) { + const State& s(getDrawingState()); + + if (!s.buffer) { + return NO_ERROR; + } + + auto& engine(mFlinger->getRenderEngine()); + if (!engine.isCurrent()) { + ALOGE("RenderEngine is not current"); + return INVALID_OPERATION; + } + engine.checkErrors(); + + // TODO(marissaw): once buffers are cached, don't create a new image everytime + mTextureImage = engine.createImage(); + + // Reject if the layer is invalid + uint32_t bufferWidth = s.buffer->width; + uint32_t bufferHeight = s.buffer->height; + + if (s.transform & Transform::ROT_90) { + swap(bufferWidth, bufferHeight); + } + + if (s.transformToDisplayInverse) { + uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + if (invTransform & Transform::ROT_90) { + swap(bufferWidth, bufferHeight); + } + } + + if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE && + (s.active.w != bufferWidth || s.active.h != bufferHeight)) { + ALOGE("[%s] rejecting buffer: " + "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", + mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); + mTimeStats.removeTimeRecord(getName().c_str(), getFrameNumber()); + return BAD_VALUE; + } + + // Handle sync fences + if (SyncFeatures::getInstance().useNativeFenceSync()) { + base::unique_fd fenceFd = engine.flush(); + if (fenceFd == -1) { + ALOGE("failed to flush RenderEngine"); + mTimeStats.clearLayerRecord(getName().c_str()); + return UNKNOWN_ERROR; + } + + sp<Fence> fence(new Fence(std::move(fenceFd))); + + // Check status of fences first because merging is expensive. + // Merging an invalid fence with any other fence results in an + // invalid fence. + auto currentStatus = s.acquireFence->getStatus(); + if (currentStatus == Fence::Status::Invalid) { + ALOGE("Existing fence has invalid state"); + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + + auto incomingStatus = fence->getStatus(); + if (incomingStatus == Fence::Status::Invalid) { + ALOGE("New fence has invalid state"); + mDrawingState.acquireFence = fence; + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + + // If both fences are signaled or both are unsignaled, we need to merge + // them to get an accurate timestamp. + if (currentStatus == incomingStatus) { + char fenceName[32] = {}; + snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber); + sp<Fence> mergedFence = Fence::merge(fenceName, mDrawingState.acquireFence, fence); + if (!mergedFence.get()) { + ALOGE("failed to merge release fences"); + // synchronization is broken, the best we can do is hope fences + // signal in order so the new fence will act like a union + mDrawingState.acquireFence = fence; + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + mDrawingState.acquireFence = mergedFence; + } else if (incomingStatus == Fence::Status::Unsignaled) { + // If one fence has signaled and the other hasn't, the unsignaled + // fence will approximately correspond with the correct timestamp. + // There's a small race if both fences signal at about the same time + // and their statuses are retrieved with unfortunate timing. However, + // by this point, they will have both signaled and only the timestamp + // will be slightly off; any dependencies after this point will + // already have been met. + mDrawingState.acquireFence = fence; + } + } else { + // Bind the new buffer to the GL texture. + // + // Older devices require the "implicit" synchronization provided + // by glEGLImageTargetTexture2DOES, which this method calls. Newer + // devices will either call this in Layer::onDraw, or (if it's not + // a GL-composited layer) not at all. + status_t err = bindTextureImage(); + if (err != NO_ERROR) { + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + } + + // TODO(marissaw): properly support mTimeStats + const std::string layerName(getName().c_str()); + mTimeStats.setPostTime(getName().c_str(), getFrameNumber(), latchTime); + mTimeStats.setAcquireFence(layerName, getFrameNumber(), getCurrentFenceTime()); + mTimeStats.setLatchTime(layerName, getFrameNumber(), latchTime); + + return NO_ERROR; +} + +status_t BufferStateLayer::updateActiveBuffer() { + const State& s(getDrawingState()); + + if (s.buffer == nullptr) { + return BAD_VALUE; + } + + mActiveBuffer = s.buffer; + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.mBufferSlot = 0; + + return NO_ERROR; +} + +status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { + // TODO(marissaw): support frame history events + mCurrentFrameNumber = mFrameNumber; + return NO_ERROR; +} + +void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) { + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + + const State& s(getDrawingState()); + + // TODO(marissaw): support more than one slot + uint32_t hwcSlot = 0; + + auto error = hwcLayer->setBuffer(hwcSlot, s.buffer, s.acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + s.buffer->handle, to_string(error).c_str(), static_cast<int32_t>(error)); + } + + mFrameNumber++; +} + +void BufferStateLayer::onFirstRef() { + BufferLayer::onFirstRef(); + + if (const auto display = mFlinger->getDefaultDisplayDevice()) { + updateTransformHint(display); + } +} + +} // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h new file mode 100644 index 0000000000..4d7396ef81 --- /dev/null +++ b/services/surfaceflinger/BufferStateLayer.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "RenderEngine/Image.h" +#include "RenderEngine/RenderEngine.h" + +#include "BufferLayer.h" +#include "Layer.h" + +#include <gui/GLConsumer.h> +#include <system/window.h> +#include <utils/String8.h> + +namespace android { + +class BufferStateLayer : public BufferLayer { +public: + BufferStateLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags); + + // ----------------------------------------------------------------------- + // Interface implementation for Layer + // ----------------------------------------------------------------------- + void onLayerDisplayed(const sp<Fence>& releaseFence) override; + void setTransformHint(uint32_t orientation) const override; + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; + + bool shouldPresentNow(const DispSync& dispSync) const override; + + bool getTransformToDisplayInverse() const override; + + uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { + return flags; + } + void pushPendingState() override; + bool applyPendingStates(Layer::State* stateToCommit) override; + + uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; } + uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; } + Transform getActiveTransform(const Layer::State& s) const override { + return s.active.transform; + } + Region getActiveTransparentRegion(const Layer::State& s) const override { + return s.transparentRegionHint; + } + Rect getCrop(const Layer::State& s) const; + Rect getFinalCrop(const Layer::State& /*s*/) const { return Rect::EMPTY_RECT; } + + bool setTransform(uint32_t transform) override; + bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; + bool setCrop(const Rect& crop) override; + bool setBuffer(sp<GraphicBuffer> buffer) override; + bool setAcquireFence(const sp<Fence>& fence) override; + bool setDataspace(ui::Dataspace dataspace) override; + bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; + bool setSurfaceDamageRegion(const Region& surfaceDamage) override; + bool setApi(int32_t api) override; + bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override; + + bool setSize(uint32_t w, uint32_t h) override; + bool setPosition(float x, float y, bool immediate) override; + bool setTransparentRegionHint(const Region& transparent) override; + bool setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) override; + + // Override to ignore legacy layer state properties that are not used by BufferStateLayer + bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; + bool setFinalCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; + void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/, + uint64_t /*frameNumber*/) override {} + void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/, + uint64_t /*frameNumber*/) override {} + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayer + // ----------------------------------------------------------------------- + bool fenceHasSignaled() const override; + +private: + nsecs_t getDesiredPresentTime() override; + std::shared_ptr<FenceTime> getCurrentFenceTime() const override; + + void getDrawingTransformMatrix(float *matrix) override; + uint32_t getDrawingTransform() const override; + ui::Dataspace getDrawingDataSpace() const override; + Rect getDrawingCrop() const override; + uint32_t getDrawingScalingMode() const override; + Region getDrawingSurfaceDamage() const override; + const HdrMetadata& getDrawingHdrMetadata() const override; + int getDrawingApi() const override; + PixelFormat getPixelFormat() const override; + + uint64_t getFrameNumber() const override; + + bool getAutoRefresh() const override; + bool getSidebandStreamChanged() const override; + + std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override; + + bool hasDrawingBuffer() const override; + + void setFilteringEnabled(bool enabled) override; + + status_t bindTextureImage() const override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + + status_t updateActiveBuffer() override; + status_t updateFrameNumber(nsecs_t latchTime) override; + + void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override; + // ----------------------------------------------------------------------- +private: + void onFirstRef() override; + + std::unique_ptr<RE::Image> mTextureImage; + + std::array<float, 16> mTransformMatrix; + + std::atomic<bool> mSidebandStreamChanged; + + uint32_t mFrameNumber; + + // TODO(marissaw): support sticky transform for LEGACY camera mode +}; + +} // namespace android diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 512564c2db..bac46a38b4 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -43,30 +43,45 @@ ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const } void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, - bool useIdentityTransform) const { + bool useIdentityTransform) { half4 color = getColor(); if (color.a > 0) { - Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); - computeGeometry(renderArea, mesh, useIdentityTransform); - auto& engine(mFlinger->getRenderEngine()); - engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, - true /* disableTexture */, color); - engine.drawMesh(mesh); - engine.disableBlending(); + computeGeometry(renderArea, getBE().mMesh, useIdentityTransform); + getBE().compositionInfo.re.preMultipliedAlpha = getPremultipledAlpha(); + getBE().compositionInfo.re.opaque = false; + getBE().compositionInfo.re.disableTexture = true; + getBE().compositionInfo.re.color = color; } } +void ColorLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) { + CompositionInfo& compositionInfo = getBE().compositionInfo; + auto& engine(mFlinger->getRenderEngine()); + + draw(renderArea, useIdentityTransform); + + engine.setupLayerBlending(compositionInfo.re.preMultipliedAlpha, compositionInfo.re.opaque, + compositionInfo.re.disableTexture, compositionInfo.re.color); + engine.setSourceDataSpace(compositionInfo.hwc.dataspace); + engine.drawMesh(getBE().getMesh()); + engine.disableBlending(); +} + bool ColorLayer::isVisible() const { - const Layer::State& s(getDrawingState()); - return !isHiddenByPolicy() && s.color.a; + return !isHiddenByPolicy() && getAlpha() > 0.0f; } -void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) { - const Transform& tr = displayDevice->getTransform(); - const auto& viewport = displayDevice->getViewport(); +void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& display) { + const Transform& tr = display->getTransform(); + const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); - auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); if (error != HWC2::Error::None) { @@ -75,7 +90,7 @@ void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) { visible.dump(LOG_TAG); } - setCompositionType(hwcId, HWC2::Composition::SolidColor); + setCompositionType(displayId, HWC2::Composition::SolidColor); error = hwcLayer->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 0cde398ce9..429ad79a05 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -31,10 +31,14 @@ public: virtual const char* getTypeId() const { return "ColorLayer"; } virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const; + bool useIdentityTransform); + void drawNow(const RenderArea&, bool); bool isVisible() const override; - void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override; + void setPerFrameData(const sp<const DisplayDevice>& display) override; + +protected: + FloatRect computeCrop(const sp<const DisplayDevice>& /*display*/) const override { return {}; } }; } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index f259d93c3f..5ad5d562a8 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -28,7 +28,9 @@ ContainerLayer::ContainerLayer(SurfaceFlinger* flinger, const sp<Client>& client mDrawingState = mCurrentState; } -void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {} +void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) {} + +void ContainerLayer::drawNow(const RenderArea&, bool) {} bool ContainerLayer::isVisible() const { return !isHiddenByPolicy(); diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index b352b96762..051e76523c 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -31,10 +31,11 @@ public: const char* getTypeId() const override { return "ContainerLayer"; } void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const override; + bool useIdentityTransform) override; + void drawNow(const RenderArea& renderArea, bool useIdentityTransform) override; bool isVisible() const override; - void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override; + void setPerFrameData(const sp<const DisplayDevice>& display) override; bool isCreatedFromMainThread() const override { return true; } }; diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 37dc27d80d..cdfbba32dd 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -28,7 +28,6 @@ #include <utils/String8.h> #include <utils/Thread.h> #include <utils/Trace.h> -#include <utils/Vector.h> #include <ui/FenceTime.h> @@ -41,6 +40,10 @@ using std::min; namespace android { +DispSync::~DispSync() = default; + +namespace impl { + // Setting this to true enables verbose tracing that can be used to debug // vsync event model or phase issues. static const bool kTraceDetailedInfo = false; @@ -94,7 +97,7 @@ public: nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); while (true) { - Vector<CallbackInvocation> callbackInvocations; + std::vector<CallbackInvocation> callbackInvocations; nsecs_t targetTime = 0; @@ -187,7 +190,7 @@ public: // allowing any past events to fire listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase - mWakeupLatency; - mEventListeners.push(listener); + mEventListeners.push_back(listener); mCond.signal(); @@ -198,9 +201,10 @@ public: if (kTraceDetailedInfo) ATRACE_CALL(); Mutex::Autolock lock(mMutex); - for (size_t i = 0; i < mEventListeners.size(); i++) { - if (mEventListeners[i].mCallback == callback) { - mEventListeners.removeAt(i); + for (std::vector<EventListener>::iterator it = mEventListeners.begin(); + it != mEventListeners.end(); ++it) { + if (it->mCallback == callback) { + mEventListeners.erase(it); mCond.signal(); return NO_ERROR; } @@ -213,11 +217,10 @@ public: if (kTraceDetailedInfo) ATRACE_CALL(); Mutex::Autolock lock(mMutex); - for (size_t i = 0; i < mEventListeners.size(); i++) { - if (mEventListeners[i].mCallback == callback) { - EventListener& listener = mEventListeners.editItemAt(i); - const nsecs_t oldPhase = listener.mPhase; - listener.mPhase = phase; + for (auto& eventListener : mEventListeners) { + if (eventListener.mCallback == callback) { + const nsecs_t oldPhase = eventListener.mPhase; + eventListener.mPhase = phase; // Pretend that the last time this event was handled at the same frame but with the // new offset to allow for a seamless offset change without double-firing or @@ -228,7 +231,7 @@ public: } else if (diff < -mPeriod / 2) { diff += mPeriod; } - listener.mLastEventTime -= diff; + eventListener.mLastEventTime -= diff; mCond.signal(); return NO_ERROR; } @@ -237,14 +240,6 @@ public: return BAD_VALUE; } - // This method is only here to handle the !SurfaceFlinger::hasSyncFramework - // case. - bool hasAnyEventListeners() { - if (kTraceDetailedInfo) ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - return !mEventListeners.empty(); - } - private: struct EventListener { const char* mName; @@ -274,23 +269,23 @@ private: return nextEventTime; } - Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) { + std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) { if (kTraceDetailedInfo) ATRACE_CALL(); ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now)); - Vector<CallbackInvocation> callbackInvocations; + std::vector<CallbackInvocation> callbackInvocations; nsecs_t onePeriodAgo = now - mPeriod; - for (size_t i = 0; i < mEventListeners.size(); i++) { - nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i], onePeriodAgo); + for (auto& eventListener : mEventListeners) { + nsecs_t t = computeListenerNextEventTimeLocked(eventListener, onePeriodAgo); if (t < now) { CallbackInvocation ci; - ci.mCallback = mEventListeners[i].mCallback; + ci.mCallback = eventListener.mCallback; ci.mEventTime = t; - ALOGV("[%s] [%s] Preparing to fire", mName, mEventListeners[i].mName); - callbackInvocations.push(ci); - mEventListeners.editItemAt(i).mLastEventTime = t; + ALOGV("[%s] [%s] Preparing to fire", mName, eventListener.mName); + callbackInvocations.push_back(ci); + eventListener.mLastEventTime = t; } } @@ -348,7 +343,7 @@ private: return t; } - void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) { + void fireCallbackInvocations(const std::vector<CallbackInvocation>& callbacks) { if (kTraceDetailedInfo) ATRACE_CALL(); for (size_t i = 0; i < callbacks.size(); i++) { callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime); @@ -366,7 +361,7 @@ private: int64_t mFrameNumber; - Vector<EventListener> mEventListeners; + std::vector<EventListener> mEventListeners; Mutex mMutex; Condition mCond; @@ -408,22 +403,18 @@ void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) { reset(); beginResync(); - if (kTraceDetailedInfo) { - // If we're not getting present fences then the ZeroPhaseTracer - // would prevent HW vsync event from ever being turned off. - // Even if we're just ignoring the fences, the zero-phase tracing is - // not needed because any time there is an event registered we will - // turn on the HW vsync events. - if (!mIgnorePresentFences && kEnableZeroPhaseTracer) { - mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>(); - addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get()); - } + if (kTraceDetailedInfo && kEnableZeroPhaseTracer) { + mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>(); + addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get()); } } void DispSync::reset() { Mutex::Autolock lock(mMutex); + resetLocked(); +} +void DispSync::resetLocked() { mPhase = 0; mReferenceTime = 0; mModelUpdated = false; @@ -436,6 +427,10 @@ void DispSync::reset() { bool DispSync::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) { Mutex::Autolock lock(mMutex); + if (mIgnorePresentFences) { + return true; + } + mPresentFences[mPresentSampleOffset] = fenceTime; mPresentSampleOffset = (mPresentSampleOffset + 1) % NUM_PRESENT_SAMPLES; mNumResyncSamplesSincePresent = 0; @@ -481,12 +476,10 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { } if (mIgnorePresentFences) { - // If we don't have the sync framework we will never have - // addPresentFence called. This means we have no way to know whether + // If we're ignoring the present fences we have no way to know whether // or not we're synchronized with the HW vsyncs, so we just request - // that the HW vsync events be turned on whenever we need to generate - // SW vsync events. - return mThread->hasAnyEventListeners(); + // that the HW vsync events be turned on. + return true; } // Check against kErrorThreshold / 2 to add some hysteresis before having to @@ -660,6 +653,14 @@ nsecs_t DispSync::computeNextRefresh(int periodOffset) const { return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase; } +void DispSync::setIgnorePresentFences(bool ignore) { + Mutex::Autolock lock(mMutex); + if (mIgnorePresentFences != ignore) { + mIgnorePresentFences = ignore; + resetLocked(); + } +} + void DispSync::dump(String8& result) const { Mutex::Autolock lock(mMutex); result.appendFormat("present fences are %s\n", mIgnorePresentFences ? "ignored" : "used"); @@ -710,4 +711,6 @@ void DispSync::dump(String8& result) const { result.appendFormat("current monotonic time: %" PRId64 "\n", now); } +} // namespace impl + } // namespace android diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index 077256ac11..1be131ff6e 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -31,6 +31,36 @@ namespace android { class String8; class FenceTime; + +class DispSync { +public: + class Callback { + public: + virtual ~Callback() = default; + virtual void onDispSyncEvent(nsecs_t when) = 0; + }; + + virtual ~DispSync(); + + virtual void reset() = 0; + virtual bool addPresentFence(const std::shared_ptr<FenceTime>&) = 0; + virtual void beginResync() = 0; + virtual bool addResyncSample(nsecs_t timestamp) = 0; + virtual void endResync() = 0; + virtual void setPeriod(nsecs_t period) = 0; + virtual nsecs_t getPeriod() = 0; + virtual void setRefreshSkipCount(int count) = 0; + virtual status_t addEventListener(const char* name, nsecs_t phase, Callback* callback) = 0; + virtual status_t removeEventListener(Callback* callback) = 0; + virtual status_t changePhaseOffset(Callback* callback, nsecs_t phase) = 0; + virtual nsecs_t computeNextRefresh(int periodOffset) const = 0; + virtual void setIgnorePresentFences(bool ignore) = 0; + + virtual void dump(String8& result) const = 0; +}; + +namespace impl { + class DispSyncThread; // DispSync maintains a model of the periodic hardware-based vsync events of a @@ -46,21 +76,15 @@ class DispSyncThread; // current model accurately represents the hardware event times it will return // false to indicate that a resynchronization (via addResyncSample) is not // needed. -class DispSync { +class DispSync : public android::DispSync { public: - class Callback { - public: - virtual ~Callback(){}; - virtual void onDispSyncEvent(nsecs_t when) = 0; - }; - explicit DispSync(const char* name); - ~DispSync(); + ~DispSync() override; void init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset); // reset clears the resync samples and error value. - void reset(); + void reset() override; // addPresentFence adds a fence for use in validating the current vsync // event model. The fence need not be signaled at the time @@ -71,7 +95,7 @@ public: // // This method should be called with the retire fence from each HWComposer // set call that affects the display. - bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime); + bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) override; // The beginResync, addResyncSample, and endResync methods are used to re- // synchronize the DispSync's model to the hardware vsync events. The re- @@ -84,52 +108,61 @@ public: // is turned on (i.e. once immediately after it's turned on) and whenever // addPresentFence returns true indicating that the model has drifted away // from the hardware vsync events. - void beginResync(); - bool addResyncSample(nsecs_t timestamp); - void endResync(); + void beginResync() override; + bool addResyncSample(nsecs_t timestamp) override; + void endResync() override; // The setPeriod method sets the vsync event model's period to a specific // value. This should be used to prime the model when a display is first // turned on. It should NOT be used after that. - void setPeriod(nsecs_t period); + void setPeriod(nsecs_t period) override; // The getPeriod method returns the current vsync period. - nsecs_t getPeriod(); + nsecs_t getPeriod() override; // setRefreshSkipCount specifies an additional number of refresh // cycles to skip. For example, on a 60Hz display, a skip count of 1 // will result in events happening at 30Hz. Default is zero. The idea // is to sacrifice smoothness for battery life. - void setRefreshSkipCount(int count); + void setRefreshSkipCount(int count) override; // addEventListener registers a callback to be called repeatedly at the // given phase offset from the hardware vsync events. The callback is // called from a separate thread and it should return reasonably quickly // (i.e. within a few hundred microseconds). - status_t addEventListener(const char* name, nsecs_t phase, Callback* callback); + status_t addEventListener(const char* name, nsecs_t phase, Callback* callback) override; // removeEventListener removes an already-registered event callback. Once // this method returns that callback will no longer be called by the // DispSync object. - status_t removeEventListener(Callback* callback); + status_t removeEventListener(Callback* callback) override; // changePhaseOffset changes the phase offset of an already-registered event callback. The // method will make sure that there is no skipping or double-firing on the listener per frame, // even when changing the offsets multiple times. - status_t changePhaseOffset(Callback* callback, nsecs_t phase); + status_t changePhaseOffset(Callback* callback, nsecs_t phase) override; // computeNextRefresh computes when the next refresh is expected to begin. // The periodOffset value can be used to move forward or backward; an // offset of zero is the next refresh, -1 is the previous refresh, 1 is // the refresh after next. etc. - nsecs_t computeNextRefresh(int periodOffset) const; + nsecs_t computeNextRefresh(int periodOffset) const override; + + // In certain situations the present fences aren't a good indicator of vsync + // time, e.g. when vr flinger is active, or simply aren't available, + // e.g. when the sync framework isn't present. Use this method to toggle + // whether or not DispSync ignores present fences. If present fences are + // ignored, DispSync will always ask for hardware vsync events by returning + // true from addPresentFence() and addResyncSample(). + void setIgnorePresentFences(bool ignore) override; // dump appends human-readable debug info to the result string. - void dump(String8& result) const; + void dump(String8& result) const override; private: void updateModelLocked(); void updateErrorLocked(); + void resetLocked(); void resetErrorLocked(); enum { MAX_RESYNC_SAMPLES = 32 }; @@ -197,6 +230,8 @@ private: std::unique_ptr<Callback> mZeroPhaseTracer; }; +} // namespace impl + } // namespace android #endif // ANDROID_DISPSYNC_H diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index db095a51d9..4d2b0eacaa 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -216,7 +216,7 @@ RenderIntent getHwcRenderIntent(const std::vector<RenderIntent>& hwcIntents, Ren DisplayDevice::DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, - int32_t hwcId, + int32_t id, bool isSecure, const wp<IBinder>& displayToken, const sp<ANativeWindow>& nativeWindow, @@ -232,7 +232,7 @@ DisplayDevice::DisplayDevice( : lastCompositionHadVisibleLayers(false), mFlinger(flinger), mType(type), - mHwcDisplayId(hwcId), + mId(id), mDisplayToken(displayToken), mNativeWindow(nativeWindow), mDisplaySurface(displaySurface), @@ -301,9 +301,9 @@ DisplayDevice::DisplayDevice( DisplayDevice::~DisplayDevice() = default; void DisplayDevice::disconnect(HWComposer& hwc) { - if (mHwcDisplayId >= 0) { - hwc.disconnectDisplay(mHwcDisplayId); - mHwcDisplayId = -1; + if (mId >= 0) { + hwc.disconnectDisplay(mId); + mId = -1; } } @@ -319,8 +319,8 @@ int DisplayDevice::getHeight() const { return mDisplayHeight; } -void DisplayDevice::setDisplayName(const String8& displayName) { - if (!displayName.isEmpty()) { +void DisplayDevice::setDisplayName(const std::string& displayName) { + if (!displayName.empty()) { // never override the name with an empty name mDisplayName = displayName; } @@ -347,8 +347,8 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc) { } DisplaySurface::CompositionType compositionType; - bool hasClient = hwc.hasClientComposition(mHwcDisplayId); - bool hasDevice = hwc.hasDeviceComposition(mHwcDisplayId); + bool hasClient = hwc.hasClientComposition(mId); + bool hasDevice = hwc.hasDeviceComposition(mId); if (hasClient && hasDevice) { compositionType = DisplaySurface::COMPOSITION_MIXED; } else if (hasClient) { @@ -365,14 +365,13 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc) { } void DisplayDevice::swapBuffers(HWComposer& hwc) const { - if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) { + if (hwc.hasClientComposition(mId) || hwc.hasFlipClientTargetRequest(mId)) { mSurface->swapBuffers(); } status_t result = mDisplaySurface->advanceFrame(); if (result != NO_ERROR) { - ALOGE("[%s] failed pushing new frame to HWC: %d", - mDisplayName.string(), result); + ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplayName.c_str(), result); } } @@ -437,8 +436,8 @@ int DisplayDevice::getPowerMode() const { return mPowerMode; } -bool DisplayDevice::isDisplayOn() const { - return (mPowerMode != HWC_POWER_MODE_OFF); +bool DisplayDevice::isPoweredOn() const { + return mPowerMode != HWC_POWER_MODE_OFF; } // ---------------------------------------------------------------------------- @@ -631,7 +630,7 @@ void DisplayDevice::setProjection(int orientation, } mOrientation = orientation; - if (mType == DisplayType::DISPLAY_PRIMARY) { + if (isPrimary()) { uint32_t transform = 0; switch (mOrientation) { case DisplayState::eOrientationDefault: @@ -660,11 +659,11 @@ uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() { void DisplayDevice::dump(String8& result) const { const Transform& tr(mGlobalTransform); ANativeWindow* const window = mNativeWindow.get(); - result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string()); - result.appendFormat(" type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p " + result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.c_str()); + result.appendFormat(" type=%x, ID=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p " "(%d:%d:%d:%d), orient=%2d (type=%08x), " "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n", - mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window, + mType, mId, mLayerStack, mDisplayWidth, mDisplayHeight, window, mSurface->queryRedSize(), mSurface->queryGreenSize(), mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation, tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig, @@ -704,7 +703,7 @@ void DisplayDevice::addColorMode( const Dataspace dataspace = colorModeToDataspace(mode); const Dataspace hwcDataspace = colorModeToDataspace(hwcColorMode); - ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mHwcDisplayId, + ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mId, dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(), decodeRenderIntent(intent).c_str(), dataspaceDetails(static_cast<android_dataspace_t>(hwcDataspace)).c_str(), @@ -791,18 +790,6 @@ void DisplayDevice::getBestColorMode(Dataspace dataspace, RenderIntent intent, } } -std::atomic<int32_t> DisplayDeviceState::nextDisplayId(1); - -DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure) - : type(type), - layerStack(DisplayDevice::NO_LAYER_STACK), - orientation(0), - width(0), - height(0), - isSecure(isSecure) -{ - viewport.makeInvalid(); - frame.makeInvalid(); -} +std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1); } // namespace android diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 6c3bd91793..f440d29ad7 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -39,6 +39,7 @@ #include "RenderEngine/Surface.h" #include <memory> +#include <string> struct ANativeWindow; @@ -80,7 +81,7 @@ public: DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, - int32_t hwcId, + int32_t id, bool isSecure, const wp<IBinder>& displayToken, const sp<ANativeWindow>& nativeWindow, @@ -134,7 +135,8 @@ public: uint32_t getLayerStack() const { return mLayerStack; } int32_t getDisplayType() const { return mType; } bool isPrimary() const { return mType == DISPLAY_PRIMARY; } - int32_t getHwcDisplayId() const { return mHwcDisplayId; } + bool isVirtual() const { return mType == DISPLAY_VIRTUAL; } + int32_t getId() const { return mId; } const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } int32_t getSupportedPerFrameMetadata() const { return mSupportedPerFrameMetadata; } @@ -179,8 +181,8 @@ public: } inline Rect bounds() const { return getBounds(); } - void setDisplayName(const String8& displayName); - const String8& getDisplayName() const { return mDisplayName; } + void setDisplayName(const std::string& displayName); + const std::string& getDisplayName() const { return mDisplayName; } bool makeCurrent() const; void setViewportAndProjection() const; @@ -192,7 +194,7 @@ public: */ int getPowerMode() const; void setPowerMode(int mode); - bool isDisplayOn() const; + bool isPoweredOn() const; ui::ColorMode getActiveColorMode() const; void setActiveColorMode(ui::ColorMode mode); @@ -224,7 +226,7 @@ private: */ sp<SurfaceFlinger> mFlinger; DisplayType mType; - int32_t mHwcDisplayId; + int32_t mId; wp<IBinder> mDisplayToken; // ANativeWindow this display is rendering into @@ -235,7 +237,7 @@ private: int mDisplayWidth; int mDisplayHeight; mutable uint32_t mPageFlipCount; - String8 mDisplayName; + std::string mDisplayName; bool mIsSecure; /* @@ -313,15 +315,9 @@ private: }; struct DisplayDeviceState { - DisplayDeviceState() = default; - DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure); + bool isVirtual() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; } - bool isValid() const { return type >= 0; } - bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; } - bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; } - - static std::atomic<int32_t> nextDisplayId; - int32_t displayId = nextDisplayId++; + int32_t sequenceId = sNextSequenceId++; DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_ID_INVALID; sp<IGraphicBufferProducer> surface; uint32_t layerStack = DisplayDevice::NO_LAYER_STACK; @@ -330,8 +326,11 @@ struct DisplayDeviceState { uint8_t orientation = 0; uint32_t width = 0; uint32_t height = 0; - String8 displayName; + std::string displayName; bool isSecure = false; + +private: + static std::atomic<int32_t> sNextSequenceId; }; class DisplayRenderArea : public RenderArea { diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index 37ba4339c3..741eb7cb57 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -22,7 +22,6 @@ #include "ComposerHal.h" -#include <android/hardware/graphics/composer/2.2/IComposer.h> #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> #include <gui/BufferQueue.h> #include <hidl/HidlTransportUtils.h> @@ -172,22 +171,31 @@ Composer::Composer(const std::string& serviceName) LOG_ALWAYS_FATAL("failed to get hwcomposer service"); } - mComposer->createClient( - [&](const auto& tmpError, const auto& tmpClient) - { - if (tmpError == Error::NONE) { - mClient = tmpClient; - } - }); - if (mClient == nullptr) { - LOG_ALWAYS_FATAL("failed to create composer client"); + if (sp<IComposer> composer_2_3 = IComposer::castFrom(mComposer)) { + composer_2_3->createClient_2_3([&](const auto& tmpError, const auto& tmpClient) { + if (tmpError == Error::NONE) { + mClient = tmpClient; + mClient_2_2 = tmpClient; + mClient_2_3 = tmpClient; + } + }); + } else { + mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) { + if (tmpError != Error::NONE) { + return; + } + + mClient = tmpClient; + if (sp<V2_2::IComposer> composer_2_2 = V2_2::IComposer::castFrom(mComposer)) { + mClient_2_2 = V2_2::IComposerClient::castFrom(mClient); + LOG_ALWAYS_FATAL_IF(mClient_2_2 == nullptr, + "IComposer 2.2 did not return IComposerClient 2.2"); + } + }); } - // 2.2 support is optional - sp<IComposer> composer_2_2 = IComposer::castFrom(mComposer); - if (composer_2_2 != nullptr) { - mClient_2_2 = IComposerClient::castFrom(mClient); - LOG_ALWAYS_FATAL_IF(mClient_2_2 == nullptr, "IComposer 2.2 did not return IComposerClient 2.2"); + if (mClient == nullptr) { + LOG_ALWAYS_FATAL("failed to create composer client"); } if (mIsUsingVrComposer) { @@ -897,23 +905,25 @@ Error Composer::setLayerPerFrameMetadata(Display display, Layer layer, return Error::NONE; } -Error Composer::getPerFrameMetadataKeys( - Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) { +std::vector<IComposerClient::PerFrameMetadataKey> Composer::getPerFrameMetadataKeys( + Display display) { + std::vector<IComposerClient::PerFrameMetadataKey> keys; if (!mClient_2_2) { - return Error::UNSUPPORTED; + return keys; } Error error = kDefaultError; mClient_2_2->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) { error = tmpError; if (error != Error::NONE) { + ALOGW("getPerFrameMetadataKeys failed with %d", tmpError); return; } - *outKeys = tmpKeys; + keys = tmpKeys; }); - return error; + return keys; } Error Composer::getRenderIntents(Display display, ColorMode colorMode, @@ -957,6 +967,30 @@ Error Composer::getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatri return error; } +// Composer HAL 2.3 + +Error Composer::getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector<uint8_t>* outData) { + if (!mClient_2_3) { + return Error::UNSUPPORTED; + } + + Error error = kDefaultError; + mClient_2_3->getDisplayIdentificationData(display, + [&](const auto& tmpError, const auto& tmpPort, + const auto& tmpData) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outPort = tmpPort; + *outData = tmpData; + }); + + return error; +} + CommandReader::~CommandReader() { resetData(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index beee53966f..60b0f728ed 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -25,8 +25,8 @@ #include <android/frameworks/vr/composer/1.0/IVrComposerClient.h> #include <android/hardware/graphics/common/1.1/types.h> -#include <android/hardware/graphics/composer/2.2/IComposer.h> -#include <android/hardware/graphics/composer/2.2/IComposerClient.h> +#include <android/hardware/graphics/composer/2.3/IComposer.h> +#include <android/hardware/graphics/composer/2.3/IComposerClient.h> #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> #include <gui/HdrMetadata.h> #include <math/mat4.h> @@ -43,6 +43,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; using types::V1_0::ColorTransform; using types::V1_0::Hdr; @@ -61,8 +62,9 @@ using V2_1::Layer; using V2_2::CommandReaderBase; using V2_2::CommandWriterBase; -using V2_2::IComposer; -using V2_2::IComposerClient; + +using V2_3::IComposer; +using V2_3::IComposerClient; using PerFrameMetadata = IComposerClient::PerFrameMetadata; using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey; @@ -180,11 +182,15 @@ public: virtual Error setLayerPerFrameMetadata( Display display, Layer layer, const std::vector<IComposerClient::PerFrameMetadata>& perFrameMetadatas) = 0; - virtual Error getPerFrameMetadataKeys( - Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0; + virtual std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys( + Display display) = 0; virtual Error getRenderIntents(Display display, ColorMode colorMode, std::vector<RenderIntent>* outRenderIntents) = 0; virtual Error getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatrix) = 0; + + // Composer HAL 2.3 + virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector<uint8_t>* outData) = 0; }; namespace impl { @@ -374,12 +380,16 @@ public: Error setLayerPerFrameMetadata( Display display, Layer layer, const std::vector<IComposerClient::PerFrameMetadata>& perFrameMetadatas) override; - Error getPerFrameMetadataKeys( - Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override; + std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys( + Display display) override; Error getRenderIntents(Display display, ColorMode colorMode, std::vector<RenderIntent>* outRenderIntents) override; Error getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatrix) override; + // Composer HAL 2.3 + Error getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector<uint8_t>* outData) override; + private: class CommandWriter : public CommandWriterBase { public: @@ -405,7 +415,8 @@ private: sp<V2_1::IComposer> mComposer; sp<V2_1::IComposerClient> mClient; - sp<IComposerClient> mClient_2_2; + sp<V2_2::IComposerClient> mClient_2_2; + sp<IComposerClient> mClient_2_3; // 64KiB minus a small space for metadata such as read/write pointers static constexpr size_t kWriterInitialSize = diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp new file mode 100644 index 0000000000..dcc413863e --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp @@ -0,0 +1,185 @@ +/* + * 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. + */ + +#undef LOG_TAG +#define LOG_TAG "DisplayIdentification" + +#include <algorithm> +#include <cctype> +#include <numeric> +#include <optional> + +#include <log/log.h> + +#include "DisplayIdentification.h" + +namespace android { +namespace { + +using byte_view = std::basic_string_view<uint8_t>; + +constexpr size_t kEdidHeaderLength = 5; + +std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) { + if (view.size() < kEdidHeaderLength || view[0] || view[1] || view[2] || view[4]) { + return {}; + } + + return view[3]; +} + +std::string_view parseEdidText(const byte_view& view) { + std::string_view text(reinterpret_cast<const char*>(view.data()), view.size()); + text = text.substr(0, text.find('\n')); + + if (!std::all_of(text.begin(), text.end(), ::isprint)) { + ALOGW("Invalid EDID: ASCII text is not printable."); + return {}; + } + + return text; +} + +// Big-endian 16-bit value encodes three 5-bit letters where A is 0b00001. +template <size_t I> +char getPnpLetter(uint16_t id) { + static_assert(I < 3); + const char letter = 'A' + (static_cast<uint8_t>(id >> ((2 - I) * 5)) & 0b00011111) - 1; + return letter < 'A' || letter > 'Z' ? '\0' : letter; +} + +DisplayId getEdidDisplayId(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash) { + return (static_cast<DisplayId>(manufacturerId) << 40) | + (static_cast<DisplayId>(displayNameHash) << 8) | port; +} + +} // namespace + +bool isEdid(const DisplayIdentificationData& data) { + const uint8_t kMagic[] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0}; + return data.size() >= sizeof(kMagic) && + std::equal(std::begin(kMagic), std::end(kMagic), data.begin()); +} + +std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { + constexpr size_t kMinLength = 128; + if (edid.size() < kMinLength) { + ALOGW("Invalid EDID: structure is truncated."); + // Attempt parsing even if EDID is malformed. + } else { + ALOGW_IF(edid[126] != 0, "EDID extensions are currently unsupported."); + ALOGW_IF(std::accumulate(edid.begin(), edid.begin() + kMinLength, static_cast<uint8_t>(0)), + "Invalid EDID: structure does not checksum."); + } + + constexpr size_t kManufacturerOffset = 8; + if (edid.size() < kManufacturerOffset + sizeof(uint16_t)) { + ALOGE("Invalid EDID: manufacturer ID is truncated."); + return {}; + } + + // Plug and play ID encoded as big-endian 16-bit value. + const uint16_t manufacturerId = + (edid[kManufacturerOffset] << 8) | edid[kManufacturerOffset + 1]; + + const auto pnpId = getPnpId(manufacturerId); + if (!pnpId) { + ALOGE("Invalid EDID: manufacturer ID is not a valid PnP ID."); + return {}; + } + + constexpr size_t kDescriptorOffset = 54; + if (edid.size() < kDescriptorOffset) { + ALOGE("Invalid EDID: descriptors are missing."); + return {}; + } + + byte_view view(edid.data(), edid.size()); + view.remove_prefix(kDescriptorOffset); + + std::string_view displayName; + std::string_view serialNumber; + std::string_view asciiText; + + constexpr size_t kDescriptorCount = 4; + constexpr size_t kDescriptorLength = 18; + + for (size_t i = 0; i < kDescriptorCount; i++) { + if (view.size() < kDescriptorLength) { + break; + } + + if (const auto type = getEdidDescriptorType(view)) { + byte_view descriptor(view.data(), kDescriptorLength); + descriptor.remove_prefix(kEdidHeaderLength); + + switch (*type) { + case 0xfc: + displayName = parseEdidText(descriptor); + break; + case 0xfe: + asciiText = parseEdidText(descriptor); + break; + case 0xff: + serialNumber = parseEdidText(descriptor); + break; + } + } + + view.remove_prefix(kDescriptorLength); + } + + if (displayName.empty()) { + ALOGW("Invalid EDID: falling back to serial number due to missing display name."); + displayName = serialNumber; + } + if (displayName.empty()) { + ALOGW("Invalid EDID: falling back to ASCII text due to missing serial number."); + displayName = asciiText; + } + if (displayName.empty()) { + ALOGE("Invalid EDID: display name and fallback descriptors are missing."); + return {}; + } + + return Edid{manufacturerId, *pnpId, displayName}; +} + +std::optional<PnpId> getPnpId(uint16_t manufacturerId) { + const char a = getPnpLetter<0>(manufacturerId); + const char b = getPnpLetter<1>(manufacturerId); + const char c = getPnpLetter<2>(manufacturerId); + return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt; +} + +std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData& data) { + if (!isEdid(data)) { + ALOGE("Display identification data has unknown format."); + return {}; + } + + const auto edid = parseEdid(data); + if (!edid) { + return {}; + } + + // Hash display name instead of using product code or serial number, since the latter have been + // observed to change on some displays with multiple inputs. + const auto hash = static_cast<uint32_t>(std::hash<std::string_view>()(edid->displayName)); + return getEdidDisplayId(port, edid->manufacturerId, hash); +} + +} // namespace android diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h new file mode 100644 index 0000000000..379f2d3be3 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <array> +#include <cstdint> +#include <optional> +#include <string_view> +#include <vector> + +namespace android { + +using DisplayId = uint64_t; +using DisplayIdentificationData = std::vector<uint8_t>; + +// NUL-terminated plug and play ID. +using PnpId = std::array<char, 4>; + +struct Edid { + uint16_t manufacturerId; + PnpId pnpId; + std::string_view displayName; +}; + +bool isEdid(const DisplayIdentificationData&); +std::optional<Edid> parseEdid(const DisplayIdentificationData&); +std::optional<PnpId> getPnpId(uint16_t manufacturerId); + +std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData&); + +} // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 1a60c83b01..ef31908b09 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -124,6 +124,12 @@ uint32_t Device::getMaxVirtualDisplayCount() const return mComposer->getMaxVirtualDisplayCount(); } +Error Device::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, + std::vector<uint8_t>* outData) const { + auto intError = mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData); + return static_cast<Error>(intError); +} + Error Device::createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, Display** outDisplay) { @@ -403,21 +409,17 @@ Error Display::getColorModes(std::vector<ColorMode>* outModes) const return static_cast<Error>(intError); } -Error Display::getSupportedPerFrameMetadata(int32_t* outSupportedPerFrameMetadata) const +int32_t Display::getSupportedPerFrameMetadata() const { - *outSupportedPerFrameMetadata = 0; - std::vector<Hwc2::PerFrameMetadataKey> tmpKeys; - auto intError = mComposer.getPerFrameMetadataKeys(mId, &tmpKeys); - auto error = static_cast<Error>(intError); - if (error != Error::None) { - return error; - } + int32_t supportedPerFrameMetadata = 0; + + std::vector<Hwc2::PerFrameMetadataKey> tmpKeys = mComposer.getPerFrameMetadataKeys(mId); + std::set<Hwc2::PerFrameMetadataKey> keys(tmpKeys.begin(), tmpKeys.end()); // Check whether a specific metadata type is supported. A metadata type is considered // supported if and only if all required fields are supported. // SMPTE2086 - std::set<Hwc2::PerFrameMetadataKey> keys(tmpKeys.begin(), tmpKeys.end()); if (hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X) && hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y) && hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X) && @@ -428,15 +430,15 @@ Error Display::getSupportedPerFrameMetadata(int32_t* outSupportedPerFrameMetadat hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::WHITE_POINT_Y) && hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MAX_LUMINANCE) && hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MIN_LUMINANCE)) { - *outSupportedPerFrameMetadata |= HdrMetadata::Type::SMPTE2086; + supportedPerFrameMetadata |= HdrMetadata::Type::SMPTE2086; } // CTA861_3 if (hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL) && hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL)) { - *outSupportedPerFrameMetadata |= HdrMetadata::Type::CTA861_3; + supportedPerFrameMetadata |= HdrMetadata::Type::CTA861_3; } - return Error::None; + return supportedPerFrameMetadata; } Error Display::getRenderIntents(ColorMode colorMode, diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index e423167a28..900b3d7304 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -95,6 +95,9 @@ public: }; uint32_t getMaxVirtualDisplayCount() const; + Error getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, + std::vector<uint8_t>* outData) const; + Error createVirtualDisplay(uint32_t width, uint32_t height, android::ui::PixelFormat* format, Display** outDisplay); void destroyDisplay(hwc2_display_t displayId); @@ -215,10 +218,8 @@ public: std::unordered_map<Layer*, Composition>* outTypes); [[clang::warn_unused_result]] Error getColorModes( std::vector<android::ui::ColorMode>* outModes) const; - // outSupportedPerFrameMetadata is an opaque bitmask to the callers - // but contains HdrMetadata::Type::*. - [[clang::warn_unused_result]] Error getSupportedPerFrameMetadata( - int32_t* outSupportedPerFrameMetadata) const; + // Returns a bitmask which contains HdrMetadata::Type::*. + [[clang::warn_unused_result]] int32_t getSupportedPerFrameMetadata() const; [[clang::warn_unused_result]] Error getRenderIntents( android::ui::ColorMode colorMode, std::vector<android::ui::RenderIntent>* outRenderIntents) const; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index f5f7a821f0..bf8905a56a 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -54,6 +54,9 @@ #include "../Layer.h" // needed only for debugging #include "../SurfaceFlinger.h" +#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \ + ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg) + #define LOG_DISPLAY_ERROR(displayId, msg) \ ALOGE("%s failed for display %d: %s", __FUNCTION__, displayId, msg) @@ -96,6 +99,18 @@ void HWComposer::registerCallback(HWC2::ComposerCallback* callback, mHwcDevice->registerCallback(callback, sequenceId); } +bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, + DisplayIdentificationData* outData) const { + const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData); + if (error != HWC2::Error::None) { + if (error != HWC2::Error::Unsupported) { + LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str()); + } + return false; + } + return true; +} + bool HWComposer::hasCapability(HWC2::Capability capability) const { return mHwcDevice->getCapabilities().count(capability) > 0; @@ -131,53 +146,53 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { } } -void HWComposer::onHotplug(hwc2_display_t displayId, int32_t displayType, - HWC2::Connection connection) { +std::optional<DisplayId> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, + HWC2::Connection connection) { if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) { ALOGE("Invalid display type of %d", displayType); - return; + return {}; + } + + ALOGV("hotplug: %" PRIu64 ", %s %s", hwcDisplayId, + displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external", + to_string(connection).c_str()); + mHwcDevice->onHotplug(hwcDisplayId, connection); + + std::optional<DisplayId> displayId; + + uint8_t port; + DisplayIdentificationData data; + if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) { + displayId = generateDisplayId(port, data); + ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId); } - ALOGV("hotplug: %" PRIu64 ", %s %s", displayId, - displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external", - to_string(connection).c_str()); - mHwcDevice->onHotplug(displayId, connection); // Disconnect is handled through HWComposer::disconnectDisplay via // SurfaceFlinger's onHotplugReceived callback handling if (connection == HWC2::Connection::Connected) { - mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(displayId); - mHwcDisplaySlots[displayId] = displayType; + mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); + mHwcDisplaySlots[hwcDisplayId] = displayType; } + + return displayId; } -bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp, - int32_t* outDisplay) { - auto display = mHwcDevice->getDisplayById(displayId); - if (!display) { - ALOGE("onVsync Failed to find display %" PRIu64, displayId); - return false; - } - auto displayType = HWC2::DisplayType::Invalid; - auto error = display->getType(&displayType); - if (error != HWC2::Error::None) { - ALOGE("onVsync: Failed to determine type of display %" PRIu64, - display->getId()); +bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplayId) { + const auto it = mHwcDisplaySlots.find(hwcDisplayId); + if (it == mHwcDisplaySlots.end()) { + LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid display"); return false; } - if (displayType == HWC2::DisplayType::Virtual) { - ALOGE("Virtual display %" PRIu64 " passed to vsync callback", - display->getId()); - return false; - } + const int32_t displayId = it->second; + RETURN_IF_INVALID_DISPLAY(displayId, false); - if (mHwcDisplaySlots.count(display->getId()) == 0) { - ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback", - display->getId()); + const auto& displayData = mDisplayData[displayId]; + if (displayData.isVirtual) { + LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); return false; } - int32_t disp = mHwcDisplaySlots[display->getId()]; { Mutex::Autolock _l(mLock); @@ -185,22 +200,22 @@ bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp, // with the same timestamp when turning the display off and on. This // is a bug in the HWC implementation, but filter the extra events // out here so they don't cause havoc downstream. - if (timestamp == mLastHwVSync[disp]) { + if (timestamp == mLastHwVSync[displayId]) { ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")", timestamp); return false; } - mLastHwVSync[disp] = timestamp; + mLastHwVSync[displayId] = timestamp; } - if (outDisplay) { - *outDisplay = disp; + if (outDisplayId) { + *outDisplayId = displayId; } char tag[16]; - snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp); - ATRACE_INT(tag, ++mVSyncCounts[disp] & 1); + snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", displayId); + ATRACE_INT(tag, ++mVSyncCounts[displayId] & 1); return true; } @@ -208,16 +223,15 @@ bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp, status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, ui::PixelFormat* format, int32_t *outId) { if (mRemainingHwcVirtualDisplays == 0) { - ALOGE("allocateVirtualDisplay: No remaining virtual displays"); + ALOGE("%s: No remaining virtual displays", __FUNCTION__); return NO_MEMORY; } if (SurfaceFlinger::maxVirtualDisplaySize != 0 && (width > SurfaceFlinger::maxVirtualDisplaySize || height > SurfaceFlinger::maxVirtualDisplaySize)) { - ALOGE("createVirtualDisplay: Can't create a virtual display with" - " a dimension > %" PRIu64 " (tried %u x %u)", - SurfaceFlinger::maxVirtualDisplaySize, width, height); + ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width, + height, SurfaceFlinger::maxVirtualDisplaySize); return INVALID_OPERATION; } @@ -225,7 +239,7 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, auto error = mHwcDevice->createVirtualDisplay(width, height, format, &display); if (error != HWC2::Error::None) { - ALOGE("allocateVirtualDisplay: Failed to create HWC virtual display"); + ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__); return NO_MEMORY; } @@ -238,11 +252,13 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, displaySlot = mDisplayData.size(); mDisplayData.resize(displaySlot + 1); } else { - ALOGE("allocateVirtualDisplay: Unable to allocate a display slot"); + ALOGE("%s: Unable to allocate a display slot", __FUNCTION__); return NO_MEMORY; } - mDisplayData[displaySlot].hwcDisplay = display; + auto& displayData = mDisplayData[displaySlot]; + displayData.hwcDisplay = display; + displayData.isVirtual = true; --mRemainingHwcVirtualDisplays; *outId = static_cast<int32_t>(displaySlot); @@ -319,21 +335,19 @@ std::shared_ptr<const HWC2::Display::Config> } int HWComposer::getActiveConfigIndex(int32_t displayId) const { - if (!isValidDisplay(displayId)) { - ALOGV("getActiveConfigIndex: Attempted to access invalid display %d", displayId); - return -1; - } + RETURN_IF_INVALID_DISPLAY(displayId, -1); + int index; auto error = mDisplayData[displayId].hwcDisplay->getActiveConfigIndex(&index); if (error == HWC2::Error::BadConfig) { - ALOGE("getActiveConfigIndex: No config active, returning -1"); - return -1; - } else if (error != HWC2::Error::None) { - ALOGE("getActiveConfigIndex failed for display %d: %s (%d)", displayId, - to_string(error).c_str(), static_cast<int32_t>(error)); + LOG_DISPLAY_ERROR(displayId, "No active config"); return -1; - } else if (index < 0) { - ALOGE("getActiveConfigIndex returned an unknown config for display %d", displayId); + } + + RETURN_IF_HWC_ERROR(error, displayId, -1); + + if (index < 0) { + LOG_DISPLAY_ERROR(displayId, "Unknown config"); return -1; } @@ -365,19 +379,19 @@ status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode, void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) { - if (displayId < 0 || displayId >= HWC_DISPLAY_VIRTUAL) { - ALOGD("setVsyncEnabled: Ignoring for virtual display %d", displayId); + RETURN_IF_INVALID_DISPLAY(displayId); + auto& displayData = mDisplayData[displayId]; + + if (displayData.isVirtual) { + LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); return; } - RETURN_IF_INVALID_DISPLAY(displayId); - // NOTE: we use our own internal lock here because we have to call // into the HWC with the lock held, and we want to make sure // that even if HWC blocks (which it shouldn't), it won't // affect other threads. Mutex::Autolock _l(mVsyncLock); - auto& displayData = mDisplayData[displayId]; if (enabled != displayData.vsyncEnabled) { ATRACE_CALL(); auto error = displayData.hwcDisplay->setVsyncEnabled(enabled); @@ -403,11 +417,11 @@ status_t HWComposer::setClientTarget(int32_t displayId, uint32_t slot, return NO_ERROR; } -status_t HWComposer::prepare(DisplayDevice& displayDevice) { +status_t HWComposer::prepare(DisplayDevice& display) { ATRACE_CALL(); Mutex::Autolock _l(mDisplayLock); - auto displayId = displayDevice.getHwcDisplayId(); + const auto displayId = display.getId(); if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { ALOGV("Skipping HWComposer prepare for non-HWC display"); return NO_ERROR; @@ -474,7 +488,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { displayData.hasClientComposition = false; displayData.hasDeviceComposition = false; - for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) { + for (auto& layer : display.getVisibleLayersSortedByZ()) { auto hwcLayer = layer->getHwcLayer(displayId); if (changedTypes.count(hwcLayer) != 0) { @@ -601,7 +615,8 @@ status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) { ALOGV("setPowerMode(%d, %d)", displayId, intMode); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); - if (displayId >= VIRTUAL_DISPLAY_ID_BASE) { + const auto& displayData = mDisplayData[displayId]; + if (displayData.isVirtual) { LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); return INVALID_OPERATION; } @@ -611,7 +626,7 @@ status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) { setVsyncEnabled(displayId, HWC2::Vsync::Disable); } - auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; + auto& hwcDisplay = displayData.hwcDisplay; switch (mode) { case HWC2::PowerMode::Off: case HWC2::PowerMode::On: @@ -680,43 +695,35 @@ status_t HWComposer::setColorTransform(int32_t displayId, return NO_ERROR; } -void HWComposer::disconnectDisplay(int displayId) { - LOG_ALWAYS_FATAL_IF(displayId < 0); +void HWComposer::disconnectDisplay(int32_t displayId) { + RETURN_IF_INVALID_DISPLAY(displayId); auto& displayData = mDisplayData[displayId]; - auto displayType = HWC2::DisplayType::Invalid; - auto error = displayData.hwcDisplay->getType(&displayType); - RETURN_IF_HWC_ERROR_FOR("getType", error, displayId); - // If this was a virtual display, add its slot back for reuse by future // virtual displays - if (displayType == HWC2::DisplayType::Virtual) { + if (displayData.isVirtual) { mFreeDisplaySlots.insert(displayId); ++mRemainingHwcVirtualDisplays; } - auto hwcId = displayData.hwcDisplay->getId(); - mHwcDisplaySlots.erase(hwcId); - displayData.reset(); + const auto hwcDisplayId = displayData.hwcDisplay->getId(); + mHwcDisplaySlots.erase(hwcDisplayId); + displayData = DisplayData(); - mHwcDevice->destroyDisplay(hwcId); + mHwcDevice->destroyDisplay(hwcDisplayId); } status_t HWComposer::setOutputBuffer(int32_t displayId, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto& displayData = mDisplayData[displayId]; - auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; - auto displayType = HWC2::DisplayType::Invalid; - auto error = hwcDisplay->getType(&displayType); - RETURN_IF_HWC_ERROR_FOR("getType", error, displayId, NAME_NOT_FOUND); - - if (displayType != HWC2::DisplayType::Virtual) { + if (!displayData.isVirtual) { LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display"); return INVALID_OPERATION; } - error = hwcDisplay->setOutputBuffer(buffer, acquireFence); + auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence); RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); return NO_ERROR; } @@ -738,12 +745,7 @@ status_t HWComposer::getHdrCapabilities( int32_t HWComposer::getSupportedPerFrameMetadata(int32_t displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, 0); - - int32_t supportedMetadata; - auto error = mDisplayData[displayId].hwcDisplay->getSupportedPerFrameMetadata( - &supportedMetadata); - RETURN_IF_HWC_ERROR(error, displayId, 0); - return supportedMetadata; + return mDisplayData[displayId].hwcDisplay->getSupportedPerFrameMetadata(); } std::vector<ui::RenderIntent> HWComposer::getRenderIntents(int32_t displayId, @@ -805,26 +807,4 @@ HWComposer::getHwcDisplayId(int32_t displayId) const { return mDisplayData[displayId].hwcDisplay->getId(); } -// --------------------------------------------------------------------------- - -HWComposer::DisplayData::DisplayData() - : hasClientComposition(false), - hasDeviceComposition(false), - hwcDisplay(nullptr), - lastPresentFence(Fence::NO_FENCE), - outbufHandle(nullptr), - outbufAcquireFence(Fence::NO_FENCE), - vsyncEnabled(HWC2::Vsync::Disable) { - ALOGV("Created new DisplayData"); -} - -HWComposer::DisplayData::~DisplayData() { -} - -void HWComposer::DisplayData::reset() { - ALOGV("DisplayData reset"); - *this = DisplayData(); -} - -// --------------------------------------------------------------------------- -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index f9689482cc..3c5efeaadb 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -37,6 +37,8 @@ #include <set> #include <vector> +#include "DisplayIdentification.h" + extern "C" int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, struct timespec *remain); @@ -74,6 +76,9 @@ public: void registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId); + bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, + DisplayIdentificationData* outData) const; + bool hasCapability(HWC2::Capability capability) const; // Attempts to allocate a virtual display. If the virtual display is created @@ -87,7 +92,7 @@ public: void destroyLayer(int32_t displayId, HWC2::Layer* layer); // Asks the HAL what it can do - status_t prepare(DisplayDevice& displayDevice); + status_t prepare(DisplayDevice& display); status_t setClientTarget(int32_t displayId, uint32_t slot, const sp<Fence>& acquireFence, @@ -147,9 +152,9 @@ public: // Returns true if successful, false otherwise. The // DisplayDevice::DisplayType of the display is returned as an output param. - bool onVsync(hwc2_display_t displayId, int64_t timestamp, - int32_t* outDisplay); - void onHotplug(hwc2_display_t displayId, int32_t displayType, HWC2::Connection connection); + bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay); + std::optional<DisplayId> onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, + HWC2::Connection connection); void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled); @@ -183,31 +188,26 @@ private: // For unit tests friend TestableSurfaceFlinger; - static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2; - bool isValidDisplay(int32_t displayId) const; static void validateChange(HWC2::Composition from, HWC2::Composition to); struct cb_context; struct DisplayData { - DisplayData(); - ~DisplayData(); - void reset(); - - bool hasClientComposition; - bool hasDeviceComposition; - HWC2::Display* hwcDisplay; + bool isVirtual = false; + bool hasClientComposition = false; + bool hasDeviceComposition = false; + HWC2::Display* hwcDisplay = nullptr; HWC2::DisplayRequest displayRequests; - sp<Fence> lastPresentFence; // signals when the last set op retires + sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; - buffer_handle_t outbufHandle; - sp<Fence> outbufAcquireFence; + buffer_handle_t outbufHandle = nullptr; + sp<Fence> outbufAcquireFence = Fence::NO_FENCE; mutable std::unordered_map<int32_t, std::shared_ptr<const HWC2::Display::Config>> configMap; // protected by mVsyncLock - HWC2::Vsync vsyncEnabled; + HWC2::Vsync vsyncEnabled = HWC2::Vsync::Disable; bool validateWasSkipped; HWC2::Error presentError; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h deleted file mode 100644 index fe7944f635..0000000000 --- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SF_HWCOMPOSER_HWC1_H -#define ANDROID_SF_HWCOMPOSER_HWC1_H - -#include <stdint.h> -#include <sys/types.h> - -#include <hardware/hwcomposer_defs.h> - -#include <system/graphics.h> - -#include <ui/Fence.h> - -#include <utils/BitSet.h> -#include <utils/Condition.h> -#include <utils/Mutex.h> -#include <utils/StrongPointer.h> -#include <utils/Thread.h> -#include <utils/Timers.h> -#include <utils/Vector.h> - -extern "C" int clock_nanosleep(clockid_t clock_id, int flags, - const struct timespec *request, - struct timespec *remain); - -struct hwc_composer_device_1; -struct hwc_display_contents_1; -struct hwc_layer_1; -struct hwc_procs; -struct framebuffer_device_t; - -namespace android { -// --------------------------------------------------------------------------- - -class Fence; -class FloatRect; -class GraphicBuffer; -class NativeHandle; -class Region; -class String8; -class SurfaceFlinger; - -class HWComposer -{ -public: - class EventHandler { - friend class HWComposer; - virtual void onVSyncReceived( - HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0; - virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected) = 0; - virtual void onInvalidateReceived(HWComposer* composer) = 0; - protected: - virtual ~EventHandler() {} - }; - - enum { - NUM_BUILTIN_DISPLAYS = HWC_NUM_PHYSICAL_DISPLAY_TYPES, - MAX_HWC_DISPLAYS = HWC_NUM_DISPLAY_TYPES, - VIRTUAL_DISPLAY_ID_BASE = HWC_DISPLAY_VIRTUAL, - }; - - HWComposer( - const sp<SurfaceFlinger>& flinger, - EventHandler& handler); - - ~HWComposer(); - - status_t initCheck() const; - - // Returns a display ID starting at VIRTUAL_DISPLAY_ID_BASE, this ID is to - // be used with createWorkList (and all other methods requiring an ID - // below). - // IDs below NUM_BUILTIN_DISPLAYS are pre-defined and therefore are - // always valid. - // Returns -1 if an ID cannot be allocated - int32_t allocateDisplayId(); - - // Recycles the given virtual display ID and frees the associated worklist. - // IDs below NUM_BUILTIN_DISPLAYS are not recycled. - status_t freeDisplayId(int32_t id); - - - // Asks the HAL what it can do - status_t prepare(); - - // commits the list - status_t commit(); - - // set power mode - status_t setPowerMode(int disp, int mode); - - // set active config - status_t setActiveConfig(int disp, int mode); - - // reset state when an external, non-virtual display is disconnected - void disconnectDisplay(int disp); - - // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED. - status_t createWorkList(int32_t id, size_t numLayers); - - bool supportsFramebufferTarget() const; - - // does this display have layers handled by HWC - bool hasHwcComposition(int32_t id) const; - - // does this display have layers handled by GLES - bool hasGlesComposition(int32_t id) const; - - // get the releaseFence file descriptor for a display's framebuffer layer. - // the release fence is only valid after commit() - sp<Fence> getAndResetReleaseFence(int32_t id); - - // needed forward declarations - class LayerListIterator; - - // return the visual id to be used to find a suitable EGLConfig for - // *ALL* displays. - int getVisualID() const; - - // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface). - int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf); - int fbCompositionComplete(); - void fbDump(String8& result); - - // Set the output buffer and acquire fence for a virtual display. - // Returns INVALID_OPERATION if id is not a virtual display. - status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence, - const sp<GraphicBuffer>& buf); - - // Get the retire fence for the last committed frame. This fence will - // signal when the h/w composer is completely finished with the frame. - // For physical displays, it is no longer being displayed. For virtual - // displays, writes to the output buffer are complete. - sp<Fence> getLastRetireFence(int32_t id) const; - - status_t setCursorPositionAsync(int32_t id, const Rect &pos); - - /* - * Interface to hardware composer's layers functionality. - * This abstracts the HAL interface to layers which can evolve in - * incompatible ways from one release to another. - * The idea is that we could extend this interface as we add - * features to h/w composer. - */ - class HWCLayerInterface { - protected: - virtual ~HWCLayerInterface() { } - public: - virtual int32_t getCompositionType() const = 0; - virtual uint32_t getHints() const = 0; - virtual sp<Fence> getAndResetReleaseFence() = 0; - virtual void setDefaultState() = 0; - virtual void setSkip(bool skip) = 0; - virtual void setIsCursorLayerHint(bool isCursor = true) = 0; - virtual void setBlending(uint32_t blending) = 0; - virtual void setTransform(uint32_t transform) = 0; - virtual void setFrame(const Rect& frame) = 0; - virtual void setCrop(const FloatRect& crop) = 0; - virtual void setVisibleRegionScreen(const Region& reg) = 0; - virtual void setSurfaceDamage(const Region& reg) = 0; - virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0; - virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0; - virtual void setAcquireFenceFd(int fenceFd) = 0; - virtual void setPlaneAlpha(uint8_t alpha) = 0; - virtual void onDisplayed() = 0; - }; - - /* - * Interface used to implement an iterator to a list - * of HWCLayer. - */ - class HWCLayer : public HWCLayerInterface { - friend class LayerListIterator; - // select the layer at the given index - virtual status_t setLayer(size_t index) = 0; - virtual HWCLayer* dup() = 0; - static HWCLayer* copy(HWCLayer *rhs) { - return rhs ? rhs->dup() : nullptr; - } - protected: - virtual ~HWCLayer() { } - }; - - /* - * Iterator through a HWCLayer list. - * This behaves more or less like a forward iterator. - */ - class LayerListIterator { - friend class HWComposer; - HWCLayer* const mLayerList; - size_t mIndex; - - LayerListIterator() : mLayerList(nullptr), mIndex(0) { } - - LayerListIterator(HWCLayer* layer, size_t index) - : mLayerList(layer), mIndex(index) { } - - // we don't allow assignment, because we don't need it for now - LayerListIterator& operator = (const LayerListIterator& rhs); - - public: - // copy operators - LayerListIterator(const LayerListIterator& rhs) - : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) { - } - - ~LayerListIterator() { delete mLayerList; } - - // pre-increment - LayerListIterator& operator++() { - mLayerList->setLayer(++mIndex); - return *this; - } - - // dereference - HWCLayerInterface& operator * () { return *mLayerList; } - HWCLayerInterface* operator -> () { return mLayerList; } - - // comparison - bool operator == (const LayerListIterator& rhs) const { - return mIndex == rhs.mIndex; - } - bool operator != (const LayerListIterator& rhs) const { - return !operator==(rhs); - } - }; - - // Returns an iterator to the beginning of the layer list - LayerListIterator begin(int32_t id); - - // Returns an iterator to the end of the layer list - LayerListIterator end(int32_t id); - - - // Events handling --------------------------------------------------------- - - enum { - EVENT_VSYNC = HWC_EVENT_VSYNC - }; - - void eventControl(int disp, int event, int enabled); - - struct DisplayConfig { - uint32_t width; - uint32_t height; - float xdpi; - float ydpi; - nsecs_t refresh; - android_color_mode_t colorMode; - bool operator==(const DisplayConfig& rhs) const { - return width == rhs.width && - height == rhs.height && - xdpi == rhs.xdpi && - ydpi == rhs.ydpi && - refresh == rhs.refresh && - colorMode == rhs.colorMode; - } - }; - - // Query display parameters. Pass in a display index (e.g. - // HWC_DISPLAY_PRIMARY). - nsecs_t getRefreshTimestamp(int disp) const; - sp<Fence> getDisplayFence(int disp) const; - uint32_t getFormat(int disp) const; - bool isConnected(int disp) const; - - // These return the values for the current config of a given display index. - // To get the values for all configs, use getConfigs below. - uint32_t getWidth(int disp) const; - uint32_t getHeight(int disp) const; - float getDpiX(int disp) const; - float getDpiY(int disp) const; - nsecs_t getRefreshPeriod(int disp) const; - android_color_mode_t getColorMode(int disp) const; - - const Vector<DisplayConfig>& getConfigs(int disp) const; - size_t getCurrentConfig(int disp) const; - - status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h, - uint32_t format); - - // this class is only used to fake the VSync event on systems that don't - // have it. - class VSyncThread : public Thread { - HWComposer& mHwc; - mutable Mutex mLock; - Condition mCondition; - bool mEnabled; - mutable nsecs_t mNextFakeVSync; - nsecs_t mRefreshPeriod; - virtual void onFirstRef(); - virtual bool threadLoop(); - public: - VSyncThread(HWComposer& hwc); - void setEnabled(bool enabled); - }; - - friend class VSyncThread; - - // for debugging ---------------------------------------------------------- - void dump(String8& out) const; - -private: - void loadHwcModule(); - int loadFbHalModule(); - - LayerListIterator getLayerIterator(int32_t id, size_t index); - - struct cb_context; - - static void hook_invalidate(const struct hwc_procs* procs); - static void hook_vsync(const struct hwc_procs* procs, int disp, - int64_t timestamp); - static void hook_hotplug(const struct hwc_procs* procs, int disp, - int connected); - - inline void invalidate(); - inline void vsync(int disp, int64_t timestamp); - inline void hotplug(int disp, int connected); - - status_t queryDisplayProperties(int disp); - - status_t setFramebufferTarget(int32_t id, - const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf); - - struct DisplayData { - DisplayData(); - ~DisplayData(); - Vector<DisplayConfig> configs; - size_t currentConfig; - uint32_t format; // pixel format from FB hal, for pre-hwc-1.1 - bool connected; - bool hasFbComp; - bool hasOvComp; - size_t capacity; - hwc_display_contents_1* list; - hwc_layer_1* framebufferTarget; - buffer_handle_t fbTargetHandle; - sp<Fence> lastRetireFence; // signals when the last set op retires - sp<Fence> lastDisplayFence; // signals when the last set op takes - // effect on screen - buffer_handle_t outbufHandle; - sp<Fence> outbufAcquireFence; - - // protected by mEventControlLock - int32_t events; - - // We need to hold "copies" of these for memory management purposes. The - // actual hwc_layer_1_t holds pointers to the memory within. Vector<> - // internally doesn't copy the memory unless one of the copies is - // modified. - Vector<Region> visibleRegions; - Vector<Region> surfaceDamageRegions; - }; - - sp<SurfaceFlinger> mFlinger; - framebuffer_device_t* mFbDev; - struct hwc_composer_device_1* mHwc; - // invariant: mLists[0] != nullptr iff mHwc != nullptr - // mLists[i>0] can be nullptr. that display is to be ignored - struct hwc_display_contents_1* mLists[MAX_HWC_DISPLAYS]; - DisplayData mDisplayData[MAX_HWC_DISPLAYS]; - // protect mDisplayData from races between prepare and dump - mutable Mutex mDisplayLock; - size_t mNumDisplays; - - cb_context* mCBContext; - EventHandler& mEventHandler; - size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]; - sp<VSyncThread> mVSyncThread; - bool mDebugForceFakeVSync; - BitSet32 mAllocatedDisplayIDs; - - // protected by mLock - mutable Mutex mLock; - mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES]; - - // thread-safe - mutable Mutex mEventControlLock; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_SF_HWCOMPOSER_H diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 9a2817dba1..c111a27f51 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -32,11 +32,11 @@ namespace android { // --------------------------------------------------------------------------- #define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \ - mDisplayName.string(), ##__VA_ARGS__) + mDisplayName.c_str(), ##__VA_ARGS__) #define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \ - mDisplayName.string(), ##__VA_ARGS__) + mDisplayName.c_str(), ##__VA_ARGS__) #define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \ - mDisplayName.string(), ##__VA_ARGS__) + mDisplayName.c_str(), ##__VA_ARGS__) static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) { switch (type) { @@ -52,7 +52,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, const sp<IGraphicBufferProducer>& sink, const sp<IGraphicBufferProducer>& bqProducer, const sp<IGraphicBufferConsumer>& bqConsumer, - const String8& name) + const std::string& name) : ConsumerBase(bqConsumer), mHwc(hwc), mDisplayId(dispId), @@ -102,7 +102,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, } mOutputFormat = mDefaultOutputFormat; - ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string()); + ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.c_str()); mConsumer->setConsumerName(ConsumerBase::mName); mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER); mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 5c8aceae92..4bd4d0fe61 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -17,6 +17,8 @@ #ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H #define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H +#include <string> + #include "DisplaySurface.h" #include "HWComposerBufferCache.h" @@ -77,7 +79,7 @@ public: const sp<IGraphicBufferProducer>& sink, const sp<IGraphicBufferProducer>& bqProducer, const sp<IGraphicBufferConsumer>& bqConsumer, - const String8& name); + const std::string& name); // // DisplaySurface interface @@ -153,7 +155,7 @@ private: // HWComposer& mHwc; const int32_t mDisplayId; - const String8 mDisplayName; + const std::string mDisplayName; sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_* uint32_t mDefaultOutputFormat; diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index bc271c8ec5..5a8fd25270 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -155,20 +155,17 @@ void EventThread::onVSyncEvent(nsecs_t timestamp) { mCondition.notify_all(); } -void EventThread::onHotplugReceived(int type, bool connected) { - ALOGE_IF(type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, - "received hotplug event for an invalid display (id=%d)", type); - +void EventThread::onHotplugReceived(DisplayType displayType, bool connected) { std::lock_guard<std::mutex> lock(mMutex); - if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { - DisplayEventReceiver::Event event; - event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG; - event.header.id = type; - event.header.timestamp = systemTime(); - event.hotplug.connected = connected; - mPendingEvents.add(event); - mCondition.notify_all(); - } + + DisplayEventReceiver::Event event; + event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG; + event.header.id = displayType == DisplayType::Primary ? 0 : 1; + event.header.timestamp = systemTime(); + event.hotplug.connected = connected; + + mPendingEvents.add(event); + mCondition.notify_all(); } void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { @@ -205,7 +202,7 @@ void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { // This will return when (1) a vsync event has been received, and (2) there was // at least one connection interested in receiving it when we started waiting. Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked( - std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* event) { + std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* outEvent) { Vector<sp<EventThread::Connection> > signalConnections; while (signalConnections.isEmpty() && mKeepRunning) { @@ -214,16 +211,16 @@ Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked( size_t vsyncCount = 0; nsecs_t timestamp = 0; - for (int32_t i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; i++) { - timestamp = mVSyncEvent[i].header.timestamp; + for (auto& event : mVSyncEvent) { + timestamp = event.header.timestamp; if (timestamp) { // we have a vsync event to dispatch if (mInterceptVSyncsCallback) { mInterceptVSyncsCallback(timestamp); } - *event = mVSyncEvent[i]; - mVSyncEvent[i].header.timestamp = 0; - vsyncCount = mVSyncEvent[i].vsync.count; + *outEvent = event; + event.header.timestamp = 0; + vsyncCount = event.vsync.count; break; } } @@ -233,7 +230,7 @@ Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked( eventPending = !mPendingEvents.isEmpty(); if (eventPending) { // we have some other event to dispatch - *event = mPendingEvents[0]; + *outEvent = mPendingEvents[0]; mPendingEvents.removeAt(0); } } @@ -319,7 +316,7 @@ Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked( // FIXME: how do we decide which display id the fake // vsync came from ? mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; - mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY; + mVSyncEvent[0].header.id = 0; mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); mVSyncEvent[0].vsync.count++; } @@ -364,8 +361,7 @@ void EventThread::dump(String8& result) const { result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled"); result.appendFormat(" soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled"); result.appendFormat(" numListeners=%zu,\n events-delivered: %u\n", - mDisplayEventConnections.size(), - mVSyncEvent[DisplayDevice::DISPLAY_PRIMARY].vsync.count); + mDisplayEventConnections.size(), mVSyncEvent[0].vsync.count); for (size_t i = 0; i < mDisplayEventConnections.size(); i++) { sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote(); result.appendFormat(" %p: count=%d\n", connection.get(), diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index 9c13ed2755..a0262b2ad9 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -16,9 +16,11 @@ #pragma once -#include <stdint.h> #include <sys/types.h> + +#include <array> #include <condition_variable> +#include <cstdint> #include <mutex> #include <thread> @@ -31,8 +33,6 @@ #include <utils/Errors.h> #include <utils/SortedVector.h> -#include "DisplayDevice.h" - // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- @@ -59,6 +59,9 @@ public: class EventThread { public: + // TODO: Remove once stable display IDs are plumbed through SF/WM interface. + enum class DisplayType { Primary, External }; + virtual ~EventThread(); virtual sp<BnDisplayEventConnection> createEventConnection() const = 0; @@ -70,7 +73,7 @@ public: virtual void onScreenAcquired() = 0; // called when receiving a hotplug event - virtual void onHotplugReceived(int type, bool connected) = 0; + virtual void onHotplugReceived(DisplayType displayType, bool connected) = 0; virtual void dump(String8& result) const = 0; @@ -122,7 +125,7 @@ public: void onScreenAcquired() override; // called when receiving a hotplug event - void onHotplugReceived(int type, bool connected) override; + void onHotplugReceived(DisplayType displayType, bool connected) override; void dump(String8& result) const override; @@ -155,8 +158,7 @@ private: // protected by mLock SortedVector<wp<Connection>> mDisplayEventConnections GUARDED_BY(mMutex); Vector<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex); - DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES] GUARDED_BY( - mMutex); + std::array<DisplayEventReceiver::Event, 2> mVSyncEvent GUARDED_BY(mMutex); bool mUseSoftwareVSync GUARDED_BY(mMutex) = false; bool mVsyncEnabled GUARDED_BY(mMutex) = false; bool mKeepRunning GUARDED_BY(mMutex) = true; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a14bb98d8d..ee9ee78fae 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -63,11 +63,6 @@ namespace android { -LayerBE::LayerBE() - : mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { -} - - int32_t Layer::sSequence = 1; Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, @@ -80,12 +75,8 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& n mTransactionFlags(0), mPendingStateMutex(), mPendingStates(), - mQueuedFrames(0), - mSidebandStreamChanged(false), - mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mCurrentTransform(0), mOverrideScalingMode(-1), - mCurrentOpacity(true), mCurrentFrameNumber(0), mFrameLatencyNeeded(false), mFiltering(false), @@ -93,14 +84,11 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& n mProtectedByApp(false), mClientRef(client), mPotentialCursor(false), - mQueueItemLock(), - mQueueItemCondition(), - mQueueItems(), - mLastFrameNumberReceived(0), - mAutoRefresh(false), mFreezeGeometryUpdates(false), mCurrentChildren(LayerVector::StateSet::Current), - mDrawingChildren(LayerVector::StateSet::Drawing) { + mDrawingChildren(LayerVector::StateSet::Drawing), + mBE{this, name.string()} { + mCurrentCrop.makeInvalid(); uint32_t layerFlags = 0; @@ -111,21 +99,32 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& n mName = name; mTransactionName = String8("TX - ") + mName; - mCurrentState.active.w = w; - mCurrentState.active.h = h; + mCurrentState.active_legacy.w = w; + mCurrentState.active_legacy.h = h; mCurrentState.flags = layerFlags; - mCurrentState.active.transform.set(0, 0); - mCurrentState.crop.makeInvalid(); - mCurrentState.finalCrop.makeInvalid(); - mCurrentState.requestedFinalCrop = mCurrentState.finalCrop; - mCurrentState.requestedCrop = mCurrentState.crop; + mCurrentState.active_legacy.transform.set(0, 0); + mCurrentState.crop_legacy.makeInvalid(); + mCurrentState.finalCrop_legacy.makeInvalid(); + mCurrentState.requestedFinalCrop_legacy = mCurrentState.finalCrop_legacy; + mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy; mCurrentState.z = 0; mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; mCurrentState.sequence = 0; - mCurrentState.requested = mCurrentState.active; + mCurrentState.requested_legacy = mCurrentState.active_legacy; mCurrentState.appId = 0; mCurrentState.type = 0; + mCurrentState.active.w = 0; + mCurrentState.active.h = 0; + mCurrentState.active.transform.set(0, 0); + mCurrentState.transform = 0; + mCurrentState.transformToDisplayInverse = false; + mCurrentState.crop.makeInvalid(); + mCurrentState.acquireFence = new Fence(-1); + mCurrentState.dataspace = ui::Dataspace::UNKNOWN; + mCurrentState.hdrMetadata.validTypes = 0; + mCurrentState.surfaceDamageRegion.clear(); + mCurrentState.api = -1; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -228,32 +227,32 @@ sp<IBinder> Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { - LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, - "Already have a layer for hwcId %d", hwcId); - HWC2::Layer* layer = hwc->createLayer(hwcId); +bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) { + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, + "Already have a layer for display %d", displayId); + HWC2::Layer* layer = hwc->createLayer(displayId); if (!layer) { return false; } - LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId]; + LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[displayId]; hwcInfo.hwc = hwc; hwcInfo.layer = layer; layer->setLayerDestroyedListener( - [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); }); + [this, displayId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(displayId); }); return true; } -bool Layer::destroyHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { +bool Layer::destroyHwcLayer(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { return false; } - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[displayId]; LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer"); LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer"); - hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer); + hwcInfo.hwc->destroyLayer(displayId, hwcInfo.layer); // The layer destroyed listener should have cleared the entry from // mHwcLayers. Verify that. - LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, "Stale layer entry in getBE().mHwcLayers"); return true; } @@ -305,17 +304,19 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active.w, s.active.h); + Rect win(getActiveWidth(s), getActiveHeight(s)); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } Transform t = getTransform(); win = t.transform(win); - if (!s.finalCrop.isEmpty()) { - win.intersect(s.finalCrop, &win); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + win.intersect(finalCrop, &win); } const sp<Layer>& p = mDrawingParent.promote(); @@ -334,7 +335,7 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { } if (reduceTransparentRegion) { - auto const screenTransparentRegion = t.transform(s.activeTransparentRegion); + auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s)); win = reduce(win, screenTransparentRegion); } @@ -343,15 +344,16 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { FloatRect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); - return computeBounds(s.activeTransparentRegion); + return computeBounds(getActiveTransparentRegion(s)); } FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active.w, s.active.h); + Rect win(getActiveWidth(s), getActiveHeight(s)); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } const auto& p = mDrawingParent.promote(); @@ -363,15 +365,14 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { parentBounds = p->computeBounds(Region()); } - Transform t = s.active.transform; - + Transform t = s.active_legacy.transform; - if (p != nullptr || !s.finalCrop.isEmpty()) { + if (p != nullptr || !s.finalCrop_legacy.isEmpty()) { floatWin = t.transform(floatWin); floatWin = floatWin.intersect(parentBounds); - if (!s.finalCrop.isEmpty()) { - floatWin = floatWin.intersect(s.finalCrop.toFloatRect()); + if (!s.finalCrop_legacy.isEmpty()) { + floatWin = floatWin.intersect(s.finalCrop_legacy.toFloatRect()); } floatWin = t.inverse().transform(floatWin); } @@ -380,7 +381,7 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { return reduce(floatWin, activeTransparentRegion); } -Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const { +Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const { // the crop is the area of the window that gets cropped, but not // scaled in any ways. const State& s(getDrawingState()); @@ -392,32 +393,34 @@ Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const { // FIXME: the 3 lines below can produce slightly incorrect clipping when we have // a viewport clipping and a window transform. we should use floating point to fix this. - Rect activeCrop(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - activeCrop.intersect(s.crop, &activeCrop); + Rect activeCrop(getActiveWidth(s), getActiveHeight(s)); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + activeCrop.intersect(crop, &activeCrop); } Transform t = getTransform(); activeCrop = t.transform(activeCrop); - if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) { + if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } - if (!s.finalCrop.isEmpty()) { - if (!activeCrop.intersect(s.finalCrop, &activeCrop)) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + if (!activeCrop.intersect(finalCrop, &activeCrop)) { activeCrop.clear(); } } const auto& p = mDrawingParent.promote(); if (p != nullptr) { - auto parentCrop = p->computeInitialCrop(hw); + auto parentCrop = p->computeInitialCrop(display); activeCrop.intersect(parentCrop, &activeCrop); } return activeCrop; } -FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { +FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const { // the content crop is the area of the content that gets scaled to the // layer's size. This is in buffer space. FloatRect crop = getContentCrop().toFloatRect(); @@ -426,7 +429,7 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { const State& s(getDrawingState()); // Screen space to make reduction to parent crop clearer. - Rect activeCrop = computeInitialCrop(hw); + Rect activeCrop = computeInitialCrop(display); Transform t = getTransform(); // Back to layer space to work with the content crop. activeCrop = t.inverse().transform(activeCrop); @@ -437,12 +440,12 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { activeCrop.clear(); } // subtract the transparent region and snap to the bounds - activeCrop = reduce(activeCrop, s.activeTransparentRegion); + activeCrop = reduce(activeCrop, getActiveTransparentRegion(s)); // Transform the window crop to match the buffer coordinate system, // which means using the inverse of the current transform set on the @@ -462,8 +465,8 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); } - int winWidth = s.active.w; - int winHeight = s.active.h; + int winWidth = getActiveWidth(s); + int winHeight = getActiveHeight(s); if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { // If the activeCrop has been rotate the ends are rotated but not // the space itself so when transforming ends back we can't rely on @@ -475,10 +478,10 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { if (is_h_flipped == is_v_flipped) { invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } - winWidth = s.active.h; - winHeight = s.active.w; + winWidth = getActiveHeight(s); + winHeight = getActiveWidth(s); } - const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h); + const Rect winCrop = activeCrop.transform(invTransform, getActiveWidth(s), getActiveHeight(s)); // below, crop is intersected with winCrop expressed in crop's coordinate space float xScale = crop.getWidth() / float(winWidth); @@ -497,15 +500,19 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { return crop; } -void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z) -{ - const auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = getBE().mHwcLayers[hwcId]; +void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) { + const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setGeometry: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; // enable this layer hwcInfo.forceClientComposition = false; - if (isSecure() && !displayDevice->isSecure()) { + if (isSecure() && !display->isSecure()) { hwcInfo.forceClientComposition = true; } @@ -527,12 +534,12 @@ void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects - Region activeTransparentRegion(s.activeTransparentRegion); + Region activeTransparentRegion(getActiveTransparentRegion(s)); Transform t = getTransform(); - if (!s.crop.isEmpty()) { - Rect activeCrop(s.crop); + Rect activeCrop = getCrop(s); + if (!activeCrop.isEmpty()) { activeCrop = t.transform(activeCrop); - if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { + if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } activeCrop = t.inverse().transform(activeCrop, true); @@ -542,29 +549,31 @@ void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { activeCrop.clear(); } // mark regions outside the crop as transparent - activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top)); - activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, s.active.w, s.active.h)); + activeTransparentRegion.orSelf(Rect(0, 0, getActiveWidth(s), activeCrop.top)); + activeTransparentRegion.orSelf( + Rect(0, activeCrop.bottom, getActiveWidth(s), getActiveHeight(s))); activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); activeTransparentRegion.orSelf( - Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom)); + Rect(activeCrop.right, activeCrop.top, getActiveWidth(s), activeCrop.bottom)); } // computeBounds returns a FloatRect to provide more accuracy during the // transformation. We then round upon constructing 'frame'. Rect frame{t.transform(computeBounds(activeTransparentRegion))}; - if (!s.finalCrop.isEmpty()) { - if (!frame.intersect(s.finalCrop, &frame)) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + if (!frame.intersect(finalCrop, &frame)) { frame.clear(); } } - if (!frame.intersect(displayDevice->getViewport(), &frame)) { + if (!frame.intersect(display->getViewport(), &frame)) { frame.clear(); } - const Transform& tr(displayDevice->getTransform()); + const Transform& tr = display->getTransform(); Rect transformedFrame = tr.transform(frame); error = hwcLayer->setDisplayFrame(transformedFrame); if (error != HWC2::Error::None) { @@ -575,7 +584,7 @@ void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z hwcInfo.displayFrame = transformedFrame; } - FloatRect sourceCrop = computeCrop(displayDevice); + FloatRect sourceCrop = computeCrop(display); error = hwcLayer->setSourceCrop(sourceCrop); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " @@ -660,28 +669,28 @@ void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z } } -void Layer::forceClientComposition(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { - ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId); +void Layer::forceClientComposition(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { + ALOGE("forceClientComposition: no HWC layer found (%d)", displayId); return; } - getBE().mHwcLayers[hwcId].forceClientComposition = true; + getBE().mHwcLayers[displayId].forceClientComposition = true; } -bool Layer::getForceClientComposition(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { - ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId); +bool Layer::getForceClientComposition(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { + ALOGE("getForceClientComposition: no HWC layer found (%d)", displayId); return false; } - return getBE().mHwcLayers[hwcId].forceClientComposition; + return getBE().mHwcLayers[displayId].forceClientComposition; } -void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) { - auto hwcId = displayDevice->getHwcDisplayId(); - if (getBE().mHwcLayers.count(hwcId) == 0 || - getCompositionType(hwcId) != HWC2::Composition::Cursor) { +void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) { + const auto displayId = display->getId(); + if (getBE().mHwcLayers.count(displayId) == 0 || + getCompositionType(displayId) != HWC2::Composition::Cursor) { return; } @@ -690,22 +699,24 @@ void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) { // Apply the layer's transform, followed by the display's global transform // Here we're guaranteed that the layer's transform preserves rects - Rect win(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + Rect win(getActiveWidth(s), getActiveHeight(s)); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } // Subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, s.activeTransparentRegion); + Rect bounds = reduce(win, getActiveTransparentRegion(s)); Rect frame(getTransform().transform(bounds)); - frame.intersect(displayDevice->getViewport(), &frame); - if (!s.finalCrop.isEmpty()) { - frame.intersect(s.finalCrop, &frame); + frame.intersect(display->getViewport(), &frame); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + frame.intersect(finalCrop, &frame); } - auto& displayTransform(displayDevice->getTransform()); + auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); - auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left, - position.top); + auto error = + getBE().mHwcLayers[displayId].layer->setCursorPosition(position.left, position.top); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " "to (%d, %d): %s (%d)", @@ -717,15 +728,15 @@ void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) { // drawing... // --------------------------------------------------------------------------- -void Layer::draw(const RenderArea& renderArea, const Region& clip) const { +void Layer::draw(const RenderArea& renderArea, const Region& clip) { onDraw(renderArea, clip, false); } -void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const { +void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) { onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform); } -void Layer::draw(const RenderArea& renderArea) const { +void Layer::draw(const RenderArea& renderArea) { onDraw(renderArea, Region(renderArea.getBounds()), false); } @@ -741,12 +752,12 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 0); } -void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) { - if (getBE().mHwcLayers.count(hwcId) == 0) { +void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc) { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; } - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), static_cast<int>(callIntoHwc)); @@ -764,33 +775,33 @@ void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callI } } -HWC2::Composition Layer::getCompositionType(int32_t hwcId) const { - if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { +HWC2::Composition Layer::getCompositionType(int32_t displayId) const { + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { // If we're querying the composition type for a display that does not // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - if (getBE().mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("getCompositionType called with an invalid HWC layer"); return HWC2::Composition::Invalid; } - return getBE().mHwcLayers.at(hwcId).compositionType; + return getBE().mHwcLayers.at(displayId).compositionType; } -void Layer::setClearClientTarget(int32_t hwcId, bool clear) { - if (getBE().mHwcLayers.count(hwcId) == 0) { +void Layer::setClearClientTarget(int32_t displayId, bool clear) { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setClearClientTarget called without a valid HWC layer"); return; } - getBE().mHwcLayers[hwcId].clearClientTarget = clear; + getBE().mHwcLayers[displayId].clearClientTarget = clear; } -bool Layer::getClearClientTarget(int32_t hwcId) const { - if (getBE().mHwcLayers.count(hwcId) == 0) { +bool Layer::getClearClientTarget(int32_t displayId) const { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("getClearClientTarget called without a valid HWC layer"); return false; } - return getBE().mHwcLayers.at(hwcId).clearClientTarget; + return getBE().mHwcLayers.at(displayId).clearClientTarget; } bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) { @@ -852,11 +863,12 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, rt = layerTransform.transform(rt); } - if (!s.finalCrop.isEmpty()) { - boundPoint(<, s.finalCrop); - boundPoint(&lb, s.finalCrop); - boundPoint(&rb, s.finalCrop); - boundPoint(&rt, s.finalCrop); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + boundPoint(<, finalCrop); + boundPoint(&lb, finalCrop); + boundPoint(&rb, finalCrop); + boundPoint(&rt, finalCrop); } Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); @@ -906,22 +918,22 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. - if (mCurrentState.barrierLayer != nullptr) { - sp<Layer> barrierLayer = mCurrentState.barrierLayer.promote(); + if (mCurrentState.barrierLayer_legacy != nullptr) { + sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction // to be applied as per normal (no synchronization). - mCurrentState.barrierLayer = nullptr; + mCurrentState.barrierLayer_legacy = nullptr; } else { - auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber); + auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy); if (barrierLayer->addSyncPoint(syncPoint)) { mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { // We already missed the frame we're supposed to synchronize // on, so go ahead and apply the state update - mCurrentState.barrierLayer = nullptr; + mCurrentState.barrierLayer_legacy = nullptr; } } @@ -943,7 +955,7 @@ void Layer::popPendingState(State* stateToCommit) { bool Layer::applyPendingStates(State* stateToCommit) { bool stateUpdateAvailable = false; while (!mPendingStates.empty()) { - if (mPendingStates[0].barrierLayer != nullptr) { + if (mPendingStates[0].barrierLayer_legacy != nullptr) { if (mRemoteSyncPoints.empty()) { // If we don't have a sync point for this, apply it anyway. It // will be visually wrong, but it should keep us from getting @@ -954,7 +966,8 @@ bool Layer::applyPendingStates(State* stateToCommit) { continue; } - if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) { + if (mRemoteSyncPoints.front()->getFrameNumber() != + mPendingStates[0].frameNumber_legacy) { ALOGE("[%s] Unexpected sync point frame number found", mName.string()); // Signal our end of the sync point and then dispose of it @@ -991,18 +1004,11 @@ bool Layer::applyPendingStates(State* stateToCommit) { return stateUpdateAvailable; } -uint32_t Layer::doTransaction(uint32_t flags) { - ATRACE_CALL(); - - pushPendingState(); - Layer::State c = getCurrentState(); - if (!applyPendingStates(&c)) { - return 0; - } - +uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const Layer::State& s(getDrawingState()); - const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h); + const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) || + (stateToCommit->requested_legacy.h != s.requested_legacy.h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer @@ -1012,16 +1018,19 @@ uint32_t Layer::doTransaction(uint32_t flags) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, - getEffectiveScalingMode(), c.active.w, c.active.h, c.crop.left, c.crop.top, - c.crop.right, c.crop.bottom, c.crop.getWidth(), c.crop.getHeight(), c.requested.w, - c.requested.h, s.active.w, s.active.h, s.crop.left, s.crop.top, s.crop.right, - s.crop.bottom, s.crop.getWidth(), s.crop.getHeight(), s.requested.w, - s.requested.h); + this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), + stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, + stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, + stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, + stateToCommit->crop_legacy.getWidth(), stateToCommit->crop_legacy.getHeight(), + stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h, + s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, + s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), + s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - setDefaultBufferSize(c.requested.w, c.requested.h); + setDefaultBufferSize(stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h); } // Don't let Layer::doTransaction update the drawing state @@ -1042,7 +1051,9 @@ uint32_t Layer::doTransaction(uint32_t flags) { // resizePending state is to avoid applying the state of the new buffer // to the old buffer. However in the state where we don't have an old buffer // there is no such concern but we may still be being used as a parent layer. - const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) && + const bool resizePending = + ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || + (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && (getBE().compositionInfo.mBuffer != nullptr); if (!isFixedSize()) { if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) { @@ -1066,21 +1077,37 @@ uint32_t Layer::doTransaction(uint32_t flags) { // being stored in the same data structure while having different latching rules. // b/38182305 // - // Careful that "c" and editCurrentState may not begin as equivalent due to + // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. if (mFreezeGeometryUpdates) { - float tx = c.active.transform.tx(); - float ty = c.active.transform.ty(); - c.active = c.requested; - c.active.transform.set(tx, ty); - editCurrentState.active = c.active; + float tx = stateToCommit->active_legacy.transform.tx(); + float ty = stateToCommit->active_legacy.transform.ty(); + stateToCommit->active_legacy = stateToCommit->requested_legacy; + stateToCommit->active_legacy.transform.set(tx, ty); + editCurrentState.active_legacy = stateToCommit->active_legacy; } else { - editCurrentState.active = editCurrentState.requested; - c.active = c.requested; + editCurrentState.active_legacy = editCurrentState.requested_legacy; + stateToCommit->active_legacy = stateToCommit->requested_legacy; } } - if (s.active != c.active) { + return flags; +} + +uint32_t Layer::doTransaction(uint32_t flags) { + ATRACE_CALL(); + + pushPendingState(); + Layer::State c = getCurrentState(); + if (!applyPendingStates(&c)) { + return 0; + } + + flags = doTransactionResize(flags, &c); + + const Layer::State& s(getDrawingState()); + + if (getActiveGeometry(c) != getActiveGeometry(s)) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } @@ -1091,8 +1118,8 @@ uint32_t Layer::doTransaction(uint32_t flags) { this->contentDirty = true; // we may use linear filtering, if the matrix scales us - const uint8_t type = c.active.transform.getType(); - mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE)); + const uint8_t type = getActiveTransform(c).getType(); + mNeedsFiltering = (!getActiveTransform(c).preserveRects() || (type >= Transform::SCALE)); } // If the layer is hidden, signal and clear out all local sync points so @@ -1120,20 +1147,21 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { } bool Layer::setPosition(float x, float y, bool immediate) { - if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y) + if (mCurrentState.requested_legacy.transform.tx() == x && + mCurrentState.requested_legacy.transform.ty() == y) return false; mCurrentState.sequence++; // We update the requested and active position simultaneously because // we want to apply the position portion of the transform matrix immediately, // but still delay scaling when resizing a SCALING_MODE_FREEZE layer. - mCurrentState.requested.transform.set(x, y); + mCurrentState.requested_legacy.transform.set(x, y); if (immediate && !mFreezeGeometryUpdates) { // Here we directly update the active state // unlike other setters, because we store it within // the transform, but use different latching rules. // b/38182305 - mCurrentState.active.transform.set(x, y); + mCurrentState.active_legacy.transform.set(x, y); } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1233,9 +1261,10 @@ bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relati } bool Layer::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; - mCurrentState.requested.w = w; - mCurrentState.requested.h = h; + if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h) + return false; + mCurrentState.requested_legacy.w = w; + mCurrentState.requested_legacy.h = h; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1273,13 +1302,15 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, return false; } mCurrentState.sequence++; - mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, + matrix.dsdy); mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } + bool Layer::setTransparentRegionHint(const Region& transparent) { - mCurrentState.requestedTransparentRegion = transparent; + mCurrentState.requestedTransparentRegion_legacy = transparent; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1294,12 +1325,12 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { return true; } -bool Layer::setCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedCrop == crop) return false; +bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { + if (mCurrentState.requestedCrop_legacy == crop) return false; mCurrentState.sequence++; - mCurrentState.requestedCrop = crop; + mCurrentState.requestedCrop_legacy = crop; if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.crop = crop; + mCurrentState.crop_legacy = crop; } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1308,12 +1339,12 @@ bool Layer::setCrop(const Rect& crop, bool immediate) { return true; } -bool Layer::setFinalCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedFinalCrop == crop) return false; +bool Layer::setFinalCrop_legacy(const Rect& crop, bool immediate) { + if (mCurrentState.requestedFinalCrop_legacy == crop) return false; mCurrentState.sequence++; - mCurrentState.requestedFinalCrop = crop; + mCurrentState.requestedFinalCrop_legacy = crop; if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.finalCrop = crop; + mCurrentState.finalCrop_legacy = crop; } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1353,24 +1384,23 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } -void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber) { - mCurrentState.barrierLayer = barrierLayer; - mCurrentState.frameNumber = frameNumber; +void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) { + mCurrentState.barrierLayer_legacy = barrierLayer; + mCurrentState.frameNumber_legacy = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral // request without any other state updates shouldn't actually induce a delay mCurrentState.modified = true; pushPendingState(); - mCurrentState.barrierLayer = nullptr; - mCurrentState.frameNumber = 0; + mCurrentState.barrierLayer_legacy = nullptr; + mCurrentState.frameNumber_legacy = 0; mCurrentState.modified = false; } -void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber) { +void Layer::deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, uint64_t frameNumber) { sp<Handle> handle = static_cast<Handle*>(barrierHandle.get()); - deferTransactionUntil(handle->owner.promote(), frameNumber); + deferTransactionUntil_legacy(handle->owner.promote(), frameNumber); } - // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- @@ -1397,13 +1427,13 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const { return usage; } -void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { +void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { // The transform hint is used to improve performance, but we can // only have a single transform hint, it cannot // apply to all displays. - const Transform& planeTransform(hw->getTransform()); + const Transform& planeTransform = display->getTransform(); orientation = planeTransform.getOrientation(); if (orientation & Transform::ROT_INVALID) { orientation = 0; @@ -1416,6 +1446,7 @@ void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { // debugging // ---------------------------------------------------------------------------- +// TODO(marissaw): add new layer state info to layer debugging LayerDebugInfo Layer::getLayerDebugInfo() const { LayerDebugInfo info; const Layer::State& ds = getDrawingState(); @@ -1423,27 +1454,27 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { sp<Layer> parent = getParent(); info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); info.mType = String8(getTypeId()); - info.mTransparentRegion = ds.activeTransparentRegion; + info.mTransparentRegion = ds.activeTransparentRegion_legacy; info.mVisibleRegion = visibleRegion; info.mSurfaceDamageRegion = surfaceDamageRegion; info.mLayerStack = getLayerStack(); - info.mX = ds.active.transform.tx(); - info.mY = ds.active.transform.ty(); + info.mX = ds.active_legacy.transform.tx(); + info.mY = ds.active_legacy.transform.ty(); info.mZ = ds.z; - info.mWidth = ds.active.w; - info.mHeight = ds.active.h; - info.mCrop = ds.crop; - info.mFinalCrop = ds.finalCrop; + info.mWidth = ds.active_legacy.w; + info.mHeight = ds.active_legacy.h; + info.mCrop = ds.crop_legacy; + info.mFinalCrop = ds.finalCrop_legacy; info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); info.mDataSpace = static_cast<android_dataspace>(mCurrentDataSpace); - info.mMatrix[0][0] = ds.active.transform[0][0]; - info.mMatrix[0][1] = ds.active.transform[0][1]; - info.mMatrix[1][0] = ds.active.transform[1][0]; - info.mMatrix[1][1] = ds.active.transform[1][1]; + info.mMatrix[0][0] = ds.active_legacy.transform[0][0]; + info.mMatrix[0][1] = ds.active_legacy.transform[0][1]; + info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; + info.mMatrix[1][1] = ds.active_legacy.transform[1][1]; { - sp<const GraphicBuffer> buffer = getBE().compositionInfo.mBuffer; + sp<const GraphicBuffer> buffer = mActiveBuffer; if (buffer != 0) { info.mActiveBufferWidth = buffer->getWidth(); info.mActiveBufferHeight = buffer->getHeight(); @@ -1464,19 +1495,22 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { } void Layer::miniDumpHeader(String8& result) { - result.append("----------------------------------------"); - result.append("---------------------------------------\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-----------------------------\n"); result.append(" Layer name\n"); result.append(" Z | "); result.append(" Comp Type | "); + result.append(" Transform | "); result.append(" Disp Frame (LTRB) | "); result.append(" Source Crop (LTRB)\n"); - result.append("----------------------------------------"); - result.append("---------------------------------------\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-----------------------------\n"); } -void Layer::miniDump(String8& result, int32_t hwcId) const { - if (getBE().mHwcLayers.count(hwcId) == 0) { +void Layer::miniDump(String8& result, int32_t displayId) const { + if (getBE().mHwcLayers.count(displayId) == 0) { return; } @@ -1494,20 +1528,22 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); - const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId); + const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId); if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { result.appendFormat(" rel %6d | ", layerState.z); } else { result.appendFormat(" %10d | ", layerState.z); } - result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str()); + result.appendFormat("%10s | ", to_string(getCompositionType(displayId)).c_str()); + result.appendFormat("%10s | ", to_string(hwcInfo.transform).c_str()); const Rect& frame = hwcInfo.displayFrame; result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); const FloatRect& crop = hwcInfo.sourceCrop; result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom); - result.append("- - - - - - - - - - - - - - - - - - - - "); - result.append("- - - - - - - - - - - - - - - - - - - -\n"); + result.append("- - - - - - - - - - - - - - - -"); + result.append("- - - - - - - - - - - - - - - -"); + result.append("- - - - - - - - - - - - - - -\n"); } void Layer::dumpFrameStats(String8& result) const { @@ -1885,14 +1921,14 @@ Transform Layer::getTransform() const { bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth(); bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight(); } - float sx = p->getDrawingState().active.w / static_cast<float>(bufferWidth); - float sy = p->getDrawingState().active.h / static_cast<float>(bufferHeight); + float sx = p->getActiveWidth(p->getDrawingState()) / static_cast<float>(bufferWidth); + float sy = p->getActiveHeight(p->getDrawingState()) / static_cast<float>(bufferHeight); Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; } } - return t * getDrawingState().active.transform; + return t * getActiveTransform(getDrawingState()); } half Layer::getAlpha() const { @@ -1921,7 +1957,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; - Transform requestedTransform = state.active.transform; + Transform requestedTransform = state.active_legacy.transform; Transform transform = getTransform(); layerInfo->set_id(sequence); @@ -1939,7 +1975,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) } } - LayerProtoHelper::writeToProto(state.activeTransparentRegion, + LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy, layerInfo->mutable_transparent_region()); LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region()); LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region()); @@ -1956,11 +1992,11 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) requestedPosition->set_y(requestedTransform.ty()); SizeProto* size = layerInfo->mutable_size(); - size->set_w(state.active.w); - size->set_h(state.active.h); + size->set_w(state.active_legacy.w); + size->set_h(state.active_legacy.h); - LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop()); - LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop()); + LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop()); + LayerProtoHelper::writeToProto(state.finalCrop_legacy, layerInfo->mutable_final_crop()); layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); @@ -1990,6 +2026,8 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) auto buffer = getBE().compositionInfo.mBuffer; if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer()); + LayerProtoHelper::writeToProto(Transform(mCurrentTransform), + layerInfo->mutable_buffer_transform()); } layerInfo->set_queued_frames(getQueuedFrameCount()); @@ -1999,19 +2037,23 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_curr_frame(mCurrentFrameNumber); for (const auto& pendingState : mPendingStates) { - auto barrierLayer = pendingState.barrierLayer.promote(); + auto barrierLayer = pendingState.barrierLayer_legacy.promote(); if (barrierLayer != nullptr) { BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); barrierLayerProto->set_id(barrierLayer->sequence); - barrierLayerProto->set_frame_number(pendingState.frameNumber); + barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); } } } -void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { +void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) { + if (!hasHwcLayer(displayId)) { + return; + } + writeToProto(layerInfo, LayerVector::StateSet::Drawing); - const auto& hwcInfo = getBE().mHwcLayers.at(hwcId); + const auto& hwcInfo = getBE().mHwcLayers.at(displayId); const Rect& frame = hwcInfo.displayFrame; LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 22396796ed..a48cdffd8b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -38,6 +38,7 @@ #include "Client.h" #include "FrameTracker.h" +#include "LayerBE.h" #include "LayerVector.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" @@ -74,70 +75,6 @@ class SurfaceInterceptor; // --------------------------------------------------------------------------- -struct CompositionInfo { - HWC2::Composition compositionType; - sp<GraphicBuffer> mBuffer = nullptr; - int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; - struct { - HWComposer* hwc; - sp<Fence> fence; - HWC2::BlendMode blendMode; - Rect displayFrame; - float alpha; - FloatRect sourceCrop; - HWC2::Transform transform; - int z; - int type; - int appId; - Region visibleRegion; - Region surfaceDamage; - sp<NativeHandle> sidebandStream; - android_dataspace dataspace; - hwc_color_t color; - } hwc; - struct { - RE::RenderEngine* renderEngine; - Mesh* mesh; - } renderEngine; -}; - -class LayerBE { -public: - LayerBE(); - - // The mesh used to draw the layer in GLES composition mode - Mesh mMesh; - - // HWC items, accessed from the main thread - struct HWCInfo { - HWCInfo() - : hwc(nullptr), - layer(nullptr), - forceClientComposition(false), - compositionType(HWC2::Composition::Invalid), - clearClientTarget(false), - transform(HWC2::Transform::None) {} - - HWComposer* hwc; - HWC2::Layer* layer; - bool forceClientComposition; - HWC2::Composition compositionType; - bool clearClientTarget; - Rect displayFrame; - FloatRect sourceCrop; - HWComposerBufferCache bufferCache; - HWC2::Transform transform; - }; - - // A layer can be attached to multiple displays when operating in mirror mode - // (a.k.a: when several displays are attached with equal layerStack). In this - // case we need to keep track. In non-mirror mode, a layer will have only one - // HWCInfo. This map key is a display layerStack. - std::unordered_map<int32_t, HWCInfo> mHwcLayers; - - CompositionInfo compositionInfo; -}; - class Layer : public virtual RefBase { static int32_t sSequence; @@ -174,8 +111,8 @@ public: }; struct State { - Geometry active; - Geometry requested; + Geometry active_legacy; + Geometry requested_legacy; int32_t z; // The identifier of the layer stack this layer belongs to. A layer can @@ -191,23 +128,23 @@ public: bool modified; // Crop is expressed in layer space coordinate. - Rect crop; - Rect requestedCrop; + Rect crop_legacy; + Rect requestedCrop_legacy; // finalCrop is expressed in display space coordinate. - Rect finalCrop; - Rect requestedFinalCrop; + Rect finalCrop_legacy; + Rect requestedFinalCrop_legacy; // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber - wp<Layer> barrierLayer; - uint64_t frameNumber; + wp<Layer> barrierLayer_legacy; + uint64_t frameNumber_legacy; // the transparentRegion hint is a bit special, it's latched only // when we receive a buffer -- this is because it's "content" // dependent. - Region activeTransparentRegion; - Region requestedTransparentRegion; + Region activeTransparentRegion_legacy; + Region requestedTransparentRegion_legacy; int32_t appId; int32_t type; @@ -219,6 +156,24 @@ public: SortedVector<wp<Layer>> zOrderRelatives; half4 color; + + // The fields below this point are only used by BufferStateLayer + Geometry active; + + uint32_t transform; + bool transformToDisplayInverse; + + Rect crop; + Region transparentRegionHint; + + sp<GraphicBuffer> buffer; + sp<Fence> acquireFence; + ui::Dataspace dataspace; + HdrMetadata hdrMetadata; + Region surfaceDamageRegion; + int32_t api; + + sp<NativeHandle> sidebandStream; }; Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, @@ -254,11 +209,12 @@ public: // also the rendered size of the layer prior to any transformations. Parent // or local matrix transformations will not affect the size of the buffer, // but may affect it's on-screen size or clipping. - bool setSize(uint32_t w, uint32_t h); + virtual bool setSize(uint32_t w, uint32_t h); // Set a 2x2 transformation matrix on the layer. This transform // will be applied after parent transforms, but before any final // producer specified transform. - bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms); + virtual bool setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms); // This second set of geometry attributes are controlled by // setGeometryAppliesWithResize, and their default mode is to be @@ -268,32 +224,45 @@ public: // setPosition operates in parent buffer space (pre parent-transform) or display // space for top-level layers. - bool setPosition(float x, float y, bool immediate); + virtual bool setPosition(float x, float y, bool immediate); // Buffer space - bool setCrop(const Rect& crop, bool immediate); + virtual bool setCrop_legacy(const Rect& crop, bool immediate); // Parent buffer space/display space - bool setFinalCrop(const Rect& crop, bool immediate); + virtual bool setFinalCrop_legacy(const Rect& crop, bool immediate); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? // ----------------------------------------------------------------------- - bool setLayer(int32_t z); - bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ); - - bool setAlpha(float alpha); - bool setColor(const half3& color); - bool setTransparentRegionHint(const Region& transparent); - bool setFlags(uint8_t flags, uint8_t mask); - bool setLayerStack(uint32_t layerStack); - uint32_t getLayerStack() const; - void deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber); - void deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber); - bool setOverrideScalingMode(int32_t overrideScalingMode); - void setInfo(int32_t type, int32_t appId); - bool reparentChildren(const sp<IBinder>& layer); - void setChildrenDrawingParent(const sp<Layer>& layer); - bool reparent(const sp<IBinder>& newParentHandle); - bool detachChildren(); + virtual bool setLayer(int32_t z); + virtual bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ); + + virtual bool setAlpha(float alpha); + virtual bool setColor(const half3& color); + virtual bool setTransparentRegionHint(const Region& transparent); + virtual bool setFlags(uint8_t flags, uint8_t mask); + virtual bool setLayerStack(uint32_t layerStack); + virtual uint32_t getLayerStack() const; + virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, + uint64_t frameNumber); + virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber); + virtual bool setOverrideScalingMode(int32_t overrideScalingMode); + virtual void setInfo(int32_t type, int32_t appId); + virtual bool reparentChildren(const sp<IBinder>& layer); + virtual void setChildrenDrawingParent(const sp<Layer>& layer); + virtual bool reparent(const sp<IBinder>& newParentHandle); + virtual bool detachChildren(); + + // Used only to set BufferStateLayer state + virtual bool setTransform(uint32_t /*transform*/) { return false; }; + virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; + virtual bool setCrop(const Rect& /*crop*/) { return false; }; + virtual bool setBuffer(sp<GraphicBuffer> /*buffer*/) { return false; }; + virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; }; + virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; }; + virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; }; + virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; + virtual bool setApi(int32_t /*api*/) { return false; }; + virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/) { return false; }; ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } @@ -371,32 +340,44 @@ public: void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); - void writeToProto(LayerProto* layerInfo, int32_t hwcId); + void writeToProto(LayerProto* layerInfo, int32_t displayId); + + virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; } + virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; } + virtual uint32_t getActiveHeight(const Layer::State& s) const { return s.active_legacy.h; } + virtual Transform getActiveTransform(const Layer::State& s) const { + return s.active_legacy.transform; + } + virtual Region getActiveTransparentRegion(const Layer::State& s) const { + return s.activeTransparentRegion_legacy; + } + virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } + virtual Rect getFinalCrop(const Layer::State& s) const { return s.finalCrop_legacy; } protected: /* * onDraw - draws the surface. */ virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const = 0; + bool useIdentityTransform) = 0; public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} virtual bool isHdrY410() const { return false; } - void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z); - void forceClientComposition(int32_t hwcId); - bool getForceClientComposition(int32_t hwcId); - virtual void setPerFrameData(const sp<const DisplayDevice>& displayDevice) = 0; + void setGeometry(const sp<const DisplayDevice>& display, uint32_t z); + void forceClientComposition(int32_t displayId); + bool getForceClientComposition(int32_t displayId); + virtual void setPerFrameData(const sp<const DisplayDevice>& display) = 0; // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state - void setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc = true); - HWC2::Composition getCompositionType(int32_t hwcId) const; - void setClearClientTarget(int32_t hwcId, bool clear); - bool getClearClientTarget(int32_t hwcId) const; - void updateCursorPosition(const sp<const DisplayDevice>& hw); + void setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc = true); + HWC2::Composition getCompositionType(int32_t displayId) const; + void setClearClientTarget(int32_t displayId, bool clear); + bool getClearClientTarget(int32_t displayId) const; + void updateCursorPosition(const sp<const DisplayDevice>& display); /* * called after page-flip @@ -432,9 +413,19 @@ public: * draw - performs some global clipping optimizations * and calls onDraw(). */ - void draw(const RenderArea& renderArea, const Region& clip) const; - void draw(const RenderArea& renderArea, bool useIdentityTransform) const; - void draw(const RenderArea& renderArea) const; + void draw(const RenderArea& renderArea, const Region& clip); + void draw(const RenderArea& renderArea, bool useIdentityTransform); + void draw(const RenderArea& renderArea); + + /* + * drawNow uses the renderEngine to draw the layer. This is different than the + * draw function as with the FE/BE split, the draw function runs in the FE and + * sets up state for the BE to do the actual drawing. drawNow is used to tell + * the layer to skip the state setup and just go ahead and draw the layer. This + * is used for screen captures which happens separately from the frame + * compositing path. + */ + virtual void drawNow(const RenderArea& renderArea, bool useIdentityTransform) = 0; /* * doTransaction - process the transaction. This is a good place to figure @@ -478,7 +469,6 @@ public: virtual bool isBufferLatched() const { return false; } - bool isPotentialCursor() const { return mPotentialCursor; } /* * called with the state lock from a binder thread when the layer is * removed from the current list to the pending removal list @@ -493,7 +483,7 @@ public: // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. - void updateTransformHint(const sp<const DisplayDevice>& hw) const; + void updateTransformHint(const sp<const DisplayDevice>& display) const; /* * returns the rectangle that crops the content of the layer and scales it @@ -502,29 +492,25 @@ public: Rect getContentCrop() const; /* - * Returns if a frame is queued. + * Returns if a frame is ready */ - bool hasQueuedFrame() const { - return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; - } + virtual bool hasReadyFrame() const { return false; } - int32_t getQueuedFrameCount() const { return mQueuedFrames; } + virtual int32_t getQueuedFrameCount() const { return 0; } // ----------------------------------------------------------------------- - bool createHwcLayer(HWComposer* hwc, int32_t hwcId); - bool destroyHwcLayer(int32_t hwcId); + bool createHwcLayer(HWComposer* hwc, int32_t displayId); + bool destroyHwcLayer(int32_t displayId); void destroyAllHwcLayers(); - bool hasHwcLayer(int32_t hwcId) { - return getBE().mHwcLayers.count(hwcId) > 0; - } + bool hasHwcLayer(int32_t displayId) { return getBE().mHwcLayers.count(displayId) > 0; } - HWC2::Layer* getHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { + HWC2::Layer* getHwcLayer(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { return nullptr; } - return getBE().mHwcLayers[hwcId].layer; + return getBE().mHwcLayers[displayId].layer; } // ----------------------------------------------------------------------- @@ -542,7 +528,7 @@ public: /* always call base class first */ static void miniDumpHeader(String8& result); - void miniDump(String8& result, int32_t hwcId) const; + void miniDump(String8& result, int32_t displayId) const; void dumpFrameStats(String8& result) const; void dumpFrameEvents(String8& result); void clearFrameStats(); @@ -594,7 +580,7 @@ public: // SurfaceFlinger to complete a transaction. void commitChildList(); int32_t getZ() const; - void pushPendingState(); + virtual void pushPendingState(); protected: // constant @@ -626,12 +612,12 @@ protected: uint32_t getEffectiveUsage(uint32_t usage) const; - FloatRect computeCrop(const sp<const DisplayDevice>& hw) const; + virtual FloatRect computeCrop(const sp<const DisplayDevice>& display) const; // Compute the initial crop as specified by parent layers and the // SurfaceControl for this layer. Does not include buffer crop from the // IGraphicBufferProducer client, as that should not affect child clipping. // Returns in screen space. - Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const; + Rect computeInitialCrop(const sp<const DisplayDevice>& display) const; // drawing void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, @@ -678,7 +664,8 @@ protected: bool addSyncPoint(const std::shared_ptr<SyncPoint>& point); void popPendingState(State* stateToCommit); - bool applyPendingStates(State* stateToCommit); + virtual bool applyPendingStates(State* stateToCommit); + virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); void clearSyncPoints(); @@ -729,10 +716,6 @@ protected: Mutex mPendingStateMutex; Vector<State> mPendingStates; - // thread-safe - volatile int32_t mQueuedFrames; - volatile int32_t mSidebandStreamChanged; // used like an atomic boolean - // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; @@ -746,15 +729,12 @@ protected: TimeStats& mTimeStats = TimeStats::getInstance(); // main thread - int mActiveBufferSlot; sp<GraphicBuffer> mActiveBuffer; - sp<NativeHandle> mSidebandStream; ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; Rect mCurrentCrop; uint32_t mCurrentTransform; // We encode unset as -1. int32_t mOverrideScalingMode; - bool mCurrentOpacity; std::atomic<uint64_t> mCurrentFrameNumber; bool mFrameLatencyNeeded; // Whether filtering is forced on or not @@ -775,12 +755,6 @@ protected: // This layer can be a cursor on some displays. bool mPotentialCursor; - // Local copy of the queued contents of the incoming BufferQueue - mutable Mutex mQueueItemLock; - Condition mQueueItemCondition; - Vector<BufferItem> mQueueItems; - std::atomic<uint64_t> mLastFrameNumberReceived; - bool mAutoRefresh; bool mFreezeGeometryUpdates; // Child list about to be committed/used for editing. diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp new file mode 100644 index 0000000000..51b615b586 --- /dev/null +++ b/services/surfaceflinger/LayerBE.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 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 LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "LayerBE" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "Layer.h" + +namespace android { + +LayerBE::LayerBE(Layer* layer, std::string layerName) + : mLayer(layer), + mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { + compositionInfo.layer = this; + compositionInfo.layerName = layerName; +} + +void LayerBE::onLayerDisplayed(const sp<Fence>& releaseFence) { + mLayer->onLayerDisplayed(releaseFence); +} + +void CompositionInfo::dumpHwc(const char* tag) const { + ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer); + ALOGV("[%s]\tfence=%p", tag, hwc.fence.get()); + ALOGV("[%s]\ttransform=%d", tag, hwc.transform); + ALOGV("[%s]\tz=%d", tag, hwc.z); + ALOGV("[%s]\ttype=%d", tag, hwc.type); + ALOGV("[%s]\tappId=%d", tag, hwc.appId); + ALOGV("[%s]\tdisplayFrame=%4d %4d %4d %4d", tag, hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom); + ALOGV("[%s]\talpha=%.3f", tag, hwc.alpha); + ALOGV("[%s]\tsourceCrop=%6.1f %6.1f %6.1f %6.1f", tag, hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom); + + std::string label = tag; + label+=":visibleRegion"; + hwc.visibleRegion.dump(label.c_str()); + label = tag; + label+=":surfaceDamage"; + hwc.surfaceDamage.dump(label.c_str()); +} + +void CompositionInfo::dumpRe(const char* tag) const { + ALOGV("[%s]\tblackoutLayer=%d", tag, re.blackoutLayer); + ALOGV("[%s]\tclearArea=%d", tag, re.clearArea); + ALOGV("[%s]\tpreMultipliedAlpha=%d", tag, re.preMultipliedAlpha); + ALOGV("[%s]\topaque=%d", tag, re.opaque); + ALOGV("[%s]\tdisableTexture=%d", tag, re.disableTexture); + ALOGV("[%s]\ttexture:name(%d), target(%d), size(%d/%d)", tag, re.texture.getTextureName(), re.texture.getTextureTarget(), (unsigned int)re.texture.getWidth(), (unsigned int)re.texture.getHeight()); + ALOGV("[%s]\tuseIdentityTransform=%d\n", tag, re.useIdentityTransform); +} + +void CompositionInfo::dump(const char* tag) const { + ALOGV("[%s] CompositionInfo", tag); + ALOGV("[%s]\tLayerName: %s", tag, layerName.c_str()); + ALOGV("[%s]\tCompositionType: %d", tag, compositionType); + ALOGV("[%s]\tmBuffer = %p", tag, mBuffer.get()); + ALOGV("[%s]\tmBufferSlot=%d", tag, mBufferSlot); + switch (compositionType) { + case HWC2::Composition::Device: + dumpHwc(tag); + break; + case HWC2::Composition::Client: + dumpRe(tag); + default: + break; + } +} + +}; // namespace android diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h new file mode 100644 index 0000000000..b5acebafb1 --- /dev/null +++ b/services/surfaceflinger/LayerBE.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <stdint.h> +#include <sys/types.h> + +#include <ui/Region.h> + +#include "SurfaceFlinger.h" + +#include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/HWComposerBufferCache.h" +#include "RenderEngine/Mesh.h" +#include "RenderEngine/Texture.h" + +namespace android { + +class LayerBE; + +struct CompositionInfo { + std::string layerName; + HWC2::Composition compositionType; + sp<GraphicBuffer> mBuffer = nullptr; + int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; + LayerBE* layer = nullptr; + struct { + HWC2::Layer* hwcLayer; + sp<Fence> fence; + HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; + Rect displayFrame; + float alpha; + FloatRect sourceCrop; + HWC2::Transform transform = HWC2::Transform::None; + int z; + int type; + int appId; + Region visibleRegion; + Region surfaceDamage; + sp<NativeHandle> sidebandStream; + ui::Dataspace dataspace; + hwc_color_t color; + } hwc; + struct { + Mesh* mesh; + bool blackoutLayer = false; + bool clearArea = false; + bool preMultipliedAlpha = false; + bool opaque = false; + bool disableTexture = false; + half4 color; + Texture texture; + bool useIdentityTransform = false; + bool Y410BT2020 = false; + } re; + + void dump(const char* tag) const; + void dumpHwc(const char* tag) const; + void dumpRe(const char* tag) const; +}; + +class LayerBE { +public: + friend class Layer; + friend class BufferLayer; + friend class BufferQueueLayer; + friend class BufferStateLayer; + friend class ColorLayer; + friend class SurfaceFlinger; + + LayerBE(Layer* layer, std::string layerName); + + void onLayerDisplayed(const sp<Fence>& releaseFence); + Mesh& getMesh() { return mMesh; } + +private: + Layer*const mLayer; + // The mesh used to draw the layer in GLES composition mode + Mesh mMesh; + + // HWC items, accessed from the main thread + struct HWCInfo { + HWCInfo() + : hwc(nullptr), + layer(nullptr), + forceClientComposition(false), + compositionType(HWC2::Composition::Invalid), + clearClientTarget(false), + transform(HWC2::Transform::None) {} + + HWComposer* hwc; + HWC2::Layer* layer; + bool forceClientComposition; + HWC2::Composition compositionType; + bool clearClientTarget; + Rect displayFrame; + FloatRect sourceCrop; + HWComposerBufferCache bufferCache; + HWC2::Transform transform; + }; + + + // A layer can be attached to multiple displays when operating in mirror mode + // (a.k.a: when several displays are attached with equal layerStack). In this + // case we need to keep track. In non-mirror mode, a layer will have only one + // HWCInfo. This map key is a display layerStack. + std::unordered_map<int32_t, HWCInfo> mHwcLayers; + + CompositionInfo compositionInfo; +}; + +}; // namespace android + diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index a5f0b9878c..70558d4cc8 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -31,6 +31,7 @@ LayerRejecter::LayerRejecter(Layer::State& front, bool stickySet, const char* name, int32_t overrideScalingMode, + bool transformToDisplayInverse, bool& freezePositionUpdates) : mFront(front), mCurrent(current), @@ -38,6 +39,7 @@ LayerRejecter::LayerRejecter(Layer::State& front, mStickyTransformSet(stickySet), mName(name), mOverrideScalingMode(overrideScalingMode), + mTransformToDisplayInverse(transformToDisplayInverse), mFreezeGeometryUpdates(freezePositionUpdates) {} bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) { @@ -54,22 +56,30 @@ bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) swap(bufWidth, bufHeight); } + if (mTransformToDisplayInverse) { + uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + if (invTransform & Transform::ROT_90) { + swap(bufWidth, bufHeight); + } + } + int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode; bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; - if (mFront.active != mFront.requested) { - if (isFixedSize || (bufWidth == mFront.requested.w && bufHeight == mFront.requested.h)) { + if (mFront.active_legacy != mFront.requested_legacy) { + if (isFixedSize || + (bufWidth == mFront.requested_legacy.w && bufHeight == mFront.requested_legacy.h)) { // Here we pretend the transaction happened by updating the // current and drawing states. Drawing state is only accessed // in this thread, no need to have it locked - mFront.active = mFront.requested; + mFront.active_legacy = mFront.requested_legacy; // We also need to update the current state so that // we don't end-up overwriting the drawing state with // this stale current state during the next transaction // // NOTE: We don't need to hold the transaction lock here - // because State::active is only accessed from this thread. - mCurrent.active = mFront.active; + // because State::active_legacy is only accessed from this thread. + mCurrent.active_legacy = mFront.active_legacy; mCurrent.modified = true; // recompute visible region @@ -77,35 +87,37 @@ bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) mFreezeGeometryUpdates = false; - if (mFront.crop != mFront.requestedCrop) { - mFront.crop = mFront.requestedCrop; - mCurrent.crop = mFront.requestedCrop; + if (mFront.crop_legacy != mFront.requestedCrop_legacy) { + mFront.crop_legacy = mFront.requestedCrop_legacy; + mCurrent.crop_legacy = mFront.requestedCrop_legacy; mRecomputeVisibleRegions = true; } - if (mFront.finalCrop != mFront.requestedFinalCrop) { - mFront.finalCrop = mFront.requestedFinalCrop; - mCurrent.finalCrop = mFront.requestedFinalCrop; + if (mFront.finalCrop_legacy != mFront.requestedFinalCrop_legacy) { + mFront.finalCrop_legacy = mFront.requestedFinalCrop_legacy; + mCurrent.finalCrop_legacy = mFront.requestedFinalCrop_legacy; mRecomputeVisibleRegions = true; } } ALOGD_IF(DEBUG_RESIZE, "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" - " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) " + " drawing={ active_legacy ={ wh={%4u,%4u} crop_legacy={%4d,%4d,%4d,%4d} " + "(%4d,%4d) " "}\n" - " requested={ wh={%4u,%4u} }}\n", - mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, mFront.active.w, - mFront.active.h, mFront.crop.left, mFront.crop.top, mFront.crop.right, - mFront.crop.bottom, mFront.crop.getWidth(), mFront.crop.getHeight(), - mFront.requested.w, mFront.requested.h); + " requested_legacy={ wh={%4u,%4u} }}\n", + mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, + mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left, + mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom, + mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(), + mFront.requested_legacy.w, mFront.requested_legacy.h); } if (!isFixedSize && !mStickyTransformSet) { - if (mFront.active.w != bufWidth || mFront.active.h != bufHeight) { + if (mFront.active_legacy.w != bufWidth || mFront.active_legacy.h != bufHeight) { // reject this buffer ALOGE("[%s] rejecting buffer: " - "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}", - mName, bufWidth, bufHeight, mFront.active.w, mFront.active.h); + "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}", + mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h); return true; } } @@ -118,16 +130,17 @@ bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) // We latch the transparent region here, instead of above where we latch // the rest of the geometry because it is only content but not necessarily // resize dependent. - if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) { - mFront.activeTransparentRegion = mFront.requestedTransparentRegion; + if (!mFront.activeTransparentRegion_legacy.isTriviallyEqual( + mFront.requestedTransparentRegion_legacy)) { + mFront.activeTransparentRegion_legacy = mFront.requestedTransparentRegion_legacy; // We also need to update the current state so that // we don't end-up overwriting the drawing state with // this stale current state during the next transaction // // NOTE: We don't need to hold the transaction lock here - // because State::active is only accessed from this thread. - mCurrent.activeTransparentRegion = mFront.activeTransparentRegion; + // because State::active_legacy is only accessed from this thread. + mCurrent.activeTransparentRegion_legacy = mFront.activeTransparentRegion_legacy; // recompute visible region mRecomputeVisibleRegions = true; diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h index 40972aac87..63d51de0ca 100644 --- a/services/surfaceflinger/LayerRejecter.h +++ b/services/surfaceflinger/LayerRejecter.h @@ -29,6 +29,7 @@ namespace android { bool stickySet, const char *name, int32_t overrideScalingMode, + bool transformToDisplayInverse, bool &freezePositionUpdates); virtual bool reject(const sp<GraphicBuffer> &buf, const BufferItem &item); @@ -40,6 +41,7 @@ namespace android { bool mStickyTransformSet; const char *mName; int32_t mOverrideScalingMode; + bool mTransformToDisplayInverse; bool &mFreezeGeometryUpdates; }; } // namespace android diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp index dc09a376bb..23480b412e 100644 --- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp +++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp @@ -99,10 +99,6 @@ void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExt if (hasEGLExtension("EGL_KHR_wait_sync")) { mHasWaitSync = true; } - - if (hasEGLExtension("EGL_ANDROID_image_crop")) { - mHasImageCrop = true; - } if (hasEGLExtension("EGL_EXT_protected_content")) { mHasProtectedContent = true; } diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h index 0d8c10b0ac..a6a5053f89 100644 --- a/services/surfaceflinger/RenderEngine/GLExtensions.h +++ b/services/surfaceflinger/RenderEngine/GLExtensions.h @@ -39,7 +39,6 @@ class GLExtensions : public Singleton<GLExtensions> { bool mHasNativeFenceSync = false; bool mHasFenceSync = false; bool mHasWaitSync = false; - bool mHasImageCrop = false; bool mHasProtectedContent = false; bool mHasContextPriority = false; @@ -66,7 +65,6 @@ public: bool hasNativeFenceSync() const { return mHasNativeFenceSync; } bool hasFenceSync() const { return mHasFenceSync; } bool hasWaitSync() const { return mHasWaitSync; } - bool hasImageCrop() const { return mHasImageCrop; } bool hasProtectedContent() const { return mHasProtectedContent; } bool hasContextPriority() const { return mHasContextPriority; } diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/Image.cpp index 0d06422a41..6e0a8803e9 100644 --- a/services/surfaceflinger/RenderEngine/Image.cpp +++ b/services/surfaceflinger/RenderEngine/Image.cpp @@ -33,11 +33,10 @@ namespace impl { Image::Image(const RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {} Image::~Image() { - setNativeWindowBuffer(nullptr, false, 0, 0); + setNativeWindowBuffer(nullptr, false); } -static std::vector<EGLint> buildAttributeList(bool isProtected, int32_t cropWidth, - int32_t cropHeight) { +static std::vector<EGLint> buildAttributeList(bool isProtected) { std::vector<EGLint> attrs; attrs.reserve(16); @@ -49,24 +48,12 @@ static std::vector<EGLint> buildAttributeList(bool isProtected, int32_t cropWidt attrs.push_back(EGL_TRUE); } - if (cropWidth > 0 && cropHeight > 0) { - attrs.push_back(EGL_IMAGE_CROP_LEFT_ANDROID); - attrs.push_back(0); - attrs.push_back(EGL_IMAGE_CROP_TOP_ANDROID); - attrs.push_back(0); - attrs.push_back(EGL_IMAGE_CROP_RIGHT_ANDROID); - attrs.push_back(cropWidth); - attrs.push_back(EGL_IMAGE_CROP_BOTTOM_ANDROID); - attrs.push_back(cropHeight); - } - attrs.push_back(EGL_NONE); return attrs; } -bool Image::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth, - int32_t cropHeight) { +bool Image::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) { if (mEGLImage != EGL_NO_IMAGE_KHR) { if (!eglDestroyImageKHR(mEGLDisplay, mEGLImage)) { ALOGE("failed to destroy image: %#x", eglGetError()); @@ -75,7 +62,7 @@ bool Image::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, } if (buffer) { - std::vector<EGLint> attrs = buildAttributeList(isProtected, cropWidth, cropHeight); + std::vector<EGLint> attrs = buildAttributeList(isProtected); mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, static_cast<EGLClientBuffer>(buffer), attrs.data()); if (mEGLImage == EGL_NO_IMAGE_KHR) { diff --git a/services/surfaceflinger/RenderEngine/Image.h b/services/surfaceflinger/RenderEngine/Image.h index 1ae7e09cba..c38fe0a2ff 100644 --- a/services/surfaceflinger/RenderEngine/Image.h +++ b/services/surfaceflinger/RenderEngine/Image.h @@ -29,8 +29,7 @@ namespace RE { class Image { public: virtual ~Image() = 0; - virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, - int32_t cropWidth, int32_t cropHeight) = 0; + virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) = 0; }; namespace impl { @@ -45,8 +44,7 @@ public: Image(const Image&) = delete; Image& operator=(const Image&) = delete; - bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth, - int32_t cropHeight) override; + bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override; private: // methods internal to RenderEngine diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index d745770bb7..39f7e30396 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -29,6 +29,7 @@ #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <configstore/Utils.h> +#include <private/gui/SyncFeatures.h> using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; @@ -175,8 +176,12 @@ EGLConfig RenderEngine::getEGLConfig() const { return mEGLConfig; } -bool RenderEngine::supportsImageCrop() const { - return GLExtensions::getInstance().hasImageCrop(); +bool RenderEngine::useNativeFenceSync() const { + return SyncFeatures::getInstance().useNativeFenceSync(); +} + +bool RenderEngine::useWaitSync() const { + return SyncFeatures::getInstance().useWaitSync(); } bool RenderEngine::isCurrent() const { diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 1786155486..40bc966fd1 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -69,7 +69,8 @@ public: // dump the extension strings. always call the base class. virtual void dump(String8& result) = 0; - virtual bool supportsImageCrop() const = 0; + virtual bool useNativeFenceSync() const = 0; + virtual bool useWaitSync() const = 0; virtual bool isCurrent() const = 0; virtual bool setCurrentSurface(const RE::Surface& surface) = 0; @@ -192,7 +193,8 @@ public: // dump the extension strings. always call the base class. void dump(String8& result) override; - bool supportsImageCrop() const override; + bool useNativeFenceSync() const override; + bool useWaitSync() const override; bool isCurrent() const; bool setCurrentSurface(const RE::Surface& surface) override; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cf53930fa1..31e44449b3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -63,6 +63,8 @@ #include <private/gui/SyncFeatures.h> #include "BufferLayer.h" +#include "BufferQueueLayer.h" +#include "BufferStateLayer.h" #include "Client.h" #include "ColorLayer.h" #include "Colorizer.h" @@ -79,6 +81,7 @@ #include "clz.h" #include "DisplayHardware/ComposerHal.h" +#include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" @@ -113,6 +116,33 @@ using ui::Hdr; using ui::RenderIntent; namespace { + +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wswitch-enum" + +bool isWideColorMode(const ColorMode colorMode) { + switch (colorMode) { + case ColorMode::DISPLAY_P3: + case ColorMode::ADOBE_RGB: + case ColorMode::DCI_P3: + case ColorMode::BT2020: + case ColorMode::BT2100_PQ: + case ColorMode::BT2100_HLG: + return true; + case ColorMode::NATIVE: + case ColorMode::STANDARD_BT601_625: + case ColorMode::STANDARD_BT601_625_UNADJUSTED: + case ColorMode::STANDARD_BT601_525: + case ColorMode::STANDARD_BT601_525_UNADJUSTED: + case ColorMode::STANDARD_BT709: + case ColorMode::SRGB: + return false; + } + return false; +} + +#pragma clang diagnostic pop + class ConditionalLock { public: ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) { @@ -125,6 +155,7 @@ private: Mutex& mMutex; bool mLocked; }; + } // namespace anonymous // --------------------------------------------------------------------------- @@ -219,7 +250,7 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mLayersAdded(false), mRepaintEverything(0), mBootTime(systemTime()), - mBuiltinDisplays(), + mDisplayTokens(), mVisibleRegionsDirty(false), mGeometryInvalid(false), mAnimCompositionPending(false), @@ -233,7 +264,6 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mDebugInTransaction(0), mLastTransactionTime(0), mForceFullDamage(false), - mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), mHWVsyncAvailable(false), mHasPoweredOff(false), @@ -294,7 +324,13 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { } ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation); - mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset); + // Note: We create a local temporary with the real DispSync implementation + // type temporarily so we can initialize it with the configured values, + // before storing it for more generic use using the interface type. + auto primaryDispSync = std::make_unique<impl::DispSync>("PrimaryDispSync"); + primaryDispSync->init(SurfaceFlinger::hasSyncFramework, + SurfaceFlinger::dispSyncPresentTimeOffset); + mPrimaryDispSync = std::move(primaryDispSync); // debugging stuff... char value[PROPERTY_VALUE_MAX]; @@ -322,7 +358,7 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { property_get("debug.sf.enable_hwc_vds", value, "0"); mUseHwcVirtualDisplays = atoi(value); - ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays"); + ALOGI_IF(mUseHwcVirtualDisplays, "Enabling HWC virtual displays"); property_get("ro.sf.disable_triple_buffer", value, "1"); mLayerTripleBufferingDisabled = atoi(value); @@ -433,28 +469,30 @@ sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, sp<BBinder> token = new DisplayToken(this); Mutex::Autolock _l(mStateLock); - DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure); + DisplayDeviceState info; + info.type = DisplayDevice::DISPLAY_VIRTUAL; info.displayName = displayName; + info.isSecure = secure; mCurrentState.displays.add(token, info); mInterceptor->saveDisplayCreation(info); return token; } -void SurfaceFlinger::destroyDisplay(const sp<IBinder>& display) { +void SurfaceFlinger::destroyDisplay(const sp<IBinder>& displayToken) { Mutex::Autolock _l(mStateLock); - ssize_t idx = mCurrentState.displays.indexOfKey(display); + ssize_t idx = mCurrentState.displays.indexOfKey(displayToken); if (idx < 0) { - ALOGW("destroyDisplay: invalid display token"); + ALOGE("destroyDisplay: Invalid display token %p", displayToken.get()); return; } const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); - if (!info.isVirtualDisplay()) { + if (!info.isVirtual()) { ALOGE("destroyDisplay called for non-virtual display"); return; } - mInterceptor->saveDisplayDeletion(info.displayId); + mInterceptor->saveDisplayDeletion(info.sequenceId); mCurrentState.displays.removeItemsAt(idx); setTransactionFlags(eDisplayTransactionNeeded); } @@ -464,7 +502,7 @@ sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) { ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id); return nullptr; } - return mBuiltinDisplays[id]; + return mDisplayTokens[id]; } void SurfaceFlinger::bootFinished() @@ -496,11 +534,10 @@ void SurfaceFlinger::bootFinished() LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); - sp<LambdaMessage> readProperties = new LambdaMessage([&]() { + postMessageAsync(new LambdaMessage([this] { readPersistentProperties(); mBootStage = BootStage::FINISHED; - }); - postMessageAsync(readProperties); + })); } uint32_t SurfaceFlinger::getNewTexture() { @@ -525,18 +562,7 @@ uint32_t SurfaceFlinger::getNewTexture() { } void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { - class MessageDestroyGLTexture : public MessageBase { - RE::RenderEngine& engine; - uint32_t texture; - public: - MessageDestroyGLTexture(RE::RenderEngine& engine, uint32_t texture) - : engine(engine), texture(texture) {} - virtual bool handler() { - engine.deleteTextures(1, &texture); - return true; - } - }; - postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture)); + postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); })); } class DispSyncSource final : public VSyncSource, private DispSync::Callback { @@ -682,19 +708,19 @@ void SurfaceFlinger::init() { // start the EventThread mEventThreadSource = - std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, - true, "app"); + std::make_unique<DispSyncSource>(mPrimaryDispSync.get(), + SurfaceFlinger::vsyncPhaseOffsetNs, true, "app"); mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(), - [this]() { resyncWithRateLimit(); }, + [this] { resyncWithRateLimit(); }, impl::EventThread::InterceptVSyncsCallback(), "appEventThread"); mSfEventThreadSource = - std::make_unique<DispSyncSource>(&mPrimaryDispSync, + std::make_unique<DispSyncSource>(mPrimaryDispSync.get(), SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = std::make_unique<impl::EventThread>(mSfEventThreadSource.get(), - [this]() { resyncWithRateLimit(); }, + [this] { resyncWithRateLimit(); }, [this](nsecs_t timestamp) { mInterceptor->saveVSyncEvent(timestamp); }, @@ -717,31 +743,34 @@ void SurfaceFlinger::init() { getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId); // Process any initial hotplug and resulting display changes. processDisplayHotplugEventsLocked(); - LOG_ALWAYS_FATAL_IF(!getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY), - "Registered composer callback but didn't create the default primary display"); + const auto display = getDefaultDisplayDeviceLocked(); + LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback."); + LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(display->getId()), + "Internal display is disconnected."); // make the default display GLContext current so that we can create textures // when creating Layers (which may happens before we render something) - getDefaultDisplayDeviceLocked()->makeCurrent(); + display->makeCurrent(); if (useVrFlinger) { - auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) { + auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) { // This callback is called from the vr flinger dispatch thread. We // need to call signalTransaction(), which requires holding // mStateLock when we're not on the main thread. Acquiring // mStateLock from the vr flinger dispatch thread might trigger a // deadlock in surface flinger (see b/66916578), so post a message // to be handled on the main thread instead. - sp<LambdaMessage> message = new LambdaMessage([=]() { + postMessageAsync(new LambdaMessage([=] { ALOGI("VR request display mode: requestDisplay=%d", requestDisplay); mVrFlingerRequestsDisplay = requestDisplay; signalTransaction(); - }); - postMessageAsync(message); + })); }; - mVrFlinger = dvr::VrFlinger::Create(getBE().mHwc->getComposer(), - getBE().mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0), - vrFlingerRequestDisplayCallback); + mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(), + getHwComposer() + .getHwcDisplayId(display->getId()) + .value_or(0), + vrFlingerRequestDisplayCallback); if (!mVrFlinger) { ALOGE("Failed to start vrflinger"); } @@ -776,7 +805,7 @@ void SurfaceFlinger::init() { // and apply this saturation matrix on Display P3 content. Unless the risk of applying // such saturation matrix on Display P3 is understood fully, the API should always return // identify matrix. - mEnhancedSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY, + mEnhancedSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(display->getId(), Dataspace::SRGB_LINEAR); // we will apply this on Display P3. @@ -858,18 +887,15 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( return NO_ERROR; } -status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, - Vector<DisplayInfo>* configs) { - if (configs == nullptr || display.get() == nullptr) { +status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken, + Vector<DisplayInfo>* configs) { + if (!displayToken || !configs) { return BAD_VALUE; } - if (!display.get()) - return NAME_NOT_FOUND; - int32_t type = NAME_NOT_FOUND; - for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) { - if (display == mBuiltinDisplays[i]) { + for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { + if (displayToken == mDisplayTokens[i]) { type = i; break; } @@ -923,8 +949,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, info.density = density; // TODO: this needs to go away (currently needed only by webkit) - sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked()); - info.orientation = hw ? hw->getOrientation() : 0; + const auto display = getDefaultDisplayDeviceLocked(); + info.orientation = display ? display->getOrientation() : 0; } else { // TODO: where should this value come from? static const int TV_DENSITY = 213; @@ -968,100 +994,74 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, return NO_ERROR; } -status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */, - DisplayStatInfo* stats) { - if (stats == nullptr) { +status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>&, DisplayStatInfo* stats) { + if (!stats) { return BAD_VALUE; } // FIXME for now we always return stats for the primary display memset(stats, 0, sizeof(*stats)); - stats->vsyncTime = mPrimaryDispSync.computeNextRefresh(0); - stats->vsyncPeriod = mPrimaryDispSync.getPeriod(); + stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0); + stats->vsyncPeriod = mPrimaryDispSync->getPeriod(); return NO_ERROR; } -int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) { - if (display == nullptr) { - ALOGE("%s : display is nullptr", __func__); +int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("getActiveConfig: Invalid display token %p", displayToken.get()); return BAD_VALUE; } - sp<const DisplayDevice> device(getDisplayDevice(display)); - if (device != nullptr) { - return device->getActiveConfig(); - } - - return BAD_VALUE; + return display->getActiveConfig(); } -void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode) { - ALOGD("Set active config mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), - this); - int32_t type = hw->getDisplayType(); - int currentMode = hw->getActiveConfig(); - +void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& display, int mode) { + int currentMode = display->getActiveConfig(); if (mode == currentMode) { - ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode); return; } - if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + if (display->isVirtual()) { ALOGW("Trying to set config for virtual display"); return; } - hw->setActiveConfig(mode); - getHwComposer().setActiveConfig(type, mode); + display->setActiveConfig(mode); + getHwComposer().setActiveConfig(display->getDisplayType(), mode); } -status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) { - class MessageSetActiveConfig: public MessageBase { - SurfaceFlinger& mFlinger; - sp<IBinder> mDisplay; - int mMode; - public: - MessageSetActiveConfig(SurfaceFlinger& flinger, const sp<IBinder>& disp, - int mode) : - mFlinger(flinger), mDisplay(disp) { mMode = mode; } - virtual bool handler() { - Vector<DisplayInfo> configs; - mFlinger.getDisplayConfigs(mDisplay, &configs); - if (mMode < 0 || mMode >= static_cast<int>(configs.size())) { - ALOGE("Attempt to set active config = %d for display with %zu configs", - mMode, configs.size()); - return true; - } - sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == nullptr) { - ALOGE("Attempt to set active config = %d for null display %p", - mMode, mDisplay.get()); - } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { - ALOGW("Attempt to set active config = %d for virtual display", - mMode); - } else { - mFlinger.setActiveConfigInternal(hw, mMode); - } - return true; +status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) { + postMessageSync(new LambdaMessage([&] { + Vector<DisplayInfo> configs; + getDisplayConfigs(displayToken, &configs); + if (mode < 0 || mode >= static_cast<int>(configs.size())) { + ALOGE("Attempt to set active config %d for display with %zu configs", mode, + configs.size()); + return; } - }; - sp<MessageBase> msg = new MessageSetActiveConfig(*this, display, mode); - postMessageSync(msg); + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("Attempt to set active config %d for invalid display token %p", mode, + displayToken.get()); + } else if (display->isVirtual()) { + ALOGW("Attempt to set active config %d for virtual display", mode); + } else { + setActiveConfigInternal(display, mode); + } + })); + return NO_ERROR; } -status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display, - Vector<ColorMode>* outColorModes) { - if ((outColorModes == nullptr) || (display.get() == nullptr)) { +status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken, + Vector<ColorMode>* outColorModes) { + if (!displayToken || !outColorModes) { return BAD_VALUE; } - if (!display.get()) { - return NAME_NOT_FOUND; - } - int32_t type = NAME_NOT_FOUND; - for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) { - if (display == mBuiltinDisplays[i]) { + for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { + if (displayToken == mDisplayTokens[i]) { type = i; break; } @@ -1083,79 +1083,62 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display, return NO_ERROR; } -ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) { - sp<const DisplayDevice> device(getDisplayDevice(display)); - if (device != nullptr) { - return device->getActiveColorMode(); +ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) { + if (const auto display = getDisplayDevice(displayToken)) { + return display->getActiveColorMode(); } return static_cast<ColorMode>(BAD_VALUE); } -void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw, - ColorMode mode, Dataspace dataSpace, - RenderIntent renderIntent) { - int32_t type = hw->getDisplayType(); - ColorMode currentMode = hw->getActiveColorMode(); - Dataspace currentDataSpace = hw->getCompositionDataSpace(); - RenderIntent currentRenderIntent = hw->getActiveRenderIntent(); +void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& display, ColorMode mode, + Dataspace dataSpace, RenderIntent renderIntent) { + ColorMode currentMode = display->getActiveColorMode(); + Dataspace currentDataSpace = display->getCompositionDataSpace(); + RenderIntent currentRenderIntent = display->getActiveRenderIntent(); if (mode == currentMode && dataSpace == currentDataSpace && renderIntent == currentRenderIntent) { return; } - if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + if (display->isVirtual()) { ALOGW("Trying to set config for virtual display"); return; } - hw->setActiveColorMode(mode); - hw->setCompositionDataSpace(dataSpace); - hw->setActiveRenderIntent(renderIntent); - getHwComposer().setActiveColorMode(type, mode, renderIntent); + display->setActiveColorMode(mode); + display->setCompositionDataSpace(dataSpace); + display->setActiveRenderIntent(renderIntent); + getHwComposer().setActiveColorMode(display->getDisplayType(), mode, renderIntent); ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d", - decodeColorMode(mode).c_str(), mode, - decodeRenderIntent(renderIntent).c_str(), renderIntent, - hw->getDisplayType()); -} - - -status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display, - ColorMode colorMode) { - class MessageSetActiveColorMode: public MessageBase { - SurfaceFlinger& mFlinger; - sp<IBinder> mDisplay; - ColorMode mMode; - public: - MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp<IBinder>& disp, - ColorMode mode) : - mFlinger(flinger), mDisplay(disp) { mMode = mode; } - virtual bool handler() { - Vector<ColorMode> modes; - mFlinger.getDisplayColorModes(mDisplay, &modes); - bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes); - if (mMode < ColorMode::NATIVE || !exists) { - ALOGE("Attempt to set invalid active color mode %s (%d) for display %p", - decodeColorMode(mMode).c_str(), mMode, mDisplay.get()); - return true; - } - sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == nullptr) { - ALOGE("Attempt to set active color mode %s (%d) for null display %p", - decodeColorMode(mMode).c_str(), mMode, mDisplay.get()); - } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { - ALOGW("Attempt to set active color mode %s %d for virtual display", - decodeColorMode(mMode).c_str(), mMode); - } else { - mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN, - RenderIntent::COLORIMETRIC); - } - return true; + decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), + renderIntent, display->getDisplayType()); +} + +status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) { + postMessageSync(new LambdaMessage([&] { + Vector<ColorMode> modes; + getDisplayColorModes(displayToken, &modes); + bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes); + if (mode < ColorMode::NATIVE || !exists) { + ALOGE("Attempt to set invalid active color mode %s (%d) for display token %p", + decodeColorMode(mode).c_str(), mode, displayToken.get()); + return; } - }; - sp<MessageBase> msg = new MessageSetActiveColorMode(*this, display, colorMode); - postMessageSync(msg); + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("Attempt to set active color mode %s (%d) for invalid display token %p", + decodeColorMode(mode).c_str(), mode, displayToken.get()); + } else if (display->isVirtual()) { + ALOGW("Attempt to set active color mode %s (%d) for virtual display", + decodeColorMode(mode).c_str(), mode); + } else { + setActiveColorModeInternal(display, mode, Dataspace::UNKNOWN, + RenderIntent::COLORIMETRIC); + } + })); + return NO_ERROR; } @@ -1171,20 +1154,20 @@ status_t SurfaceFlinger::getAnimationFrameStats(FrameStats* outStats) const { return NO_ERROR; } -status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display, - HdrCapabilities* outCapabilities) const { +status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& displayToken, + HdrCapabilities* outCapabilities) const { Mutex::Autolock _l(mStateLock); - sp<const DisplayDevice> displayDevice(getDisplayDeviceLocked(display)); - if (displayDevice == nullptr) { - ALOGE("getHdrCapabilities: Invalid display %p", displayDevice.get()); + const auto display = getDisplayDeviceLocked(displayToken); + if (!display) { + ALOGE("getHdrCapabilities: Invalid display token %p", displayToken.get()); return BAD_VALUE; } // At this point the DisplayDeivce should already be set up, // meaning the luminance information is already queried from // hardware composer and stored properly. - const HdrCapabilities& capabilities = displayDevice->getHdrCapabilities(); + const HdrCapabilities& capabilities = display->getHdrCapabilities(); *outCapabilities = HdrCapabilities(capabilities.getSupportedHdrTypes(), capabilities.getDesiredMaxLuminance(), capabilities.getDesiredMaxAverageLuminance(), @@ -1194,7 +1177,7 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display, } status_t SurfaceFlinger::enableVSyncInjections(bool enable) { - sp<LambdaMessage> enableVSyncInjections = new LambdaMessage([&]() { + postMessageSync(new LambdaMessage([&] { Mutex::Autolock _l(mStateLock); if (mInjectVSyncs == enable) { @@ -1206,8 +1189,7 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { if (mVSyncInjector.get() == nullptr) { mVSyncInjector = std::make_unique<InjectVSyncSource>(); mInjectorEventThread = std::make_unique< - impl::EventThread>(mVSyncInjector.get(), - [this]() { resyncWithRateLimit(); }, + impl::EventThread>(mVSyncInjector.get(), [this] { resyncWithRateLimit(); }, impl::EventThread::InterceptVSyncsCallback(), "injEventThread"); } @@ -1218,8 +1200,8 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { } mInjectVSyncs = enable; - }); - postMessageSync(enableVSyncInjections); + })); + return NO_ERROR; } @@ -1318,8 +1300,7 @@ void SurfaceFlinger::run() { void SurfaceFlinger::enableHardwareVsync() { Mutex::Autolock _l(mHWVsyncLock); if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) { - mPrimaryDispSync.beginResync(); - //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true); + mPrimaryDispSync->beginResync(); mEventControlThread->setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } @@ -1336,15 +1317,19 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) { return; } - const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const auto displayId = DisplayDevice::DISPLAY_PRIMARY; + if (!getHwComposer().isConnected(displayId)) { + return; + } + + const auto activeConfig = getHwComposer().getActiveConfig(displayId); const nsecs_t period = activeConfig->getVsyncPeriod(); - mPrimaryDispSync.reset(); - mPrimaryDispSync.setPeriod(period); + mPrimaryDispSync->reset(); + mPrimaryDispSync->setPeriod(period); if (!mPrimaryHWVsyncEnabled) { - mPrimaryDispSync.beginResync(); - //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true); + mPrimaryDispSync->beginResync(); mEventControlThread->setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } @@ -1353,9 +1338,8 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) { void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) { Mutex::Autolock _l(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { - //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false); mEventControlThread->setVsyncEnabled(false); - mPrimaryDispSync.endResync(); + mPrimaryDispSync->endResync(); mPrimaryHWVsyncEnabled = false; } if (makeUnavailable) { @@ -1375,8 +1359,10 @@ void SurfaceFlinger::resyncWithRateLimit() { sLastResyncAttempted = now; } -void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, - hwc2_display_t displayId, int64_t timestamp) { +void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, + int64_t timestamp) { + ATRACE_NAME("SF onVsync"); + Mutex::Autolock lock(mStateLock); // Ignore any vsyncs from a previous hardware composer. if (sequenceId != getBE().mComposerSequenceId) { @@ -1384,7 +1370,12 @@ void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, } int32_t type; - if (!getBE().mHwc->onVsync(displayId, timestamp, &type)) { + if (!getBE().mHwc->onVsync(hwcDisplayId, timestamp, &type)) { + return; + } + + if (type != DisplayDevice::DISPLAY_PRIMARY) { + // For now, we don't do anything with external display vsyncs. return; } @@ -1392,8 +1383,8 @@ void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, { // Scope for the lock Mutex::Autolock _l(mHWVsyncLock); - if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) { - needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); + if (mPrimaryHWVsyncEnabled) { + needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp); } } @@ -1409,9 +1400,9 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } -void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display, +void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, HWC2::Connection connection) { - ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s)", sequenceId, display, + ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == HWC2::Connection::Connected ? "connected" : "disconnected"); // Ignore events that do not have the right sequenceId. @@ -1425,7 +1416,7 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t displa // acquire it here. ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); - mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection}); + mPendingHotplugEvents.emplace_back(HotplugEvent{hwcDisplayId, connection}); if (std::this_thread::get_id() == mMainThreadId) { // Process all pending hot plug events immediately if we are on the main thread. @@ -1435,8 +1426,7 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t displa setTransactionFlags(eDisplayTransactionNeeded); } -void SurfaceFlinger::onRefreshReceived(int sequenceId, - hwc2_display_t /*display*/) { +void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) { Mutex::Autolock lock(mStateLock); if (sequenceId != getBE().mComposerSequenceId) { return; @@ -1481,8 +1471,13 @@ void SurfaceFlinger::updateVrFlinger() { Mutex::Autolock _l(mStateLock); - int currentDisplayPowerMode = getDisplayDeviceLocked( - mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode(); + sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); + LOG_ALWAYS_FATAL_IF(!display); + const int currentDisplayPowerMode = display->getPowerMode(); + // This DisplayDevice will no longer be relevant once resetDisplayState() is + // called below. Clear the reference now so we don't accidentally use it + // later. + display.clear(); if (!vrFlingerRequestsDisplay) { mVrFlinger->SeizeDisplayOwnership(); @@ -1499,27 +1494,32 @@ void SurfaceFlinger::updateVrFlinger() { if (vrFlingerRequestsDisplay) { mVrFlinger->GrantDisplayOwnership(); - } else { - enableHardwareVsync(); } mVisibleRegionsDirty = true; invalidateHwcGeometry(); // Re-enable default display. - sp<DisplayDevice> hw(getDisplayDeviceLocked( - mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])); - setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true); + display = getDefaultDisplayDeviceLocked(); + LOG_ALWAYS_FATAL_IF(!display); + setPowerModeInternal(display, currentDisplayPowerMode, /*stateLockHeld*/ true); // Reset the timing values to account for the period of the swapped in HWC - const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); + // The present fences returned from vr_hwc are not an accurate + // representation of vsync times. + mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() || + !hasSyncFramework); + // Use phase of 0 since phase is not known. // Use latency of 0, which will snap to the ideal latency. setCompositorTimingSnapped(0, period, 0); + resyncToHardwareVsync(false); + android_atomic_or(1, &mRepaintEverything); setTransactionFlags(eDisplayTransactionNeeded); } @@ -1532,6 +1532,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { mPreviousPresentFence != Fence::NO_FENCE && (mPreviousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING); + mFrameMissedCount += frameMissed; ATRACE_INT("FrameMissed", static_cast<int>(frameMissed)); if (frameMissed) { mTimeStats.incrementMissedFrames(); @@ -1594,13 +1595,10 @@ void SurfaceFlinger::handleMessageRefresh() { doComposition(); postComposition(refreshStartTime); - mPreviousPresentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); - mHadClientComposition = false; - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - const sp<DisplayDevice>& displayDevice = mDisplays[displayId]; + for (const auto& [token, display] : mDisplays) { mHadClientComposition = mHadClientComposition || - getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); + getBE().mHwc->hasClientComposition(display->getId()); } mVsyncModulator.onRefreshed(mHadClientComposition); @@ -1614,21 +1612,20 @@ void SurfaceFlinger::doDebugFlashRegions() return; const bool repaintEverything = mRepaintEverything; - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - const sp<DisplayDevice>& hw(mDisplays[dpy]); - if (hw->isDisplayOn()) { + for (const auto& [token, display] : mDisplays) { + if (display->isPoweredOn()) { // transform the dirty region into this screen's coordinate space - const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); + const Region dirtyRegion = display->getDirtyRegion(repaintEverything); if (!dirtyRegion.isEmpty()) { // redraw the whole screen - doComposeSurfaces(hw); + doComposeSurfaces(display); // and draw the dirty region - const int32_t height = hw->getHeight(); + const int32_t height = display->getHeight(); auto& engine(getRenderEngine()); engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1); - hw->swapBuffers(getHwComposer()); + display->swapBuffers(getHwComposer()); } } } @@ -1639,17 +1636,14 @@ void SurfaceFlinger::doDebugFlashRegions() usleep(mDebugRegion * 1000); } - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (!displayDevice->isDisplayOn()) { + for (const auto& [token, display] : mDisplays) { + if (!display->isPoweredOn()) { continue; } - status_t result = displayDevice->prepareFrame(*getBE().mHwc); - ALOGE_IF(result != NO_ERROR, - "prepareFrame for display %zd failed:" - " %d (%s)", - displayId, result, strerror(-result)); + status_t result = display->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", + display->getId(), result, strerror(-result)); } } @@ -1664,19 +1658,14 @@ void SurfaceFlinger::doTracing(const char* where) { void SurfaceFlinger::logLayerStats() { ATRACE_CALL(); if (CC_UNLIKELY(mLayerStats.isEnabled())) { - int32_t hwcId = -1; - for (size_t dpy = 0; dpy < mDisplays.size(); ++dpy) { - const sp<const DisplayDevice>& displayDevice(mDisplays[dpy]); - if (displayDevice->isPrimary()) { - hwcId = displayDevice->getHwcDisplayId(); - break; + for (const auto& [token, display] : mDisplays) { + if (display->isPrimary()) { + mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(*display)); + return; } } - if (hwcId < 0) { - ALOGE("LayerStats: Hmmm, no primary display?"); - return; - } - mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(hwcId)); + + ALOGE("logLayerStats: no primary display"); } } @@ -1768,25 +1757,26 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } // |mStateLock| not needed as we are on the main thread - const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked()); + const auto display = getDefaultDisplayDeviceLocked(); getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; - if (hw && getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { + if (display && getHwComposer().hasClientComposition(display->getId())) { glCompositionDoneFenceTime = - std::make_shared<FenceTime>(hw->getClientTargetAcquireFence()); + std::make_shared<FenceTime>(display->getClientTargetAcquireFence()); getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; } getBE().mDisplayTimeline.updateSignalTimes(); - sp<Fence> presentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); - auto presentFenceTime = std::make_shared<FenceTime>(presentFence); + mPreviousPresentFence = + display ? getHwComposer().getPresentFence(display->getId()) : Fence::NO_FENCE; + auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence); getBE().mDisplayTimeline.push(presentFenceTime); - nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); - nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); + nsecs_t vsyncPhase = mPrimaryDispSync->computeNextRefresh(0); + nsecs_t vsyncInterval = mPrimaryDispSync->getPeriod(); // We use the refreshStartTime which might be sampled a little later than // when we started doing work for this frame, but that should be okay @@ -1809,7 +1799,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) }); if (presentFenceTime->isValid()) { - if (mPrimaryDispSync.addPresentFence(presentFenceTime)) { + if (mPrimaryDispSync->addPresentFence(presentFenceTime)) { enableHardwareVsync(); } else { disableHardwareVsync(false); @@ -1817,7 +1807,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } if (!hasSyncFramework) { - if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && hw->isDisplayOn()) { + if (display && getHwComposer().isConnected(display->getId()) && display->isPoweredOn()) { enableHardwareVsync(); } } @@ -1828,11 +1818,10 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); - } else if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) { + } else if (display && getHwComposer().isConnected(display->getId())) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. - nsecs_t presentTime = - getBE().mHwc->getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(display->getId()); mAnimFrameTracker.setActualPresentTime(presentTime); } mAnimFrameTracker.advanceFrame(); @@ -1843,8 +1832,8 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) mTimeStats.incrementClientCompositionFrames(); } - if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && - hw->getPowerMode() == HWC_POWER_MODE_OFF) { + if (display && getHwComposer().isConnected(display->getId()) && + display->getPowerMode() == HWC_POWER_MODE_OFF) { return; } @@ -1885,21 +1874,20 @@ void SurfaceFlinger::rebuildLayerStacks() { mVisibleRegionsDirty = false; invalidateHwcGeometry(); - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + for (const auto& pair : mDisplays) { + const auto& display = pair.second; Region opaqueRegion; Region dirtyRegion; Vector<sp<Layer>> layersSortedByZ; Vector<sp<Layer>> layersNeedingFences; - const sp<DisplayDevice>& displayDevice(mDisplays[dpy]); - const Transform& tr(displayDevice->getTransform()); - const Rect bounds(displayDevice->getBounds()); - if (displayDevice->isDisplayOn()) { - computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion); + const Transform& tr = display->getTransform(); + const Rect bounds = display->getBounds(); + if (display->isPoweredOn()) { + computeVisibleRegions(display, dirtyRegion, opaqueRegion); mDrawingState.traverseInZOrder([&](Layer* layer) { bool hwcLayerDestroyed = false; - if (layer->belongsToDisplay(displayDevice->getLayerStack(), - displayDevice->isPrimary())) { + if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1908,15 +1896,13 @@ void SurfaceFlinger::rebuildLayerStacks() { } else { // Clear out the HWC layer if this layer was // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer( - displayDevice->getHwcDisplayId()); + hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); } } else { - // WM changes displayDevice->layerStack upon sleep/awake. + // WM changes display->layerStack upon sleep/awake. // Here we make sure we delete the HWC layers even if // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer( - displayDevice->getHwcDisplayId()); + hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); } // If a layer is not going to get a release fence because @@ -1932,12 +1918,11 @@ void SurfaceFlinger::rebuildLayerStacks() { } }); } - displayDevice->setVisibleLayersSortedByZ(layersSortedByZ); - displayDevice->setLayersNeedingFences(layersNeedingFences); - displayDevice->undefinedRegion.set(bounds); - displayDevice->undefinedRegion.subtractSelf( - tr.transform(opaqueRegion)); - displayDevice->dirtyRegion.orSelf(dirtyRegion); + display->setVisibleLayersSortedByZ(layersSortedByZ); + display->setLayersNeedingFences(layersNeedingFences); + display->undefinedRegion.set(bounds); + display->undefinedRegion.subtractSelf(tr.transform(opaqueRegion)); + display->dirtyRegion.orSelf(dirtyRegion); } } } @@ -1950,12 +1935,12 @@ void SurfaceFlinger::rebuildLayerStacks() { // - Dataspace::UNKNOWN // - Dataspace::BT2020_HLG // - Dataspace::BT2020_PQ -Dataspace SurfaceFlinger::getBestDataspace( - const sp<const DisplayDevice>& displayDevice, Dataspace* outHdrDataSpace) const { +Dataspace SurfaceFlinger::getBestDataspace(const sp<const DisplayDevice>& display, + Dataspace* outHdrDataSpace) const { Dataspace bestDataSpace = Dataspace::SRGB; *outHdrDataSpace = Dataspace::UNKNOWN; - for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + for (const auto& layer : display->getVisibleLayersSortedByZ()) { switch (layer->getDataSpace()) { case Dataspace::V0_SCRGB: case Dataspace::V0_SCRGB_LINEAR: @@ -1983,9 +1968,8 @@ Dataspace SurfaceFlinger::getBestDataspace( } // Pick the ColorMode / Dataspace for the display device. -void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& displayDevice, - ColorMode* outMode, Dataspace* outDataSpace, - RenderIntent* outRenderIntent) const { +void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& display, ColorMode* outMode, + Dataspace* outDataSpace, RenderIntent* outRenderIntent) const { if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) { *outMode = ColorMode::NATIVE; *outDataSpace = Dataspace::UNKNOWN; @@ -1994,11 +1978,11 @@ void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& displayDevice, } Dataspace hdrDataSpace; - Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace); + Dataspace bestDataSpace = getBestDataspace(display, &hdrDataSpace); // respect hdrDataSpace only when there is no legacy HDR support const bool isHdr = hdrDataSpace != Dataspace::UNKNOWN && - !displayDevice->hasLegacyHdrSupport(hdrDataSpace); + !display->hasLegacyHdrSupport(hdrDataSpace); if (isHdr) { bestDataSpace = hdrDataSpace; } @@ -2017,17 +2001,17 @@ void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& displayDevice, break; } - displayDevice->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); + display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } void SurfaceFlinger::setUpHWComposer() { ATRACE_CALL(); ALOGV("setUpHWComposer"); - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - bool dirty = !mDisplays[dpy]->getDirtyRegion(mRepaintEverything).isEmpty(); - bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0; - bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers; + for (const auto& [token, display] : mDisplays) { + bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty(); + bool empty = display->getVisibleLayersSortedByZ().size() == 0; + bool wasEmpty = !display->lastCompositionHadVisibleLayers; // If nothing has changed (!dirty), don't recompose. // If something changed, but we don't currently have any visible layers, @@ -2039,41 +2023,36 @@ void SurfaceFlinger::setUpHWComposer() { // emit any black frames until a layer is added to the layer stack. bool mustRecompose = dirty && !(empty && wasEmpty); - ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL, - "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy, - mustRecompose ? "doing" : "skipping", - dirty ? "+" : "-", - empty ? "+" : "-", - wasEmpty ? "+" : "-"); + ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)", + display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-", + empty ? "+" : "-", wasEmpty ? "+" : "-"); - mDisplays[dpy]->beginFrame(mustRecompose); + display->beginFrame(mustRecompose); if (mustRecompose) { - mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty; + display->lastCompositionHadVisibleLayers = !empty; } } // build the h/w work list if (CC_UNLIKELY(mGeometryInvalid)) { mGeometryInvalid = false; - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - sp<const DisplayDevice> displayDevice(mDisplays[dpy]); - const auto hwcId = displayDevice->getHwcDisplayId(); - if (hwcId >= 0) { - const Vector<sp<Layer>>& currentLayers( - displayDevice->getVisibleLayersSortedByZ()); + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + if (displayId >= 0) { + const Vector<sp<Layer>>& currentLayers = display->getVisibleLayersSortedByZ(); for (size_t i = 0; i < currentLayers.size(); i++) { const auto& layer = currentLayers[i]; - if (!layer->hasHwcLayer(hwcId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) { - layer->forceClientComposition(hwcId); + if (!layer->hasHwcLayer(displayId)) { + if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { + layer->forceClientComposition(displayId); continue; } } - layer->setGeometry(displayDevice, i); + layer->setGeometry(display, i); if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(hwcId); + layer->forceClientComposition(displayId); } } } @@ -2081,61 +2060,59 @@ void SurfaceFlinger::setUpHWComposer() { } // Set the per-frame data - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - const auto hwcId = displayDevice->getHwcDisplayId(); - - if (hwcId < 0) { + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + if (displayId < 0) { continue; } + if (mDrawingState.colorMatrixChanged) { - displayDevice->setColorTransform(mDrawingState.colorMatrix); - status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " - "display %zd: %d", displayId, result); + display->setColorTransform(mDrawingState.colorMatrix); + status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d", + displayId, result); } - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + for (auto& layer : display->getVisibleLayersSortedByZ()) { if (layer->isHdrY410()) { - layer->forceClientComposition(hwcId); + layer->forceClientComposition(displayId); } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && - !displayDevice->hasHDR10Support()) { - layer->forceClientComposition(hwcId); + !display->hasHDR10Support()) { + layer->forceClientComposition(displayId); } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && - !displayDevice->hasHLGSupport()) { - layer->forceClientComposition(hwcId); + !display->hasHLGSupport()) { + layer->forceClientComposition(displayId); } - if (layer->getForceClientComposition(hwcId)) { + if (layer->getForceClientComposition(displayId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(hwcId, HWC2::Composition::Client); + layer->setCompositionType(displayId, HWC2::Composition::Client); continue; } - layer->setPerFrameData(displayDevice); + layer->setPerFrameData(display); } if (hasWideColorDisplay) { ColorMode colorMode; Dataspace dataSpace; RenderIntent renderIntent; - pickColorMode(displayDevice, &colorMode, &dataSpace, &renderIntent); - setActiveColorModeInternal(displayDevice, colorMode, dataSpace, renderIntent); + pickColorMode(display, &colorMode, &dataSpace, &renderIntent); + setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent); } } mDrawingState.colorMatrixChanged = false; - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (!displayDevice->isDisplayOn()) { + for (const auto& [token, display] : mDisplays) { + if (!display->isPoweredOn()) { continue; } - status_t result = displayDevice->prepareFrame(*getBE().mHwc); - ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" - " %d (%s)", displayId, result, strerror(-result)); + status_t result = display->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", + display->getId(), result, strerror(-result)); } } @@ -2144,17 +2121,16 @@ void SurfaceFlinger::doComposition() { ALOGV("doComposition"); const bool repaintEverything = android_atomic_and(0, &mRepaintEverything); - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - const sp<DisplayDevice>& hw(mDisplays[dpy]); - if (hw->isDisplayOn()) { + for (const auto& [token, display] : mDisplays) { + if (display->isPoweredOn()) { // transform the dirty region into this screen's coordinate space - const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); + const Region dirtyRegion = display->getDirtyRegion(repaintEverything); // repaint the framebuffer (if needed) - doDisplayComposition(hw, dirtyRegion); + doDisplayComposition(display, dirtyRegion); - hw->dirtyRegion.clear(); - hw->flip(); + display->dirtyRegion.clear(); + display->flip(); } } postFramebuffer(); @@ -2168,49 +2144,52 @@ void SurfaceFlinger::postFramebuffer() const nsecs_t now = systemTime(); mDebugInSwapBuffers = now; - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (!displayDevice->isDisplayOn()) { + for (const auto& [token, display] : mDisplays) { + if (!display->isPoweredOn()) { continue; } - const auto hwcId = displayDevice->getHwcDisplayId(); - if (hwcId >= 0) { - getBE().mHwc->presentAndGetReleaseFences(hwcId); + const auto displayId = display->getId(); + if (displayId >= 0) { + getBE().mHwc->presentAndGetReleaseFences(displayId); } - displayDevice->onSwapBuffersCompleted(); - displayDevice->makeCurrent(); - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + display->onSwapBuffersCompleted(); + display->makeCurrent(); + for (auto& layer : display->getVisibleLayersSortedByZ()) { + sp<Fence> releaseFence = Fence::NO_FENCE; + // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. - auto hwcLayer = layer->getHwcLayer(hwcId); - sp<Fence> releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer); + auto hwcLayer = layer->getHwcLayer(displayId); + if (displayId >= 0) { + releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer); + } // If the layer was client composited in the previous frame, we // need to merge with the previous client target acquire fence. // Since we do not track that, always merge with the current // client target acquire fence when it is available, even though // this is suboptimal. - if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) { + if (layer->getCompositionType(displayId) == HWC2::Composition::Client) { releaseFence = Fence::merge("LayerRelease", releaseFence, - displayDevice->getClientTargetAcquireFence()); + display->getClientTargetAcquireFence()); } - layer->onLayerDisplayed(releaseFence); + layer->getBE().onLayerDisplayed(releaseFence); } // We've got a list of layers needing fences, that are disjoint with - // displayDevice->getVisibleLayersSortedByZ. The best we can do is to + // display->getVisibleLayersSortedByZ. The best we can do is to // supply them with the present fence. - if (!displayDevice->getLayersNeedingFences().isEmpty()) { - sp<Fence> presentFence = getBE().mHwc->getPresentFence(hwcId); - for (auto& layer : displayDevice->getLayersNeedingFences()) { - layer->onLayerDisplayed(presentFence); + if (!display->getLayersNeedingFences().isEmpty()) { + sp<Fence> presentFence = getBE().mHwc->getPresentFence(displayId); + for (auto& layer : display->getLayersNeedingFences()) { + layer->getBE().onLayerDisplayed(presentFence); } } - if (hwcId >= 0) { - getBE().mHwc->clearReleaseFences(hwcId); + if (displayId >= 0) { + getBE().mHwc->clearReleaseFences(displayId); } } @@ -2218,8 +2197,9 @@ void SurfaceFlinger::postFramebuffer() mDebugInSwapBuffers = 0; // |mStateLock| not needed as we are on the main thread - if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) { - uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount(); + const auto display = getDefaultDisplayDeviceLocked(); + if (display && getHwComposer().isConnected(display->getId())) { + const uint32_t flipCount = display->getPageFlipCount(); if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { logFrameStats(); } @@ -2256,7 +2236,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // here the transaction has been committed } -DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display, +DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t hwcDisplayId, HWC2::Connection connection) const { // Figure out whether the event is for the primary display or an // external display by matching the Hwc display id against one for a @@ -2265,17 +2245,16 @@ DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t d // have a connected primary display, we assume the new display is meant to // be the primary display, and then if we don't have an external display, // we assume it is that. - const auto primaryDisplayId = - getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); - const auto externalDisplayId = + const auto primaryHwcDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); + const auto externalHwcDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL); - if (primaryDisplayId && primaryDisplayId == display) { + if (primaryHwcDisplayId && primaryHwcDisplayId == hwcDisplayId) { return DisplayDevice::DISPLAY_PRIMARY; - } else if (externalDisplayId && externalDisplayId == display) { - return DisplayDevice::DISPLAY_EXTERNAL; - } else if (connection == HWC2::Connection::Connected && !primaryDisplayId) { + } else if (externalHwcDisplayId && externalHwcDisplayId == hwcDisplayId) { + return DisplayDevice::DISPLAY_EXTERNAL; + } else if (connection == HWC2::Connection::Connected && !primaryHwcDisplayId) { return DisplayDevice::DISPLAY_PRIMARY; - } else if (connection == HWC2::Connection::Connected && !externalDisplayId) { + } else if (connection == HWC2::Connection::Connected && !externalHwcDisplayId) { return DisplayDevice::DISPLAY_EXTERNAL; } @@ -2284,9 +2263,9 @@ DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t d void SurfaceFlinger::processDisplayHotplugEventsLocked() { for (const auto& event : mPendingHotplugEvents) { - auto displayType = determineDisplayType(event.display, event.connection); + auto displayType = determineDisplayType(event.hwcDisplayId, event.connection); if (displayType == DisplayDevice::DISPLAY_ID_INVALID) { - ALOGW("Unable to determine the display type for display %" PRIu64, event.display); + ALOGW("Unable to determine the display type for display %" PRIu64, event.hwcDisplayId); continue; } @@ -2295,29 +2274,34 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { continue; } - getBE().mHwc->onHotplug(event.display, displayType, event.connection); + const auto displayId = + getBE().mHwc->onHotplug(event.hwcDisplayId, displayType, event.connection); + if (displayId) { + ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.hwcDisplayId, *displayId); + } if (event.connection == HWC2::Connection::Connected) { - if (!mBuiltinDisplays[displayType].get()) { + if (!mDisplayTokens[displayType].get()) { ALOGV("Creating built in display %d", displayType); - mBuiltinDisplays[displayType] = new BBinder(); - // All non-virtual displays are currently considered secure. - DisplayDeviceState info(displayType, true); + mDisplayTokens[displayType] = new BBinder(); + DisplayDeviceState info; + info.type = displayType; info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? "Built-in Screen" : "External Screen"; - mCurrentState.displays.add(mBuiltinDisplays[displayType], info); + info.isSecure = true; // All physical displays are currently considered secure. + mCurrentState.displays.add(mDisplayTokens[displayType], info); mInterceptor->saveDisplayCreation(info); } } else { ALOGV("Removing built in display %d", displayType); - ssize_t idx = mCurrentState.displays.indexOfKey(mBuiltinDisplays[displayType]); + ssize_t idx = mCurrentState.displays.indexOfKey(mDisplayTokens[displayType]); if (idx >= 0) { const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); - mInterceptor->saveDisplayDeletion(info.displayId); + mInterceptor->saveDisplayDeletion(info.sequenceId); mCurrentState.displays.removeItemsAt(idx); } - mBuiltinDisplays[displayType].clear(); + mDisplayTokens[displayType].clear(); } processDisplayChangesLocked(); @@ -2327,32 +2311,28 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( - const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state, + const wp<IBinder>& displayToken, int32_t displayId, const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { bool hasWideColorGamut = false; std::unordered_map<ColorMode, std::vector<RenderIntent>> hwcColorModes; + HdrCapabilities hdrCapabilities; + int32_t supportedPerFrameMetadata = 0; - if (hasWideColorDisplay) { - std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId); + if (hasWideColorDisplay && displayId >= 0) { + std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId); for (ColorMode colorMode : modes) { - switch (colorMode) { - case ColorMode::DISPLAY_P3: - case ColorMode::ADOBE_RGB: - case ColorMode::DCI_P3: - hasWideColorGamut = true; - break; - default: - break; + if (isWideColorMode(colorMode)) { + hasWideColorGamut = true; } - std::vector<RenderIntent> renderIntents = getHwComposer().getRenderIntents(hwcId, - colorMode); + std::vector<RenderIntent> renderIntents = + getHwComposer().getRenderIntents(displayId, colorMode); hwcColorModes.emplace(colorMode, renderIntents); } - } - HdrCapabilities hdrCapabilities; - getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities); + getHwComposer().getHdrCapabilities(displayId, &hdrCapabilities); + supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(displayId); + } auto nativeWindowSurface = mCreateNativeWindowSurface(producer); auto nativeWindow = nativeWindowSurface->getNativeWindow(); @@ -2362,7 +2342,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( */ std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface(); renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY); - renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL); + renderSurface->setAsync(state.isVirtual()); renderSurface->setNativeWindow(nativeWindow.get()); const int displayWidth = renderSurface->queryWidth(); const int displayHeight = renderSurface->queryHeight(); @@ -2374,20 +2354,18 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the // window's swap interval in eglMakeCurrent, so they'll override the // interval we set here. - if (state.type >= DisplayDevice::DISPLAY_VIRTUAL) { + if (state.isVirtual()) { nativeWindow->setSwapInterval(nativeWindow.get(), 0); } // virtual displays are always considered enabled - auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL - : HWC_POWER_MODE_OFF; + auto initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; - sp<DisplayDevice> hw = - new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, - dispSurface, std::move(renderSurface), displayWidth, displayHeight, - hasWideColorGamut, hdrCapabilities, - getHwComposer().getSupportedPerFrameMetadata(hwcId), - hwcColorModes, initialPowerMode); + sp<DisplayDevice> display = + new DisplayDevice(this, state.type, displayId, state.isSecure, displayToken, + nativeWindow, dispSurface, std::move(renderSurface), displayWidth, + displayHeight, hasWideColorGamut, hdrCapabilities, + supportedPerFrameMetadata, hwcColorModes, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); @@ -2399,16 +2377,16 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( defaultColorMode = ColorMode::SRGB; defaultDataSpace = Dataspace::SRGB; } - setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace, + setActiveColorModeInternal(display, defaultColorMode, defaultDataSpace, RenderIntent::COLORIMETRIC); if (state.type < DisplayDevice::DISPLAY_VIRTUAL) { - hw->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type)); + display->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type)); } - hw->setLayerStack(state.layerStack); - hw->setProjection(state.orientation, state.viewport, state.frame); - hw->setDisplayName(state.displayName); + display->setLayerStack(state.layerStack); + display->setProjection(state.orientation, state.viewport, state.frame); + display->setDisplayName(state.displayName); - return hw; + return display; } void SurfaceFlinger::processDisplayChangesLocked() { @@ -2433,17 +2411,22 @@ void SurfaceFlinger::processDisplayChangesLocked() { // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display // is current. - const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked()); - if (defaultDisplay != nullptr) defaultDisplay->makeCurrent(); - sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i))); - if (hw != nullptr) hw->disconnect(getHwComposer()); - if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) - mEventThread->onHotplugReceived(draw[i].type, false); - mDisplays.removeItem(draw.keyAt(i)); + if (const auto defaultDisplay = getDefaultDisplayDeviceLocked()) { + defaultDisplay->makeCurrent(); + } + if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) { + display->disconnect(getHwComposer()); + } + if (draw[i].type == DisplayDevice::DISPLAY_PRIMARY) { + mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false); + } else if (draw[i].type == DisplayDevice::DISPLAY_EXTERNAL) { + mEventThread->onHotplugReceived(EventThread::DisplayType::External, false); + } + mDisplays.erase(draw.keyAt(i)); } else { // this display is in both lists. see if something changed. const DisplayDeviceState& state(curr[j]); - const wp<IBinder>& display(curr.keyAt(j)); + const wp<IBinder>& displayToken = curr.keyAt(j); const sp<IBinder> state_binder = IInterface::asBinder(state.surface); const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface); if (state_binder != draw_binder) { @@ -2451,26 +2434,26 @@ void SurfaceFlinger::processDisplayChangesLocked() { // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added // below. - sp<DisplayDevice> hw(getDisplayDeviceLocked(display)); - if (hw != nullptr) hw->disconnect(getHwComposer()); - mDisplays.removeItem(display); + if (const auto display = getDisplayDeviceLocked(displayToken)) { + display->disconnect(getHwComposer()); + } + mDisplays.erase(displayToken); mDrawingState.displays.removeItemsAt(i); dc--; // at this point we must loop to the next item continue; } - const sp<DisplayDevice> disp(getDisplayDeviceLocked(display)); - if (disp != nullptr) { + if (const auto display = getDisplayDeviceLocked(displayToken)) { if (state.layerStack != draw[i].layerStack) { - disp->setLayerStack(state.layerStack); + display->setLayerStack(state.layerStack); } if ((state.orientation != draw[i].orientation) || (state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) { - disp->setProjection(state.orientation, state.viewport, state.frame); + display->setProjection(state.orientation, state.viewport, state.frame); } if (state.width != draw[i].width || state.height != draw[i].height) { - disp->setDisplaySize(state.width, state.height); + display->setDisplaySize(state.width, state.height); } } } @@ -2489,8 +2472,8 @@ void SurfaceFlinger::processDisplayChangesLocked() { sp<IGraphicBufferConsumer> bqConsumer; mCreateBufferQueue(&bqProducer, &bqConsumer, false); - int32_t hwcId = -1; - if (state.isVirtualDisplay()) { + int32_t displayId = -1; + if (state.isVirtual()) { // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, // etc.) but no internal state (i.e. a DisplayDevice). @@ -2508,13 +2491,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); auto format = static_cast<ui::PixelFormat>(intFormat); - getBE().mHwc->allocateVirtualDisplay(width, height, &format, &hwcId); + getBE().mHwc->allocateVirtualDisplay(width, height, &format, + &displayId); } // TODO: Plumb requested format back up to consumer sp<VirtualDisplaySurface> vds = - new VirtualDisplaySurface(*getBE().mHwc, hwcId, state.surface, + new VirtualDisplaySurface(*getBE().mHwc, displayId, state.surface, bqProducer, bqConsumer, state.displayName); @@ -2527,18 +2511,24 @@ void SurfaceFlinger::processDisplayChangesLocked() { "surface is provided (%p), ignoring it", state.surface.get()); - hwcId = state.type; - dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer); + displayId = state.type; + dispSurface = new FramebufferSurface(*getBE().mHwc, displayId, bqConsumer); producer = bqProducer; } - const wp<IBinder>& display(curr.keyAt(i)); + const wp<IBinder>& displayToken = curr.keyAt(i); if (dispSurface != nullptr) { - mDisplays.add(display, - setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, - producer)); - if (!state.isVirtualDisplay()) { - mEventThread->onHotplugReceived(state.type, true); + mDisplays.emplace(displayToken, + setupNewDisplayDeviceInternal(displayToken, displayId, state, + dispSurface, producer)); + if (!state.isVirtual()) { + if (state.type == DisplayDevice::DISPLAY_PRIMARY) { + mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, + true); + } else if (state.type == DisplayDevice::DISPLAY_EXTERNAL) { + mEventThread->onHotplugReceived(EventThread::DisplayType::External, + true); + } } } } @@ -2600,7 +2590,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // happened yet, so we must use the current state layer list // (soon to become the drawing state list). // - sp<const DisplayDevice> disp; + sp<const DisplayDevice> hintDisplay; uint32_t currentlayerStack = 0; bool first = true; mCurrentState.traverseInZOrder([&](Layer* layer) { @@ -2613,34 +2603,33 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // figure out if this layerstack is mirrored // (more than one display) if so, pick the default display, // if not, pick the only display it's on. - disp.clear(); - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - sp<const DisplayDevice> hw(mDisplays[dpy]); - if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) { - if (disp == nullptr) { - disp = std::move(hw); - } else { - disp = nullptr; + hintDisplay = nullptr; + for (const auto& [token, display] : mDisplays) { + if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { + if (hintDisplay) { + hintDisplay = nullptr; break; + } else { + hintDisplay = display; } } } } - if (disp == nullptr) { + if (!hintDisplay) { // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to // redraw after transform hint changes. See bug 8508397. // could be null when this layer is using a layerStack // that is not visible on any display. Also can occur at // screen off/on times. - disp = getDefaultDisplayDeviceLocked(); + hintDisplay = getDefaultDisplayDeviceLocked(); } - // disp can be null if there is no display available at all to get + // could be null if there is no display available at all to get // the transform hint from. - if (disp != nullptr) { - layer->updateTransformHint(disp); + if (hintDisplay) { + layer->updateTransformHint(hintDisplay); } first = false; @@ -2683,14 +2672,13 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) void SurfaceFlinger::updateCursorAsync() { - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (displayDevice->getHwcDisplayId() < 0) { + for (const auto& [token, display] : mDisplays) { + if (display->getId() < 0) { continue; } - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - layer->updateCursorPosition(displayDevice); + for (auto& layer : display->getVisibleLayersSortedByZ()) { + layer->updateCursorPosition(display); } } } @@ -2723,9 +2711,8 @@ void SurfaceFlinger::commitTransaction() mTransactionCV.broadcast(); } -void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice, - Region& outDirtyRegion, Region& outOpaqueRegion) -{ +void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& display, + Region& outDirtyRegion, Region& outOpaqueRegion) { ATRACE_CALL(); ALOGV("computeVisibleRegions"); @@ -2740,8 +2727,9 @@ void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displa const Layer::State& s(layer->getDrawingState()); // only consider the layers on the given layer stack - if (!layer->belongsToDisplay(displayDevice->getLayerStack(), displayDevice->isPrimary())) + if (!layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { return; + } /* * opaqueRegion: area of a surface that is fully opaque. @@ -2784,7 +2772,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displa if (translucent) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(s.activeTransparentRegion); + transparentRegion = tr.transform(layer->getActiveTransparentRegion(s)); } else { // transformation too complex, can't do the // transparent region optimization. @@ -2861,10 +2849,9 @@ void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displa } void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) { - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - const sp<DisplayDevice>& hw(mDisplays[dpy]); - if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) { - hw->dirtyRegion.orSelf(dirty); + for (const auto& [token, display] : mDisplays) { + if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { + display->dirtyRegion.orSelf(dirty); } } } @@ -2889,9 +2876,9 @@ bool SurfaceFlinger::handlePageFlip() // Display is now waiting on Layer 1's frame, which is behind layer 0's // second frame. But layer 0's second frame could be waiting on display. mDrawingState.traverseInZOrder([&](Layer* layer) { - if (layer->hasQueuedFrame()) { + if (layer->hasReadyFrame()) { frameQueued = true; - if (layer->shouldPresentNow(mPrimaryDispSync)) { + if (layer->shouldPresentNow(*mPrimaryDispSync)) { mLayersWithQueuedFrames.push_back(layer); } else { layer->useEmptyDamage(); @@ -2934,36 +2921,32 @@ void SurfaceFlinger::invalidateHwcGeometry() mGeometryInvalid = true; } - -void SurfaceFlinger::doDisplayComposition( - const sp<const DisplayDevice>& displayDevice, - const Region& inDirtyRegion) -{ +void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& display, + const Region& inDirtyRegion) { // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) - bool isHwcDisplay = displayDevice->getHwcDisplayId() >= 0; + bool isHwcDisplay = display->getId() >= 0; if (!isHwcDisplay && inDirtyRegion.isEmpty()) { ALOGV("Skipping display composition"); return; } ALOGV("doDisplayComposition"); - if (!doComposeSurfaces(displayDevice)) return; + if (!doComposeSurfaces(display)) return; // swap buffers (presentation) - displayDevice->swapBuffers(getHwComposer()); + display->swapBuffers(getHwComposer()); } -bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDevice) -{ +bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& display) { ALOGV("doComposeSurfaces"); - const Region bounds(displayDevice->bounds()); - const DisplayRenderArea renderArea(displayDevice); - const auto hwcId = displayDevice->getHwcDisplayId(); - const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); + const Region bounds(display->bounds()); + const DisplayRenderArea renderArea(display); + const auto displayId = display->getId(); + const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId); ATRACE_INT("hasClientComposition", hasClientComposition); bool applyColorMatrix = false; @@ -2973,14 +2956,14 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev ALOGV("hasClientComposition"); Dataspace outputDataspace = Dataspace::UNKNOWN; - if (displayDevice->hasWideColorGamut()) { - outputDataspace = displayDevice->getCompositionDataSpace(); + if (display->hasWideColorGamut()) { + outputDataspace = display->getCompositionDataSpace(); } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); getBE().mRenderEngine->setDisplayMaxLuminance( - displayDevice->getHdrCapabilities().getDesiredMaxLuminance()); + display->getHdrCapabilities().getDesiredMaxLuminance()); - const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); + const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(displayId); const bool skipClientColorTransform = getBE().mHwc->hasCapability( HWC2::Capability::SkipClientColorTransform); @@ -2994,7 +2977,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev // thus we only apply this matrix when the render intent is not colorimetric // and the output color space is Display P3. needsEnhancedColorMatrix = - (displayDevice->getActiveRenderIntent() >= RenderIntent::ENHANCE && + (display->getActiveRenderIntent() >= RenderIntent::ENHANCE && outputDataspace == Dataspace::DISPLAY_P3); if (needsEnhancedColorMatrix) { colorMatrix *= mEnhancedSaturationMatrix; @@ -3002,14 +2985,15 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev getRenderEngine().setupColorTransform(colorMatrix); - if (!displayDevice->makeCurrent()) { + if (!display->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", - displayDevice->getDisplayName().string()); + display->getDisplayName().c_str()); getRenderEngine().resetCurrentSurface(); // |mStateLock| not needed as we are on the main thread - if(!getDefaultDisplayDeviceLocked()->makeCurrent()) { - ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting."); + const auto defaultDisplay = getDefaultDisplayDeviceLocked(); + if (!defaultDisplay || !defaultDisplay->makeCurrent()) { + ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting."); } return false; } @@ -3026,31 +3010,31 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev // we start with the whole screen area and remove the scissor part // we're left with the letterbox region // (common case is that letterbox ends-up being empty) - const Region letterbox(bounds.subtract(displayDevice->getScissor())); + const Region letterbox = bounds.subtract(display->getScissor()); // compute the area to clear - Region region(displayDevice->undefinedRegion.merge(letterbox)); + const Region region = display->undefinedRegion.merge(letterbox); // screen is already cleared here if (!region.isEmpty()) { // can happen with SurfaceView - drawWormhole(displayDevice, region); + drawWormhole(display, region); } } - if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) { + if (!display->isPrimary()) { // just to be on the safe side, we don't set the // scissor on the main display. It should never be needed // anyways (though in theory it could since the API allows it). - const Rect& bounds(displayDevice->getBounds()); - const Rect& scissor(displayDevice->getScissor()); + const Rect& bounds = display->getBounds(); + const Rect& scissor = display->getScissor(); if (scissor != bounds) { // scissor doesn't match the screen's dimensions, so we // need to clear everything outside of it and enable // the GL scissor so we don't draw anything where we shouldn't // enable scissor for this frame - const uint32_t height = displayDevice->getHeight(); + const uint32_t height = display->getHeight(); getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom, scissor.getWidth(), scissor.getHeight()); } @@ -3062,24 +3046,23 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev */ ALOGV("Rendering client layers"); - const Transform& displayTransform = displayDevice->getTransform(); + const Transform& displayTransform = display->getTransform(); bool firstLayer = true; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + for (auto& layer : display->getVisibleLayersSortedByZ()) { const Region clip(bounds.intersect( displayTransform.transform(layer->visibleRegion))); ALOGV("Layer: %s", layer->getName().string()); - ALOGV(" Composition type: %s", - to_string(layer->getCompositionType(hwcId)).c_str()); + ALOGV(" Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str()); if (!clip.isEmpty()) { - switch (layer->getCompositionType(hwcId)) { + switch (layer->getCompositionType(displayId)) { case HWC2::Composition::Cursor: case HWC2::Composition::Device: case HWC2::Composition::Sideband: case HWC2::Composition::SolidColor: { const Layer::State& state(layer->getDrawingState()); - if (layer->getClearClientTarget(hwcId) && !firstLayer && - layer->isOpaque(state) && (state.color.a == 1.0f) - && hasClientComposition) { + if (layer->getClearClientTarget(displayId) && !firstLayer && + layer->isOpaque(state) && (layer->getAlpha() == 1.0f) && + hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared layer->clearWithOpenGL(renderArea); @@ -3108,8 +3091,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev return true; } -void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const { - const int32_t height = displayDevice->getHeight(); +void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& display, + const Region& region) const { + const int32_t height = display->getHeight(); auto& engine(getRenderEngine()); engine.fillRegionWithColor(region, height, 0, 0, 0, 0); } @@ -3340,53 +3324,51 @@ void SurfaceFlinger::setTransactionState( } } -uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) -{ - ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token); - if (dpyIdx < 0) - return 0; +uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) { + const ssize_t index = mCurrentState.displays.indexOfKey(s.token); + if (index < 0) return 0; uint32_t flags = 0; - DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx)); - if (disp.isValid()) { - const uint32_t what = s.what; - if (what & DisplayState::eSurfaceChanged) { - if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) { - disp.surface = s.surface; - flags |= eDisplayTransactionNeeded; - } + DisplayDeviceState& state = mCurrentState.displays.editValueAt(index); + + const uint32_t what = s.what; + if (what & DisplayState::eSurfaceChanged) { + if (IInterface::asBinder(state.surface) != IInterface::asBinder(s.surface)) { + state.surface = s.surface; + flags |= eDisplayTransactionNeeded; } - if (what & DisplayState::eLayerStackChanged) { - if (disp.layerStack != s.layerStack) { - disp.layerStack = s.layerStack; - flags |= eDisplayTransactionNeeded; - } + } + if (what & DisplayState::eLayerStackChanged) { + if (state.layerStack != s.layerStack) { + state.layerStack = s.layerStack; + flags |= eDisplayTransactionNeeded; } - if (what & DisplayState::eDisplayProjectionChanged) { - if (disp.orientation != s.orientation) { - disp.orientation = s.orientation; - flags |= eDisplayTransactionNeeded; - } - if (disp.frame != s.frame) { - disp.frame = s.frame; - flags |= eDisplayTransactionNeeded; - } - if (disp.viewport != s.viewport) { - disp.viewport = s.viewport; - flags |= eDisplayTransactionNeeded; - } + } + if (what & DisplayState::eDisplayProjectionChanged) { + if (state.orientation != s.orientation) { + state.orientation = s.orientation; + flags |= eDisplayTransactionNeeded; } - if (what & DisplayState::eDisplaySizeChanged) { - if (disp.width != s.width) { - disp.width = s.width; - flags |= eDisplayTransactionNeeded; - } - if (disp.height != s.height) { - disp.height = s.height; - flags |= eDisplayTransactionNeeded; - } + if (state.frame != s.frame) { + state.frame = s.frame; + flags |= eDisplayTransactionNeeded; + } + if (state.viewport != s.viewport) { + state.viewport = s.viewport; + flags |= eDisplayTransactionNeeded; + } + } + if (what & DisplayState::eDisplaySizeChanged) { + if (state.width != s.width) { + state.width = s.width; + flags |= eDisplayTransactionNeeded; + } + if (state.height != s.height) { + state.height = s.height; + flags |= eDisplayTransactionNeeded; } } + return flags; } @@ -3424,7 +3406,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState // If we are deferring transaction, make sure to push the pending state, as otherwise the // pending state will also be deferred. - if (what & layer_state_t::eDeferTransaction) { + if (what & layer_state_t::eDeferTransaction_legacy) { layer->pushPendingState(); } @@ -3509,12 +3491,12 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setFlags(s.flags, s.mask)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eCropChanged) { - if (layer->setCrop(s.crop, !geometryAppliesWithResize)) + if (what & layer_state_t::eCropChanged_legacy) { + if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFinalCropChanged) { - if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize)) + if (what & layer_state_t::eFinalCropChanged_legacy) { + if (layer->setFinalCrop_legacy(s.finalCrop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } if (what & layer_state_t::eLayerStackChanged) { @@ -3536,15 +3518,15 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState flags |= eTransactionNeeded|eTraversalNeeded|eDisplayLayerStackChanged; } } - if (what & layer_state_t::eDeferTransaction) { - if (s.barrierHandle != nullptr) { - layer->deferTransactionUntil(s.barrierHandle, s.frameNumber); - } else if (s.barrierGbp != nullptr) { - const sp<IGraphicBufferProducer>& gbp = s.barrierGbp; + if (what & layer_state_t::eDeferTransaction_legacy) { + if (s.barrierHandle_legacy != nullptr) { + layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.frameNumber_legacy); + } else if (s.barrierGbp_legacy != nullptr) { + const sp<IGraphicBufferProducer>& gbp = s.barrierGbp_legacy; if (authenticateSurfaceTextureLocked(gbp)) { const auto& otherLayer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer(); - layer->deferTransactionUntil(otherLayer, s.frameNumber); + layer->deferTransactionUntil_legacy(otherLayer, s.frameNumber_legacy); } else { ALOGE("Attempt to defer transaction to to an" " unrecognized GraphicBufferProducer"); @@ -3575,6 +3557,37 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } + if (what & layer_state_t::eTransformChanged) { + if (layer->setTransform(s.transform)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eTransformToDisplayInverseChanged) { + if (layer->setTransformToDisplayInverse(s.transformToDisplayInverse)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eCropChanged) { + if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eBufferChanged) { + if (layer->setBuffer(s.buffer)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eAcquireFenceChanged) { + if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eDataspaceChanged) { + if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eHdrMetadataChanged) { + if (layer->setHdrMetadata(s.hdrMetadata)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eSurfaceDamageRegionChanged) { + if (layer->setSurfaceDamageRegion(s.surfaceDamageRegion)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eApiChanged) { + if (layer->setApi(s.api)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eSidebandStreamChanged) { + if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded; + } return flags; } @@ -3617,12 +3630,14 @@ status_t SurfaceFlinger::createLayer( String8 uniqueName = getUniqueLayerName(name); switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { - case ISurfaceComposerClient::eFXSurfaceNormal: - result = createBufferLayer(client, - uniqueName, w, h, flags, format, - handle, gbp, &layer); + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + result = createBufferQueueLayer(client, uniqueName, w, h, flags, format, handle, gbp, + &layer); break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + result = createBufferStateLayer(client, uniqueName, w, h, flags, handle, &layer); + break; case ISurfaceComposerClient::eFXSurfaceColor: result = createColorLayer(client, uniqueName, w, h, flags, @@ -3678,15 +3693,17 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) }); } - ALOGD_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), uniqueName.c_str()); + ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), + uniqueName.c_str()); return uniqueName; } -status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, - sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) -{ +status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, + PixelFormat& format, sp<IBinder>* handle, + sp<IGraphicBufferProducer>* gbp, + sp<Layer>* outLayer) { // initialize the surfaces switch (format) { case PIXEL_FORMAT_TRANSPARENT: @@ -3698,18 +3715,28 @@ status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client, break; } - sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags); - status_t err = layer->setBuffers(w, h, format, flags); + sp<BufferQueueLayer> layer = new BufferQueueLayer(this, client, name, w, h, flags); + status_t err = layer->setDefaultBufferProperties(w, h, format); if (err == NO_ERROR) { *handle = layer->getHandle(); *gbp = layer->getProducer(); *outLayer = layer; } - ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err)); + ALOGE_IF(err, "createBufferQueueLayer() failed (%s)", strerror(-err)); return err; } +status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, + sp<IBinder>* handle, sp<Layer>* outLayer) { + sp<BufferStateLayer> layer = new BufferStateLayer(this, client, name, w, h, flags); + *handle = layer->getHandle(); + *outLayer = layer; + + return NO_ERROR; +} + status_t SurfaceFlinger::createColorLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* handle, sp<Layer>* outLayer) @@ -3749,13 +3776,16 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer) // --------------------------------------------------------------------------- void SurfaceFlinger::onInitializeDisplays() { + const auto displayToken = mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]; + if (!displayToken) return; + // reset screen orientation and use primary layer stack Vector<ComposerState> state; Vector<DisplayState> displays; DisplayState d; d.what = DisplayState::eDisplayProjectionChanged | DisplayState::eLayerStackChanged; - d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]; + d.token = displayToken; d.layerStack = 0; d.orientation = DisplayState::eOrientationDefault; d.frame.makeInvalid(); @@ -3764,10 +3794,13 @@ void SurfaceFlinger::onInitializeDisplays() { d.height = 0; displays.add(d); setTransactionState(state, displays, 0); - setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL, - /*stateLockHeld*/ false); - const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const auto display = getDisplayDevice(displayToken); + if (!display) return; + + setPowerModeInternal(display, HWC_POWER_MODE_NORMAL, /*stateLockHeld*/ false); + + const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); @@ -3777,51 +3810,42 @@ void SurfaceFlinger::onInitializeDisplays() { } void SurfaceFlinger::initializeDisplays() { - class MessageScreenInitialized : public MessageBase { - SurfaceFlinger* flinger; - public: - explicit MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { } - virtual bool handler() { - flinger->onInitializeDisplays(); - return true; - } - }; - sp<MessageBase> msg = new MessageScreenInitialized(this); - postMessageAsync(msg); // we may be called from main thread, use async message + // Async since we may be called from the main thread. + postMessageAsync(new LambdaMessage([this] { onInitializeDisplays(); })); } -void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw, - int mode, bool stateLockHeld) { - ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), - this); - int32_t type = hw->getDisplayType(); - int currentMode = hw->getPowerMode(); +void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode, + bool stateLockHeld) { + const int32_t displayId = display->getId(); + ALOGD("Setting power mode %d on display %d", mode, displayId); + int currentMode = display->getPowerMode(); if (mode == currentMode) { return; } - hw->setPowerMode(mode); - if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + if (display->isVirtual()) { ALOGW("Trying to set power mode for virtual display"); return; } + display->setPowerMode(mode); + if (mInterceptor->isEnabled()) { ConditionalLock lock(mStateLock, !stateLockHeld); - ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken()); + ssize_t idx = mCurrentState.displays.indexOfKey(display->getDisplayToken()); if (idx < 0) { ALOGW("Surface Interceptor SavePowerMode: invalid display token"); return; } - mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode); + mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).sequenceId, mode); } + int32_t type = display->getDisplayType(); if (currentMode == HWC_POWER_MODE_OFF) { // Turn on the display getHwComposer().setPowerMode(type, mode); - if (type == DisplayDevice::DISPLAY_PRIMARY && - mode != HWC_POWER_MODE_DOZE_SUSPEND) { + if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) { // FIXME: eventthread only knows about the main display right now mEventThread->onScreenAcquired(); resyncToHardwareVsync(true); @@ -3843,8 +3867,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw, ALOGW("Couldn't set SCHED_OTHER on display off"); } - if (type == DisplayDevice::DISPLAY_PRIMARY && - currentMode != HWC_POWER_MODE_DOZE_SUSPEND) { + if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) { disableHardwareVsync(true); // also cancels any in-progress resync // FIXME: eventthread only knows about the main display right now @@ -3858,15 +3881,14 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw, mode == HWC_POWER_MODE_NORMAL) { // Update display while dozing getHwComposer().setPowerMode(type, mode); - if (type == DisplayDevice::DISPLAY_PRIMARY && - currentMode == HWC_POWER_MODE_DOZE_SUSPEND) { + if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) { // FIXME: eventthread only knows about the main display right now mEventThread->onScreenAcquired(); resyncToHardwareVsync(true); } } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) { // Leave display going to doze - if (type == DisplayDevice::DISPLAY_PRIMARY) { + if (display->isPrimary()) { disableHardwareVsync(true); // also cancels any in-progress resync // FIXME: eventthread only knows about the main display right now mEventThread->onScreenReleased(); @@ -3876,35 +3898,22 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw, ALOGE("Attempting to set unknown power mode: %d\n", mode); getHwComposer().setPowerMode(type, mode); } - ALOGD("Finished set power mode=%d, type=%d", mode, hw->getDisplayType()); + + ALOGD("Finished setting power mode %d on display %d", mode, displayId); } -void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) { - class MessageSetPowerMode: public MessageBase { - SurfaceFlinger& mFlinger; - sp<IBinder> mDisplay; - int mMode; - public: - MessageSetPowerMode(SurfaceFlinger& flinger, - const sp<IBinder>& disp, int mode) : mFlinger(flinger), - mDisplay(disp) { mMode = mode; } - virtual bool handler() { - sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == nullptr) { - ALOGE("Attempt to set power mode = %d for null display %p", - mMode, mDisplay.get()); - } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { - ALOGW("Attempt to set power mode = %d for virtual display", - mMode); - } else { - mFlinger.setPowerModeInternal( - hw, mMode, /*stateLockHeld*/ false); - } - return true; +void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { + postMessageSync(new LambdaMessage([&] { + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("Attempt to set power mode %d for invalid display token %p", mode, + displayToken.get()); + } else if (display->isVirtual()) { + ALOGW("Attempt to set power mode %d for virtual display", mode); + } else { + setPowerModeInternal(display, mode, /*stateLockHeld*/ false); } - }; - sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode); - postMessageSync(msg); + })); } // --------------------------------------------------------------------------- @@ -3962,7 +3971,7 @@ status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asPro if ((index < numArgs) && (args[index] == String16("--dispsync"))) { index++; - mPrimaryDispSync.dump(result); + mPrimaryDispSync->dump(result); dumpAll = false; } @@ -4014,6 +4023,13 @@ status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asPro dumpAll = false; } + if ((index < numArgs) && + (args[index] == String16("--display-identification"))) { + index++; + dumpDisplayIdentificationData(result); + dumpAll = false; + } + if ((index < numArgs) && (args[index] == String16("--timestats"))) { index++; mTimeStats.parseArgs(asProto, args, index, result); @@ -4055,9 +4071,12 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index index++; } - const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); - const nsecs_t period = activeConfig->getVsyncPeriod(); - result.appendFormat("%" PRId64 "\n", period); + if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY; + getHwComposer().isConnected(displayId)) { + const auto activeConfig = getBE().mHwc->getActiveConfig(displayId); + const nsecs_t period = activeConfig->getVsyncPeriod(); + result.appendFormat("%" PRId64 "\n", period); + } if (name.isEmpty()) { mAnimFrameTracker.dumpStats(result); @@ -4193,6 +4212,48 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { result.append("\n"); } +void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { + for (const auto& [token, display] : mDisplays) { + const int32_t displayId = display->getId(); + const auto hwcDisplayId = getHwComposer().getHwcDisplayId(displayId); + if (!hwcDisplayId) { + continue; + } + + result.appendFormat("Display %d (HWC display %" PRIu64 "): ", displayId, *hwcDisplayId); + uint8_t port; + DisplayIdentificationData data; + if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) { + result.append("no identification data\n"); + continue; + } + + if (!isEdid(data)) { + result.append("unknown identification data: "); + for (uint8_t byte : data) { + result.appendFormat("%x ", byte); + } + result.append("\n"); + continue; + } + + const auto edid = parseEdid(data); + if (!edid) { + result.append("invalid EDID: "); + for (uint8_t byte : data) { + result.appendFormat("%x ", byte); + } + result.append("\n"); + continue; + } + + result.appendFormat("port=%u pnpId=%s displayName=\"", port, edid->pnpId.data()); + result.append(edid->displayName.data(), edid->displayName.length()); + result.append("\"\n"); + } + result.append("\n"); +} + void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay); result.appendFormat("DisplayColorSetting: %s\n", @@ -4200,20 +4261,19 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { // TODO: print out if wide-color mode is active or not - for (size_t d = 0; d < mDisplays.size(); d++) { - const sp<const DisplayDevice>& displayDevice(mDisplays[d]); - int32_t hwcId = displayDevice->getHwcDisplayId(); - if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { + for (const auto& [token, display] : mDisplays) { + const int32_t displayId = display->getId(); + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { continue; } - result.appendFormat("Display %d color modes:\n", hwcId); - std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId); + result.appendFormat("Display %d color modes:\n", displayId); + std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId); for (auto&& mode : modes) { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); } - ColorMode currentMode = displayDevice->getActiveColorMode(); + ColorMode currentMode = display->getActiveColorMode(); result.appendFormat(" Current color mode: %s (%d)\n", decodeColorMode(currentMode).c_str(), currentMode); } @@ -4232,23 +4292,22 @@ LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const return layersProto; } -LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const { +LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& display) const { LayersProto layersProto; - const sp<DisplayDevice>& displayDevice(mDisplays[hwcId]); SizeProto* resolution = layersProto.mutable_resolution(); - resolution->set_w(displayDevice->getWidth()); - resolution->set_h(displayDevice->getHeight()); + resolution->set_w(display.getWidth()); + resolution->set_h(display.getHeight()); - layersProto.set_color_mode(decodeColorMode(displayDevice->getActiveColorMode())); - layersProto.set_color_transform(decodeColorTransform(displayDevice->getColorTransform())); - layersProto.set_global_transform( - static_cast<int32_t>(displayDevice->getOrientationTransform())); + layersProto.set_color_mode(decodeColorMode(display.getActiveColorMode())); + layersProto.set_color_transform(decodeColorTransform(display.getColorTransform())); + layersProto.set_global_transform(static_cast<int32_t>(display.getOrientationTransform())); + const int32_t displayId = display.getId(); mDrawingState.traverseInZOrder([&](Layer* layer) { - if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) { + if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(displayId)) { LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProto(layerProto, hwcId); + layer->writeToProto(layerProto, displayId); } }); @@ -4286,6 +4345,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, appendGuiConfigString(result); result.append("\n"); + result.append("\nDisplay identification data:\n"); + dumpDisplayIdentificationData(result); + result.append("\nWide-Color information:\n"); dumpWideColorInfo(result); @@ -4295,28 +4357,32 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.append(SyncFeatures::getInstance().toString()); result.append("\n"); - const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); - colorizer.bold(result); - result.append("DispSync configuration: "); + result.append("DispSync configuration:\n"); colorizer.reset(result); + const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets(); const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets(); - result.appendFormat( - "app phase %" PRId64 " ns, " - "sf phase %" PRId64 " ns, " - "early app phase %" PRId64 " ns, " - "early sf phase %" PRId64 " ns, " - "early app gl phase %" PRId64 " ns, " - "early sf gl phase %" PRId64 " ns, " - "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", - vsyncPhaseOffsetNs, - sfVsyncPhaseOffsetNs, - appEarlyOffset, - sfEarlyOffset, - appEarlyGlOffset, - sfEarlyOffset, - dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); + if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY; + getHwComposer().isConnected(displayId)) { + const auto activeConfig = getHwComposer().getActiveConfig(displayId); + result.appendFormat("Display %d: " + "app phase %" PRId64 " ns, " + "sf phase %" PRId64 " ns, " + "early app phase %" PRId64 " ns, " + "early sf phase %" PRId64 " ns, " + "early app gl phase %" PRId64 " ns, " + "early sf gl phase %" PRId64 " ns, " + "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", + displayId, + vsyncPhaseOffsetNs, + sfVsyncPhaseOffsetNs, + appEarlyOffset, + sfEarlyOffset, + appEarlyGlOffset, + sfEarlyOffset, + dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); + } result.append("\n"); // Dump static screen stats @@ -4324,6 +4390,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, dumpStaticScreenStats(result); result.append("\n"); + result.appendFormat("Missed frame count: %u\n\n", mFrameMissedCount.load()); + dumpBufferingStats(result); /* @@ -4347,9 +4415,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, colorizer.bold(result); result.appendFormat("Displays (%zu entries)\n", mDisplays.size()); colorizer.reset(result); - for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - const sp<const DisplayDevice>& hw(mDisplays[dpy]); - hw->dump(result); + for (const auto& [token, display] : mDisplays) { + display->dump(result); } result.append("\n"); @@ -4362,31 +4429,30 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, colorizer.reset(result); HWComposer& hwc(getHwComposer()); - sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked()); + const auto display = getDefaultDisplayDeviceLocked(); getBE().mRenderEngine->dump(result); - if (hw) { - hw->undefinedRegion.dump(result, "undefinedRegion"); - result.appendFormat(" orientation=%d, isDisplayOn=%d\n", - hw->getOrientation(), hw->isDisplayOn()); - } - result.appendFormat( - " last eglSwapBuffers() time: %f us\n" - " last transaction time : %f us\n" - " transaction-flags : %08x\n" - " refresh-rate : %f fps\n" - " x-dpi : %f\n" - " y-dpi : %f\n" - " gpu_to_cpu_unsupported : %d\n" - , - mLastSwapBufferTime/1000.0, - mLastTransactionTime/1000.0, - mTransactionFlags, - 1e9 / activeConfig->getVsyncPeriod(), - activeConfig->getDpiX(), - activeConfig->getDpiY(), - !mGpuToCpuSupported); + if (display) { + display->undefinedRegion.dump(result, "undefinedRegion"); + result.appendFormat(" orientation=%d, isPoweredOn=%d\n", display->getOrientation(), + display->isPoweredOn()); + } + result.appendFormat(" last eglSwapBuffers() time: %f us\n" + " last transaction time : %f us\n" + " transaction-flags : %08x\n" + " gpu_to_cpu_unsupported : %d\n", + mLastSwapBufferTime / 1000.0, mLastTransactionTime / 1000.0, + mTransactionFlags, !mGpuToCpuSupported); + + if (display) { + const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); + result.appendFormat(" refresh-rate : %f fps\n" + " x-dpi : %f\n" + " y-dpi : %f\n", + 1e9 / activeConfig->getVsyncPeriod(), activeConfig->getDpiX(), + activeConfig->getDpiY()); + } result.appendFormat(" eglSwapBuffers time: %f us\n", inSwapBuffersDuration/1000.0); @@ -4403,18 +4469,15 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, /* * HWC layer minidump */ - for (size_t d = 0; d < mDisplays.size(); d++) { - const sp<const DisplayDevice>& displayDevice(mDisplays[d]); - int32_t hwcId = displayDevice->getHwcDisplayId(); - if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { + for (const auto& [token, display] : mDisplays) { + const int32_t displayId = display->getId(); + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { continue; } - result.appendFormat("Display %d HWC layers:\n", hwcId); + result.appendFormat("Display %d HWC layers:\n", displayId); Layer::miniDumpHeader(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { - layer->miniDump(result, hwcId); - }); + mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, displayId); }); result.append("\n"); } @@ -4445,22 +4508,17 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, } } -const Vector< sp<Layer> >& -SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) { +const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t displayId) { // Note: mStateLock is held here - wp<IBinder> dpy; - for (size_t i=0 ; i<mDisplays.size() ; i++) { - if (mDisplays.valueAt(i)->getHwcDisplayId() == id) { - dpy = mDisplays.keyAt(i); - break; + for (const auto& [token, display] : mDisplays) { + if (display->getId() == displayId) { + return getDisplayDeviceLocked(token)->getVisibleLayersSortedByZ(); } } - if (dpy == nullptr) { - ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); - // Just use the primary display so we have something to return - dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); - } - return getDisplayDeviceLocked(dpy)->getVisibleLayersSortedByZ(); + + ALOGE("%s: Invalid display %d", __FUNCTION__, displayId); + static const Vector<sp<Layer>> empty; + return empty; } bool SurfaceFlinger::startDdmConnection() @@ -4632,8 +4690,12 @@ status_t SurfaceFlinger::onTransact( reply->writeInt32(mDebugDisableHWC); return NO_ERROR; case 1013: { - sp<const DisplayDevice> hw(getDefaultDisplayDevice()); - reply->writeInt32(hw->getPageFlipCount()); + const auto display = getDefaultDisplayDevice(); + if (!display) { + return NAME_NOT_FOUND; + } + + reply->writeInt32(display->getPageFlipCount()); return NO_ERROR; } case 1014: { @@ -4692,7 +4754,7 @@ status_t SurfaceFlinger::onTransact( // Needs to be shifted to proper binder interface when we productize case 1016: { n = data.readInt32(); - mPrimaryDispSync.setRefreshSkipCount(n); + mPrimaryDispSync->setRefreshSkipCount(n); return NO_ERROR; } case 1017: { @@ -4764,8 +4826,8 @@ status_t SurfaceFlinger::onTransact( } // Is a DisplayColorSetting supported? case 1027: { - sp<const DisplayDevice> hw(getDefaultDisplayDevice()); - if (!hw) { + const auto display = getDefaultDisplayDevice(); + if (!display) { return NAME_NOT_FOUND; } @@ -4778,14 +4840,21 @@ status_t SurfaceFlinger::onTransact( reply->writeBool(true); break; case DisplayColorSetting::ENHANCED: - reply->writeBool(hw->hasRenderIntent(RenderIntent::ENHANCE)); + reply->writeBool(display->hasRenderIntent(RenderIntent::ENHANCE)); break; default: // vendor display color setting - reply->writeBool(hw->hasRenderIntent(static_cast<RenderIntent>(setting))); + reply->writeBool( + display->hasRenderIntent(static_cast<RenderIntent>(setting))); break; } return NO_ERROR; } + // Is VrFlinger active? + case 1028: { + Mutex::Autolock _l(mStateLock); + reply->writeBool(getBE().mHwc->isUsingVrComposer()); + return NO_ERROR; + } } } return err; @@ -4809,22 +4878,22 @@ private: const int mApi; }; -status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, +status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken, + sp<GraphicBuffer>* outBuffer, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, + int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); - if (CC_UNLIKELY(display == 0)) return BAD_VALUE; + if (!displayToken) return BAD_VALUE; - const sp<const DisplayDevice> device(getDisplayDeviceLocked(display)); - if (CC_UNLIKELY(device == 0)) return BAD_VALUE; + const auto display = getDisplayDeviceLocked(displayToken); + if (!display) return BAD_VALUE; - DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); + DisplayRenderArea renderArea(display, sourceCrop, reqHeight, reqWidth, rotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, - device, minLayerZ, maxLayerZ, std::placeholders::_1); + display, minLayerZ, maxLayerZ, std::placeholders::_1); return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); } @@ -4845,10 +4914,12 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, const Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); - return Rect(layerState.active.w, layerState.active.h); + return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState)); + } + int getHeight() const override { + return mLayer->getActiveHeight(mLayer->getDrawingState()); } - int getHeight() const override { return mLayer->getDrawingState().active.h; } - int getWidth() const override { return mLayer->getDrawingState().active.w; } + int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } Rect getSourceCrop() const override { @@ -4916,12 +4987,12 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; - crop.right = parent->getCurrentState().active.w; + crop.right = parent->getActiveWidth(parent->getCurrentState()); } if (sourceCrop.height() <= 0) { crop.top = 0; - crop.bottom = parent->getCurrentState().active.h; + crop.bottom = parent->getActiveHeight(parent->getCurrentState()); } int32_t reqWidth = crop.width() * frameScale; @@ -4966,7 +5037,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, const int uid = IPCThreadState::self()->getCallingUid(); const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; - sp<LambdaMessage> message = new LambdaMessage([&]() { + sp<LambdaMessage> message = new LambdaMessage([&] { // If there is a refresh pending, bug out early and tell the binder thread to try again // after the refresh. if (mRefreshPending) { @@ -4981,7 +5052,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - renderArea.render([&]() { + renderArea.render([&] { result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), useIdentityTransform, forSystem, &fd); }); @@ -4997,14 +5068,14 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, status_t result = postMessageAsync(message); if (result == NO_ERROR) { - captureCondition.wait(captureLock, [&]() { return captureResult; }); + captureCondition.wait(captureLock, [&] { return captureResult; }); while (*captureResult == EAGAIN) { captureResult.reset(); result = postMessageAsync(message); if (result != NO_ERROR) { return result; } - captureCondition.wait(captureLock, [&]() { return captureResult; }); + captureCondition.wait(captureLock, [&] { return captureResult; }); } result = *captureResult; } @@ -5126,7 +5197,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, traverseLayers([&](Layer* layer) { if (filtering) layer->setFiltering(true); - layer->draw(renderArea, useIdentityTransform); + layer->drawNow(renderArea, useIdentityTransform); if (filtering) layer->setFiltering(false); }); } @@ -5222,13 +5293,13 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } -void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& hw, int32_t minLayerZ, - int32_t maxLayerZ, +void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& display, + int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor) { // We loop through the first level of layers without traversing, // as we need to interpret min/max layer Z in the top level Z space. for (const auto& layer : mDrawingState.layersSortedByZ) { - if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + if (!layer->belongsToDisplay(display->getLayerStack(), false)) { continue; } const Layer::State& state(layer->getDrawingState()); @@ -5237,7 +5308,7 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& hw, continue; } layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + if (!layer->belongsToDisplay(display->getLayerStack(), false)) { return; } if (!layer->isVisible()) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8f724e98d1..12f4185e80 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -45,6 +45,7 @@ #include <gui/LayerState.h> #include <gui/OccupancyTracker.h> +#include <gui/BufferQueue.h> #include <hardware/hwcomposer_defs.h> @@ -64,6 +65,7 @@ #include "SurfaceTracing.h" #include "StartPropertySetThread.h" #include "TimeStats/TimeStats.h" +#include "LayerBE.h" #include "VSyncModulator.h" #include "DisplayHardware/HWC2.h" @@ -353,6 +355,8 @@ private: friend class impl::EventThread; friend class Layer; friend class BufferLayer; + friend class BufferQueueLayer; + friend class BufferStateLayer; friend class MonitoredProducer; // For unit tests @@ -410,7 +414,7 @@ private: virtual sp<ISurfaceComposerClient> createConnection(); virtual sp<ISurfaceComposerClient> createScopedConnection(const sp<IGraphicBufferProducer>& gbp); virtual sp<IBinder> createDisplay(const String8& displayName, bool secure); - virtual void destroyDisplay(const sp<IBinder>& display); + virtual void destroyDisplay(const sp<IBinder>& displayToken); virtual sp<IBinder> getBuiltInDisplay(int32_t id); virtual void setTransactionState(const Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags); @@ -421,27 +425,26 @@ private: std::vector<FrameEvent>* outSupported) const; virtual sp<IDisplayEventConnection> createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, + virtual status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop, float frameScale, bool childrenOnly); - virtual status_t getDisplayStats(const sp<IBinder>& display, - DisplayStatInfo* stats); - virtual status_t getDisplayConfigs(const sp<IBinder>& display, - Vector<DisplayInfo>* configs); - virtual int getActiveConfig(const sp<IBinder>& display); - virtual status_t getDisplayColorModes(const sp<IBinder>& display, - Vector<ui::ColorMode>* configs); - virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display); - virtual status_t setActiveColorMode(const sp<IBinder>& display, ui::ColorMode colorMode); - virtual void setPowerMode(const sp<IBinder>& display, int mode); - virtual status_t setActiveConfig(const sp<IBinder>& display, int id); + virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats); + virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken, + Vector<DisplayInfo>* configs); + virtual int getActiveConfig(const sp<IBinder>& displayToken); + virtual status_t getDisplayColorModes(const sp<IBinder>& displayToken, + Vector<ui::ColorMode>* configs); + virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken); + virtual status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode); + virtual void setPowerMode(const sp<IBinder>& displayToken, int mode); + virtual status_t setActiveConfig(const sp<IBinder>& displayToken, int id); virtual status_t clearAnimationFrameStats(); virtual status_t getAnimationFrameStats(FrameStats* outStats) const; - virtual status_t getHdrCapabilities(const sp<IBinder>& display, - HdrCapabilities* outCapabilities) const; + virtual status_t getHdrCapabilities(const sp<IBinder>& displayToken, + HdrCapabilities* outCapabilities) const; virtual status_t enableVSyncInjections(bool enable); virtual status_t injectVSync(nsecs_t when); virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const; @@ -460,11 +463,11 @@ private: /* ------------------------------------------------------------------------ * HWC2::ComposerCallback / HWComposer::EventHandler interface */ - void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, + void onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, int64_t timestamp) override; - void onHotplugReceived(int32_t sequenceId, hwc2_display_t display, + void onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, HWC2::Connection connection) override; - void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override; + void onRefreshReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId) override; /* ------------------------------------------------------------------------ * Message handling @@ -479,16 +482,13 @@ private: // called on the main thread in response to initializeDisplays() void onInitializeDisplays(); // called on the main thread in response to setActiveConfig() - void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode); + void setActiveConfigInternal(const sp<DisplayDevice>& display, int mode); // called on the main thread in response to setPowerMode() - void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode, - bool stateLockHeld); + void setPowerModeInternal(const sp<DisplayDevice>& display, int mode, bool stateLockHeld); // Called on the main thread in response to setActiveColorMode() - void setActiveColorModeInternal(const sp<DisplayDevice>& hw, - ui::ColorMode colorMode, - ui::Dataspace dataSpace, - ui::RenderIntent renderIntent); + void setActiveColorModeInternal(const sp<DisplayDevice>& display, ui::ColorMode colorMode, + ui::Dataspace dataSpace, ui::RenderIntent renderIntent); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -531,10 +531,14 @@ private: int32_t windowType, int32_t ownerUid, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent); - status_t createBufferLayer(const sp<Client>& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, - sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp, - sp<Layer>* outLayer); + status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags, PixelFormat& format, + sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp, + sp<Layer>* outLayer); + + status_t createBufferStateLayer(const sp<Client>& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags, sp<IBinder>* outHandle, + sp<Layer>* outLayer); status_t createColorLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle, @@ -599,38 +603,33 @@ private: // called when starting, or restarting after system_server death void initializeDisplays(); - sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const { - Mutex::Autolock _l(mStateLock); - return getDisplayDeviceLocked(dpy); + sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& displayToken) const { + Mutex::Autolock _l(mStateLock); + return getDisplayDeviceLocked(displayToken); } - sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) { - Mutex::Autolock _l(mStateLock); - return getDisplayDeviceLocked(dpy); + sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& displayToken) { + Mutex::Autolock _l(mStateLock); + return getDisplayDeviceLocked(displayToken); } // NOTE: can only be called from the main thread or with mStateLock held - sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) const { - return mDisplays.valueFor(dpy); + sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) const { + return const_cast<SurfaceFlinger*>(this)->getDisplayDeviceLocked(displayToken); } // NOTE: can only be called from the main thread or with mStateLock held - sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) { - return mDisplays.valueFor(dpy); + sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) { + const auto it = mDisplays.find(displayToken); + return it == mDisplays.end() ? nullptr : it->second; } sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const { - return getDisplayDeviceLocked(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]); + return const_cast<SurfaceFlinger*>(this)->getDefaultDisplayDeviceLocked(); } - int32_t getDisplayType(const sp<IBinder>& display) { - if (!display.get()) return NAME_NOT_FOUND; - for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { - if (display == mBuiltinDisplays[i]) { - return i; - } - } - return NAME_NOT_FOUND; + sp<DisplayDevice> getDefaultDisplayDeviceLocked() { + return getDisplayDeviceLocked(mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]); } // mark a region of a layer stack dirty. this updates the dirty @@ -647,8 +646,8 @@ private: * Compositing */ void invalidateHwcGeometry(); - void computeVisibleRegions(const sp<const DisplayDevice>& displayDevice, - Region& dirtyRegion, Region& opaqueRegion); + void computeVisibleRegions(const sp<const DisplayDevice>& display, Region& dirtyRegion, + Region& opaqueRegion); void preComposition(nsecs_t refreshStartTime); void postComposition(nsecs_t refreshStartTime); @@ -660,37 +659,35 @@ private: nsecs_t compositeToPresentLatency); void rebuildLayerStacks(); - ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& displayDevice, + ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& display, ui::Dataspace* outHdrDataSpace) const; // Returns the appropriate ColorMode, Dataspace and RenderIntent for the // DisplayDevice. The function only returns the supported ColorMode, // Dataspace and RenderIntent. - void pickColorMode(const sp<DisplayDevice>& displayDevice, - ui::ColorMode* outMode, - ui::Dataspace* outDataSpace, - ui::RenderIntent* outRenderIntent) const; + void pickColorMode(const sp<DisplayDevice>& display, ui::ColorMode* outMode, + ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const; void setUpHWComposer(); void doComposition(); void doDebugFlashRegions(); void doTracing(const char* where); void logLayerStats(); - void doDisplayComposition(const sp<const DisplayDevice>& displayDevice, const Region& dirtyRegion); + void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion); - // compose surfaces for display hw. this fails if using GL and the surface - // has been destroyed and is no longer valid. - bool doComposeSurfaces(const sp<const DisplayDevice>& displayDevice); + // This fails if using GL and the surface has been destroyed. + bool doComposeSurfaces(const sp<const DisplayDevice>& display); void postFramebuffer(); - void drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const; + void drawWormhole(const sp<const DisplayDevice>& display, const Region& region) const; /* ------------------------------------------------------------------------ * Display management */ - DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display, - HWC2::Connection connection) const; - sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId, + DisplayDevice::DisplayType determineDisplayType(hwc2_display_t hwcDisplayId, + HWC2::Connection connection) const; + sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, + int32_t displayId, const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer); @@ -740,9 +737,10 @@ private: void recordBufferingStats(const char* layerName, std::vector<OccupancyTracker::Segment>&& history); void dumpBufferingStats(String8& result) const; + void dumpDisplayIdentificationData(String8& result) const; void dumpWideColorInfo(String8& result) const; LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const; - LayersProto dumpVisibleLayersProtoInfo(int32_t hwcId) const; + LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; @@ -798,7 +796,7 @@ private: std::unique_ptr<VSyncSource> mSfEventThreadSource; std::unique_ptr<InjectVSyncSource> mVSyncInjector; std::unique_ptr<EventControlThread> mEventControlThread; - sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; + sp<IBinder> mDisplayTokens[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; VSyncModulator mVsyncModulator; @@ -820,7 +818,7 @@ private: BootStage mBootStage; struct HotplugEvent { - hwc2_display_t display; + hwc2_display_t hwcDisplayId; HWC2::Connection connection = HWC2::Connection::Invalid; }; // protected by mStateLock @@ -828,7 +826,7 @@ private: // this may only be written from the main thread with mStateLock held // it may be read from other threads with mStateLock held - DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays; + std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays; // don't use a lock for these, we don't care int mDebugRegion; @@ -847,6 +845,7 @@ private: LayerStats mLayerStats; TimeStats& mTimeStats = TimeStats::getInstance(); bool mUseHwcVirtualDisplays = false; + std::atomic<uint32_t> mFrameMissedCount{0}; // Restrict layers to use two buffers in their bufferqueues. bool mLayerTripleBufferingDisabled = false; @@ -854,7 +853,7 @@ private: // these are thread safe mutable std::unique_ptr<MessageQueue> mEventQueue{std::make_unique<impl::MessageQueue>()}; FrameTracker mAnimFrameTracker; - DispSync mPrimaryDispSync; + std::unique_ptr<DispSync> mPrimaryDispSync; int mPrimaryDisplayOrientation = DisplayState::eOrientationDefault; // protected by mDestroyedLayerLock; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 4596a21f12..f504c13a97 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -30,6 +30,7 @@ namespace android { // ---------------------------------------------------------------------------- +// TODO(marissaw): add new layer state values to SurfaceInterceptor SurfaceInterceptor::~SurfaceInterceptor() = default; @@ -99,18 +100,20 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation); const int32_t layerId(getLayerId(layer)); - addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(), - layer->mCurrentState.active.transform.ty()); + addPositionLocked(transaction, layerId, layer->mCurrentState.active_legacy.transform.tx(), + layer->mCurrentState.active_legacy.transform.ty()); addDepthLocked(transaction, layerId, layer->mCurrentState.z); addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a); - addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); + addTransparentRegionLocked(transaction, layerId, + layer->mCurrentState.activeTransparentRegion_legacy); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); - addCropLocked(transaction, layerId, layer->mCurrentState.crop); - if (layer->mCurrentState.barrierLayer != nullptr) { - addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer.promote(), - layer->mCurrentState.frameNumber); + addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy); + if (layer->mCurrentState.barrierLayer_legacy != nullptr) { + addDeferTransactionLocked(transaction, layerId, + layer->mCurrentState.barrierLayer_legacy.promote(), + layer->mCurrentState.frameNumber_legacy); } - addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop); + addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop_legacy); addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); } @@ -122,10 +125,10 @@ void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, transaction->set_synchronous(false); transaction->set_animation(false); - addDisplaySurfaceLocked(transaction, display.displayId, display.surface); - addDisplayLayerStackLocked(transaction, display.displayId, display.layerStack); - addDisplaySizeLocked(transaction, display.displayId, display.width, display.height); - addDisplayProjectionLocked(transaction, display.displayId, display.orientation, + addDisplaySurfaceLocked(transaction, display.sequenceId, display.surface); + addDisplayLayerStackLocked(transaction, display.sequenceId, display.layerStack); + addDisplaySizeLocked(transaction, display.sequenceId, display.width, display.height); + addDisplayProjectionLocked(transaction, display.sequenceId, display.orientation, display.viewport, display.frame); } @@ -177,10 +180,10 @@ SurfaceChange* SurfaceInterceptor::createSurfaceChangeLocked(Transaction* transa } DisplayChange* SurfaceInterceptor::createDisplayChangeLocked(Transaction* transaction, - int32_t displayId) + int32_t sequenceId) { DisplayChange* dispChange(transaction->add_display_change()); - dispChange->set_id(displayId); + dispChange->set_id(sequenceId); return dispChange; } @@ -353,25 +356,26 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eLayerStackChanged) { addLayerStackLocked(transaction, layerId, state.layerStack); } - if (state.what & layer_state_t::eCropChanged) { - addCropLocked(transaction, layerId, state.crop); + if (state.what & layer_state_t::eCropChanged_legacy) { + addCropLocked(transaction, layerId, state.crop_legacy); } - if (state.what & layer_state_t::eDeferTransaction) { + if (state.what & layer_state_t::eDeferTransaction_legacy) { sp<Layer> otherLayer = nullptr; - if (state.barrierHandle != nullptr) { - otherLayer = static_cast<Layer::Handle*>(state.barrierHandle.get())->owner.promote(); - } else if (state.barrierGbp != nullptr) { - auto const& gbp = state.barrierGbp; + if (state.barrierHandle_legacy != nullptr) { + otherLayer = + static_cast<Layer::Handle*>(state.barrierHandle_legacy.get())->owner.promote(); + } else if (state.barrierGbp_legacy != nullptr) { + auto const& gbp = state.barrierGbp_legacy; if (mFlinger->authenticateSurfaceTextureLocked(gbp)) { otherLayer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer(); } else { ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer"); } } - addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber); + addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy); } - if (state.what & layer_state_t::eFinalCropChanged) { - addFinalCropLocked(transaction, layerId, state.finalCrop); + if (state.what & layer_state_t::eFinalCropChanged_legacy) { + addFinalCropLocked(transaction, layerId, state.finalCrop_legacy); } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); @@ -379,19 +383,19 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, } void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction, - const DisplayState& state, int32_t displayId) + const DisplayState& state, int32_t sequenceId) { if (state.what & DisplayState::eSurfaceChanged) { - addDisplaySurfaceLocked(transaction, displayId, state.surface); + addDisplaySurfaceLocked(transaction, sequenceId, state.surface); } if (state.what & DisplayState::eLayerStackChanged) { - addDisplayLayerStackLocked(transaction, displayId, state.layerStack); + addDisplayLayerStackLocked(transaction, sequenceId, state.layerStack); } if (state.what & DisplayState::eDisplaySizeChanged) { - addDisplaySizeLocked(transaction, displayId, state.width, state.height); + addDisplaySizeLocked(transaction, sequenceId, state.width, state.height); } if (state.what & DisplayState::eDisplayProjectionChanged) { - addDisplayProjectionLocked(transaction, displayId, state.orientation, state.viewport, + addDisplayProjectionLocked(transaction, sequenceId, state.orientation, state.viewport, state.frame); } } @@ -411,7 +415,7 @@ void SurfaceInterceptor::addTransactionLocked(Increment* increment, ssize_t dpyIdx = displays.indexOfKey(disp.token); if (dpyIdx >= 0) { const DisplayDeviceState& dispState(displays.valueAt(dpyIdx)); - addDisplayChangesLocked(transaction, disp, dispState.displayId); + addDisplayChangesLocked(transaction, disp, dispState.sequenceId); } } } @@ -422,8 +426,8 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); creation->set_name(getLayerName(layer)); - creation->set_w(layer->mCurrentState.active.w); - creation->set_h(layer->mCurrentState.active.h); + creation->set_w(layer->mCurrentState.active_legacy.w); + creation->set_h(layer->mCurrentState.active_legacy.h); } void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment, @@ -448,7 +452,7 @@ void SurfaceInterceptor::addVSyncUpdateLocked(Increment* increment, nsecs_t time event->set_when(timestamp); } -void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId, +void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32_t sequenceId, const sp<const IGraphicBufferProducer>& surface) { if (surface == nullptr) { @@ -457,7 +461,7 @@ void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32 uint64_t bufferQueueId = 0; status_t err(surface->getUniqueId(&bufferQueueId)); if (err == NO_ERROR) { - DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId)); + DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId)); DispSurfaceChange* surfaceChange(dispChange->mutable_surface()); surfaceChange->set_buffer_queue_id(bufferQueueId); surfaceChange->set_buffer_queue_name(surface->getConsumerName().string()); @@ -469,26 +473,26 @@ void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32 } void SurfaceInterceptor::addDisplayLayerStackLocked(Transaction* transaction, - int32_t displayId, uint32_t layerStack) + int32_t sequenceId, uint32_t layerStack) { - DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId)); + DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId)); LayerStackChange* layerStackChange(dispChange->mutable_layer_stack()); layerStackChange->set_layer_stack(layerStack); } -void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t displayId, +void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId, uint32_t w, uint32_t h) { - DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId)); + DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId)); SizeChange* sizeChange(dispChange->mutable_size()); sizeChange->set_w(w); sizeChange->set_h(h); } void SurfaceInterceptor::addDisplayProjectionLocked(Transaction* transaction, - int32_t displayId, int32_t orientation, const Rect& viewport, const Rect& frame) + int32_t sequenceId, int32_t orientation, const Rect& viewport, const Rect& frame) { - DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId)); + DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId)); ProjectionChange* projectionChange(dispChange->mutable_projection()); projectionChange->set_orientation(orientation); Rectangle* viewportRect(projectionChange->mutable_viewport()); @@ -501,22 +505,22 @@ void SurfaceInterceptor::addDisplayCreationLocked(Increment* increment, const DisplayDeviceState& info) { DisplayCreation* creation(increment->mutable_display_creation()); - creation->set_id(info.displayId); + creation->set_id(info.sequenceId); creation->set_name(info.displayName); creation->set_type(info.type); creation->set_is_secure(info.isSecure); } -void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t displayId) { +void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t sequenceId) { DisplayDeletion* deletion(increment->mutable_display_deletion()); - deletion->set_id(displayId); + deletion->set_id(sequenceId); } -void SurfaceInterceptor::addPowerModeUpdateLocked(Increment* increment, int32_t displayId, +void SurfaceInterceptor::addPowerModeUpdateLocked(Increment* increment, int32_t sequenceId, int32_t mode) { PowerModeUpdate* powerModeUpdate(increment->mutable_power_mode_update()); - powerModeUpdate->set_id(displayId); + powerModeUpdate->set_id(sequenceId); powerModeUpdate->set_mode(mode); } @@ -579,22 +583,22 @@ void SurfaceInterceptor::saveDisplayCreation(const DisplayDeviceState& info) { addDisplayCreationLocked(createTraceIncrementLocked(), info); } -void SurfaceInterceptor::saveDisplayDeletion(int32_t displayId) { +void SurfaceInterceptor::saveDisplayDeletion(int32_t sequenceId) { if (!mEnabled) { return; } ATRACE_CALL(); std::lock_guard<std::mutex> protoGuard(mTraceMutex); - addDisplayDeletionLocked(createTraceIncrementLocked(), displayId); + addDisplayDeletionLocked(createTraceIncrementLocked(), sequenceId); } -void SurfaceInterceptor::savePowerModeUpdate(int32_t displayId, int32_t mode) { +void SurfaceInterceptor::savePowerModeUpdate(int32_t sequenceId, int32_t mode) { if (!mEnabled) { return; } ATRACE_CALL(); std::lock_guard<std::mutex> protoGuard(mTraceMutex); - addPowerModeUpdateLocked(createTraceIncrementLocked(), displayId, mode); + addPowerModeUpdateLocked(createTraceIncrementLocked(), sequenceId, mode); } } // namespace impl diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 96defcc265..218a1d2d22 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -66,8 +66,8 @@ public: // Intercept display data virtual void saveDisplayCreation(const DisplayDeviceState& info) = 0; - virtual void saveDisplayDeletion(int32_t displayId) = 0; - virtual void savePowerModeUpdate(int32_t displayId, int32_t mode) = 0; + virtual void saveDisplayDeletion(int32_t sequenceId) = 0; + virtual void savePowerModeUpdate(int32_t sequenceId, int32_t mode) = 0; virtual void saveVSyncEvent(nsecs_t timestamp) = 0; }; @@ -101,8 +101,8 @@ public: // Intercept display data void saveDisplayCreation(const DisplayDeviceState& info) override; - void saveDisplayDeletion(int32_t displayId) override; - void savePowerModeUpdate(int32_t displayId, int32_t mode) override; + void saveDisplayDeletion(int32_t sequenceId) override; + void savePowerModeUpdate(int32_t sequenceId, int32_t mode) override; void saveVSyncEvent(nsecs_t timestamp) override; private: @@ -127,8 +127,8 @@ private: uint32_t height, uint64_t frameNumber); void addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp); void addDisplayCreationLocked(Increment* increment, const DisplayDeviceState& info); - void addDisplayDeletionLocked(Increment* increment, int32_t displayId); - void addPowerModeUpdateLocked(Increment* increment, int32_t displayId, int32_t mode); + void addDisplayDeletionLocked(Increment* increment, int32_t sequenceId); + void addPowerModeUpdateLocked(Increment* increment, int32_t sequenceId, int32_t mode); // Add surface transactions to the trace SurfaceChange* createSurfaceChangeLocked(Transaction* transaction, int32_t layerId); @@ -155,17 +155,17 @@ private: const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags); // Add display transactions to the trace - DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t displayId); - void addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId, + DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId); + void addDisplaySurfaceLocked(Transaction* transaction, int32_t sequenceId, const sp<const IGraphicBufferProducer>& surface); - void addDisplayLayerStackLocked(Transaction* transaction, int32_t displayId, + void addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId, uint32_t layerStack); - void addDisplaySizeLocked(Transaction* transaction, int32_t displayId, uint32_t w, + void addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId, uint32_t w, uint32_t h); - void addDisplayProjectionLocked(Transaction* transaction, int32_t displayId, + void addDisplayProjectionLocked(Transaction* transaction, int32_t sequenceId, int32_t orientation, const Rect& viewport, const Rect& frame); void addDisplayChangesLocked(Transaction* transaction, - const DisplayState& state, int32_t displayId); + const DisplayState& state, int32_t sequenceId); bool mEnabled {false}; diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index f8c466ea19..0e9b04eed1 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -58,7 +58,9 @@ bool SurfaceTracing::isEnabled() { void SurfaceTracing::traceLayers(const char* where, LayersProto layers) { std::lock_guard<std::mutex> protoGuard(mTraceMutex); - + if (!mEnabled) { + return; + } LayersTraceProto* entry = mTrace.add_entry(); entry->set_elapsed_realtime_nanos(elapsedRealtimeNano()); entry->set_where(where); diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index d4f1e29042..d77a324027 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -109,7 +109,7 @@ void TimeStats::incrementClientCompositionFrames() { bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord) { if (!timeRecord->ready) { ALOGV("[%s]-[%" PRIu64 "]-presentFence is still not received", layerName.c_str(), - timeRecord->frameNumber); + timeRecord->frameTime.frameNumber); return false; } @@ -118,11 +118,11 @@ bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* time return false; } if (timeRecord->acquireFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) { - timeRecord->acquireTime = timeRecord->acquireFence->getSignalTime(); + timeRecord->frameTime.acquireTime = timeRecord->acquireFence->getSignalTime(); timeRecord->acquireFence = nullptr; } else { ALOGV("[%s]-[%" PRIu64 "]-acquireFence signal time is invalid", layerName.c_str(), - timeRecord->frameNumber); + timeRecord->frameTime.frameNumber); } } @@ -131,11 +131,11 @@ bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* time return false; } if (timeRecord->presentFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) { - timeRecord->presentTime = timeRecord->presentFence->getSignalTime(); + timeRecord->frameTime.presentTime = timeRecord->presentFence->getSignalTime(); timeRecord->presentFence = nullptr; } else { ALOGV("[%s]-[%" PRIu64 "]-presentFence signal time invalid", layerName.c_str(), - timeRecord->frameNumber); + timeRecord->frameTime.frameNumber); } } @@ -172,48 +172,53 @@ void TimeStats::flushAvailableRecordsToStatsLocked(const std::string& layerName) while (!timeRecords.empty()) { if (!recordReadyLocked(layerName, &timeRecords[0])) break; ALOGV("[%s]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerName.c_str(), - timeRecords[0].frameNumber, timeRecords[0].presentTime); + timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime); if (prevTimeRecord.ready) { if (!timeStats.stats.count(layerName)) { timeStats.stats[layerName].layerName = layerName; timeStats.stats[layerName].packageName = getPackageName(layerName); - timeStats.stats[layerName].statsStart = static_cast<int64_t>(std::time(0)); } TimeStatsHelper::TimeStatsLayer& timeStatsLayer = timeStats.stats[layerName]; timeStatsLayer.totalFrames++; + timeStatsLayer.droppedFrames += layerRecord.droppedFrames; + layerRecord.droppedFrames = 0; - const int32_t postToPresentMs = - msBetween(timeRecords[0].postTime, timeRecords[0].presentTime); + const int32_t postToAcquireMs = msBetween(timeRecords[0].frameTime.postTime, + timeRecords[0].frameTime.acquireTime); + ALOGV("[%s]-[%" PRIu64 "]-post2acquire[%d]", layerName.c_str(), + timeRecords[0].frameTime.frameNumber, postToAcquireMs); + timeStatsLayer.deltas["post2acquire"].insert(postToAcquireMs); + + const int32_t postToPresentMs = msBetween(timeRecords[0].frameTime.postTime, + timeRecords[0].frameTime.presentTime); ALOGV("[%s]-[%" PRIu64 "]-post2present[%d]", layerName.c_str(), - timeRecords[0].frameNumber, postToPresentMs); + timeRecords[0].frameTime.frameNumber, postToPresentMs); timeStatsLayer.deltas["post2present"].insert(postToPresentMs); - const int32_t acquireToPresentMs = - msBetween(timeRecords[0].acquireTime, timeRecords[0].presentTime); + const int32_t acquireToPresentMs = msBetween(timeRecords[0].frameTime.acquireTime, + timeRecords[0].frameTime.presentTime); ALOGV("[%s]-[%" PRIu64 "]-acquire2present[%d]", layerName.c_str(), - timeRecords[0].frameNumber, acquireToPresentMs); + timeRecords[0].frameTime.frameNumber, acquireToPresentMs); timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs); - const int32_t latchToPresentMs = - msBetween(timeRecords[0].latchTime, timeRecords[0].presentTime); + const int32_t latchToPresentMs = msBetween(timeRecords[0].frameTime.latchTime, + timeRecords[0].frameTime.presentTime); ALOGV("[%s]-[%" PRIu64 "]-latch2present[%d]", layerName.c_str(), - timeRecords[0].frameNumber, latchToPresentMs); + timeRecords[0].frameTime.frameNumber, latchToPresentMs); timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs); - const int32_t desiredToPresentMs = - msBetween(timeRecords[0].desiredTime, timeRecords[0].presentTime); + const int32_t desiredToPresentMs = msBetween(timeRecords[0].frameTime.desiredTime, + timeRecords[0].frameTime.presentTime); ALOGV("[%s]-[%" PRIu64 "]-desired2present[%d]", layerName.c_str(), - timeRecords[0].frameNumber, desiredToPresentMs); + timeRecords[0].frameTime.frameNumber, desiredToPresentMs); timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs); - const int32_t presentToPresentMs = - msBetween(prevTimeRecord.presentTime, timeRecords[0].presentTime); + const int32_t presentToPresentMs = msBetween(prevTimeRecord.frameTime.presentTime, + timeRecords[0].frameTime.presentTime); ALOGV("[%s]-[%" PRIu64 "]-present2present[%d]", layerName.c_str(), - timeRecords[0].frameNumber, presentToPresentMs); + timeRecords[0].frameTime.frameNumber, presentToPresentMs); timeStatsLayer.deltas["present2present"].insert(presentToPresentMs); - - timeStats.stats[layerName].statsEnd = static_cast<int64_t>(std::time(0)); } prevTimeRecord = timeRecords[0]; timeRecords.pop_front(); @@ -225,12 +230,12 @@ static bool layerNameIsValid(const std::string& layerName) { // This regular expression captures the following layer names for instance: // 1) StatusBat#0 // 2) NavigationBar#1 - // 3) com.*#0 - // 4) SurfaceView - com.*#0 - // Using [-\\s\t]+ for the conjunction part between SurfaceView and com.* is - // a bit more robust in case there's a slight change. + // 3) co(m).*#0 + // 4) SurfaceView - co(m).*#0 + // Using [-\\s\t]+ for the conjunction part between SurfaceView and co(m).* + // is a bit more robust in case there's a slight change. // The layer name would only consist of . / $ _ 0-9 a-z A-Z in most cases. - std::regex re("(((SurfaceView[-\\s\\t]+)?com\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+"); + std::regex re("(((SurfaceView[-\\s\\t]+)?com?\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+"); return std::regex_match(layerName.begin(), layerName.end(), re); } @@ -257,9 +262,12 @@ void TimeStats::setPostTime(const std::string& layerName, uint64_t frameNumber, // ready at the queueBuffer stage. In this case, acquireTime should be given // a default value as postTime. TimeRecord timeRecord = { - .frameNumber = frameNumber, - .postTime = postTime, - .acquireTime = postTime, + .frameTime = + { + .frameNumber = frameNumber, + .postTime = postTime, + .acquireTime = postTime, + }, }; layerRecord.timeRecords.push_back(timeRecord); if (layerRecord.waitData < 0 || @@ -278,8 +286,8 @@ void TimeStats::setLatchTime(const std::string& layerName, uint64_t frameNumber, if (!timeStatsTracker.count(layerName)) return; LayerRecord& layerRecord = timeStatsTracker[layerName]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; - if (timeRecord.frameNumber == frameNumber) { - timeRecord.latchTime = latchTime; + if (timeRecord.frameTime.frameNumber == frameNumber) { + timeRecord.frameTime.latchTime = latchTime; } } @@ -295,8 +303,8 @@ void TimeStats::setDesiredTime(const std::string& layerName, uint64_t frameNumbe if (!timeStatsTracker.count(layerName)) return; LayerRecord& layerRecord = timeStatsTracker[layerName]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; - if (timeRecord.frameNumber == frameNumber) { - timeRecord.desiredTime = desiredTime; + if (timeRecord.frameTime.frameNumber == frameNumber) { + timeRecord.frameTime.desiredTime = desiredTime; } } @@ -312,8 +320,8 @@ void TimeStats::setAcquireTime(const std::string& layerName, uint64_t frameNumbe if (!timeStatsTracker.count(layerName)) return; LayerRecord& layerRecord = timeStatsTracker[layerName]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; - if (timeRecord.frameNumber == frameNumber) { - timeRecord.acquireTime = acquireTime; + if (timeRecord.frameTime.frameNumber == frameNumber) { + timeRecord.frameTime.acquireTime = acquireTime; } } @@ -329,7 +337,7 @@ void TimeStats::setAcquireFence(const std::string& layerName, uint64_t frameNumb if (!timeStatsTracker.count(layerName)) return; LayerRecord& layerRecord = timeStatsTracker[layerName]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; - if (timeRecord.frameNumber == frameNumber) { + if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.acquireFence = acquireFence; } } @@ -346,8 +354,8 @@ void TimeStats::setPresentTime(const std::string& layerName, uint64_t frameNumbe if (!timeStatsTracker.count(layerName)) return; LayerRecord& layerRecord = timeStatsTracker[layerName]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; - if (timeRecord.frameNumber == frameNumber) { - timeRecord.presentTime = presentTime; + if (timeRecord.frameTime.frameNumber == frameNumber) { + timeRecord.frameTime.presentTime = presentTime; timeRecord.ready = true; layerRecord.waitData++; } @@ -367,7 +375,7 @@ void TimeStats::setPresentFence(const std::string& layerName, uint64_t frameNumb if (!timeStatsTracker.count(layerName)) return; LayerRecord& layerRecord = timeStatsTracker[layerName]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; - if (timeRecord.frameNumber == frameNumber) { + if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.presentFence = presentFence; timeRecord.ready = true; layerRecord.waitData++; @@ -400,6 +408,7 @@ void TimeStats::clearLayerRecord(const std::string& layerName) { layerRecord.timeRecords.clear(); layerRecord.prevTimeRecord.ready = false; layerRecord.waitData = -1; + layerRecord.droppedFrames = 0; } void TimeStats::removeTimeRecord(const std::string& layerName, uint64_t frameNumber) { @@ -413,14 +422,15 @@ void TimeStats::removeTimeRecord(const std::string& layerName, uint64_t frameNum LayerRecord& layerRecord = timeStatsTracker[layerName]; size_t removeAt = 0; for (const TimeRecord& record : layerRecord.timeRecords) { - if (record.frameNumber == frameNumber) break; + if (record.frameTime.frameNumber == frameNumber) break; removeAt++; } if (removeAt == layerRecord.timeRecords.size()) return; layerRecord.timeRecords.erase(layerRecord.timeRecords.begin() + removeAt); if (layerRecord.waitData > static_cast<int32_t>(removeAt)) { - --layerRecord.waitData; + layerRecord.waitData--; } + layerRecord.droppedFrames++; } void TimeStats::enable() { diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 831821000f..5ab3934021 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -40,14 +40,18 @@ class TimeStats { // static const size_t MAX_NUM_LAYER_RECORDS = 200; static const size_t MAX_NUM_TIME_RECORDS = 64; - struct TimeRecord { - bool ready = false; + struct FrameTime { uint64_t frameNumber = 0; nsecs_t postTime = 0; nsecs_t latchTime = 0; nsecs_t acquireTime = 0; nsecs_t desiredTime = 0; nsecs_t presentTime = 0; + }; + + struct TimeRecord { + bool ready = false; + FrameTime frameTime; std::shared_ptr<FenceTime> acquireFence; std::shared_ptr<FenceTime> presentFence; }; @@ -57,6 +61,7 @@ class TimeStats { // specific frame are still not fully received. This is not waiting for // fences to signal, but rather waiting to receive those fences/timestamps. int32_t waitData = -1; + uint32_t droppedFrames = 0; TimeRecord prevTimeRecord; std::deque<TimeRecord> timeRecords; }; @@ -77,8 +82,11 @@ public: void setPresentTime(const std::string& layerName, uint64_t frameNumber, nsecs_t presentTime); void setPresentFence(const std::string& layerName, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence); + // On producer disconnect with BufferQueue. void onDisconnect(const std::string& layerName); + // When SF is cleaning up the queue, clear the LayerRecord as well. void clearLayerRecord(const std::string& layerName); + // If SF skips or rejects a buffer, remove the corresponding TimeRecord. void removeTimeRecord(const std::string& layerName, uint64_t frameNumber); private: diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp index 21f3ef3d7e..b7b2778c5c 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp +++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp @@ -68,12 +68,11 @@ std::string TimeStatsHelper::Histogram::toString() const { } std::string TimeStatsHelper::TimeStatsLayer::toString() const { - std::string result = ""; + std::string result = "\n"; StringAppendF(&result, "layerName = %s\n", layerName.c_str()); StringAppendF(&result, "packageName = %s\n", packageName.c_str()); - StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart)); - StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd)); - StringAppendF(&result, "totalFrames= %d\n", totalFrames); + StringAppendF(&result, "totalFrames = %d\n", totalFrames); + StringAppendF(&result, "droppedFrames = %d\n", droppedFrames); auto iter = deltas.find("present2present"); if (iter != deltas.end()) { StringAppendF(&result, "averageFPS = %.3f\n", 1000.0 / iter->second.averageTime()); @@ -90,10 +89,9 @@ std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional<uint32_t> m std::string result = "SurfaceFlinger TimeStats:\n"; StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart)); StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd)); - StringAppendF(&result, "totalFrames= %d\n", totalFrames); - StringAppendF(&result, "missedFrames= %d\n", missedFrames); - StringAppendF(&result, "clientCompositionFrames= %d\n", clientCompositionFrames); - StringAppendF(&result, "TimeStats for each layer is as below:\n"); + StringAppendF(&result, "totalFrames = %d\n", totalFrames); + StringAppendF(&result, "missedFrames = %d\n", missedFrames); + StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames); const auto dumpStats = generateDumpStats(maxLayers); for (auto& ele : dumpStats) { StringAppendF(&result, "%s", ele->toString().c_str()); @@ -106,15 +104,14 @@ SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() const { SFTimeStatsLayerProto layerProto; layerProto.set_layer_name(layerName); layerProto.set_package_name(packageName); - layerProto.set_stats_start(statsStart); - layerProto.set_stats_end(statsEnd); layerProto.set_total_frames(totalFrames); + layerProto.set_dropped_frames(droppedFrames); for (auto& ele : deltas) { SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas(); deltaProto->set_delta_name(ele.first); for (auto& histEle : ele.second.hist) { SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms(); - histProto->set_render_millis(histEle.first); + histProto->set_time_millis(histEle.first); histProto->set_frame_count(histEle.second); } } diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h index 1798555be5..99c891bf69 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h @@ -42,9 +42,8 @@ public: public: std::string layerName; std::string packageName; - int64_t statsStart = 0; - int64_t statsEnd = 0; int32_t totalFrames = 0; + int32_t droppedFrames = 0; std::unordered_map<std::string, Histogram> deltas; std::string toString() const; diff --git a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto index f29fbd187a..ab7527e433 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto +++ b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto @@ -20,46 +20,59 @@ package android.surfaceflinger; option optimize_for = LITE_RUNTIME; +// //depot/google3/java/com/google/android/apps/graphics/proto/timestats.proto +// is based on this proto. Please only make valid protobuf changes to these +// messages, and keep the other file in sync per Android release. Please also +// do not include "option optimize_for = LITE_RUNTIME;" on google3 side. + +// Next tag: 7 message SFTimeStatsGlobalProto { - // The start & end timestamps in UTC as - // milliseconds since January 1, 1970 + // The stats start time in UTC as seconds since January 1, 1970 optional int64 stats_start = 1; + // The stats end time in UTC as seconds since January 1, 1970 optional int64 stats_end = 2; - // Total frames + // Total number of frames presented during tracing period. optional int32 total_frames = 3; // Total missed frames of SurfaceFlinger. optional int32 missed_frames = 4; // Total frames fallback to client composition. optional int32 client_composition_frames = 5; - + // Stats per layer. Apps could have multiple layers. repeated SFTimeStatsLayerProto stats = 6; } +// Next tag: 8 message SFTimeStatsLayerProto { - // The layer name + // The name of the visible view layer. optional string layer_name = 1; - // The package name + // The package name of the application owning this layer. optional string package_name = 2; - // The start & end timestamps in UTC as - // milliseconds since January 1, 1970 + // The stats start time in UTC as seconds since January 1, 1970 optional int64 stats_start = 3; + // The stats end time in UTC as seconds since January 1, 1970 optional int64 stats_end = 4; - // Distinct frame count. + // Total number of frames presented during tracing period. optional int32 total_frames = 5; - + // Total number of frames dropped by SurfaceFlinger. + optional int32 dropped_frames = 7; + // There are multiple timestamps tracked in SurfaceFlinger, and these are the + // histograms of deltas between different combinations of those timestamps. repeated SFTimeStatsDeltaProto deltas = 6; } +// Next tag: 3 message SFTimeStatsDeltaProto { // Name of the time interval optional string delta_name = 1; - // Histogram of the delta time + // Histogram of the delta time. There should be at most 85 buckets ranging + // from [0ms, 1ms) to [1000ms, infinity) repeated SFTimeStatsHistogramBucketProto histograms = 2; } +// Next tag: 3 message SFTimeStatsHistogramBucketProto { - // Lower bound of render time in milliseconds. - optional int32 render_millis = 1; + // Lower bound of time interval in milliseconds. + optional int32 time_millis = 1; // Number of frames in the bucket. optional int32 frame_count = 2; } diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index fcf42f00a9..e1c0fd340d 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -114,6 +114,7 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->transform = generateTransform(layerProto.transform()); layer->requestedTransform = generateTransform(layerProto.requested_transform()); layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); + layer->bufferTransform = generateTransform(layerProto.buffer_transform()); layer->queuedFrames = layerProto.queued_frames(); layer->refreshPending = layerProto.refresh_pending(); layer->hwcFrame = generateRect(layerProto.hwc_frame()); @@ -312,6 +313,7 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, " zOrderRelativeOf=%s\n", zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str()); StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); + StringAppendF(&result, " tr=%s", bufferTransform.to_string().c_str()); StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending); StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId); diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 74a6f28f2b..360e5997d1 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -105,6 +105,7 @@ public: Layer* parent = 0; Layer* zOrderRelativeOf = 0; LayerProtoParser::ActiveBuffer activeBuffer; + Transform bufferTransform; int32_t queuedFrames; bool refreshPending; LayerProtoParser::Rect hwcFrame; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index edf56abc4a..e34772fd4f 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -80,10 +80,12 @@ message LayerProto { optional int32 hwc_composition_type = 35; // If it's a buffer layer, indicate if the content is protected optional bool is_protected = 36; + // If active_buffer is not null, record its transform + optional TransformProto buffer_transform = 37; // Current frame number being rendered. - optional uint64 curr_frame = 37; + optional uint64 curr_frame = 38; // A list of barriers that the layer is waiting to update state. - repeated BarrierLayerProto barrier_layer = 38; + repeated BarrierLayerProto barrier_layer = 39; } message PositionProto { diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 36424b9c5e..731e628bb8 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*" + "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize" } } diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index de78c3f355..8ac2c87b9e 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -42,13 +42,16 @@ constexpr uint32_t BUFFER_UPDATES = 18; constexpr uint32_t LAYER_UPDATE = INT_MAX - 2; constexpr uint32_t SIZE_UPDATE = 134; constexpr uint32_t STACK_UPDATE = 1; -constexpr uint64_t DEFERRED_UPDATE = 13; +constexpr uint64_t DEFERRED_UPDATE = 0; constexpr float ALPHA_UPDATE = 0.29f; constexpr float POSITION_UPDATE = 121; const Rect CROP_UPDATE(16, 16, 32, 32); const String8 DISPLAY_NAME("SurfaceInterceptor Display Test"); +constexpr auto TEST_SURFACE_NAME = "BG Interceptor Test Surface"; +constexpr auto UNIQUE_TEST_SURFACE_NAME = "BG Interceptor Test Surface#0"; constexpr auto LAYER_NAME = "Layer Create and Delete Test"; +constexpr auto UNIQUE_LAYER_NAME = "Layer Create and Delete Test#0"; constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat"; @@ -94,30 +97,21 @@ static void disableInterceptor() { system("service call SurfaceFlinger 1020 i32 0 > /dev/null"); } -int32_t getSurfaceId(const std::string& surfaceName) { - enableInterceptor(); - disableInterceptor(); - Trace capturedTrace; - readProtoFile(&capturedTrace); +int32_t getSurfaceId(const Trace& capturedTrace, const std::string& surfaceName) { int32_t layerId = 0; - for (const auto& increment : *capturedTrace.mutable_increment()) { + for (const auto& increment : capturedTrace.increment()) { if (increment.increment_case() == increment.kSurfaceCreation) { if (increment.surface_creation().name() == surfaceName) { layerId = increment.surface_creation().id(); - break; } } } return layerId; } -int32_t getDisplayId(const std::string& displayName) { - enableInterceptor(); - disableInterceptor(); - Trace capturedTrace; - readProtoFile(&capturedTrace); +int32_t getDisplayId(const Trace& capturedTrace, const std::string& displayName) { int32_t displayId = 0; - for (const auto& increment : *capturedTrace.mutable_increment()) { + for (const auto& increment : capturedTrace.increment()) { if (increment.increment_case() == increment.kDisplayCreation) { if (increment.display_creation().name() == displayName) { displayId = increment.display_creation().id(); @@ -130,36 +124,15 @@ int32_t getDisplayId(const std::string& displayName) { class SurfaceInterceptorTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { // Allow SurfaceInterceptor write to /data system("setenforce 0"); mComposerClient = new SurfaceComposerClient; ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); - - sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay( - ISurfaceComposer::eDisplayIdMain)); - DisplayInfo info; - SurfaceComposerClient::getDisplayInfo(display, &info); - ssize_t displayWidth = info.w; - ssize_t displayHeight = info.h; - - // Background surface - mBGSurfaceControl = mComposerClient->createSurface( - String8("BG Interceptor Test Surface"), displayWidth, displayHeight, - PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(mBGSurfaceControl != nullptr); - ASSERT_TRUE(mBGSurfaceControl->isValid()); - mBGLayerId = getSurfaceId("BG Interceptor Test Surface"); - - Transaction t; - t.setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3) - .show(mBGSurfaceControl) - .apply()); } - virtual void TearDown() { + void TearDown() override { mComposerClient->dispose(); mBGSurfaceControl.clear(); mComposerClient.clear(); @@ -168,18 +141,25 @@ protected: sp<SurfaceComposerClient> mComposerClient; sp<SurfaceControl> mBGSurfaceControl; int32_t mBGLayerId; - // Used to verify creation and destruction of surfaces and displays - int32_t mTargetId; public: - void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), - bool (SurfaceInterceptorTest::* verification)(Trace *)); - void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), - SurfaceChange::SurfaceChangeCase changeCase); - void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), - Increment::IncrementCase incrementCase); - void runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&), - bool intercepted = false); + using TestTransactionAction = void (SurfaceInterceptorTest::*)(Transaction&); + using TestAction = void (SurfaceInterceptorTest::*)(); + using TestBooleanVerification = bool (SurfaceInterceptorTest::*)(const Trace&); + using TestVerification = void (SurfaceInterceptorTest::*)(const Trace&); + + void setupBackgroundSurface(); + void preProcessTrace(const Trace& trace); + + // captureTest will enable SurfaceInterceptor, setup background surface, + // disable SurfaceInterceptor, collect the trace and process the trace for + // id of background surface before further verification. + void captureTest(TestTransactionAction action, TestBooleanVerification verification); + void captureTest(TestTransactionAction action, SurfaceChange::SurfaceChangeCase changeCase); + void captureTest(TestTransactionAction action, Increment::IncrementCase incrementCase); + void captureTest(TestAction action, TestBooleanVerification verification); + void captureTest(TestAction action, TestVerification verification); + void runInTransaction(TestTransactionAction action); // Verification of changes to a surface bool positionUpdateFound(const SurfaceChange& change, bool foundPosition); @@ -196,18 +176,22 @@ public: bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag); bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag); bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred); - bool surfaceUpdateFound(Trace* trace, SurfaceChange::SurfaceChangeCase changeCase); - void assertAllUpdatesFound(Trace* trace); + bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase); + + // Find all of the updates in the single trace + void assertAllUpdatesFound(const Trace& trace); // Verification of creation and deletion of a surface bool surfaceCreationFound(const Increment& increment, bool foundSurface); - bool surfaceDeletionFound(const Increment& increment, bool foundSurface); + bool surfaceDeletionFound(const Increment& increment, const int32_t targetId, + bool foundSurface); bool displayCreationFound(const Increment& increment, bool foundDisplay); - bool displayDeletionFound(const Increment& increment, bool foundDisplay); - bool singleIncrementFound(Trace* trace, Increment::IncrementCase incrementCase); + bool displayDeletionFound(const Increment& increment, const int32_t targetId, + bool foundDisplay); + bool singleIncrementFound(const Trace& trace, Increment::IncrementCase incrementCase); // Verification of buffer updates - bool bufferUpdatesFound(Trace* trace); + bool bufferUpdatesFound(const Trace& trace); // Perform each of the possible changes to a surface void positionUpdate(Transaction&); @@ -230,48 +214,93 @@ public: void nBufferUpdates(); void runAllUpdates(); + +private: + void captureInTransaction(TestTransactionAction action, Trace*); + void capture(TestAction action, Trace*); }; -void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), - bool (SurfaceInterceptorTest::* verification)(Trace *)) -{ - runInTransaction(action, true); +void SurfaceInterceptorTest::captureInTransaction(TestTransactionAction action, Trace* outTrace) { + enableInterceptor(); + setupBackgroundSurface(); + runInTransaction(action); + disableInterceptor(); + ASSERT_EQ(NO_ERROR, readProtoFile(outTrace)); + preProcessTrace(*outTrace); +} + +void SurfaceInterceptorTest::capture(TestAction action, Trace* outTrace) { + enableInterceptor(); + setupBackgroundSurface(); + (this->*action)(); + disableInterceptor(); + ASSERT_EQ(NO_ERROR, readProtoFile(outTrace)); + preProcessTrace(*outTrace); +} + +void SurfaceInterceptorTest::setupBackgroundSurface() { + sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay( + ISurfaceComposer::eDisplayIdMain)); + DisplayInfo info; + SurfaceComposerClient::getDisplayInfo(display, &info); + ssize_t displayWidth = info.w; + ssize_t displayHeight = info.h; + + // Background surface + mBGSurfaceControl = mComposerClient->createSurface( + String8(TEST_SURFACE_NAME), displayWidth, displayHeight, + PIXEL_FORMAT_RGBA_8888, 0); + ASSERT_TRUE(mBGSurfaceControl != nullptr); + ASSERT_TRUE(mBGSurfaceControl->isValid()); + + Transaction t; + t.setDisplayLayerStack(display, 0); + ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3) + .show(mBGSurfaceControl) + .apply()); +} + +void SurfaceInterceptorTest::preProcessTrace(const Trace& trace) { + mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_SURFACE_NAME); +} + +void SurfaceInterceptorTest::captureTest(TestTransactionAction action, + TestBooleanVerification verification) { Trace capturedTrace; - ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - ASSERT_TRUE((this->*verification)(&capturedTrace)); + captureInTransaction(action, &capturedTrace); + ASSERT_TRUE((this->*verification)(capturedTrace)); } -void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), - Increment::IncrementCase incrementCase) -{ - runInTransaction(action, true); +void SurfaceInterceptorTest::captureTest(TestTransactionAction action, + Increment::IncrementCase incrementCase) { Trace capturedTrace; - ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - ASSERT_TRUE(singleIncrementFound(&capturedTrace, incrementCase)); + captureInTransaction(action, &capturedTrace); + ASSERT_TRUE(singleIncrementFound(capturedTrace, incrementCase)); } -void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&), - SurfaceChange::SurfaceChangeCase changeCase) -{ - runInTransaction(action, true); +void SurfaceInterceptorTest::captureTest(TestTransactionAction action, + SurfaceChange::SurfaceChangeCase changeCase) { Trace capturedTrace; - ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - ASSERT_TRUE(surfaceUpdateFound(&capturedTrace, changeCase)); + captureInTransaction(action, &capturedTrace); + ASSERT_TRUE(surfaceUpdateFound(capturedTrace, changeCase)); } -void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&), - bool intercepted) -{ - if (intercepted) { - enableInterceptor(); - } +void SurfaceInterceptorTest::captureTest(TestAction action, TestBooleanVerification verification) { + Trace capturedTrace; + capture(action, &capturedTrace); + ASSERT_TRUE((this->*verification)(capturedTrace)); +} + +void SurfaceInterceptorTest::captureTest(TestAction action, TestVerification verification) { + Trace capturedTrace; + capture(action, &capturedTrace); + (this->*verification)(capturedTrace); +} + +void SurfaceInterceptorTest::runInTransaction(TestTransactionAction action) { Transaction t; (this->*action)(t); t.apply(true); - - if (intercepted) { - disableInterceptor(); - } } void SurfaceInterceptorTest::positionUpdate(Transaction& t) { @@ -291,11 +320,11 @@ void SurfaceInterceptorTest::layerUpdate(Transaction& t) { } void SurfaceInterceptorTest::cropUpdate(Transaction& t) { - t.setCrop(mBGSurfaceControl, CROP_UPDATE); + t.setCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) { - t.setFinalCrop(mBGSurfaceControl, CROP_UPDATE); + t.setFinalCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } void SurfaceInterceptorTest::matrixUpdate(Transaction& t) { @@ -328,7 +357,8 @@ void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) { } void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) { - t.deferTransactionUntil(mBGSurfaceControl, mBGSurfaceControl->getHandle(), DEFERRED_UPDATE); + t.deferTransactionUntil_legacy(mBGSurfaceControl, mBGSurfaceControl->getHandle(), + DEFERRED_UPDATE); } void SurfaceInterceptorTest::displayCreation(Transaction&) { @@ -338,7 +368,6 @@ void SurfaceInterceptorTest::displayCreation(Transaction&) { void SurfaceInterceptorTest::displayDeletion(Transaction&) { sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false); - mTargetId = getDisplayId(DISPLAY_NAME.string()); SurfaceComposerClient::destroyDisplay(testDisplay); } @@ -380,9 +409,8 @@ bool SurfaceInterceptorTest::positionUpdateFound(const SurfaceChange& change, bo bool hasY(change.position().y() == POSITION_UPDATE); if (hasX && hasY && !foundPosition) { foundPosition = true; - } - // Failed because the position update was found a second time - else if (hasX && hasY && foundPosition) { + } else if (hasX && hasY && foundPosition) { + // Failed because the position update was found a second time [] () { FAIL(); }(); } return foundPosition; @@ -393,8 +421,7 @@ bool SurfaceInterceptorTest::sizeUpdateFound(const SurfaceChange& change, bool f bool hasHeight(change.size().w() == SIZE_UPDATE); if (hasWidth && hasHeight && !foundSize) { foundSize = true; - } - else if (hasWidth && hasHeight && foundSize) { + } else if (hasWidth && hasHeight && foundSize) { [] () { FAIL(); }(); } return foundSize; @@ -404,8 +431,7 @@ bool SurfaceInterceptorTest::alphaUpdateFound(const SurfaceChange& change, bool bool hasAlpha(change.alpha().alpha() == ALPHA_UPDATE); if (hasAlpha && !foundAlpha) { foundAlpha = true; - } - else if (hasAlpha && foundAlpha) { + } else if (hasAlpha && foundAlpha) { [] () { FAIL(); }(); } return foundAlpha; @@ -415,8 +441,7 @@ bool SurfaceInterceptorTest::layerUpdateFound(const SurfaceChange& change, bool bool hasLayer(change.layer().layer() == LAYER_UPDATE); if (hasLayer && !foundLayer) { foundLayer = true; - } - else if (hasLayer && foundLayer) { + } else if (hasLayer && foundLayer) { [] () { FAIL(); }(); } return foundLayer; @@ -429,24 +454,21 @@ bool SurfaceInterceptorTest::cropUpdateFound(const SurfaceChange& change, bool f bool hasBottom(change.crop().rectangle().bottom() == CROP_UPDATE.bottom); if (hasLeft && hasRight && hasTop && hasBottom && !foundCrop) { foundCrop = true; - } - else if (hasLeft && hasRight && hasTop && hasBottom && foundCrop) { + } else if (hasLeft && hasRight && hasTop && hasBottom && foundCrop) { [] () { FAIL(); }(); } return foundCrop; } bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change, - bool foundFinalCrop) -{ + bool foundFinalCrop) { bool hasLeft(change.final_crop().rectangle().left() == CROP_UPDATE.left); bool hasTop(change.final_crop().rectangle().top() == CROP_UPDATE.top); bool hasRight(change.final_crop().rectangle().right() == CROP_UPDATE.right); bool hasBottom(change.final_crop().rectangle().bottom() == CROP_UPDATE.bottom); if (hasLeft && hasRight && hasTop && hasBottom && !foundFinalCrop) { foundFinalCrop = true; - } - else if (hasLeft && hasRight && hasTop && hasBottom && foundFinalCrop) { + } else if (hasLeft && hasRight && hasTop && hasBottom && foundFinalCrop) { [] () { FAIL(); }(); } return foundFinalCrop; @@ -455,33 +477,29 @@ bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change, bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool foundMatrix) { bool hasSx((float)change.matrix().dsdx() == (float)M_SQRT1_2); bool hasTx((float)change.matrix().dtdx() == (float)M_SQRT1_2); - bool hasSy((float)change.matrix().dsdy() == (float)-M_SQRT1_2); - bool hasTy((float)change.matrix().dtdy() == (float)M_SQRT1_2); + bool hasSy((float)change.matrix().dsdy() == (float)M_SQRT1_2); + bool hasTy((float)change.matrix().dtdy() == (float)-M_SQRT1_2); if (hasSx && hasTx && hasSy && hasTy && !foundMatrix) { foundMatrix = true; - } - else if (hasSx && hasTx && hasSy && hasTy && foundMatrix) { + } else if (hasSx && hasTx && hasSy && hasTy && foundMatrix) { [] () { FAIL(); }(); } return foundMatrix; } bool SurfaceInterceptorTest::scalingModeUpdateFound(const SurfaceChange& change, - bool foundScalingMode) -{ + bool foundScalingMode) { bool hasScalingUpdate(change.override_scaling_mode().override_scaling_mode() == SCALING_UPDATE); if (hasScalingUpdate && !foundScalingMode) { foundScalingMode = true; - } - else if (hasScalingUpdate && foundScalingMode) { + } else if (hasScalingUpdate && foundScalingMode) { [] () { FAIL(); }(); } return foundScalingMode; } bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const SurfaceChange& change, - bool foundTransparentRegion) -{ + bool foundTransparentRegion) { auto traceRegion = change.transparent_region_hint().region(0); bool hasLeft(traceRegion.left() == CROP_UPDATE.left); bool hasTop(traceRegion.top() == CROP_UPDATE.top); @@ -489,84 +507,72 @@ bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const SurfaceChang bool hasBottom(traceRegion.bottom() == CROP_UPDATE.bottom); if (hasLeft && hasRight && hasTop && hasBottom && !foundTransparentRegion) { foundTransparentRegion = true; - } - else if (hasLeft && hasRight && hasTop && hasBottom && foundTransparentRegion) { + } else if (hasLeft && hasRight && hasTop && hasBottom && foundTransparentRegion) { [] () { FAIL(); }(); } return foundTransparentRegion; } bool SurfaceInterceptorTest::layerStackUpdateFound(const SurfaceChange& change, - bool foundLayerStack) -{ + bool foundLayerStack) { bool hasLayerStackUpdate(change.layer_stack().layer_stack() == STACK_UPDATE); if (hasLayerStackUpdate && !foundLayerStack) { foundLayerStack = true; - } - else if (hasLayerStackUpdate && foundLayerStack) { + } else if (hasLayerStackUpdate && foundLayerStack) { [] () { FAIL(); }(); } return foundLayerStack; } bool SurfaceInterceptorTest::hiddenFlagUpdateFound(const SurfaceChange& change, - bool foundHiddenFlag) -{ + bool foundHiddenFlag) { bool hasHiddenFlag(change.hidden_flag().hidden_flag()); if (hasHiddenFlag && !foundHiddenFlag) { foundHiddenFlag = true; - } - else if (hasHiddenFlag && foundHiddenFlag) { + } else if (hasHiddenFlag && foundHiddenFlag) { [] () { FAIL(); }(); } return foundHiddenFlag; } bool SurfaceInterceptorTest::opaqueFlagUpdateFound(const SurfaceChange& change, - bool foundOpaqueFlag) -{ + bool foundOpaqueFlag) { bool hasOpaqueFlag(change.opaque_flag().opaque_flag()); if (hasOpaqueFlag && !foundOpaqueFlag) { foundOpaqueFlag = true; - } - else if (hasOpaqueFlag && foundOpaqueFlag) { + } else if (hasOpaqueFlag && foundOpaqueFlag) { [] () { FAIL(); }(); } return foundOpaqueFlag; } bool SurfaceInterceptorTest::secureFlagUpdateFound(const SurfaceChange& change, - bool foundSecureFlag) -{ + bool foundSecureFlag) { bool hasSecureFlag(change.secure_flag().secure_flag()); if (hasSecureFlag && !foundSecureFlag) { foundSecureFlag = true; - } - else if (hasSecureFlag && foundSecureFlag) { + } else if (hasSecureFlag && foundSecureFlag) { [] () { FAIL(); }(); } return foundSecureFlag; } bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const SurfaceChange& change, - bool foundDeferred) -{ + bool foundDeferred) { bool hasId(change.deferred_transaction().layer_id() == mBGLayerId); bool hasFrameNumber(change.deferred_transaction().frame_number() == DEFERRED_UPDATE); if (hasId && hasFrameNumber && !foundDeferred) { foundDeferred = true; - } - else if (hasId && hasFrameNumber && foundDeferred) { + } else if (hasId && hasFrameNumber && foundDeferred) { [] () { FAIL(); }(); } return foundDeferred; } -bool SurfaceInterceptorTest::surfaceUpdateFound(Trace* trace, - SurfaceChange::SurfaceChangeCase changeCase) -{ +bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, + SurfaceChange::SurfaceChangeCase changeCase) { bool foundUpdate = false; - for (const auto& increment : *trace->mutable_increment()) { + for (const auto& increment : trace.increment()) { if (increment.increment_case() == increment.kTransaction) { for (const auto& change : increment.transaction().surface_change()) { if (change.id() == mBGLayerId && change.SurfaceChange_case() == changeCase) { @@ -624,7 +630,7 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(Trace* trace, return foundUpdate; } -void SurfaceInterceptorTest::assertAllUpdatesFound(Trace* trace) { +void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kPosition)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSize)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kAlpha)); @@ -642,24 +648,23 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(Trace* trace) { } bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) { - bool isMatch(increment.surface_creation().name() == LAYER_NAME && + bool isMatch(increment.surface_creation().name() == UNIQUE_LAYER_NAME && increment.surface_creation().w() == SIZE_UPDATE && increment.surface_creation().h() == SIZE_UPDATE); if (isMatch && !foundSurface) { foundSurface = true; - } - else if (isMatch && foundSurface) { + } else if (isMatch && foundSurface) { [] () { FAIL(); }(); } return foundSurface; } -bool SurfaceInterceptorTest::surfaceDeletionFound(const Increment& increment, bool foundSurface) { - bool isMatch(increment.surface_deletion().id() == mTargetId); +bool SurfaceInterceptorTest::surfaceDeletionFound(const Increment& increment, + const int32_t targetId, bool foundSurface) { + bool isMatch(increment.surface_deletion().id() == targetId); if (isMatch && !foundSurface) { foundSurface = true; - } - else if (isMatch && foundSurface) { + } else if (isMatch && foundSurface) { [] () { FAIL(); }(); } return foundSurface; @@ -670,42 +675,45 @@ bool SurfaceInterceptorTest::displayCreationFound(const Increment& increment, bo increment.display_creation().is_secure()); if (isMatch && !foundDisplay) { foundDisplay = true; - } - else if (isMatch && foundDisplay) { + } else if (isMatch && foundDisplay) { [] () { FAIL(); }(); } return foundDisplay; } -bool SurfaceInterceptorTest::displayDeletionFound(const Increment& increment, bool foundDisplay) { - bool isMatch(increment.display_deletion().id() == mTargetId); +bool SurfaceInterceptorTest::displayDeletionFound(const Increment& increment, + const int32_t targetId, bool foundDisplay) { + bool isMatch(increment.display_deletion().id() == targetId); if (isMatch && !foundDisplay) { foundDisplay = true; - } - else if (isMatch && foundDisplay) { + } else if (isMatch && foundDisplay) { [] () { FAIL(); }(); } return foundDisplay; } -bool SurfaceInterceptorTest::singleIncrementFound(Trace* trace, - Increment::IncrementCase incrementCase) -{ +bool SurfaceInterceptorTest::singleIncrementFound(const Trace& trace, + Increment::IncrementCase incrementCase) { bool foundIncrement = false; - for (const auto& increment : *trace->mutable_increment()) { + for (const auto& increment : trace.increment()) { if (increment.increment_case() == incrementCase) { + int32_t targetId = 0; switch (incrementCase) { case Increment::IncrementCase::kSurfaceCreation: foundIncrement = surfaceCreationFound(increment, foundIncrement); break; case Increment::IncrementCase::kSurfaceDeletion: - foundIncrement = surfaceDeletionFound(increment, foundIncrement); + // Find the id of created surface. + targetId = getSurfaceId(trace, UNIQUE_LAYER_NAME); + foundIncrement = surfaceDeletionFound(increment, targetId, foundIncrement); break; case Increment::IncrementCase::kDisplayCreation: foundIncrement = displayCreationFound(increment, foundIncrement); break; case Increment::IncrementCase::kDisplayDeletion: - foundIncrement = displayDeletionFound(increment, foundIncrement); + // Find the id of created display. + targetId = getDisplayId(trace, DISPLAY_NAME.string()); + foundIncrement = displayDeletionFound(increment, targetId, foundIncrement); break; default: /* code */ @@ -716,9 +724,9 @@ bool SurfaceInterceptorTest::singleIncrementFound(Trace* trace, return foundIncrement; } -bool SurfaceInterceptorTest::bufferUpdatesFound(Trace* trace) { +bool SurfaceInterceptorTest::bufferUpdatesFound(const Trace& trace) { uint32_t updates = 0; - for (const auto& inc : *trace->mutable_increment()) { + for (const auto& inc : trace.increment()) { if (inc.increment_case() == inc.kBufferUpdate && inc.buffer_update().id() == mBGLayerId) { updates++; } @@ -792,14 +800,8 @@ TEST_F(SurfaceInterceptorTest, InterceptDeferredTransactionUpdateWorks) { } TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) { - enableInterceptor(); - runAllUpdates(); - disableInterceptor(); - - // Find all of the updates in the single trace - Trace capturedTrace; - ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - assertAllUpdatesFound(&capturedTrace); + captureTest(&SurfaceInterceptorTest::runAllUpdates, + &SurfaceInterceptorTest::assertAllUpdatesFound); } TEST_F(SurfaceInterceptorTest, InterceptSurfaceCreationWorks) { @@ -808,16 +810,15 @@ TEST_F(SurfaceInterceptorTest, InterceptSurfaceCreationWorks) { } TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) { + enableInterceptor(); sp<SurfaceControl> layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME), SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0); - this->mTargetId = getSurfaceId(LAYER_NAME); - enableInterceptor(); mComposerClient->destroySurface(layerToDelete->getHandle()); disableInterceptor(); Trace capturedTrace; ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceDeletion)); + ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceDeletion)); } TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) { @@ -826,21 +827,24 @@ TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) { } TEST_F(SurfaceInterceptorTest, InterceptDisplayDeletionWorks) { - captureTest(&SurfaceInterceptorTest::displayDeletion, - Increment::IncrementCase::kDisplayDeletion); + enableInterceptor(); + runInTransaction(&SurfaceInterceptorTest::displayDeletion); + disableInterceptor(); + Trace capturedTrace; + ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); + ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kDisplayDeletion)); } TEST_F(SurfaceInterceptorTest, InterceptBufferUpdateWorks) { - nBufferUpdates(); - Trace capturedTrace; - ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - ASSERT_TRUE(bufferUpdatesFound(&capturedTrace)); + captureTest(&SurfaceInterceptorTest::nBufferUpdates, + &SurfaceInterceptorTest::bufferUpdatesFound); } // If the interceptor is enabled while buffer updates are being pushed, the interceptor should // first create a snapshot of the existing displays and surfaces and then start capturing // the buffer updates TEST_F(SurfaceInterceptorTest, InterceptWhileBufferUpdatesWorks) { + setupBackgroundSurface(); std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this); enableInterceptor(); disableInterceptor(); @@ -854,6 +858,7 @@ TEST_F(SurfaceInterceptorTest, InterceptWhileBufferUpdatesWorks) { TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) { enableInterceptor(); + setupBackgroundSurface(); std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this); std::thread surfaceUpdates(&SurfaceInterceptorTest::runAllUpdates, this); runInTransaction(&SurfaceInterceptorTest::surfaceCreation); @@ -863,10 +868,11 @@ TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) { Trace capturedTrace; ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); + preProcessTrace(capturedTrace); - assertAllUpdatesFound(&capturedTrace); - ASSERT_TRUE(bufferUpdatesFound(&capturedTrace)); - ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceCreation)); + assertAllUpdatesFound(capturedTrace); + ASSERT_TRUE(bufferUpdatesFound(capturedTrace)); + ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceCreation)); } } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 5108279043..bde6614b61 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -62,38 +62,54 @@ const Color Color::WHITE{255, 255, 255, 255}; const Color Color::BLACK{0, 0, 0, 255}; const Color Color::TRANSPARENT{0, 0, 0, 0}; +using android::hardware::graphics::common::V1_1::BufferUsage; + std::ostream& operator<<(std::ostream& os, const Color& color) { os << int(color.r) << ", " << int(color.g) << ", " << int(color.b) << ", " << int(color.a); return os; } // Fill a region with the specified color. -void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const Color& color) { - int32_t x = rect.left; - int32_t y = rect.top; - int32_t width = rect.right - rect.left; - int32_t height = rect.bottom - rect.top; - - if (x < 0) { - width += x; - x = 0; - } - if (y < 0) { - height += y; - y = 0; +void fillANativeWindowBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, + const Color& color) { + Rect r(0, 0, buffer.width, buffer.height); + if (!r.intersect(rect, &r)) { + return; } - if (x + width > buffer.width) { - x = std::min(x, buffer.width); - width = buffer.width - x; + + int32_t width = r.right - r.left; + int32_t height = r.bottom - r.top; + + for (int32_t row = 0; row < height; row++) { + uint8_t* dst = + static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (r.top + row) + r.left) * 4; + for (int32_t column = 0; column < width; column++) { + dst[0] = color.r; + dst[1] = color.g; + dst[2] = color.b; + dst[3] = color.a; + dst += 4; + } } - if (y + height > buffer.height) { - y = std::min(y, buffer.height); - height = buffer.height - y; +} + +// Fill a region with the specified color. +void fillGraphicBufferColor(const sp<GraphicBuffer>& buffer, const Rect& rect, const Color& color) { + Rect r(0, 0, buffer->width, buffer->height); + if (!r.intersect(rect, &r)) { + return; } - for (int32_t j = 0; j < height; j++) { - uint8_t* dst = static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (y + j) + x) * 4; - for (int32_t i = 0; i < width; i++) { + int32_t width = r.right - r.left; + int32_t height = r.bottom - r.top; + + uint8_t* pixels; + buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast<void**>(&pixels)); + + for (int32_t row = 0; row < height; row++) { + uint8_t* dst = pixels + (buffer->getStride() * (r.top + row) + r.left) * 4; + for (int32_t column = 0; column < width; column++) { dst[0] = color.r; dst[1] = color.g; dst[2] = color.b; @@ -101,6 +117,7 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const dst += 4; } } + buffer->unlock(); } // Check if a region has the specified color. @@ -301,8 +318,8 @@ protected: ASSERT_NO_FATAL_FAILURE(SetUpDisplay()); } - sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, - uint32_t flags = 0) { + virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0) { auto layer = mClient->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags); EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; @@ -319,7 +336,7 @@ protected: return layer; } - ANativeWindow_Buffer getLayerBuffer(const sp<SurfaceControl>& layer) { + ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { // wait for previous transactions (such as setSize) to complete Transaction().apply(true); @@ -329,35 +346,103 @@ protected: return buffer; } - void postLayerBuffer(const sp<SurfaceControl>& layer) { + void postBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost()); // wait for the newly posted buffer to be latched waitForLayerBuffers(); } - void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color) { + virtual void fillBufferQueueLayerColor(const sp<SurfaceControl>& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - fillBufferColor(buffer, Rect(0, 0, buffer.width, buffer.height), color); - postLayerBuffer(layer); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + fillANativeWindowBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); + postBufferQueueLayerBuffer(layer); + } + + virtual void fillBufferStateLayerColor(const sp<SurfaceControl>& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + sp<GraphicBuffer> buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); + Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); + } + + void fillLayerColor(uint32_t mLayerType, const sp<SurfaceControl>& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } } - void fillLayerQuadrant(const sp<SurfaceControl>& layer, const Color& topLeft, + void fillLayerQuadrant(uint32_t mLayerType, const sp<SurfaceControl>& layer, + int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft, const Color& topRight, const Color& bottomLeft, const Color& bottomRight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } + } + + virtual void fillBufferQueueLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_TRUE(buffer.width % 2 == 0 && buffer.height % 2 == 0); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); + + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight); + fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft); + fillANativeWindowBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), + bottomRight); + + postBufferQueueLayerBuffer(layer); + } + + virtual void fillBufferStateLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { + sp<GraphicBuffer> buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); - const int32_t halfW = buffer.width / 2; - const int32_t halfH = buffer.height / 2; - fillBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); - fillBufferColor(buffer, Rect(halfW, 0, buffer.width, halfH), topRight); - fillBufferColor(buffer, Rect(0, halfH, halfW, buffer.height), bottomLeft); - fillBufferColor(buffer, Rect(halfW, halfH, buffer.width, buffer.height), bottomRight); + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); - postLayerBuffer(layer); + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight); + fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft); + fillGraphicBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), bottomRight); + + Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); } sp<ScreenCapture> screenshot() { @@ -376,6 +461,10 @@ protected: // leave room for ~256 layers const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256; + void setPositionWithResizeHelper(uint32_t layerType); + void setSizeBasicHelper(uint32_t layerType); + void setMatrixWithResizeHelper(uint32_t layerType); + private: void SetUpDisplay() { mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain); @@ -404,10 +493,48 @@ private: int32_t mBufferPostDelay; }; -TEST_F(LayerTransactionTest, SetPositionBasic) { +class LayerTypeTransactionTest : public LayerTransactionTest, + public ::testing::WithParamInterface<uint32_t> { +public: + LayerTypeTransactionTest() { mLayerType = GetParam(); } + + sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0) override { + // if the flags already have a layer type specified, return an error + if (flags & ISurfaceComposerClient::eFXSurfaceMask) { + return nullptr; + } + return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType); + } + + void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth, + int32_t bufferHeight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color, + bufferWidth, bufferHeight)); + } + + void fillLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, const Color& topRight, + const Color& bottomLeft, const Color& bottomRight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer, + bufferWidth, bufferHeight, + topLeft, topRight, + bottomLeft, bottomRight)); + } + +protected: + uint32_t mLayerType; +}; + +INSTANTIATE_TEST_CASE_P( + LayerTypeTransactionTests, LayerTypeTransactionTest, + ::testing::Values(static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue), + static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState))); + +TEST_P(LayerTypeTransactionTest, SetPositionBasic) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); { SCOPED_TRACE("default position"); @@ -425,10 +552,10 @@ TEST_F(LayerTransactionTest, SetPositionBasic) { } } -TEST_F(LayerTransactionTest, SetPositionRounding) { +TEST_P(LayerTypeTransactionTest, SetPositionRounding) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // GLES requires only 4 bits of subpixel precision during rasterization // XXX GLES composition does not match HWC composition due to precision @@ -447,10 +574,10 @@ TEST_F(LayerTransactionTest, SetPositionRounding) { } } -TEST_F(LayerTransactionTest, SetPositionOutOfBounds) { +TEST_P(LayerTypeTransactionTest, SetPositionOutOfBounds) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setPosition(layer, -32, -32).apply(); { @@ -465,10 +592,10 @@ TEST_F(LayerTransactionTest, SetPositionOutOfBounds) { } } -TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) { +TEST_P(LayerTypeTransactionTest, SetPositionPartiallyOutOfBounds) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // partially out of bounds Transaction().setPosition(layer, -30, -30).apply(); @@ -486,10 +613,10 @@ TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) { } } -TEST_F(LayerTransactionTest, SetPositionWithResize) { +void LayerTransactionTest::setPositionWithResizeHelper(uint32_t layerType) { sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); // setPosition is applied immediately by default, with or without resize // pending @@ -497,21 +624,43 @@ TEST_F(LayerTransactionTest, SetPositionWithResize) { { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(5, 10, 37, 42), Color::RED); - shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {5, 10, 37, 42}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {5, 10, 69, 74}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED); } } -TEST_F(LayerTransactionTest, SetPositionWithNextResize) { +TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) { + ASSERT_NO_FATAL_FAILURE( + setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetPositionWithResize_BufferState) { + ASSERT_NO_FATAL_FAILURE( + setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_F(LayerTransactionTest, SetPositionWithNextResize_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // request setPosition to be applied with the next resize Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply(); @@ -533,17 +682,17 @@ TEST_F(LayerTransactionTest, SetPositionWithNextResize) { } // finally resize and latch the buffer - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("new position applied"); screenshot()->expectColor(Rect(15, 20, 79, 84), Color::RED); } } -TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setPosition is not immediate even with SCALE_TO_WINDOW override Transaction() @@ -557,27 +706,38 @@ TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("new position applied"); screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED); } } -TEST_F(LayerTransactionTest, SetSizeBasic) { +void LayerTransactionTest::setSizeBasicHelper(uint32_t layerType) { sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); Transaction().setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {0, 0, 32, 32}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {0, 0, 64, 64}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -586,14 +746,22 @@ TEST_F(LayerTransactionTest, SetSizeBasic) { } } -TEST_F(LayerTransactionTest, SetSizeInvalid) { +TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) { + setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue); +} + +TEST_F(LayerTransactionTest, SetSizeBasic_BufferState) { + setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState); +} + +TEST_P(LayerTypeTransactionTest, SetSizeInvalid) { // cannot test robustness against invalid sizes (zero or really huge) } -TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) { +TEST_P(LayerTypeTransactionTest, SetSizeWithScaleToWindow) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -603,13 +771,13 @@ TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED); } -TEST_F(LayerTransactionTest, SetZBasic) { +TEST_P(LayerTypeTransactionTest, SetZBasic) { sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction().setLayer(layerR, mLayerZBase + 1).apply(); { @@ -624,13 +792,13 @@ TEST_F(LayerTransactionTest, SetZBasic) { } } -TEST_F(LayerTransactionTest, SetZNegative) { +TEST_P(LayerTypeTransactionTest, SetZNegative) { sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply(); { @@ -649,13 +817,13 @@ TEST_F(LayerTransactionTest, SetZNegative) { } } -TEST_F(LayerTransactionTest, SetRelativeZBasic) { +TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) { sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setPosition(layerG, 16, 16) @@ -677,16 +845,16 @@ TEST_F(LayerTransactionTest, SetRelativeZBasic) { } } -TEST_F(LayerTransactionTest, SetRelativeZNegative) { +TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; sp<SurfaceControl> layerB; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); @@ -697,16 +865,16 @@ TEST_F(LayerTransactionTest, SetRelativeZNegative) { screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); } -TEST_F(LayerTransactionTest, SetRelativeZGroup) { +TEST_P(LayerTypeTransactionTest, SetRelativeZGroup) { sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; sp<SurfaceControl> layerB; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); // layerR = 0, layerG = layerR + 3, layerB = 2 Transaction() @@ -764,14 +932,14 @@ TEST_F(LayerTransactionTest, SetRelativeZGroup) { } } -TEST_F(LayerTransactionTest, SetRelativeZBug64572777) { +TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) { sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setPosition(layerG, 16, 16) @@ -783,10 +951,10 @@ TEST_F(LayerTransactionTest, SetRelativeZBug64572777) { screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } -TEST_F(LayerTransactionTest, SetFlagsHidden) { +TEST_P(LayerTypeTransactionTest, SetFlagsHidden) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply(); { @@ -801,14 +969,14 @@ TEST_F(LayerTransactionTest, SetFlagsHidden) { } } -TEST_F(LayerTransactionTest, SetFlagsOpaque) { +TEST_P(LayerTypeTransactionTest, SetFlagsOpaque) { const Color translucentRed = {100, 0, 0, 100}; sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setLayer(layerR, mLayerZBase + 1) @@ -827,10 +995,10 @@ TEST_F(LayerTransactionTest, SetFlagsOpaque) { } } -TEST_F(LayerTransactionTest, SetFlagsSecure) { +TEST_P(LayerTypeTransactionTest, SetFlagsSecure) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); sp<ISurfaceComposer> composer = ComposerService::getComposerService(); sp<GraphicBuffer> outBuffer; @@ -847,19 +1015,19 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { false)); } -TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { +TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferQueue) { const Rect top(0, 0, 32, 16); const Rect bottom(0, 16, 32, 32); sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::RED)); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::RED)); // setTransparentRegionHint always applies to the following buffer Transaction().setTransparentRegionHint(layer, Region(top)).apply(); - ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); { SCOPED_TRACE("top transparent"); auto shot = screenshot(); @@ -875,10 +1043,10 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { shot->expectColor(bottom, Color::RED); } - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); { SCOPED_TRACE("bottom transparent"); auto shot = screenshot(); @@ -887,7 +1055,58 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { } } -TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) { +TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferState) { + const Rect top(0, 0, 32, 16); + const Rect bottom(0, 16, 32, 32); + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::RED)); + Transaction() + .setTransparentRegionHint(layer, Region(top)) + .setBuffer(layer, buffer) + .setSize(layer, 32, 32) + .apply(); + { + SCOPED_TRACE("top transparent"); + auto shot = screenshot(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::RED); + } + + Transaction().setTransparentRegionHint(layer, Region(bottom)).apply(); + { + SCOPED_TRACE("transparent region hint intermediate"); + auto shot = screenshot(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::BLACK); + } + + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT)); + Transaction().setBuffer(layer, buffer).setSize(layer, 32, 32).apply(); + { + SCOPED_TRACE("bottom transparent"); + auto shot = screenshot(); + shot->expectColor(top, Color::RED); + shot->expectColor(bottom, Color::BLACK); + } +} + +TEST_P(LayerTypeTransactionTest, SetTransparentRegionHintOutOfBounds) { sp<SurfaceControl> layerTransparent; sp<SurfaceControl> layerR; ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); @@ -900,18 +1119,18 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) { .setPosition(layerR, 16, 16) .setLayer(layerR, mLayerZBase + 1) .apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED); } -TEST_F(LayerTransactionTest, SetAlphaBasic) { +TEST_P(LayerTypeTransactionTest, SetAlphaBasic) { sp<SurfaceControl> layer1; sp<SurfaceControl> layer2; ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32)); ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255})); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255})); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}, 32, 32)); Transaction() .setAlpha(layer1, 0.25f) @@ -931,11 +1150,11 @@ TEST_F(LayerTransactionTest, SetAlphaBasic) { } } -TEST_F(LayerTransactionTest, SetAlphaClamped) { +TEST_P(LayerTypeTransactionTest, SetAlphaClamped) { const Color color = {64, 0, 0, 255}; sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32)); Transaction().setAlpha(layer, 2.0f).apply(); { @@ -954,7 +1173,7 @@ TEST_F(LayerTransactionTest, SetColorBasic) { sp<SurfaceControl> bufferLayer; sp<SurfaceControl> colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -989,7 +1208,7 @@ TEST_F(LayerTransactionTest, SetColorWithAlpha) { sp<SurfaceControl> bufferLayer; sp<SurfaceControl> colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -1014,7 +1233,7 @@ TEST_F(LayerTransactionTest, SetColorWithParentAlpha_Bug74220420) { sp<SurfaceControl> colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer( "childWithColor", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -1034,20 +1253,20 @@ TEST_F(LayerTransactionTest, SetColorWithParentAlpha_Bug74220420) { tolerance); } -TEST_F(LayerTransactionTest, SetColorWithBuffer) { +TEST_P(LayerTypeTransactionTest, SetColorWithBuffer) { sp<SurfaceControl> bufferLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32)); // color is ignored Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } -TEST_F(LayerTransactionTest, SetLayerStackBasic) { +TEST_P(LayerTypeTransactionTest, SetLayerStackBasic) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply(); { @@ -1062,11 +1281,11 @@ TEST_F(LayerTransactionTest, SetLayerStackBasic) { } } -TEST_F(LayerTransactionTest, SetMatrixBasic) { +TEST_P(LayerTypeTransactionTest, SetMatrixBasic) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply(); { @@ -1104,11 +1323,11 @@ TEST_F(LayerTransactionTest, SetMatrixBasic) { } } -TEST_F(LayerTransactionTest, SetMatrixRot45) { +TEST_P(LayerTypeTransactionTest, SetMatrixRot45) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); const float rot = M_SQRT1_2; // 45 degrees const float trans = M_SQRT2 * 16.0f; @@ -1127,31 +1346,52 @@ TEST_F(LayerTransactionTest, SetMatrixRot45) { shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE); } -TEST_F(LayerTransactionTest, SetMatrixWithResize) { +void LayerTransactionTest::setMatrixWithResizeHelper(uint32_t layerType) { sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); // setMatrix is applied after any pending resize, unlike setPosition Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {0, 0, 32, 32}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {0, 0, 128, 128}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); } } -TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) { +TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) { + ASSERT_NO_FATAL_FAILURE( + setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferState) { + ASSERT_NO_FATAL_FAILURE( + setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_P(LayerTypeTransactionTest, SetMatrixWithScaleToWindow) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -1162,11 +1402,11 @@ TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); } -TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) { +TEST_P(LayerTypeTransactionTest, SetOverrideScalingModeBasic) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); // XXX SCALE_CROP is not respected; calling setSize and // setOverrideScalingMode in separate transactions does not work @@ -1182,10 +1422,23 @@ TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) { } } -TEST_F(LayerTransactionTest, SetCropBasic) { +TEST_F(LayerTransactionTest, SetCropBasic_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + const Rect crop(8, 8, 24, 24); + + Transaction().setCrop_legacy(layer, crop).apply(); + auto shot = screenshot(); + shot->expectColor(crop, Color::RED); + shot->expectBorder(crop, Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Rect crop(8, 8, 24, 24); Transaction().setCrop(layer, crop).apply(); @@ -1194,10 +1447,29 @@ TEST_F(LayerTransactionTest, SetCropBasic) { shot->expectBorder(crop, Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropEmpty) { +TEST_F(LayerTransactionTest, SetCropEmpty_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("empty rect"); + Transaction().setCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } + + { + SCOPED_TRACE("negative rect"); + Transaction().setCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } +} + +TEST_F(LayerTransactionTest, SetCropEmpty_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); { SCOPED_TRACE("empty rect"); @@ -1212,10 +1484,22 @@ TEST_F(LayerTransactionTest, SetCropEmpty) { } } -TEST_F(LayerTransactionTest, SetCropOutOfBounds) { +TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); @@ -1223,10 +1507,24 @@ TEST_F(LayerTransactionTest, SetCropOutOfBounds) { shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithTranslation) { +TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + const Point position(32, 32); + const Rect crop(8, 8, 24, 24); + Transaction().setPosition(layer, position.x, position.y).setCrop_legacy(layer, crop).apply(); + auto shot = screenshot(); + shot->expectColor(crop + position, Color::RED); + shot->expectBorder(crop + position, Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Point position(32, 32); const Rect crop(8, 8, 24, 24); @@ -1236,10 +1534,26 @@ TEST_F(LayerTransactionTest, SetCropWithTranslation) { shot->expectBorder(crop + position, Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithScale) { +TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // crop is affected by matrix + Transaction() + .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) + .setCrop_legacy(layer, Rect(8, 8, 24, 24)) + .apply(); + auto shot = screenshot(); + shot->expectColor(Rect(16, 16, 48, 48), Color::RED); + shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithScale_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); // crop is affected by matrix Transaction() @@ -1251,13 +1565,13 @@ TEST_F(LayerTransactionTest, SetCropWithScale) { shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithResize) { +TEST_F(LayerTransactionTest, SetCropWithResize_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - // setCrop is applied immediately by default, with or without resize pending - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + // setCrop_legacy is applied immediately by default, with or without resize pending + Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); @@ -1265,7 +1579,7 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -1274,19 +1588,46 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResize) { +TEST_F(LayerTransactionTest, SetCropWithResize_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // setCrop_legacy is applied immediately by default, with or without resize pending + Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + { + SCOPED_TRACE("new buffer pending"); + auto shot = screenshot(); + shot->expectColor(Rect(8, 8, 16, 16), Color::RED); + shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); + { + SCOPED_TRACE("new buffer"); + auto shot = screenshot(); + shot->expectColor(Rect(8, 8, 16, 16), Color::RED); + shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - // request setCrop to be applied with the next resize - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply(); + // request setCrop_legacy to be applied with the next resize + Transaction() + .setCrop_legacy(layer, Rect(8, 8, 24, 24)) + .setGeometryAppliesWithResize(layer) + .apply(); { SCOPED_TRACE("waiting for next resize"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } - Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply(); + Transaction().setCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); { SCOPED_TRACE("pending crop modified"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); @@ -1299,7 +1640,7 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { } // finally resize - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("new crop applied"); auto shot = screenshot(); @@ -1308,14 +1649,49 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // request setCrop_legacy to be applied with the next resize + Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply(); + { + SCOPED_TRACE("set crop 1"); + screenshot()->expectColor(Rect(8, 8, 24, 24), Color::RED); + } + + Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply(); + { + SCOPED_TRACE("set crop 2"); + screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); + } + + Transaction().setSize(layer, 16, 16).apply(); + { + SCOPED_TRACE("resize"); + screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); + } + + // finally resize + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); + { + SCOPED_TRACE("new buffer"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - // setCrop is not immediate even with SCALE_TO_WINDOW override + // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override Transaction() - .setCrop(layer, Rect(4, 4, 12, 12)) + .setCrop_legacy(layer, Rect(4, 4, 12, 12)) .setSize(layer, 16, 16) .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) .setGeometryAppliesWithResize(layer) @@ -1329,7 +1705,7 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { // XXX crop is never latched without other geometry change (b/69315677) Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); Transaction().setPosition(layer, 0, 0).apply(); { SCOPED_TRACE("new crop applied"); @@ -1339,84 +1715,115 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { } } -TEST_F(LayerTransactionTest, SetFinalCropBasic) { +TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // all properties are applied immediate so setGeometryAppliesWithResize has no effect + Transaction() + .setCrop(layer, Rect(4, 4, 12, 12)) + .setSize(layer, 16, 16) + .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) + .setGeometryAppliesWithResize(layer) + .apply(); + { + SCOPED_TRACE("new crop pending"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } + + Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); + Transaction().setPosition(layer, 0, 0).apply(); + { + SCOPED_TRACE("new crop applied"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetFinalCropBasic_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); const Rect crop(8, 8, 24, 24); // same as in SetCropBasic - Transaction().setFinalCrop(layer, crop).apply(); + Transaction().setFinalCrop_legacy(layer, crop).apply(); auto shot = screenshot(); shot->expectColor(crop, Color::RED); shot->expectBorder(crop, Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropEmpty) { +TEST_F(LayerTransactionTest, SetFinalCropEmpty_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropEmpty { SCOPED_TRACE("empty rect"); - Transaction().setFinalCrop(layer, Rect(8, 8, 8, 8)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); - Transaction().setFinalCrop(layer, Rect(8, 8, 0, 0)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } -TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) { +TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropOutOfBounds - Transaction().setFinalCrop(layer, Rect(-128, -64, 128, 64)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); shot->expectColor(Rect(0, 0, 32, 32), Color::RED); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) { +TEST_F(LayerTransactionTest, SetFinalCropWithTranslation_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // final crop is applied post-translation - Transaction().setPosition(layer, 16, 16).setFinalCrop(layer, Rect(8, 8, 24, 24)).apply(); + Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply(); auto shot = screenshot(); shot->expectColor(Rect(16, 16, 24, 24), Color::RED); shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithScale) { +TEST_F(LayerTransactionTest, SetFinalCropWithScale_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // final crop is not affected by matrix Transaction() .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setFinalCrop(layer, Rect(8, 8, 24, 24)) + .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) .apply(); auto shot = screenshot(); shot->expectColor(Rect(8, 8, 24, 24), Color::RED); shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithResize) { +TEST_F(LayerTransactionTest, SetFinalCropWithResize_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithResize - Transaction().setFinalCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); @@ -1424,7 +1831,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -1433,14 +1840,14 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { } } -TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { +TEST_F(LayerTransactionTest, SetFinalCropWithNextResize_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithNextResize Transaction() - .setFinalCrop(layer, Rect(8, 8, 24, 24)) + .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) .setGeometryAppliesWithResize(layer) .apply(); { @@ -1448,7 +1855,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } - Transaction().setFinalCrop(layer, Rect(4, 4, 12, 12)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); { SCOPED_TRACE("pending final crop modified"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); @@ -1461,7 +1868,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { } // finally resize - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("new final crop applied"); auto shot = screenshot(); @@ -1470,14 +1877,14 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { } } -TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow_BufferQueue) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithNextResizeScaleToWindow Transaction() - .setFinalCrop(layer, Rect(4, 4, 12, 12)) + .setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)) .setSize(layer, 16, 16) .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) .setGeometryAppliesWithResize(layer) @@ -1491,7 +1898,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { // XXX final crop is never latched without other geometry change (b/69315677) Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); Transaction().setPosition(layer, 0, 0).apply(); { SCOPED_TRACE("new final crop applied"); @@ -1501,6 +1908,282 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } +TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetBufferMultipleBuffers_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 1"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); + + { + SCOPED_TRACE("set buffer 2"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 3"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetBufferMultipleLayers_BufferState) { + sp<SurfaceControl> layer1; + ASSERT_NO_FATAL_FAILURE( + layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<SurfaceControl> layer2; + ASSERT_NO_FATAL_FAILURE( + layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + + { + SCOPED_TRACE("set layer 1 buffer red"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + + { + SCOPED_TRACE("set layer 2 buffer blue"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::RED); + shot->expectColor(Rect(0, 32, 32, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64)); + { + SCOPED_TRACE("set layer 1 buffer green"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32)); + + { + SCOPED_TRACE("set layer 2 buffer white"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } +} + +TEST_F(LayerTransactionTest, SetTransformRotate90_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE, + Color::GREEN, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformFlipH_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE, + Color::BLUE, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformFlipV_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED, + Color::GREEN, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction().setTransformToDisplayInverse(layer, false).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32)); + + Transaction().setTransformToDisplayInverse(layer, true).apply(); +} + +TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + sp<Fence> fence = new Fence(-1); + + Transaction() + .setBuffer(layer, buffer) + .setAcquireFence(layer, fence) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetDataspaceBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction() + .setBuffer(layer, buffer) + .setDataspace(layer, ui::Dataspace::UNKNOWN) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetHdrMetadataBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + HdrMetadata hdrMetadata; + hdrMetadata.validTypes = 0; + Transaction() + .setBuffer(layer, buffer) + .setHdrMetadata(layer, hdrMetadata) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Region region; + region.set(32, 32); + Transaction() + .setBuffer(layer, buffer) + .setSurfaceDamageRegion(layer, region) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetApiBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction() + .setBuffer(layer, buffer) + .setApi(layer, NATIVE_WINDOW_API_CPU) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + // verify this doesn't cause a crash + Transaction().setSidebandStream(layer, nullptr).apply(); +} + class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { @@ -1649,8 +2332,8 @@ protected: asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 64, 64); t.setPosition(mFGSurfaceControl, 64, 64); - t.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64)); - t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); }); EXPECT_INITIAL_STATE("After restoring initial state"); @@ -1686,7 +2369,7 @@ TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { // Normally the crop applies immediately even while a resize is pending. asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 128); - t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); }); EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); @@ -1700,7 +2383,7 @@ TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 128); t.setGeometryAppliesWithResize(mFGSurfaceControl); - t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); }); EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); @@ -1729,14 +2412,14 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { // set up two deferred transactions on different frames asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.75); - t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber()); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber()); }); asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 128, 128); - t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); }); { @@ -1881,7 +2564,7 @@ TEST_F(ChildLayerTest, ChildLayerCropping) { t.show(mChild); t.setPosition(mChild, 0, 0); t.setPosition(mFGSurfaceControl, 0, 0); - t.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); }); { @@ -1897,7 +2580,7 @@ TEST_F(ChildLayerTest, ChildLayerFinalCropping) { t.show(mChild); t.setPosition(mChild, 0, 0); t.setPosition(mFGSurfaceControl, 0, 0); - t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); }); { @@ -2166,8 +2849,8 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction asTransaction([&](Transaction& t) { - t.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); + t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); t.show(mChild); }); @@ -2465,8 +3148,9 @@ TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) { } TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) { - - SurfaceComposerClient::Transaction().setCrop(mFGSurfaceControl, Rect(0, 0, 1, 1)).apply(true); + SurfaceComposerClient::Transaction() + .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1)) + .apply(true); // Even though the parent is cropped out we should still capture the child. verify(); @@ -2565,8 +3249,8 @@ TEST_F(ScreenCaptureTest, CaptureCrop) { mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); SurfaceComposerClient::Transaction() .setLayer(redLayer, INT32_MAX - 1) @@ -2599,8 +3283,8 @@ TEST_F(ScreenCaptureTest, CaptureSize) { mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); SurfaceComposerClient::Transaction() .setLayer(redLayer, INT32_MAX - 1) @@ -2632,7 +3316,7 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); @@ -2651,9 +3335,9 @@ protected: void SetUp() override { LayerTransactionTest::SetUp(); bgLayer = createLayer("BG layer", 20, 20); - fillLayerColor(bgLayer, Color::RED); + fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20); fgLayer = createLayer("FG layer", 20, 20); - fillLayerColor(fgLayer, Color::BLUE); + fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20); Transaction().setLayer(fgLayer, mLayerZBase + 1).apply(); { SCOPED_TRACE("before anything"); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 9b319854e6..7fafab9302 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -624,7 +624,7 @@ TEST_F(TransactionTest, LayerCrop) { { TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ts.setCrop(mFGSurfaceControl, cropRect); + ts.setCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -639,7 +639,7 @@ TEST_F(TransactionTest, LayerFinalCrop) { { TransactionScope ts(*sFakeComposer); Rect cropRect(32, 32, 32 + 64, 32 + 64); - ts.setFinalCrop(mFGSurfaceControl, cropRect); + ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -657,7 +657,7 @@ TEST_F(TransactionTest, LayerFinalCropEmpty) { { TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ts.setFinalCrop(mFGSurfaceControl, cropRect); + ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -847,18 +847,16 @@ TEST_F(TransactionTest, DeferredTransaction) { { TransactionScope ts(*sFakeComposer); ts.setAlpha(mFGSurfaceControl, 0.75); - ts.deferTransactionUntil(mFGSurfaceControl, - syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber()); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber()); } EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { TransactionScope ts(*sFakeComposer); ts.setPosition(mFGSurfaceControl, 128, 128); - ts.deferTransactionUntil(mFGSurfaceControl, - syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); } EXPECT_EQ(4, sFakeComposer->getFrameCount()); EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); @@ -981,7 +979,7 @@ TEST_F(ChildLayerTest, Cropping) { ts.show(mChild); ts.setPosition(mChild, 0, 0); ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); } // NOTE: The foreground surface would be occluded by the child // now, but is included in the stack because the child is @@ -1000,7 +998,7 @@ TEST_F(ChildLayerTest, FinalCropping) { ts.show(mChild); ts.setPosition(mChild, 0, 0); ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); } auto referenceFrame = mBaseFrame; referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; @@ -1095,7 +1093,7 @@ TEST_F(ChildLayerTest, ReparentChildren) { EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); } -TEST_F(ChildLayerTest, DetachChildren) { +TEST_F(ChildLayerTest, DetachChildrenSameClient) { { TransactionScope ts(*sFakeComposer); ts.show(mChild); @@ -1111,12 +1109,57 @@ TEST_F(ChildLayerTest, DetachChildren) { { TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 0, 0); ts.detachChildren(mFGSurfaceControl); } { TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 64, 64); + ts.hide(mChild); + } + + std::vector<RenderState> refFrame(2); + refFrame[BG_LAYER] = mBaseFrame[BG_LAYER]; + refFrame[FG_LAYER] = mBaseFrame[FG_LAYER]; + + EXPECT_TRUE(framesAreSame(refFrame, sFakeComposer->getLatestFrame())); +} + +TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { + sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; + sp<SurfaceControl> childNewClient = + newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + ASSERT_TRUE(childNewClient != nullptr); + ASSERT_TRUE(childNewClient->isValid()); + fillSurfaceRGBA8(childNewClient, LIGHT_GRAY); + + { + TransactionScope ts(*sFakeComposer); ts.hide(mChild); + ts.show(childNewClient); + ts.setPosition(childNewClient, 10, 10); + ts.setPosition(mFGSurfaceControl, 64, 64); + } + + auto referenceFrame = mBaseFrame; + referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; + referenceFrame[CHILD_LAYER].mDisplayFrame = + hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10}; + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + { + TransactionScope ts(*sFakeComposer); + ts.detachChildren(mFGSurfaceControl); + ts.setPosition(mFGSurfaceControl, 0, 0); + } + + { + TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 64, 64); + ts.setPosition(childNewClient, 0, 0); + ts.hide(childNewClient); } // Nothing should have changed. The child control becomes a no-op @@ -1193,8 +1236,8 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction { TransactionScope ts(*sFakeComposer); - ts.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); + ts.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); ts.show(mChild); } @@ -1217,6 +1260,81 @@ TEST_F(ChildLayerTest, Bug36858924) { sFakeComposer->runVSyncAndWait(); } +class ChildColorLayerTest : public ChildLayerTest { +protected: + void SetUp() override { + TransactionTest::SetUp(); + mChild = mComposerClient->createSurface(String8("Child surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, + mFGSurfaceControl.get()); + { + TransactionScope ts(*sFakeComposer); + ts.setColor(mChild, + {LIGHT_GRAY.r / 255.0f, LIGHT_GRAY.g / 255.0f, LIGHT_GRAY.b / 255.0f}); + } + + sFakeComposer->runVSyncAndWait(); + mBaseFrame.push_back(makeSimpleRect(64, 64, 64 + 10, 64 + 10)); + mBaseFrame[CHILD_LAYER].mSourceCrop = hwc_frect_t{0.0f, 0.0f, 0.0f, 0.0f}; + mBaseFrame[CHILD_LAYER].mSwapCount = 0; + ASSERT_EQ(2, sFakeComposer->getFrameCount()); + ASSERT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); + } +}; + +TEST_F(ChildColorLayerTest, LayerAlpha) { + { + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(mFGSurfaceControl, 0, 0); + ts.setAlpha(mChild, 0.5); + } + + auto referenceFrame = mBaseFrame; + referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64}; + referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 10, 10}; + referenceFrame[CHILD_LAYER].mPlaneAlpha = 0.5f; + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + { + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 0.5); + } + + auto referenceFrame2 = referenceFrame; + referenceFrame2[FG_LAYER].mPlaneAlpha = 0.5f; + referenceFrame2[CHILD_LAYER].mPlaneAlpha = 0.25f; + EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); +} + +TEST_F(ChildColorLayerTest, LayerZeroAlpha) { + { + TransactionScope ts(*sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(mFGSurfaceControl, 0, 0); + ts.setAlpha(mChild, 0.5); + } + + auto referenceFrame = mBaseFrame; + referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64}; + referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 10, 10}; + referenceFrame[CHILD_LAYER].mPlaneAlpha = 0.5f; + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + { + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 0.0f); + } + + std::vector<RenderState> refFrame(1); + refFrame[BG_LAYER] = mBaseFrame[BG_LAYER]; + + EXPECT_TRUE(framesAreSame(refFrame, sFakeComposer->getLatestFrame())); +} + class LatchingTest : public TransactionTest { protected: void lockAndFillFGBuffer() { fillSurfaceRGBA8(mFGSurfaceControl, RED, false); } @@ -1235,8 +1353,8 @@ protected: TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 64, 64); ts.setPosition(mFGSurfaceControl, 64, 64); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64)); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } }; @@ -1280,7 +1398,7 @@ TEST_F(LatchingTest, CropLatching) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); } auto referenceFrame1 = mBaseFrame; @@ -1294,7 +1412,7 @@ TEST_F(LatchingTest, CropLatching) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1312,7 +1430,7 @@ TEST_F(LatchingTest, FinalCropLatching) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1327,7 +1445,7 @@ TEST_F(LatchingTest, FinalCropLatching) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1348,7 +1466,7 @@ TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1367,7 +1485,7 @@ TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1396,12 +1514,12 @@ TEST_F(LatchingTest, FinalCropLatchingRegressionForb37531386) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } { TransactionScope ts(*sFakeComposer); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 9949bfa8a2..8f1f5e551f 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -18,6 +18,7 @@ cc_test { test_suites: ["device-tests"], srcs: [ ":libsurfaceflinger_sources", + "DisplayIdentificationTest.cpp", "DisplayTransactionTest.cpp", "EventControlThreadTest.cpp", "EventThreadTest.cpp", @@ -26,6 +27,7 @@ cc_test { "mock/DisplayHardware/MockPowerAdvisor.cpp", "mock/gui/MockGraphicBufferConsumer.cpp", "mock/gui/MockGraphicBufferProducer.cpp", + "mock/MockDispSync.cpp", "mock/MockEventControlThread.cpp", "mock/MockEventThread.cpp", "mock/MockMessageQueue.cpp", diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp new file mode 100644 index 0000000000..91131711d5 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp @@ -0,0 +1,144 @@ +/* + * 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 <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "DisplayHardware/DisplayIdentification.h" + +namespace android { +namespace { + +const unsigned char kInternalEdid[] = + "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00" + "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27" + "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30" + "\x13\x00\x05\xa3\x10\x00\x00\x19\x00\x00\x00\x0f\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x23\x87\x02\x64\x00\x00\x00\x00\xfe\x00\x53" + "\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x00\x00\x00\xfe" + "\x00\x31\x32\x31\x41\x54\x31\x31\x2d\x38\x30\x31\x0a\x20\x00\x45"; + +const unsigned char kExternalEdid[] = + "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01" + "\x02\x16\x01\x04\xb5\x40\x28\x78\xe2\x8d\x85\xad\x4f\x35\xb1\x25" + "\x0e\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + "\x01\x01\x01\x01\x01\x01\xe2\x68\x00\xa0\xa0\x40\x2e\x60\x30\x20" + "\x36\x00\x81\x90\x21\x00\x00\x1a\xbc\x1b\x00\xa0\x50\x20\x17\x30" + "\x30\x20\x36\x00\x81\x90\x21\x00\x00\x1a\x00\x00\x00\xfc\x00\x48" + "\x50\x20\x5a\x52\x33\x30\x77\x0a\x20\x20\x20\x20\x00\x00\x00\xff" + "\x00\x43\x4e\x34\x32\x30\x32\x31\x33\x37\x51\x0a\x20\x20\x00\x71"; + +// Extended EDID with timing extension. +const unsigned char kExternalEedid[] = + "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00" + "\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26" + "\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00" + "\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c" + "\x45\x00\xa0\x5a\x00\x00\x00\x1e\x66\x21\x56\xaa\x51\x00\x1e\x30" + "\x46\x8f\x33\x00\xa0\x5a\x00\x00\x00\x1e\x00\x00\x00\xfd\x00\x18" + "\x4b\x0f\x51\x17\x00\x0a\x20\x20\x20\x20\x20\x20\x00\x00\x00\xfc" + "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d" + "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07" + "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01" + "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00" + "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00" + "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0" + "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6"; + +template <size_t N> +DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&bytes)[N]) { + return DisplayIdentificationData(bytes, bytes + N - 1); +} + +} // namespace + +TEST(DisplayIdentificationTest, isEdid) { + EXPECT_FALSE(isEdid({})); + + EXPECT_TRUE(isEdid(asDisplayIdentificationData(kInternalEdid))); + EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEdid))); + EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEedid))); +} + +TEST(DisplayIdentificationTest, parseEdid) { + auto edid = parseEdid(asDisplayIdentificationData(kInternalEdid)); + ASSERT_TRUE(edid); + EXPECT_EQ(0x4ca3u, edid->manufacturerId); + EXPECT_STREQ("SEC", edid->pnpId.data()); + // ASCII text should be used as fallback if display name and serial number are missing. + EXPECT_EQ("121AT11-801", edid->displayName); + + edid = parseEdid(asDisplayIdentificationData(kExternalEdid)); + ASSERT_TRUE(edid); + EXPECT_EQ(0x22f0u, edid->manufacturerId); + EXPECT_STREQ("HWP", edid->pnpId.data()); + EXPECT_EQ("HP ZR30w", edid->displayName); + + edid = parseEdid(asDisplayIdentificationData(kExternalEedid)); + ASSERT_TRUE(edid); + EXPECT_EQ(0x4c2du, edid->manufacturerId); + EXPECT_STREQ("SAM", edid->pnpId.data()); + EXPECT_EQ("SAMSUNG", edid->displayName); +} + +TEST(DisplayIdentificationTest, parseInvalidEdid) { + EXPECT_FALSE(isEdid({})); + EXPECT_FALSE(parseEdid({})); + + // Display name must be printable. + auto data = asDisplayIdentificationData(kExternalEdid); + data[97] = '\x1b'; + auto edid = parseEdid(data); + ASSERT_TRUE(edid); + // Serial number should be used as fallback if display name is invalid. + EXPECT_EQ("CN4202137Q", edid->displayName); + + // Parsing should succeed even if EDID is truncated. + data.pop_back(); + edid = parseEdid(data); + ASSERT_TRUE(edid); + EXPECT_EQ("CN4202137Q", edid->displayName); +} + +TEST(DisplayIdentificationTest, getPnpId) { + EXPECT_FALSE(getPnpId(0)); + EXPECT_FALSE(getPnpId(static_cast<uint16_t>(-1))); + + EXPECT_STREQ("SEC", getPnpId(0x4ca3u).value_or(PnpId{}).data()); + EXPECT_STREQ("HWP", getPnpId(0x22f0u).value_or(PnpId{}).data()); + EXPECT_STREQ("SAM", getPnpId(0x4c2du).value_or(PnpId{}).data()); +} + +TEST(DisplayIdentificationTest, generateDisplayId) { + const auto primaryId = generateDisplayId(0, asDisplayIdentificationData(kInternalEdid)); + ASSERT_TRUE(primaryId); + + const auto secondaryId = generateDisplayId(1, asDisplayIdentificationData(kExternalEdid)); + ASSERT_TRUE(secondaryId); + + const auto tertiaryId = generateDisplayId(2, asDisplayIdentificationData(kExternalEedid)); + ASSERT_TRUE(tertiaryId); + + // Display IDs should be unique. + EXPECT_NE(primaryId, secondaryId); + EXPECT_NE(primaryId, tertiaryId); + EXPECT_NE(secondaryId, tertiaryId); +} + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 9b308bfcc8..508875de40 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -25,6 +25,7 @@ #include "TestableSurfaceFlinger.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplaySurface.h" +#include "mock/MockDispSync.h" #include "mock/MockEventControlThread.h" #include "mock/MockEventThread.h" #include "mock/MockMessageQueue.h" @@ -119,6 +120,7 @@ public: Hwc2::mock::Composer* mComposer = nullptr; mock::MessageQueue* mMessageQueue = new mock::MessageQueue(); mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor(); + mock::DispSync* mPrimaryDispSync = new mock::DispSync(); // These mocks are created only when expected to be created via a factory. sp<mock::GraphicBufferConsumer> mConsumer; @@ -154,6 +156,7 @@ DisplayTransactionTest::DisplayTransactionTest() { mFlinger.mutableEventQueue().reset(mMessageQueue); mFlinger.setupRenderEngine(std::unique_ptr<RE::RenderEngine>(mRenderEngine)); mFlinger.mutableInterceptor().reset(mSurfaceInterceptor); + mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync); injectMockComposer(0); } @@ -207,11 +210,11 @@ bool DisplayTransactionTest::hasTransactionFlagSet(int flag) { } bool DisplayTransactionTest::hasDisplayDevice(sp<IBinder> displayToken) { - return mFlinger.mutableDisplays().indexOfKey(displayToken) >= 0; + return mFlinger.mutableDisplays().count(displayToken) == 1; } sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) { - return mFlinger.mutableDisplays().valueFor(displayToken); + return mFlinger.mutableDisplays()[displayToken]; } bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) { @@ -234,8 +237,8 @@ const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBin * */ -template <DisplayDevice::DisplayType type, DisplayDevice::DisplayType hwcId, int width, int height, - Critical critical, Async async, Secure secure, int grallocUsage> +template <DisplayDevice::DisplayType type, DisplayDevice::DisplayType displayId, int width, + int height, Critical critical, Async async, Secure secure, int grallocUsage> struct DisplayVariant { // The display width and height static constexpr int WIDTH = width; @@ -245,7 +248,9 @@ struct DisplayVariant { // The type for this display static constexpr DisplayDevice::DisplayType TYPE = type; - static constexpr DisplayDevice::DisplayType HWCOMPOSER_ID = hwcId; + static_assert(TYPE != DisplayDevice::DISPLAY_ID_INVALID); + + static constexpr DisplayDevice::DisplayType DISPLAY_ID = displayId; // When creating native window surfaces for the framebuffer, whether those should be critical static constexpr Critical CRITICAL = critical; @@ -257,7 +262,7 @@ struct DisplayVariant { static constexpr Secure SECURE = secure; static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { - auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, HWCOMPOSER_ID); + auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, DISPLAY_ID); injector.setSecure(static_cast<bool>(SECURE)); return injector; } @@ -353,6 +358,8 @@ struct HwcDisplayVariant { getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, IComposerClient::Attribute::DPI_Y, _)) .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE))); + EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) + .WillRepeatedly(Return(Error::UNSUPPORTED)); } // Called by tests to set up HWC call expectations @@ -383,11 +390,6 @@ struct PhysicalDisplayVariant DisplayVariant<type, type, width, height, critical, Async::FALSE, Secure::TRUE, GRALLOC_USAGE_PHYSICAL_DISPLAY>> {}; -// An invalid display -using InvalidDisplayVariant = - DisplayVariant<DisplayDevice::DISPLAY_ID_INVALID, DisplayDevice::DISPLAY_ID_INVALID, 0, 0, - Critical::FALSE, Async::FALSE, Secure::FALSE, 0>; - // A primary display is a physical display that is critical using PrimaryDisplayVariant = PhysicalDisplayVariant<1001, DisplayDevice::DISPLAY_PRIMARY, 3840, 2160, Critical::TRUE>; @@ -578,7 +580,7 @@ struct HdrNotSupportedVariant { struct NonHwcPerFrameMetadataSupportVariant { static constexpr int PER_FRAME_METADATA_KEYS = 0; static void setupComposerCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_, _)).Times(0); + EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_)).Times(0); } }; @@ -586,9 +588,8 @@ template <typename Display> struct NoPerFrameMetadataSupportVariant { static constexpr int PER_FRAME_METADATA_KEYS = 0; static void setupComposerCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID, _)) - .WillOnce(DoAll(SetArgPointee<1>(std::vector<PerFrameMetadataKey>()), - Return(Error::NONE))); + EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID)) + .WillOnce(Return(std::vector<PerFrameMetadataKey>())); } }; @@ -596,8 +597,8 @@ template <typename Display> struct Smpte2086PerFrameMetadataSupportVariant { static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::SMPTE2086; static void setupComposerCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID, _)) - .WillOnce(DoAll(SetArgPointee<1>(std::vector<PerFrameMetadataKey>({ + EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID)) + .WillOnce(Return(std::vector<PerFrameMetadataKey>({ PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, @@ -608,8 +609,7 @@ struct Smpte2086PerFrameMetadataSupportVariant { PerFrameMetadataKey::WHITE_POINT_Y, PerFrameMetadataKey::MAX_LUMINANCE, PerFrameMetadataKey::MIN_LUMINANCE, - })), - Return(Error::NONE))); + }))); } }; @@ -617,12 +617,11 @@ template <typename Display> struct Cta861_3_PerFrameMetadataSupportVariant { static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::CTA861_3; static void setupComposerCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID, _)) - .WillOnce(DoAll(SetArgPointee<1>(std::vector<PerFrameMetadataKey>({ + EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID)) + .WillOnce(Return(std::vector<PerFrameMetadataKey>({ PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, - })), - Return(Error::NONE))); + }))); } }; @@ -658,8 +657,7 @@ using NonHwcVirtualDisplayCase = using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>; using HwcVirtualDisplayCase = Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant, - HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>, - NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>; + NonHwcDisplayHdrSupportVariant, NonHwcPerFrameMetadataSupportVariant>; using WideColorP3ColorimetricDisplayCase = Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>, HdrNotSupportedVariant<PrimaryDisplayVariant>, @@ -684,9 +682,7 @@ using HdrCta861_3_DisplayCase = Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>, HdrNotSupportedVariant<PrimaryDisplayVariant>, Cta861_3_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>; -using InvalidDisplayCase = Case<InvalidDisplayVariant, WideColorSupportNotConfiguredVariant, - NonHwcDisplayHdrSupportVariant, - NoPerFrameMetadataSupportVariant<InvalidDisplayVariant>>; + /* ------------------------------------------------------------------------ * * SurfaceFlinger::onHotplugReceived @@ -694,8 +690,8 @@ using InvalidDisplayCase = Case<InvalidDisplayVariant, WideColorSupportNotConfig TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) { constexpr int currentSequenceId = 123; - constexpr hwc2_display_t displayId1 = 456; - constexpr hwc2_display_t displayId2 = 654; + constexpr hwc2_display_t hwcDisplayId1 = 456; + constexpr hwc2_display_t hwcDisplayId2 = 654; // -------------------------------------------------------------------- // Preconditions @@ -718,8 +714,8 @@ TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) { // Invocation // Simulate two hotplug events (a connect and a disconnect) - mFlinger.onHotplugReceived(currentSequenceId, displayId1, HWC2::Connection::Connected); - mFlinger.onHotplugReceived(currentSequenceId, displayId2, HWC2::Connection::Disconnected); + mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId1, HWC2::Connection::Connected); + mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId2, HWC2::Connection::Disconnected); // -------------------------------------------------------------------- // Postconditions @@ -730,9 +726,9 @@ TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) { // All events should be in the pending event queue. const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents(); ASSERT_EQ(2u, pendingEvents.size()); - EXPECT_EQ(displayId1, pendingEvents[0].display); + EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId); EXPECT_EQ(HWC2::Connection::Connected, pendingEvents[0].connection); - EXPECT_EQ(displayId2, pendingEvents[1].display); + EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId); EXPECT_EQ(HWC2::Connection::Disconnected, pendingEvents[1].connection); } @@ -968,6 +964,9 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { // The call clears the current render engine surface EXPECT_CALL(*mRenderEngine, resetCurrentSurface()); + // The call ends any display resyncs + EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1); + // -------------------------------------------------------------------- // Invocation @@ -1032,7 +1031,10 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // -------------------------------------------------------------------- // Invocation - auto state = DisplayDeviceState(Case::Display::TYPE, static_cast<bool>(Case::Display::SECURE)); + DisplayDeviceState state; + state.type = Case::Display::TYPE; + state.isSecure = static_cast<bool>(Case::Display::SECURE); + auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, Case::Display::TYPE, state, displaySurface, producer); @@ -1160,13 +1162,23 @@ void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessin Case::PerFrameMetadataSupport::setupComposerCallExpectations(this); EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1); - EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::TYPE, true)).Times(1); + EXPECT_CALL(*mEventThread, + onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY + ? EventThread::DisplayType::Primary + : EventThread::DisplayType::External, + true)) + .Times(1); } template <typename Case> void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() { EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1); - EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::TYPE, false)).Times(1); + EXPECT_CALL(*mEventThread, + onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY + ? EventThread::DisplayType::Primary + : EventThread::DisplayType::External, + false)) + .Times(1); } template <typename Case> @@ -1197,7 +1209,7 @@ void HandleTransactionLockedTest::verifyPhysicalDisplayIsConnected() { static_assert(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, "Must use a valid physical display type index for the fixed-size array"); - auto& displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]; + auto& displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; ASSERT_TRUE(displayToken != nullptr); verifyDisplayIsConnected<Case>(displayToken); @@ -1303,7 +1315,7 @@ void HandleTransactionLockedTest::processesHotplugDisconnectCommon() { // The display should not be set up as a built-in display. ASSERT_TRUE(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]; + auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; EXPECT_TRUE(displayToken == nullptr); // The existing token should have been removed @@ -1396,7 +1408,7 @@ TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary // The display should not be set up as a primary built-in display. ASSERT_TRUE(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]; + auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; EXPECT_TRUE(displayToken == nullptr); } @@ -1439,7 +1451,7 @@ TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary static_assert(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, "Display type must be a built-in display"); - EXPECT_NE(existing.token(), mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]); + EXPECT_NE(existing.token(), mFlinger.mutableDisplayTokens()[Case::Display::TYPE]); // A new display should be connected in its place @@ -1468,7 +1480,11 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) { // A virtual display was added to the current state, and it has a // surface(producer) sp<BBinder> displayToken = new BBinder(); - DisplayDeviceState info(Case::Display::TYPE, static_cast<bool>(Case::Display::SECURE)); + + DisplayDeviceState info; + info.type = Case::Display::TYPE; + info.isSecure = static_cast<bool>(Case::Display::SECURE); + sp<mock::GraphicBufferProducer> surface{new mock::GraphicBufferProducer()}; info.surface = surface; mFlinger.mutableCurrentState().displays.add(displayToken, info); @@ -1532,7 +1548,11 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) { // A virtual display was added to the current state, but it does not have a // surface. sp<BBinder> displayToken = new BBinder(); - DisplayDeviceState info(Case::Display::TYPE, static_cast<bool>(Case::Display::SECURE)); + + DisplayDeviceState info; + info.type = Case::Display::TYPE; + info.isSecure = static_cast<bool>(Case::Display::SECURE); + mFlinger.mutableCurrentState().displays.add(displayToken, info); // -------------------------------------------------------------------- @@ -1811,40 +1831,6 @@ TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWithUnknownDispla EXPECT_FALSE(hasCurrentDisplayState(displayToken)); } -TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWithInvalidDisplay) { - using Case = InvalidDisplayCase; - - // -------------------------------------------------------------------- - // Preconditions - - // An invalid display is set up - auto display = Case::Display::makeFakeExistingDisplayInjector(this); - display.inject(); - - // The invalid display has some state - display.mutableCurrentDisplayState().layerStack = 654u; - - // The requested display state tries to change the display state. - DisplayState state; - state.what = DisplayState::eLayerStackChanged; - state.token = display.token(); - state.layerStack = 456; - - // -------------------------------------------------------------------- - // Invocation - - uint32_t flags = mFlinger.setDisplayStateLocked(state); - - // -------------------------------------------------------------------- - // Postconditions - - // The returned flags are empty - EXPECT_EQ(0u, flags); - - // The current display layer stack value is unchanged. - EXPECT_EQ(654u, getCurrentDisplayState(display.token()).layerStack); -} - TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWhenNoChanges) { using Case = SimplePrimaryDisplayCase; @@ -2420,6 +2406,24 @@ struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant { } }; +struct DispSyncIsSupportedVariant { + static void setupBeginResyncCallExpectations(DisplayTransactionTest* test) { + EXPECT_CALL(*test->mPrimaryDispSync, reset()).Times(1); + EXPECT_CALL(*test->mPrimaryDispSync, setPeriod(DEFAULT_REFRESH_RATE)).Times(1); + EXPECT_CALL(*test->mPrimaryDispSync, beginResync()).Times(1); + } + + static void setupEndResyncCallExpectations(DisplayTransactionTest* test) { + EXPECT_CALL(*test->mPrimaryDispSync, endResync()).Times(1); + } +}; + +struct DispSyncNotSupportedVariant { + static void setupBeginResyncCallExpectations(DisplayTransactionTest* /* test */) {} + + static void setupEndResyncCallExpectations(DisplayTransactionTest* /* test */) {} +}; + // -------------------------------------------------------------------- // Note: // @@ -2441,6 +2445,7 @@ struct TransitionOffToOnVariant static void setupCallExpectations(DisplayTransactionTest* test) { Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON); Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test); + Case::DispSync::setupBeginResyncCallExpectations(test); Case::setupRepaintEverythingCallExpectations(test); } @@ -2470,6 +2475,7 @@ struct TransitionOnToOffVariant template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test); + Case::DispSync::setupEndResyncCallExpectations(test); Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF); } @@ -2505,6 +2511,7 @@ struct TransitionDozeSuspendToDozeVariant template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test); + Case::DispSync::setupBeginResyncCallExpectations(test); Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE); } }; @@ -2523,6 +2530,7 @@ struct TransitionDozeSuspendToOnVariant template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test); + Case::DispSync::setupBeginResyncCallExpectations(test); Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON); } }; @@ -2532,6 +2540,7 @@ struct TransitionOnToDozeSuspendVariant template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test); + Case::DispSync::setupEndResyncCallExpectations(test); Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND); } }; @@ -2554,11 +2563,12 @@ struct TransitionOnToUnknownVariant // -------------------------------------------------------------------- template <typename DisplayVariant, typename DozeVariant, typename EventThreadVariant, - typename TransitionVariant> + typename DispSyncVariant, typename TransitionVariant> struct DisplayPowerCase { using Display = DisplayVariant; using Doze = DozeVariant; using EventThread = EventThreadVariant; + using DispSync = DispSyncVariant; using Transition = TransitionVariant; static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, int mode) { @@ -2606,15 +2616,16 @@ struct DisplayPowerCase { // In addition to having event thread support, we emulate doze support. template <typename TransitionVariant> using PrimaryDisplayPowerCase = DisplayPowerCase<PrimaryDisplayVariant, DozeIsSupportedVariant, - EventThreadIsSupportedVariant, TransitionVariant>; + EventThreadIsSupportedVariant, + DispSyncIsSupportedVariant, TransitionVariant>; // A sample configuration for the external display. // In addition to not having event thread support, we emulate not having doze // support. template <typename TransitionVariant> -using ExternalDisplayPowerCase = - DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant, - EventThreadNotSupportedVariant, TransitionVariant>; +using ExternalDisplayPowerCase = DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant, + EventThreadNotSupportedVariant, + DispSyncNotSupportedVariant, TransitionVariant>; class SetPowerModeInternalTest : public DisplayTransactionTest { public: @@ -2671,7 +2682,7 @@ TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfNoChange) { auto display = Case::Display::makeFakeExistingDisplayInjector(this); display.inject(); - // The diplay is already set to HWC_POWER_MODE_NORMAL + // The display is already set to HWC_POWER_MODE_NORMAL display.mutableDisplayDevice()->setPowerMode(HWC_POWER_MODE_NORMAL); // -------------------------------------------------------------------- @@ -2685,7 +2696,7 @@ TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfNoChange) { EXPECT_EQ(HWC_POWER_MODE_NORMAL, display.mutableDisplayDevice()->getPowerMode()); } -TEST_F(SetPowerModeInternalTest, setPowerModeInternalJustSetsInternalStateIfVirtualDisplay) { +TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay) { using Case = HwcVirtualDisplayCase; // -------------------------------------------------------------------- @@ -2700,13 +2711,13 @@ TEST_F(SetPowerModeInternalTest, setPowerModeInternalJustSetsInternalStateIfVirt auto display = Case::Display::makeFakeExistingDisplayInjector(this); display.inject(); - // The display is set to HWC_POWER_MODE_OFF - getDisplayDevice(display.token())->setPowerMode(HWC_POWER_MODE_OFF); + // The display is set to HWC_POWER_MODE_NORMAL + getDisplayDevice(display.token())->setPowerMode(HWC_POWER_MODE_NORMAL); // -------------------------------------------------------------------- // Invocation - mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_NORMAL); + mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_OFF); // -------------------------------------------------------------------- // Postconditions diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 80fdb80264..19747bd442 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -71,7 +71,8 @@ protected: ConnectionEventRecorder& connectionEventRecorder, nsecs_t expectedTimestamp, unsigned expectedCount); void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount); - void expectHotplugEventReceivedByConnection(int expectedDisplayType, bool expectedConnected); + void expectHotplugEventReceivedByConnection(EventThread::DisplayType expectedDisplayType, + bool expectedConnected); AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder; AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder; @@ -169,13 +170,16 @@ void EventThreadTest::expectVsyncEventReceivedByConnection(nsecs_t expectedTimes expectedCount); } -void EventThreadTest::expectHotplugEventReceivedByConnection(int expectedDisplayType, - bool expectedConnected) { +void EventThreadTest::expectHotplugEventReceivedByConnection( + EventThread::DisplayType expectedDisplayType, bool expectedConnected) { + const uint32_t expectedDisplayId = + expectedDisplayType == EventThread::DisplayType::Primary ? 0 : 1; + auto args = mConnectionEventCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); const auto& event = std::get<0>(args.value()); EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type); - EXPECT_EQ(static_cast<unsigned>(expectedDisplayType), event.header.id); + EXPECT_EQ(expectedDisplayId, event.header.id); EXPECT_EQ(expectedConnected, event.hotplug.connected); } @@ -394,28 +398,23 @@ TEST_F(EventThreadTest, setPhaseOffsetForwardsToVSyncSource) { } TEST_F(EventThreadTest, postHotplugPrimaryDisconnect) { - mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, false); - expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, false); + mThread->onHotplugReceived(EventThread::DisplayType::Primary, false); + expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, false); } TEST_F(EventThreadTest, postHotplugPrimaryConnect) { - mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true); - expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, true); + mThread->onHotplugReceived(EventThread::DisplayType::Primary, true); + expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, true); } TEST_F(EventThreadTest, postHotplugExternalDisconnect) { - mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, false); - expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, false); + mThread->onHotplugReceived(EventThread::DisplayType::External, false); + expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, false); } TEST_F(EventThreadTest, postHotplugExternalConnect) { - mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, true); - expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, true); -} - -TEST_F(EventThreadTest, postHotplugVirtualDisconnectIsFilteredOut) { - mThread->onHotplugReceived(DisplayDevice::DISPLAY_VIRTUAL, false); - EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); + mThread->onHotplugReceived(EventThread::DisplayType::External, true); + expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, true); } } // namespace diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index acd16fe650..9df42641cb 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -64,15 +64,17 @@ public: return mFlinger->createDisplay(displayName, secure); } - auto destroyDisplay(const sp<IBinder>& display) { return mFlinger->destroyDisplay(display); } + auto destroyDisplay(const sp<IBinder>& displayToken) { + return mFlinger->destroyDisplay(displayToken); + } auto resetDisplayState() { return mFlinger->resetDisplayState(); } - auto setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId, + auto setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, int32_t displayId, const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { - return mFlinger->setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, + return mFlinger->setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface, producer); } @@ -89,8 +91,9 @@ public: auto onInitializeDisplays() { return mFlinger->onInitializeDisplays(); } - auto setPowerModeInternal(const sp<DisplayDevice>& hw, int mode, bool stateLockHeld = false) { - return mFlinger->setPowerModeInternal(hw, mode, stateLockHeld); + auto setPowerModeInternal(const sp<DisplayDevice>& display, int mode, + bool stateLockHeld = false) { + return mFlinger->setPowerModeInternal(display, mode, stateLockHeld); } /* ------------------------------------------------------------------------ @@ -111,7 +114,7 @@ public: auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; } - auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; } + auto& mutableDisplayTokens() { return mFlinger->mDisplayTokens; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplays() { return mFlinger->mDisplays; } auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } @@ -123,6 +126,7 @@ public: auto& mutableInterceptor() { return mFlinger->mInterceptor; } auto& mutableMainThreadId() { return mFlinger->mMainThreadId; } auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; } + auto& mutablePrimaryDispSync() { return mFlinger->mPrimaryDispSync; } auto& mutablePrimaryHWVsyncEnabled() { return mFlinger->mPrimaryHWVsyncEnabled; } auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; } @@ -141,6 +145,7 @@ public: mutableEventQueue().reset(); mutableEventThread().reset(); mutableInterceptor().reset(); + mutablePrimaryDispSync().reset(); mFlinger->getBE().mHwc.reset(); mFlinger->getBE().mRenderEngine.reset(); } @@ -217,13 +222,27 @@ public: return *this; } - auto& addCapability(HWC2::Capability cap) { - mCapabilities.emplace(cap); + auto& setCapabilities(const std::unordered_set<HWC2::Capability>* capabilities) { + mCapabilities = capabilities; + return *this; + } + + auto& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) { + mPowerAdvisor = powerAdvisor; return *this; } void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) { - auto display = std::make_unique<HWC2Display>(*composer, mPowerAdvisor, mCapabilities, + static FakePowerAdvisor defaultPowerAdvisor; + if (mPowerAdvisor == nullptr) mPowerAdvisor = &defaultPowerAdvisor; + static const std::unordered_set<HWC2::Capability> defaultCapabilities; + if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities; + + // Caution - Make sure that any values passed by reference here do + // not refer to an instance owned by FakeHwcDisplayInjector. This + // class has temporary lifetime, while the constructed HWC2::Display + // is much longer lived. + auto display = std::make_unique<HWC2Display>(*composer, *mPowerAdvisor, *mCapabilities, mHwcDisplayId, mHwcDisplayType); auto config = HWC2::Display::Config::Builder(*display, mActiveConfig); @@ -236,7 +255,7 @@ public: display->mutableIsConnected() = true; ASSERT_TRUE(flinger->mutableHwcDisplayData().size() > static_cast<size_t>(mType)); - flinger->mutableHwcDisplayData()[mType].reset(); + flinger->mutableHwcDisplayData()[mType] = HWComposer::DisplayData(); flinger->mutableHwcDisplayData()[mType].hwcDisplay = display.get(); flinger->mutableHwcDisplaySlots().emplace(mHwcDisplayId, mType); @@ -253,15 +272,15 @@ public: int32_t mDpiX = DEFAULT_DPI; int32_t mDpiY = DEFAULT_DPI; int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; - std::unordered_set<HWC2::Capability> mCapabilities; - FakePowerAdvisor mPowerAdvisor; + const std::unordered_set<HWC2::Capability>* mCapabilities = nullptr; + Hwc2::PowerAdvisor* mPowerAdvisor = nullptr; }; class FakeDisplayDeviceInjector { public: FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, DisplayDevice::DisplayType type, - int hwcId) - : mFlinger(flinger), mType(type), mHwcId(hwcId) {} + int32_t displayId) + : mFlinger(flinger), mType(type), mDisplayId(displayId) {} sp<IBinder> token() const { return mDisplayToken; } @@ -281,7 +300,7 @@ public: return mFlinger.mutableCurrentState().displays.valueFor(mDisplayToken); } - auto& mutableDisplayDevice() { return mFlinger.mutableDisplays().valueFor(mDisplayToken); } + auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; } auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) { mNativeWindow = nativeWindow; @@ -306,18 +325,20 @@ public: sp<DisplayDevice> inject() { std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hdrAndRenderIntents; sp<DisplayDevice> device = - new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure, mDisplayToken, - mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0, - 0, false, HdrCapabilities(), 0, hdrAndRenderIntents, - HWC_POWER_MODE_NORMAL); - mFlinger.mutableDisplays().add(mDisplayToken, device); - - DisplayDeviceState state(mType, mSecure); + new DisplayDevice(mFlinger.mFlinger.get(), mType, mDisplayId, mSecure, + mDisplayToken, mNativeWindow, mDisplaySurface, + std::move(mRenderSurface), 0, 0, false, HdrCapabilities(), 0, + hdrAndRenderIntents, HWC_POWER_MODE_NORMAL); + mFlinger.mutableDisplays().emplace(mDisplayToken, device); + + DisplayDeviceState state; + state.type = mType; + state.isSecure = mSecure; mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); if (mType >= DisplayDevice::DISPLAY_PRIMARY && mType < DisplayDevice::DISPLAY_VIRTUAL) { - mFlinger.mutableBuiltinDisplays()[mType] = mDisplayToken; + mFlinger.mutableDisplayTokens()[mType] = mDisplayToken; } return device; @@ -327,7 +348,7 @@ public: TestableSurfaceFlinger& mFlinger; sp<BBinder> mDisplayToken = new BBinder(); DisplayDevice::DisplayType mType; - int mHwcId; + const int32_t mDisplayId; sp<ANativeWindow> mNativeWindow; sp<DisplaySurface> mDisplaySurface; std::unique_ptr<RE::Surface> mRenderSurface; diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 267670aca5..b9e07152f4 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -74,9 +74,10 @@ public: 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_METHOD2(getPerFrameMetadataKeys, - Error(Display, std::vector<IComposerClient::PerFrameMetadataKey>*)); + MOCK_METHOD1(getPerFrameMetadataKeys, + std::vector<IComposerClient::PerFrameMetadataKey>(Display)); MOCK_METHOD2(getDataspaceSaturationMatrix, Error(Dataspace, mat4*)); + MOCK_METHOD3(getDisplayIdentificationData, Error(Display, uint8_t*, std::vector<uint8_t>*)); MOCK_METHOD3(getReleaseFences, Error(Display, std::vector<Layer>*, std::vector<int>*)); MOCK_METHOD2(presentDisplay, Error(Display, int*)); MOCK_METHOD2(setActiveConfig, Error(Display, Config)); diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp new file mode 100644 index 0000000000..2f7e5ead0f --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp @@ -0,0 +1,27 @@ +/* + * 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 "mock/MockDispSync.h" + +namespace android { +namespace mock { + +// Explicit default instantiation is recommended. +DispSync::DispSync() = default; +DispSync::~DispSync() = default; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h new file mode 100644 index 0000000000..4a466efd2d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <gmock/gmock.h> + +#include <utils/String8.h> +#include "DispSync.h" + +namespace android { +namespace mock { + +class DispSync : public android::DispSync { +public: + DispSync(); + ~DispSync() override; + + MOCK_METHOD0(reset, void()); + MOCK_METHOD1(addPresentFence, bool(const std::shared_ptr<FenceTime>&)); + MOCK_METHOD0(beginResync, void()); + MOCK_METHOD1(addResyncSample, bool(nsecs_t)); + MOCK_METHOD0(endResync, void()); + MOCK_METHOD1(setPeriod, void(nsecs_t)); + MOCK_METHOD0(getPeriod, nsecs_t()); + MOCK_METHOD1(setRefreshSkipCount, void(int)); + MOCK_METHOD3(addEventListener, status_t(const char*, nsecs_t, Callback*)); + MOCK_METHOD1(removeEventListener, status_t(Callback*)); + MOCK_METHOD2(changePhaseOffset, status_t(Callback*, nsecs_t)); + MOCK_CONST_METHOD1(computeNextRefresh, nsecs_t(int)); + MOCK_METHOD1(setIgnorePresentFences, void(bool)); + + MOCK_CONST_METHOD1(dump, void(String8&)); +}; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index e6ea6634c0..df9bfc6d96 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -31,7 +31,7 @@ public: MOCK_CONST_METHOD0(createEventConnection, sp<BnDisplayEventConnection>()); MOCK_METHOD0(onScreenReleased, void()); MOCK_METHOD0(onScreenAcquired, void()); - MOCK_METHOD2(onHotplugReceived, void(int, bool)); + MOCK_METHOD2(onHotplugReceived, void(DisplayType, bool)); MOCK_CONST_METHOD1(dump, void(String8&)); MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset)); }; diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index ac082933a3..7814d32b19 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -37,7 +37,8 @@ public: MOCK_METHOD0(createImage, std::unique_ptr<RE::Image>()); MOCK_CONST_METHOD0(primeCache, void()); MOCK_METHOD1(dump, void(String8&)); - MOCK_CONST_METHOD0(supportsImageCrop, bool()); + MOCK_CONST_METHOD0(useNativeFenceSync, bool()); + MOCK_CONST_METHOD0(useWaitSync, bool()); MOCK_CONST_METHOD0(isCurrent, bool()); MOCK_METHOD1(setCurrentSurface, bool(const RE::Surface&)); MOCK_METHOD0(resetCurrentSurface, void()); @@ -98,9 +99,8 @@ public: Image(); ~Image() override; - MOCK_METHOD4(setNativeWindowBuffer, - bool(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth, - int32_t cropHeight)); + MOCK_METHOD2(setNativeWindowBuffer, + bool(ANativeWindowBuffer* buffer, bool isProtected)); }; } // namespace mock diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp index 6122846540..499a8f69ff 100644 --- a/services/vr/bufferhubd/Android.bp +++ b/services/vr/bufferhubd/Android.bp @@ -13,11 +13,12 @@ // limitations under the License. sourceFiles = [ + "buffer_channel.cpp", "buffer_hub.cpp", + "buffer_node.cpp", "bufferhubd.cpp", "consumer_channel.cpp", "producer_channel.cpp", - "detached_buffer_channel.cpp", "consumer_queue_channel.cpp", "producer_queue_channel.cpp", ] diff --git a/services/vr/bufferhubd/buffer_channel.cpp b/services/vr/bufferhubd/buffer_channel.cpp new file mode 100644 index 0000000000..2150d62c4e --- /dev/null +++ b/services/vr/bufferhubd/buffer_channel.cpp @@ -0,0 +1,206 @@ +#include "buffer_channel.h" +#include "producer_channel.h" + +using android::pdx::BorrowedHandle; +using android::pdx::ErrorStatus; +using android::pdx::Message; +using android::pdx::RemoteChannelHandle; +using android::pdx::Status; +using android::pdx::rpc::DispatchRemoteMethod; + +namespace android { +namespace dvr { + +BufferChannel::BufferChannel(BufferHubService* service, int buffer_id, + int channel_id, IonBuffer buffer, + IonBuffer metadata_buffer, + size_t user_metadata_size) + : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType), + buffer_node_(std::make_shared<BufferNode>( + std::move(buffer), std::move(metadata_buffer), user_metadata_size)), + buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) { + buffer_node_->set_buffer_state_bit(buffer_state_bit_); +} + +BufferChannel::BufferChannel(BufferHubService* service, int buffer_id, + uint32_t width, uint32_t height, + uint32_t layer_count, uint32_t format, + uint64_t usage, size_t user_metadata_size) + : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType), + buffer_node_(std::make_shared<BufferNode>( + width, height, layer_count, format, usage, user_metadata_size)), + buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) { + buffer_node_->set_buffer_state_bit(buffer_state_bit_); +} + +BufferChannel::BufferChannel(BufferHubService* service, int buffer_id, + int channel_id, + std::shared_ptr<BufferNode> buffer_node, + uint64_t buffer_state_bit) + : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType), + buffer_node_(buffer_node), + buffer_state_bit_(buffer_state_bit) { + buffer_node_->set_buffer_state_bit(buffer_state_bit_); +} + +BufferChannel::~BufferChannel() { + ALOGD_IF(TRACE, "BufferChannel::~BufferChannel: channel_id=%d buffer_id=%d.", + channel_id(), buffer_id()); + Hangup(); +} + +BufferHubChannel::BufferInfo BufferChannel::GetBufferInfo() const { + return BufferInfo( + buffer_id(), /*consumer_count=*/0, buffer_node_->buffer().width(), + buffer_node_->buffer().height(), buffer_node_->buffer().layer_count(), + buffer_node_->buffer().format(), buffer_node_->buffer().usage(), + /*pending_count=*/0, /*state=*/0, /*signaled_mask=*/0, + /*index=*/0); +} + +void BufferChannel::HandleImpulse(Message& /*message*/) { + ATRACE_NAME("BufferChannel::HandleImpulse"); +} + +bool BufferChannel::HandleMessage(Message& message) { + ATRACE_NAME("BufferChannel::HandleMessage"); + switch (message.GetOp()) { + case DetachedBufferRPC::Import::Opcode: + DispatchRemoteMethod<DetachedBufferRPC::Import>( + *this, &BufferChannel::OnImport, message); + return true; + + case DetachedBufferRPC::Duplicate::Opcode: + DispatchRemoteMethod<DetachedBufferRPC::Duplicate>( + *this, &BufferChannel::OnDuplicate, message); + return true; + + case DetachedBufferRPC::Promote::Opcode: + DispatchRemoteMethod<DetachedBufferRPC::Promote>( + *this, &BufferChannel::OnPromote, message); + return true; + + default: + return false; + } +} + +Status<BufferDescription<BorrowedHandle>> BufferChannel::OnImport( + Message& /*message*/) { + ATRACE_NAME("BufferChannel::OnImport"); + ALOGD_IF(TRACE, "BufferChannel::OnImport: buffer=%d.", + buffer_id()); + + return BufferDescription<BorrowedHandle>{buffer_node_->buffer(), + buffer_node_->metadata_buffer(), + buffer_id(), + channel_id(), + buffer_state_bit_, + BorrowedHandle{}, + BorrowedHandle{}}; +} + +Status<RemoteChannelHandle> BufferChannel::OnDuplicate( + Message& message) { + ATRACE_NAME("BufferChannel::OnDuplicate"); + ALOGD_IF(TRACE, "BufferChannel::OnDuplicate: buffer=%d.", + buffer_id()); + + int channel_id; + auto status = message.PushChannel(0, nullptr, &channel_id); + if (!status) { + ALOGE( + "BufferChannel::OnDuplicate: Failed to push buffer channel: %s", + status.GetErrorMessage().c_str()); + return ErrorStatus(ENOMEM); + } + + // Try find the next buffer state bit which has not been claimed by any + // other buffers yet. + uint64_t buffer_state_bit = + BufferHubDefs::FindNextClearedBit(buffer_node_->active_buffer_bit_mask() | + BufferHubDefs::kProducerStateBit); + if (buffer_state_bit == 0ULL) { + ALOGE( + "BufferChannel::OnDuplicate: reached the maximum mumber of channels " + "per buffer node: 63."); + return ErrorStatus(E2BIG); + } + + auto channel = + std::shared_ptr<BufferChannel>(new BufferChannel( + service(), buffer_id(), channel_id, buffer_node_, buffer_state_bit)); + if (!channel) { + ALOGE("BufferChannel::OnDuplicate: Invalid buffer."); + return ErrorStatus(EINVAL); + } + + const auto channel_status = + service()->SetChannel(channel_id, std::move(channel)); + if (!channel_status) { + // Technically, this should never fail, as we just pushed the channel. Note + // that LOG_FATAL will be stripped out in non-debug build. + LOG_FATAL( + "BufferChannel::OnDuplicate: Failed to set new buffer channel: %s.", + channel_status.GetErrorMessage().c_str()); + } + + return status; +} + +Status<RemoteChannelHandle> BufferChannel::OnPromote( + Message& message) { + ATRACE_NAME("BufferChannel::OnPromote"); + ALOGD_IF(TRACE, "BufferChannel::OnPromote: buffer_id=%d", buffer_id()); + + // Check whether this is the channel exclusive owner of the buffer_node_. + if (buffer_state_bit_ != buffer_node_->active_buffer_bit_mask()) { + ALOGE( + "BufferChannel::OnPromote: Cannot promote this BufferChannel as its " + "BufferNode is shared between multiple channels. This channel's state " + "bit=0x%" PRIx64 ", acitve_buffer_bit_mask=0x%" PRIx64 ".", + buffer_state_bit_, buffer_node_->active_buffer_bit_mask()); + return ErrorStatus(EINVAL); + } + + // Note that the new ProducerChannel will have different channel_id, but + // inherits the buffer_id from the DetachedBuffer. + int channel_id; + auto status = message.PushChannel(0, nullptr, &channel_id); + if (!status) { + ALOGE( + "BufferChannel::OnPromote: Failed to push ProducerChannel: %s.", + status.GetErrorMessage().c_str()); + return ErrorStatus(ENOMEM); + } + + IonBuffer buffer = std::move(buffer_node_->buffer()); + IonBuffer metadata_buffer = std::move(buffer_node_->metadata_buffer()); + size_t user_metadata_size = buffer_node_->user_metadata_size(); + + std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create( + service(), buffer_id(), channel_id, std::move(buffer), + std::move(metadata_buffer), user_metadata_size); + if (!channel) { + ALOGE( + "BufferChannel::OnPromote: Failed to create ProducerChannel from a " + "BufferChannel, buffer_id=%d.", + buffer_id()); + } + + const auto channel_status = + service()->SetChannel(channel_id, std::move(channel)); + if (!channel_status) { + // Technically, this should never fail, as we just pushed the channel. Note + // that LOG_FATAL will be stripped out in non-debug build. + LOG_FATAL( + "BufferChannel::OnPromote: Failed to set new producer buffer channel: " + "%s.", + channel_status.GetErrorMessage().c_str()); + } + + return status; +} + +} // namespace dvr +} // namespace android diff --git a/services/vr/bufferhubd/buffer_channel.h b/services/vr/bufferhubd/buffer_channel.h new file mode 100644 index 0000000000..ac99a73cc7 --- /dev/null +++ b/services/vr/bufferhubd/buffer_channel.h @@ -0,0 +1,66 @@ +#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_ +#define ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_ + +#include "buffer_hub.h" +#include "buffer_node.h" + +#include <pdx/channel_handle.h> +#include <pdx/file_handle.h> + +namespace android { +namespace dvr { + +class BufferChannel : public BufferHubChannel { + public: + ~BufferChannel() override; + + template <typename... Args> + static std::unique_ptr<BufferChannel> Create(Args&&... args) { + auto buffer = std::unique_ptr<BufferChannel>( + new BufferChannel(std::forward<Args>(args)...)); + return buffer->IsValid() ? std::move(buffer) : nullptr; + } + + // Returns whether the object holds a valid graphic buffer. + bool IsValid() const { + return buffer_node_ != nullptr && buffer_node_->IsValid(); + } + + // Captures buffer info for use by BufferHubService::DumpState(). + BufferInfo GetBufferInfo() const override; + + bool HandleMessage(pdx::Message& message) override; + void HandleImpulse(pdx::Message& message) override; + + private: + // Creates a detached buffer from existing IonBuffers. + BufferChannel(BufferHubService* service, int buffer_id, int channel_id, + IonBuffer buffer, IonBuffer metadata_buffer, + size_t user_metadata_size); + + // Allocates a new detached buffer. + BufferChannel(BufferHubService* service, int buffer_id, uint32_t width, + uint32_t height, uint32_t layer_count, uint32_t format, + uint64_t usage, size_t user_metadata_size); + + // Creates a detached buffer from an existing BufferNode. + BufferChannel(BufferHubService* service, int buffer_id, int channel_id, + std::shared_ptr<BufferNode> buffer_node, + uint64_t buffer_state_bit); + + pdx::Status<BufferDescription<pdx::BorrowedHandle>> OnImport( + pdx::Message& message); + pdx::Status<pdx::RemoteChannelHandle> OnDuplicate(pdx::Message& message); + pdx::Status<pdx::RemoteChannelHandle> OnPromote(pdx::Message& message); + + // The concrete implementation of the Buffer object. + std::shared_ptr<BufferNode> buffer_node_; + + // The state bit of this buffer. Must be one the lower 63 bits. + uint64_t buffer_state_bit_; +}; + +} // namespace dvr +} // namespace android + +#endif // ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_ diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp index e57c8edfe3..c0ee31b090 100644 --- a/services/vr/bufferhubd/buffer_hub.cpp +++ b/services/vr/bufferhubd/buffer_hub.cpp @@ -13,8 +13,8 @@ #include <pdx/default_transport/service_endpoint.h> #include <private/dvr/bufferhub_rpc.h> +#include "buffer_channel.h" #include "consumer_channel.h" -#include "detached_buffer_channel.h" #include "producer_channel.h" #include "producer_queue_channel.h" @@ -267,7 +267,7 @@ pdx::Status<void> BufferHubService::HandleMessage(Message& message) { return {}; case DetachedBufferRPC::Promote::Opcode: - // In addition to the message handler in the DetachedBufferChannel's + // In addition to the message handler in the BufferChannel's // HandleMessage method, we also need to invalid the channel. Note that // this has to be done after HandleMessage returns to make sure the IPC // request has went back to the client first. @@ -332,9 +332,9 @@ pdx::Status<void> BufferHubService::OnCreateDetachedBuffer( return ErrorStatus(EALREADY); } - std::unique_ptr<DetachedBufferChannel> channel = - DetachedBufferChannel::Create(this, buffer_id, width, height, layer_count, - format, usage, user_metadata_size); + std::unique_ptr<BufferChannel> channel = + BufferChannel::Create(this, buffer_id, width, height, layer_count, format, + usage, user_metadata_size); if (!channel) { ALOGE( "BufferHubService::OnCreateDetachedBuffer: Failed to allocate buffer, " diff --git a/services/vr/bufferhubd/buffer_node.cpp b/services/vr/bufferhubd/buffer_node.cpp new file mode 100644 index 0000000000..de22bbae5e --- /dev/null +++ b/services/vr/bufferhubd/buffer_node.cpp @@ -0,0 +1,53 @@ +#include "buffer_node.h" + +#include <private/dvr/buffer_hub_defs.h> + +namespace android { +namespace dvr { + +BufferNode::BufferNode(IonBuffer buffer, IonBuffer metadata_buffer, + size_t user_metadata_size) + : buffer_(std::move(buffer)), + metadata_buffer_(std::move(metadata_buffer)), + user_metadata_size_(user_metadata_size) {} + +// Allocates a new BufferNode. +BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, + uint32_t format, uint64_t usage, + size_t user_metadata_size) + : user_metadata_size_(user_metadata_size) { + // The size the of metadata buffer is used as the "width" parameter during + // allocation. Thus it cannot overflow uint32_t. + if (user_metadata_size_ >= (std::numeric_limits<uint32_t>::max() - + BufferHubDefs::kMetadataHeaderSize)) { + ALOGE( + "DetachedBufferChannel::DetachedBufferChannel: metadata size too big."); + return; + } + + if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) { + ALOGE( + "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate " + "buffer: %s", + strerror(-ret)); + return; + } + + // Buffer metadata has two parts: 1) a fixed sized metadata header; and 2) + // user requested metadata. + const size_t size = BufferHubDefs::kMetadataHeaderSize + user_metadata_size_; + if (int ret = metadata_buffer_.Alloc(size, + /*height=*/1, + /*layer_count=*/1, + BufferHubDefs::kMetadataFormat, + BufferHubDefs::kMetadataUsage)) { + ALOGE( + "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate " + "metadata: %s", + strerror(-ret)); + return; + } +} + +} // namespace dvr +} // namespace android diff --git a/services/vr/bufferhubd/buffer_node.h b/services/vr/bufferhubd/buffer_node.h new file mode 100644 index 0000000000..4bcf4e339d --- /dev/null +++ b/services/vr/bufferhubd/buffer_node.h @@ -0,0 +1,55 @@ +#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_ +#define ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_ + +#include <private/dvr/ion_buffer.h> + +namespace android { +namespace dvr { + +class BufferNode { + public: + // Creates a BufferNode from existing IonBuffers, i.e. creating from an + // existing ProducerChannel. + BufferNode(IonBuffer buffer, IonBuffer metadata_buffer, + size_t user_metadata_size); + + // Allocates a new BufferNode. + BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, + uint32_t format, uint64_t usage, size_t user_metadata_size); + + // Returns whether the object holds a valid graphic buffer. + bool IsValid() const { + return buffer_.IsValid() && metadata_buffer_.IsValid(); + } + + size_t user_metadata_size() const { return user_metadata_size_; } + uint64_t active_buffer_bit_mask() const { return active_buffer_bit_mask_; } + void set_buffer_state_bit(uint64_t buffer_state_bit) { + active_buffer_bit_mask_ |= buffer_state_bit; + } + + // Used to take out IonBuffers. + IonBuffer& buffer() { return buffer_; } + IonBuffer& metadata_buffer() { return metadata_buffer_; } + + // Used to access IonBuffers. + const IonBuffer& buffer() const { return buffer_; } + const IonBuffer& metadata_buffer() const { return metadata_buffer_; } + + private: + // Gralloc buffer handles. + IonBuffer buffer_; + IonBuffer metadata_buffer_; + + // Size of user requested metadata. + const size_t user_metadata_size_; + + // All active buffer bits. Valid bits are the lower 63 bits, while the + // highest bit is reserved for the exclusive writing and should not be set. + uint64_t active_buffer_bit_mask_ = 0ULL; +}; + +} // namespace dvr +} // namespace android + +#endif // ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_ diff --git a/services/vr/bufferhubd/detached_buffer_channel.cpp b/services/vr/bufferhubd/detached_buffer_channel.cpp deleted file mode 100644 index a5cf68dcfd..0000000000 --- a/services/vr/bufferhubd/detached_buffer_channel.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "detached_buffer_channel.h" -#include "producer_channel.h" - -using android::pdx::BorrowedHandle; -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::RemoteChannelHandle; -using android::pdx::Status; -using android::pdx::rpc::DispatchRemoteMethod; - -namespace android { -namespace dvr { - -DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service, - int buffer_id, int channel_id, - IonBuffer buffer, - IonBuffer metadata_buffer, - size_t user_metadata_size) - : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType), - buffer_(std::move(buffer)), - metadata_buffer_(std::move(metadata_buffer)), - user_metadata_size_(user_metadata_size) { -} - -DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service, - int buffer_id, uint32_t width, - uint32_t height, - uint32_t layer_count, - uint32_t format, uint64_t usage, - size_t user_metadata_size) - : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType), - user_metadata_size_(user_metadata_size) { - // The size the of metadata buffer is used as the "width" parameter during - // allocation. Thus it cannot overflow uint32_t. - if (user_metadata_size_ >= (std::numeric_limits<uint32_t>::max() - - BufferHubDefs::kMetadataHeaderSize)) { - ALOGE( - "DetachedBufferChannel::DetachedBufferChannel: metadata size too big."); - return; - } - - if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) { - ALOGE( - "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate " - "buffer: %s", - strerror(-ret)); - return; - } - - // Buffer metadata has two parts: 1) a fixed sized metadata header; and 2) - // user requested metadata. - const size_t size = BufferHubDefs::kMetadataHeaderSize + user_metadata_size_; - if (int ret = metadata_buffer_.Alloc(size, - /*height=*/1, - /*layer_count=*/1, - BufferHubDefs::kMetadataFormat, - BufferHubDefs::kMetadataUsage)) { - ALOGE( - "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate " - "metadata: %s", - strerror(-ret)); - return; - } -} - -DetachedBufferChannel::~DetachedBufferChannel() { - ALOGD_IF(TRACE, - "DetachedBufferChannel::~DetachedBufferChannel: channel_id=%d " - "buffer_id=%d.", - channel_id(), buffer_id()); - Hangup(); -} - -BufferHubChannel::BufferInfo DetachedBufferChannel::GetBufferInfo() const { - return BufferInfo(buffer_id(), /*consumer_count=*/0, buffer_.width(), - buffer_.height(), buffer_.layer_count(), buffer_.format(), - buffer_.usage(), /*pending_count=*/0, /*state=*/0, - /*signaled_mask=*/0, /*index=*/0); -} - -void DetachedBufferChannel::HandleImpulse(Message& /*message*/) { - ATRACE_NAME("DetachedBufferChannel::HandleImpulse"); -} - -bool DetachedBufferChannel::HandleMessage(Message& message) { - ATRACE_NAME("DetachedBufferChannel::HandleMessage"); - switch (message.GetOp()) { - case DetachedBufferRPC::Import::Opcode: - DispatchRemoteMethod<DetachedBufferRPC::Import>( - *this, &DetachedBufferChannel::OnImport, message); - return true; - - case DetachedBufferRPC::Promote::Opcode: - DispatchRemoteMethod<DetachedBufferRPC::Promote>( - *this, &DetachedBufferChannel::OnPromote, message); - return true; - - default: - return false; - } -} - -Status<BufferDescription<BorrowedHandle>> DetachedBufferChannel::OnImport( - Message& /*message*/) { - ATRACE_NAME("DetachedBufferChannel::OnGetBuffer"); - ALOGD_IF(TRACE, "DetachedBufferChannel::OnGetBuffer: buffer=%d.", - buffer_id()); - - return BufferDescription<BorrowedHandle>{buffer_, - metadata_buffer_, - buffer_id(), - /*buffer_state_bit=*/0, - BorrowedHandle{}, - BorrowedHandle{}}; -} - -Status<RemoteChannelHandle> DetachedBufferChannel::OnPromote( - Message& message) { - ATRACE_NAME("DetachedBufferChannel::OnPromote"); - ALOGD_IF(TRACE, "DetachedBufferChannel::OnPromote: buffer_id=%d", - buffer_id()); - - // Note that the new ProducerChannel will have different channel_id, but - // inherits the buffer_id from the DetachedBuffer. - int channel_id; - auto status = message.PushChannel(0, nullptr, &channel_id); - if (!status) { - ALOGE( - "DetachedBufferChannel::OnPromote: Failed to push ProducerChannel: %s.", - status.GetErrorMessage().c_str()); - return ErrorStatus(ENOMEM); - } - - std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create( - service(), buffer_id(), channel_id, std::move(buffer_), - std::move(metadata_buffer_), user_metadata_size_); - if (!channel) { - ALOGE( - "DetachedBufferChannel::OnPromote: Failed to create ProducerChannel " - "from a DetachedBufferChannel, buffer_id=%d.", - buffer_id()); - } - - const auto channel_status = - service()->SetChannel(channel_id, std::move(channel)); - if (!channel_status) { - // Technically, this should never fail, as we just pushed the channel. Note - // that LOG_FATAL will be stripped out in non-debug build. - LOG_FATAL( - "DetachedBufferChannel::OnPromote: Failed to set new producer buffer " - "channel: %s.", - channel_status.GetErrorMessage().c_str()); - } - - return status; -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/bufferhubd/detached_buffer_channel.h b/services/vr/bufferhubd/detached_buffer_channel.h deleted file mode 100644 index 8b6dab8538..0000000000 --- a/services/vr/bufferhubd/detached_buffer_channel.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef ANDROID_DVR_BUFFERHUBD_DETACHED_BUFFER_CHANNEL_H_ -#define ANDROID_DVR_BUFFERHUBD_DETACHED_BUFFER_CHANNEL_H_ - -#include "buffer_hub.h" - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> - -namespace android { -namespace dvr { - -class DetachedBufferChannel : public BufferHubChannel { - public: - ~DetachedBufferChannel() override; - - template <typename... Args> - static std::unique_ptr<DetachedBufferChannel> Create(Args&&... args) { - auto buffer = std::unique_ptr<DetachedBufferChannel>( - new DetachedBufferChannel(std::forward<Args>(args)...)); - return buffer->IsValid() ? std::move(buffer) : nullptr; - } - - // Returns whether the object holds a valid graphic buffer. - bool IsValid() const { - return buffer_.IsValid() && metadata_buffer_.IsValid(); - } - - size_t user_metadata_size() const { return user_metadata_size_; } - - // Captures buffer info for use by BufferHubService::DumpState(). - BufferInfo GetBufferInfo() const override; - - bool HandleMessage(pdx::Message& message) override; - void HandleImpulse(pdx::Message& message) override; - - private: - // Creates a detached buffer from existing IonBuffers. - DetachedBufferChannel(BufferHubService* service, int buffer_id, - int channel_id, IonBuffer buffer, - IonBuffer metadata_buffer, size_t user_metadata_size); - - // Allocates a new detached buffer. - DetachedBufferChannel(BufferHubService* service, int buffer_id, - uint32_t width, uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage, - size_t user_metadata_size); - - pdx::Status<BufferDescription<pdx::BorrowedHandle>> OnImport( - pdx::Message& message); - pdx::Status<pdx::RemoteChannelHandle> OnPromote(pdx::Message& message); - - // Gralloc buffer handles. - IonBuffer buffer_; - IonBuffer metadata_buffer_; - - // Size of user requested metadata. - const size_t user_metadata_size_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFERHUBD_DETACHED_BUFFER_CHANNEL_H_ diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp index b6977aaa63..19d48f2b68 100644 --- a/services/vr/bufferhubd/producer_channel.cpp +++ b/services/vr/bufferhubd/producer_channel.cpp @@ -12,8 +12,8 @@ #include <thread> #include <private/dvr/bufferhub_rpc.h> +#include "buffer_channel.h" #include "consumer_channel.h" -#include "detached_buffer_channel.h" using android::pdx::BorrowedHandle; using android::pdx::ErrorStatus; @@ -27,14 +27,6 @@ using android::pdx::rpc::WrapBuffer; namespace android { namespace dvr { -namespace { - -static inline uint64_t FindNextClearedBit(uint64_t bits) { - return ~bits - (~bits & (~bits - 1)); -} - -} // namespace - ProducerChannel::ProducerChannel(BufferHubService* service, int buffer_id, int channel_id, IonBuffer buffer, IonBuffer metadata_buffer, @@ -236,9 +228,13 @@ bool ProducerChannel::HandleMessage(Message& message) { BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer( uint64_t buffer_state_bit) { - return { - buffer_, metadata_buffer_, buffer_id(), - buffer_state_bit, acquire_fence_fd_.Borrow(), release_fence_fd_.Borrow()}; + return {buffer_, + metadata_buffer_, + buffer_id(), + channel_id(), + buffer_state_bit, + acquire_fence_fd_.Borrow(), + release_fence_fd_.Borrow()}; } Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer( @@ -266,7 +262,7 @@ Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) { // Try find the next consumer state bit which has not been claimed by any // consumer yet. - uint64_t consumer_state_bit = FindNextClearedBit( + uint64_t consumer_state_bit = BufferHubDefs::FindNextClearedBit( active_consumer_bit_mask_ | orphaned_consumer_bit_mask_ | BufferHubDefs::kProducerStateBit); if (consumer_state_bit == 0ULL) { @@ -415,10 +411,9 @@ Status<RemoteChannelHandle> ProducerChannel::OnProducerDetach( return ErrorStatus(-ret); }; - std::unique_ptr<DetachedBufferChannel> channel = - DetachedBufferChannel::Create( - service(), buffer_id(), channel_id, std::move(buffer_), - std::move(metadata_buffer_), user_metadata_size_); + std::unique_ptr<BufferChannel> channel = BufferChannel::Create( + service(), buffer_id(), channel_id, std::move(buffer_), + std::move(metadata_buffer_), user_metadata_size_); if (!channel) { ALOGE("ProducerChannel::OnProducerDetach: Invalid buffer."); return ErrorStatus(EINVAL); diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h index 67fdf150a0..10a4ce7c71 100644 --- a/services/vr/bufferhubd/producer_channel.h +++ b/services/vr/bufferhubd/producer_channel.h @@ -43,6 +43,8 @@ class ProducerChannel : public BufferHubChannel { ~ProducerChannel() override; + uint64_t buffer_state() const { return buffer_state_->load(); } + bool HandleMessage(Message& message) override; void HandleImpulse(Message& message) override; diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp index c0c48c2dc1..88f5508307 100644 --- a/services/vr/bufferhubd/producer_queue_channel.cpp +++ b/services/vr/bufferhubd/producer_queue_channel.cpp @@ -76,6 +76,11 @@ bool ProducerQueueChannel::HandleMessage(Message& message) { message); return true; + case BufferHubRPC::ProducerQueueInsertBuffer::Opcode: + DispatchRemoteMethod<BufferHubRPC::ProducerQueueInsertBuffer>( + *this, &ProducerQueueChannel::OnProducerQueueInsertBuffer, message); + return true; + case BufferHubRPC::ProducerQueueRemoveBuffer::Opcode: DispatchRemoteMethod<BufferHubRPC::ProducerQueueRemoveBuffer>( *this, &ProducerQueueChannel::OnProducerQueueRemoveBuffer, message); @@ -278,6 +283,81 @@ ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width, return {{std::move(buffer_handle), slot}}; } +Status<size_t> ProducerQueueChannel::OnProducerQueueInsertBuffer( + pdx::Message& message, int buffer_cid) { + ATRACE_NAME("ProducerQueueChannel::InsertBuffer"); + ALOGD_IF(TRACE, + "ProducerQueueChannel::InsertBuffer: channel_id=%d, buffer_cid=%d", + channel_id(), buffer_cid); + + if (capacity_ >= BufferHubRPC::kMaxQueueCapacity) { + ALOGE("ProducerQueueChannel::InsertBuffer: reaches kMaxQueueCapacity."); + return ErrorStatus(E2BIG); + } + auto producer_channel = std::static_pointer_cast<ProducerChannel>( + service()->GetChannel(buffer_cid)); + if (producer_channel == nullptr || + producer_channel->channel_type() != BufferHubChannel::kProducerType) { + // Rejects the request if the requested buffer channel is invalid and/or + // it's not a ProducerChannel. + ALOGE( + "ProducerQueueChannel::InsertBuffer: Invalid buffer_cid=%d, " + "producer_buffer=0x%p, channel_type=%d.", + buffer_cid, producer_channel.get(), + producer_channel == nullptr ? -1 : producer_channel->channel_type()); + return ErrorStatus(EINVAL); + } + if (producer_channel->GetActiveProcessId() != message.GetProcessId()) { + // Rejects the request if the requested buffer channel is not currently + // connected to the caller this is IPC request. This effectively prevents + // fake buffer_cid from being injected. + ALOGE( + "ProducerQueueChannel::InsertBuffer: Requested buffer channel " + "(buffer_cid=%d) is not connected to the calling process (pid=%d). " + "It's connected to a different process (pid=%d).", + buffer_cid, message.GetProcessId(), + producer_channel->GetActiveProcessId()); + return ErrorStatus(EINVAL); + } + uint64_t buffer_state = producer_channel->buffer_state(); + if (!BufferHubDefs::IsBufferGained(buffer_state)) { + // Rejects the request if the requested buffer is not in Gained state. + ALOGE( + "ProducerQueueChannel::InsertBuffer: The buffer (cid=%d, " + "state=0x%" PRIx64 ") is not in gained state.", + buffer_cid, buffer_state); + return ErrorStatus(EINVAL); + } + + // Register the to-be-inserted buffer's channel_id into the first empty + // buffer slot. + size_t slot = 0; + for (; slot < BufferHubRPC::kMaxQueueCapacity; slot++) { + if (buffers_[slot].expired()) + break; + } + if (slot == BufferHubRPC::kMaxQueueCapacity) { + ALOGE( + "ProducerQueueChannel::AllocateBuffer: Cannot find empty slot for new " + "buffer allocation."); + return ErrorStatus(E2BIG); + } + + buffers_[slot] = producer_channel; + capacity_++; + + // Notify each consumer channel about the new buffer. + for (auto* consumer_channel : consumer_channels_) { + ALOGD( + "ProducerQueueChannel::AllocateBuffer: Notified consumer with new " + "buffer, buffer_cid=%d", + buffer_cid); + consumer_channel->RegisterNewBuffer(producer_channel, slot); + } + + return {slot}; +} + Status<void> ProducerQueueChannel::OnProducerQueueRemoveBuffer( Message& /*message*/, size_t slot) { if (buffers_[slot].expired()) { diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h index e825f47774..e4fa24372a 100644 --- a/services/vr/bufferhubd/producer_queue_channel.h +++ b/services/vr/bufferhubd/producer_queue_channel.h @@ -38,8 +38,12 @@ class ProducerQueueChannel : public BufferHubChannel { uint32_t format, uint64_t usage, size_t buffer_count); - // Detach a BufferHubProducer indicated by |slot|. Note that the buffer must - // be in Gain'ed state for the producer queue to detach. + // Inserts a BufferProducer into the queue. Note that the buffer must be in + // Gain'ed state for the operation to succeed. + pdx::Status<size_t> OnProducerQueueInsertBuffer(pdx::Message& message, int buffer_cid); + + // Removes a BufferProducer indicated by |slot|. Note that the buffer must be + // in Gain'ed state for the operation to succeed. pdx::Status<void> OnProducerQueueRemoveBuffer(pdx::Message& message, size_t slot); diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp index 90edf69697..003775b7dc 100644 --- a/services/vr/hardware_composer/Android.bp +++ b/services/vr/hardware_composer/Android.bp @@ -39,6 +39,10 @@ cc_library_shared { "android.hardware.graphics.composer@2.1-hal", ], + export_static_lib_headers: [ + "libdisplay", + ], + export_shared_lib_headers: [ "android.frameworks.vr.composer@1.0", "android.hardware.graphics.composer@2.1", @@ -48,6 +52,7 @@ cc_library_shared { cflags: [ "-DLOG_TAG=\"vr_hwc\"", + "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", "-Wall", "-Werror", // mVrClient unused in vr_composer_client.cpp @@ -115,6 +120,7 @@ cc_library_static { cc_binary { name: "vr_hwc", + vintf_fragments: ["manifest_vr_hwc.xml"], srcs: [ "vr_hardware_composer_service.cpp" ], diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp index 4af47d2a35..d1ed12bb1d 100644 --- a/services/vr/hardware_composer/impl/vr_hwc.cpp +++ b/services/vr/hardware_composer/impl/vr_hwc.cpp @@ -16,9 +16,11 @@ #include "impl/vr_hwc.h" #include "android-base/stringprintf.h" +#include <binder/IServiceManager.h> #include <cutils/properties.h> #include <private/dvr/display_client.h> #include <ui/Fence.h> +#include <utils/Trace.h> #include <mutex> @@ -244,29 +246,38 @@ void HwcDisplay::dumpDebugInfo(std::string* result) const { //////////////////////////////////////////////////////////////////////////////// // VrHwcClient -VrHwc::VrHwc() {} +VrHwc::VrHwc() { + vsync_callback_ = new VsyncCallback; +} -VrHwc::~VrHwc() {} +VrHwc::~VrHwc() { + vsync_callback_->SetEventCallback(nullptr); +} bool VrHwc::hasCapability(hwc2_capability_t /* capability */) { return false; } void VrHwc::registerEventCallback(EventCallback* callback) { - { - std::lock_guard<std::mutex> guard(mutex_); - event_callback_ = callback; - int32_t width, height; - GetPrimaryDisplaySize(&width, &height); - // Create the primary display late to avoid initialization issues between - // VR HWC and SurfaceFlinger. - displays_[kDefaultDisplayId].reset(new HwcDisplay(width, height)); - } + std::unique_lock<std::mutex> lock(mutex_); + event_callback_ = callback; + int32_t width, height; + GetPrimaryDisplaySize(&width, &height); + // Create the primary display late to avoid initialization issues between + // VR HWC and SurfaceFlinger. + displays_[kDefaultDisplayId].reset(new HwcDisplay(width, height)); + + // Surface flinger will make calls back into vr_hwc when it receives the + // onHotplug() call, so it's important to release mutex_ here. + lock.unlock(); event_callback_->onHotplug(kDefaultDisplayId, IComposerCallback::Connection::CONNECTED); + lock.lock(); + UpdateVsyncCallbackEnabledLocked(); } void VrHwc::unregisterEventCallback() { std::lock_guard<std::mutex> guard(mutex_); event_callback_ = nullptr; + UpdateVsyncCallbackEnabledLocked(); } uint32_t VrHwc::getMaxVirtualDisplayCount() { return 1; } @@ -475,8 +486,45 @@ Error VrHwc::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) { if (!display_ptr) return Error::BAD_DISPLAY; - display_ptr->set_vsync_enabled(enabled); - return Error::NONE; + if (enabled != IComposerClient::Vsync::ENABLE && + enabled != IComposerClient::Vsync::DISABLE) { + return Error::BAD_PARAMETER; + } + + Error set_vsync_result = Error::NONE; + if (display == kDefaultDisplayId) { + sp<IVsyncService> vsync_service = interface_cast<IVsyncService>( + defaultServiceManager()->getService( + String16(IVsyncService::GetServiceName()))); + if (vsync_service == nullptr) { + ALOGE("Failed to get vsync service"); + return Error::NO_RESOURCES; + } + + if (enabled == IComposerClient::Vsync::ENABLE) { + ALOGI("Enable vsync"); + display_ptr->set_vsync_enabled(true); + status_t result = vsync_service->registerCallback(vsync_callback_); + if (result != OK) { + ALOGE("%s service registerCallback() failed: %s (%d)", + IVsyncService::GetServiceName(), strerror(-result), result); + set_vsync_result = Error::NO_RESOURCES; + } + } else if (enabled == IComposerClient::Vsync::DISABLE) { + ALOGI("Disable vsync"); + display_ptr->set_vsync_enabled(false); + status_t result = vsync_service->unregisterCallback(vsync_callback_); + if (result != OK) { + ALOGE("%s service unregisterCallback() failed: %s (%d)", + IVsyncService::GetServiceName(), strerror(-result), result); + set_vsync_result = Error::NO_RESOURCES; + } + } + + UpdateVsyncCallbackEnabledLocked(); + } + + return set_vsync_result; } Error VrHwc::setColorTransform(Display display, const float* matrix, @@ -559,7 +607,8 @@ Error VrHwc::presentDisplay(Display display, int32_t* outPresentFence, frame.display_height = display_ptr->height(); frame.active_config = display_ptr->active_config(); frame.power_mode = display_ptr->power_mode(); - frame.vsync_enabled = display_ptr->vsync_enabled(); + frame.vsync_enabled = display_ptr->vsync_enabled() ? + IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE; frame.color_transform_hint = display_ptr->color_transform_hint(); frame.color_mode = display_ptr->color_mode(); memcpy(frame.color_transform, display_ptr->color_transform(), @@ -911,6 +960,15 @@ HwcDisplay* VrHwc::FindDisplay(Display display) { return iter == displays_.end() ? nullptr : iter->second.get(); } +void VrHwc::UpdateVsyncCallbackEnabledLocked() { + auto primary_display = FindDisplay(kDefaultDisplayId); + LOG_ALWAYS_FATAL_IF(event_callback_ != nullptr && primary_display == nullptr, + "Should have created the primary display by now"); + bool send_vsync = + event_callback_ != nullptr && primary_display->vsync_enabled(); + vsync_callback_->SetEventCallback(send_vsync ? event_callback_ : nullptr); +} + void HwcLayer::dumpDebugInfo(std::string* result) const { if (!result) { return; @@ -928,5 +986,18 @@ void HwcLayer::dumpDebugInfo(std::string* result) const { buffer_metadata.layerCount, buffer_metadata.format); } +status_t VrHwc::VsyncCallback::onVsync(int64_t vsync_timestamp) { + ATRACE_NAME("vr_hwc onVsync"); + std::lock_guard<std::mutex> guard(mutex_); + if (callback_ != nullptr) + callback_->onVsync(kDefaultDisplayId, vsync_timestamp); + return NO_ERROR; +} + +void VrHwc::VsyncCallback::SetEventCallback(EventCallback* callback) { + std::lock_guard<std::mutex> guard(mutex_); + callback_ = callback; +} + } // namespace dvr } // namespace android diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h index 85e587abbe..f9872b2290 100644 --- a/services/vr/hardware_composer/impl/vr_hwc.h +++ b/services/vr/hardware_composer/impl/vr_hwc.h @@ -20,6 +20,7 @@ #include <android/frameworks/vr/composer/1.0/IVrComposerClient.h> #include <android/hardware/graphics/composer/2.1/IComposer.h> #include <composer-hal/2.1/ComposerHal.h> +#include <private/dvr/vsync_service.h> #include <ui/Fence.h> #include <ui/GraphicBuffer.h> #include <utils/StrongPointer.h> @@ -156,10 +157,8 @@ class HwcDisplay { IComposerClient::PowerMode power_mode() const { return power_mode_; } void set_power_mode(IComposerClient::PowerMode mode) { power_mode_ = mode; } - IComposerClient::Vsync vsync_enabled() const { return vsync_enabled_; } - void set_vsync_enabled(IComposerClient::Vsync vsync) { - vsync_enabled_ = vsync; - } + bool vsync_enabled() const { return vsync_enabled_; } + void set_vsync_enabled(bool vsync) {vsync_enabled_ = vsync;} const float* color_transform() const { return color_transform_; } int32_t color_transform_hint() const { return color_transform_hint_; } @@ -187,7 +186,7 @@ class HwcDisplay { Config active_config_; ColorMode color_mode_; IComposerClient::PowerMode power_mode_; - IComposerClient::Vsync vsync_enabled_; + bool vsync_enabled_ = false; float color_transform_[16]; int32_t color_transform_hint_; @@ -299,8 +298,23 @@ class VrHwc : public IComposer, public ComposerHal, public ComposerView { void UnregisterObserver(Observer* observer) override; private: + class VsyncCallback : public BnVsyncCallback { + public: + status_t onVsync(int64_t vsync_timestamp) override; + void SetEventCallback(EventCallback* callback); + private: + std::mutex mutex_; + EventCallback* callback_; + }; + HwcDisplay* FindDisplay(Display display); + // Re-evaluate whether or not we should start making onVsync() callbacks to + // the client. We need enableCallback(true) to have been called, and + // setVsyncEnabled() to have been called for the primary display. The caller + // must have mutex_ locked already. + void UpdateVsyncCallbackEnabledLocked(); + wp<VrComposerClient> client_; // Guard access to internal state from binder threads. @@ -312,6 +326,8 @@ class VrHwc : public IComposer, public ComposerHal, public ComposerView { EventCallback* event_callback_ = nullptr; Observer* observer_ = nullptr; + sp<VsyncCallback> vsync_callback_; + VrHwc(const VrHwc&) = delete; void operator=(const VrHwc&) = delete; }; diff --git a/services/vr/hardware_composer/manifest_vr_hwc.xml b/services/vr/hardware_composer/manifest_vr_hwc.xml new file mode 100644 index 0000000000..1068cac33a --- /dev/null +++ b/services/vr/hardware_composer/manifest_vr_hwc.xml @@ -0,0 +1,11 @@ +<manifest version="1.0" type="framework"> + <hal> + <name>android.hardware.graphics.composer</name> + <transport>hwbinder</transport> + <version>2.1</version> + <interface> + <name>IComposer</name> + <instance>vr</instance> + </interface> + </hal> +</manifest> diff --git a/services/vr/performanced/performance_service.cpp b/services/vr/performanced/performance_service.cpp index 4c26671b11..d304bac662 100644 --- a/services/vr/performanced/performance_service.cpp +++ b/services/vr/performanced/performance_service.cpp @@ -124,9 +124,6 @@ PerformanceService::PerformanceService() // TODO(eieio): Replace this witha device-specific config file. This is just a // hack for now to put some form of permission logic in place while a longer // term solution is developed. - using AllowRootSystem = - CheckAnd<SameProcess, - CheckOr<UserId<AID_ROOT, AID_SYSTEM>, GroupId<AID_SYSTEM>>>; using AllowRootSystemGraphics = CheckAnd<SameProcess, CheckOr<UserId<AID_ROOT, AID_SYSTEM, AID_GRAPHICS>, GroupId<AID_SYSTEM, AID_GRAPHICS>>>; @@ -170,17 +167,17 @@ PerformanceService::PerformanceService() {.timer_slack = kTimerSlackForegroundNs, .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, .priority = fifo_low, - .permission_check = AllowRootSystem::Check}}, + .permission_check = AllowRootSystemTrusted::Check}}, {"sensors:low", {.timer_slack = kTimerSlackForegroundNs, .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, .priority = fifo_low, - .permission_check = AllowRootSystem::Check}}, + .permission_check = AllowRootSystemTrusted::Check}}, {"sensors:high", {.timer_slack = kTimerSlackForegroundNs, .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, .priority = fifo_low + 1, - .permission_check = AllowRootSystem::Check}}, + .permission_check = AllowRootSystemTrusted::Check}}, {"vr:system:arp", {.timer_slack = kTimerSlackForegroundNs, .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp index cbba5f48fb..7eaf7b2d73 100644 --- a/vulkan/libvulkan/Android.bp +++ b/vulkan/libvulkan/Android.bp @@ -81,6 +81,8 @@ cc_library_shared { "libutils", "libcutils", "libz", + "libnativebridge", + "libnativeloader", "libnativewindow", "android.hardware.graphics.common@1.0", ], diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 56bc35ec70..4c2d223127 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -984,7 +984,7 @@ VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, uint32_t icd_api_version; PFN_vkEnumerateInstanceVersion pfn_enumerate_instance_version = reinterpret_cast<PFN_vkEnumerateInstanceVersion>( - Hal::Device().GetInstanceProcAddr(NULL, + Hal::Device().GetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion")); if (!pfn_enumerate_instance_version) { icd_api_version = VK_API_VERSION_1_0; diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp index 3a59208446..96c556393c 100644 --- a/vulkan/libvulkan/layers_extensions.cpp +++ b/vulkan/libvulkan/layers_extensions.cpp @@ -31,6 +31,8 @@ #include <cutils/properties.h> #include <graphicsenv/GraphicsEnv.h> #include <log/log.h> +#include <nativebridge/native_bridge.h> +#include <nativeloader/native_loader.h> #include <ziparchive/zip_archive.h> // TODO(jessehall): The whole way we deal with extensions is pretty hokey, and @@ -73,12 +75,14 @@ class LayerLibrary { : path_(path), filename_(filename), dlhandle_(nullptr), + native_bridge_(false), refcount_(0) {} LayerLibrary(LayerLibrary&& other) : path_(std::move(other.path_)), filename_(std::move(other.filename_)), dlhandle_(other.dlhandle_), + native_bridge_(other.native_bridge_), refcount_(other.refcount_) { other.dlhandle_ = nullptr; other.refcount_ = 0; @@ -101,6 +105,17 @@ class LayerLibrary { const std::string GetFilename() { return filename_; } private: + // TODO(b/79940628): remove that adapter when we could use NativeBridgeGetTrampoline + // for native libraries. + template<typename Func = void*> + Func GetTrampoline(const char* name) const { + if (native_bridge_) { + return reinterpret_cast<Func>(android::NativeBridgeGetTrampoline( + dlhandle_, name, nullptr, 0)); + } + return reinterpret_cast<Func>(dlsym(dlhandle_, name)); + } + const std::string path_; // Track the filename alone so we can detect duplicates @@ -108,6 +123,7 @@ class LayerLibrary { std::mutex mutex_; void* dlhandle_; + bool native_bridge_; size_t refcount_; }; @@ -123,19 +139,23 @@ bool LayerLibrary::Open() { auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace(); if (app_namespace && !android::base::StartsWith(path_, kSystemLayerLibraryDir)) { - android_dlextinfo dlextinfo = {}; - dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; - dlextinfo.library_namespace = app_namespace; - dlhandle_ = android_dlopen_ext(path_.c_str(), RTLD_NOW | RTLD_LOCAL, - &dlextinfo); + std::string error_msg; + dlhandle_ = OpenNativeLibrary( + app_namespace, path_.c_str(), &native_bridge_, &error_msg); + if (!dlhandle_) { + ALOGE("failed to load layer library '%s': %s", path_.c_str(), + error_msg.c_str()); + refcount_ = 0; + return false; + } } else { - dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL); - } - if (!dlhandle_) { - ALOGE("failed to load layer library '%s': %s", path_.c_str(), - dlerror()); - refcount_ = 0; - return false; + dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL); + if (!dlhandle_) { + ALOGE("failed to load layer library '%s': %s", path_.c_str(), + dlerror()); + refcount_ = 0; + return false; + } } } return true; @@ -153,11 +173,11 @@ void LayerLibrary::Close() { bool LayerLibrary::EnumerateLayers(size_t library_idx, std::vector<Layer>& instance_layers) const { PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers = - reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>( - dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties")); + GetTrampoline<PFN_vkEnumerateInstanceLayerProperties>( + "vkEnumerateInstanceLayerProperties"); PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions = - reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>( - dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties")); + GetTrampoline<PFN_vkEnumerateInstanceExtensionProperties>( + "vkEnumerateInstanceExtensionProperties"); if (!enumerate_instance_layers || !enumerate_instance_extensions) { ALOGE("layer library '%s' missing some instance enumeration functions", path_.c_str()); @@ -166,11 +186,11 @@ bool LayerLibrary::EnumerateLayers(size_t library_idx, // device functions are optional PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers = - reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>( - dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties")); + GetTrampoline<PFN_vkEnumerateDeviceLayerProperties>( + "vkEnumerateDeviceLayerProperties"); PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions = - reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>( - dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties")); + GetTrampoline<PFN_vkEnumerateDeviceExtensionProperties>( + "vkEnumerateDeviceExtensionProperties"); // get layer counts uint32_t num_instance_layers = 0; @@ -301,10 +321,10 @@ void* LayerLibrary::GetGPA(const Layer& layer, char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1)); strcpy(name, layer.properties.layerName); strcpy(name + layer_name_len, gpa_name); - if (!(gpa = dlsym(dlhandle_, name))) { + if (!(gpa = GetTrampoline(name))) { strcpy(name, "vk"); strcpy(name + 2, gpa_name); - gpa = dlsym(dlhandle_, name); + gpa = GetTrampoline(name); } return gpa; } diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index 3db8a3962e..915de45961 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -335,15 +335,15 @@ uint32_t get_num_ready_timings(Swapchain& swapchain) { swapchain.surface.window.get(), ti.native_frame_id_, &desired_present_time, &render_complete_time, &composition_latch_time, - NULL, //&first_composition_start_time, - NULL, //&last_composition_start_time, - NULL, //&composition_finish_time, + nullptr, //&first_composition_start_time, + nullptr, //&last_composition_start_time, + nullptr, //&composition_finish_time, // TODO(ianelliott): Maybe ask if this one is // supported, at startup time (since it may not be // supported): &actual_present_time, - NULL, //&dequeue_ready_time, - NULL /*&reads_done_time*/); + nullptr, //&dequeue_ready_time, + nullptr /*&reads_done_time*/); if (ret != android::NO_ERROR) { continue; @@ -575,15 +575,10 @@ VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/, break; } - // USAGE_CPU_READ_MASK 0xFUL - // USAGE_CPU_WRITE_MASK (0xFUL << 4) - // The currently used bits are as below: - // USAGE_CPU_READ_RARELY = 2UL - // USAGE_CPU_READ_OFTEN = 3UL - // USAGE_CPU_WRITE_RARELY = (2UL << 4) - // USAGE_CPU_WRITE_OFTEN = (3UL << 4) - *supported = static_cast<VkBool32>(format_supported || - (surface->consumer_usage & 0xFFUL) == 0); + *supported = static_cast<VkBool32>( + format_supported || (surface->consumer_usage & + (AHARDWAREBUFFER_USAGE_CPU_READ_MASK | + AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0); return VK_SUCCESS; } diff --git a/vulkan/vkjson/Android.bp b/vulkan/vkjson/Android.bp index e387165442..7fbe3153bb 100644 --- a/vulkan/vkjson/Android.bp +++ b/vulkan/vkjson/Android.bp @@ -9,7 +9,6 @@ cc_library_static { "-Werror", ], cppflags: [ - "-std=c++11", "-Wno-sign-compare", ], export_include_dirs: [ @@ -35,7 +34,6 @@ cc_library_static { "-Werror", ], cppflags: [ - "-std=c++11", "-Wno-sign-compare", ], export_include_dirs: [ |