Merge "Track focus changes on external displays (1/4)"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 2d780f5..cd0fbd4 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,3 +1,15 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+# Only turn on clang-format check for the following subfolders.
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+ libs/gui/
+ libs/ui/
+ libs/vr/
+ services/surfaceflinger/
+ services/vr/
+
[Hook Scripts]
owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
installd_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/installd/"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index d294d1e..17bb7c3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1376,6 +1376,54 @@
printf("========================================================\n");
}
+/* Dumps state for the default case. Returns true if everything went fine. */
+static bool DumpstateDefault() {
+ // Dumps systrace right away, otherwise it will be filled with unnecessary events.
+ // First try to dump anrd trace if the daemon is running. Otherwise, dump
+ // the raw trace.
+ if (!dump_anrd_trace()) {
+ dump_systrace();
+ }
+
+ // Invoking the following dumpsys calls before dump_traces() to try and
+ // keep the system stats as close to its initial state as possible.
+ RunDumpsysCritical();
+
+ /* collect stack traces from Dalvik and native processes (needs root) */
+ dump_traces_path = dump_traces();
+
+ /* Run some operations that require root. */
+ ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
+ ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
+
+ ds.AddDir(RECOVERY_DIR, true);
+ ds.AddDir(RECOVERY_DATA_DIR, true);
+ ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
+ ds.AddDir(LOGPERSIST_DATA_DIR, false);
+ if (!PropertiesHelper::IsUserBuild()) {
+ ds.AddDir(PROFILE_DATA_DIR_CUR, true);
+ ds.AddDir(PROFILE_DATA_DIR_REF, true);
+ }
+ add_mountinfo();
+ DumpIpTablesAsRoot();
+
+ // Capture any IPSec policies in play. No keys are exposed here.
+ RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
+
+ // Run ss as root so we can see socket marks.
+ RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
+
+ // Run iotop as root to show top 100 IO threads
+ RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
+
+ if (!DropRootUser()) {
+ return false;
+ }
+
+ dumpstate();
+ return true;
+}
+
// This method collects common dumpsys for telephony and wifi
static void DumpstateRadioCommon() {
DumpIpTablesAsRoot();
@@ -1716,6 +1764,178 @@
// clang-format on
}
+/*
+ * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
+ * if we are writing zip files and adds the version file.
+ */
+static void PrepareToWriteToFile() {
+ const Dumpstate::DumpOptions& options = ds.options_;
+ ds.bugreport_dir_ = dirname(options.use_outfile.c_str());
+ std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
+ std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
+ ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(options.use_outfile.c_str()),
+ device_name.c_str(), build_id.c_str());
+ if (options.do_add_date) {
+ char date[80];
+ strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
+ ds.name_ = date;
+ } else {
+ ds.name_ = "undated";
+ }
+
+ if (options.telephony_only) {
+ ds.base_name_ += "-telephony";
+ } else if (options.wifi_only) {
+ ds.base_name_ += "-wifi";
+ }
+
+ if (options.do_fb) {
+ ds.screenshot_path_ = ds.GetPath(".png");
+ }
+ ds.tmp_path_ = ds.GetPath(".tmp");
+ ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
+
+ MYLOGD(
+ "Bugreport dir: %s\n"
+ "Base name: %s\n"
+ "Suffix: %s\n"
+ "Log path: %s\n"
+ "Temporary path: %s\n"
+ "Screenshot path: %s\n",
+ ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
+ ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
+
+ if (options.do_zip_file) {
+ ds.path_ = ds.GetPath(".zip");
+ MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
+ create_parent_dirs(ds.path_.c_str());
+ ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
+ if (ds.zip_file == nullptr) {
+ MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
+ } else {
+ ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
+ }
+ ds.AddTextZipEntry("version.txt", ds.version_);
+ }
+}
+
+/*
+ * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
+ * printing zipped file status, etc.
+ */
+static void FinalizeFile() {
+ const Dumpstate::DumpOptions& options = ds.options_;
+ /* check if user changed the suffix using system properties */
+ std::string name =
+ android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
+ bool change_suffix = false;
+ if (!name.empty()) {
+ /* must whitelist which characters are allowed, otherwise it could cross directories */
+ std::regex valid_regex("^[-_a-zA-Z0-9]+$");
+ if (std::regex_match(name.c_str(), valid_regex)) {
+ change_suffix = true;
+ } else {
+ MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
+ }
+ }
+ if (change_suffix) {
+ MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
+ ds.name_ = name;
+ if (!ds.screenshot_path_.empty()) {
+ std::string new_screenshot_path = ds.GetPath(".png");
+ if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
+ MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
+ new_screenshot_path.c_str(), strerror(errno));
+ } else {
+ ds.screenshot_path_ = new_screenshot_path;
+ }
+ }
+ }
+
+ bool do_text_file = true;
+ if (options.do_zip_file) {
+ if (!ds.FinishZipFile()) {
+ MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
+ do_text_file = true;
+ } else {
+ do_text_file = false;
+ // Since zip file is already created, it needs to be renamed.
+ std::string new_path = ds.GetPath(".zip");
+ if (ds.path_ != new_path) {
+ MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
+ if (rename(ds.path_.c_str(), new_path.c_str())) {
+ MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
+ strerror(errno));
+ } else {
+ ds.path_ = new_path;
+ }
+ }
+ }
+ }
+ if (do_text_file) {
+ ds.path_ = ds.GetPath(".txt");
+ MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
+ if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
+ MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
+ ds.path_.clear();
+ }
+ }
+ if (options.use_control_socket) {
+ if (do_text_file) {
+ dprintf(ds.control_socket_fd_,
+ "FAIL:could not create zip file, check %s "
+ "for more details\n",
+ ds.log_path_.c_str());
+ } else {
+ dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
+ }
+ }
+}
+
+/* Broadcasts that we are done with the bugreport */
+static void SendBugreportFinishedBroadcast() {
+ const Dumpstate::DumpOptions& options = ds.options_;
+ if (!ds.path_.empty()) {
+ MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
+ // clang-format off
+
+ std::vector<std::string> am_args = {
+ "--receiver-permission", "android.permission.DUMP",
+ "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
+ "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
+ "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
+ "--es", "android.intent.extra.BUGREPORT", ds.path_,
+ "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
+ };
+ // clang-format on
+ if (options.do_fb) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.SCREENSHOT");
+ am_args.push_back(ds.screenshot_path_);
+ }
+ if (!ds.notification_title.empty()) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.TITLE");
+ am_args.push_back(ds.notification_title);
+ if (!ds.notification_description.empty()) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.DESCRIPTION");
+ am_args.push_back(ds.notification_description);
+ }
+ }
+ if (options.is_remote_mode) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
+ am_args.push_back(SHA256_file_hash(ds.path_));
+ SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
+ } else {
+ SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
+ }
+ } else {
+ MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
+ }
+}
+
int Dumpstate::ParseCommandlineOptions(int argc, char* argv[]) {
int ret = -1; // success
int c;
@@ -1864,8 +2084,7 @@
exit(1);
}
- // TODO: make const reference, but first avoid setting do_zip_file below.
- Dumpstate::DumpOptions& options = ds.options_;
+ const Dumpstate::DumpOptions& options = ds.options_;
if (options.show_header_only) {
ds.PrintHeader();
exit(0);
@@ -1922,60 +2141,11 @@
}
if (is_redirecting) {
- ds.bugreport_dir_ = dirname(options.use_outfile.c_str());
- std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
- std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
- ds.base_name_ =
- android::base::StringPrintf("%s-%s-%s", basename(options.use_outfile.c_str()),
- device_name.c_str(), build_id.c_str());
- if (options.do_add_date) {
- char date[80];
- strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
- ds.name_ = date;
- } else {
- ds.name_ = "undated";
- }
-
- if (options.telephony_only) {
- ds.base_name_ += "-telephony";
- } else if (options.wifi_only) {
- ds.base_name_ += "-wifi";
- }
-
- if (options.do_fb) {
- ds.screenshot_path_ = ds.GetPath(".png");
- }
- ds.tmp_path_ = ds.GetPath(".tmp");
- ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
-
- MYLOGD(
- "Bugreport dir: %s\n"
- "Base name: %s\n"
- "Suffix: %s\n"
- "Log path: %s\n"
- "Temporary path: %s\n"
- "Screenshot path: %s\n",
- ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
- ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
-
- if (options.do_zip_file) {
- ds.path_ = ds.GetPath(".zip");
- MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
- create_parent_dirs(ds.path_.c_str());
- ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
- if (ds.zip_file == nullptr) {
- MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
- options.do_zip_file = false;
- } else {
- ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
- }
- ds.AddTextZipEntry("version.txt", ds.version_);
- }
+ PrepareToWriteToFile();
if (ds.update_progress_) {
if (options.do_broadcast) {
// clang-format off
-
std::vector<std::string> am_args = {
"--receiver-permission", "android.permission.DUMP",
"--es", "android.intent.extra.NAME", ds.name_,
@@ -2013,7 +2183,7 @@
}
}
- if (options.do_zip_file) {
+ if (options.do_zip_file && ds.zip_file != nullptr) {
if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
strerror(errno));
@@ -2054,51 +2224,11 @@
} else if (options.wifi_only) {
DumpstateWifiOnly();
} else {
- // Dumps systrace right away, otherwise it will be filled with unnecessary events.
- // First try to dump anrd trace if the daemon is running. Otherwise, dump
- // the raw trace.
- if (!dump_anrd_trace()) {
- dump_systrace();
- }
-
- // Invoking the following dumpsys calls before dump_traces() to try and
- // keep the system stats as close to its initial state as possible.
- RunDumpsysCritical();
-
- /* collect stack traces from Dalvik and native processes (needs root) */
- dump_traces_path = dump_traces();
-
- /* Run some operations that require root. */
- ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
- ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
-
- ds.AddDir(RECOVERY_DIR, true);
- ds.AddDir(RECOVERY_DATA_DIR, true);
- ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
- ds.AddDir(LOGPERSIST_DATA_DIR, false);
- if (!PropertiesHelper::IsUserBuild()) {
- ds.AddDir(PROFILE_DATA_DIR_CUR, true);
- ds.AddDir(PROFILE_DATA_DIR_REF, true);
- }
- add_mountinfo();
- DumpIpTablesAsRoot();
-
- // Capture any IPSec policies in play. No keys are exposed here.
- RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
- CommandOptions::WithTimeout(10).Build());
-
- // Run ss as root so we can see socket marks.
- RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
- CommandOptions::WithTimeout(10).Build());
-
- // Run iotop as root to show top 100 IO threads
- RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
-
- if (!DropRootUser()) {
+ // Dump state for the default case. This also drops root.
+ if (!DumpstateDefault()) {
+ // Something went wrong.
return -1;
}
-
- dumpstate();
}
/* close output if needed */
@@ -2108,73 +2238,7 @@
/* rename or zip the (now complete) .tmp file to its final location */
if (!options.use_outfile.empty()) {
- /* check if user changed the suffix using system properties */
- std::string name = android::base::GetProperty(
- android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
- bool change_suffix = false;
- if (!name.empty()) {
- /* must whitelist which characters are allowed, otherwise it could cross directories */
- std::regex valid_regex("^[-_a-zA-Z0-9]+$");
- if (std::regex_match(name.c_str(), valid_regex)) {
- change_suffix = true;
- } else {
- MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
- }
- }
- if (change_suffix) {
- MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
- ds.name_ = name;
- if (!ds.screenshot_path_.empty()) {
- std::string new_screenshot_path = ds.GetPath(".png");
- if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
- new_screenshot_path.c_str(), strerror(errno));
- } else {
- ds.screenshot_path_ = new_screenshot_path;
- }
- }
- }
-
- bool do_text_file = true;
- if (options.do_zip_file) {
- if (!ds.FinishZipFile()) {
- MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
- do_text_file = true;
- } else {
- do_text_file = false;
- // Since zip file is already created, it needs to be renamed.
- std::string new_path = ds.GetPath(".zip");
- if (ds.path_ != new_path) {
- MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
- if (rename(ds.path_.c_str(), new_path.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
- strerror(errno));
- } else {
- ds.path_ = new_path;
- }
- }
- }
- }
- if (do_text_file) {
- ds.path_ = ds.GetPath(".txt");
- MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
- ds.tmp_path_.c_str());
- if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
- strerror(errno));
- ds.path_.clear();
- }
- }
- if (options.use_control_socket) {
- if (do_text_file) {
- dprintf(ds.control_socket_fd_,
- "FAIL:could not create zip file, check %s "
- "for more details\n",
- ds.log_path_.c_str());
- } else {
- dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
- }
- }
+ FinalizeFile();
}
/* vibrate a few but shortly times to let user know it's finished */
@@ -2187,46 +2251,7 @@
/* tell activity manager we're done */
if (options.do_broadcast) {
- if (!ds.path_.empty()) {
- MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
- // clang-format off
-
- std::vector<std::string> am_args = {
- "--receiver-permission", "android.permission.DUMP",
- "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
- "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
- "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
- "--es", "android.intent.extra.BUGREPORT", ds.path_,
- "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
- };
- // clang-format on
- if (options.do_fb) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.SCREENSHOT");
- am_args.push_back(ds.screenshot_path_);
- }
- if (!ds.notification_title.empty()) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.TITLE");
- am_args.push_back(ds.notification_title);
- if (!ds.notification_description.empty()) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.DESCRIPTION");
- am_args.push_back(ds.notification_description);
- }
- }
- if (options.is_remote_mode) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
- am_args.push_back(SHA256_file_hash(ds.path_));
- SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
- am_args);
- } else {
- SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
- }
- } else {
- MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
- }
+ SendBugreportFinishedBroadcast();
}
MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
diff --git a/cmds/installd/MatchExtensionGen.h b/cmds/installd/MatchExtensionGen.h
index fded6b7..35c3889 100644
--- a/cmds/installd/MatchExtensionGen.h
+++ b/cmds/installd/MatchExtensionGen.h
@@ -31,6 +31,7 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'p': case 'P':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -41,10 +42,15 @@
switch (ext[5]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
case 'a': case 'A':
switch (ext[1]) {
case 'a': case 'A':
@@ -53,7 +59,9 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'i': case 'I':
switch (ext[2]) {
case 'f': case 'F':
@@ -63,56 +71,73 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'f': case 'F':
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[2]) {
case 'r': case 'R':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 't': case 'T':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
case 'w': case 'W':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case 'i': case 'I':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'w': case 'W':
switch (ext[2]) {
case 'b': case 'B':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'b': case 'B':
switch (ext[1]) {
case 'm': case 'M':
@@ -121,8 +146,11 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'c': case 'C':
switch (ext[1]) {
case 'r': case 'R':
@@ -131,8 +159,11 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'd': case 'D':
switch (ext[1]) {
case 'i': case 'I':
@@ -141,23 +172,30 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'l': case 'L':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'f': case 'F':
switch (ext[1]) {
case 'l': case 'L':
@@ -168,13 +206,18 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'i': case 'I':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[1]) {
case 'i': case 'I':
@@ -183,15 +226,20 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'j': case 'J':
switch (ext[1]) {
case 'n': case 'N':
@@ -200,7 +248,9 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case 'e': case 'E':
@@ -210,13 +260,18 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'l': case 'L':
switch (ext[1]) {
case 's': case 'S':
@@ -225,12 +280,16 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[1]) {
case '3':
@@ -239,36 +298,46 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case '4':
switch (ext[2]) {
case 'a': case 'A':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'v': case 'V':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'k': case 'K':
switch (ext[2]) {
case 'a': case 'A':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'v': case 'V':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'o': case 'O':
switch (ext[2]) {
case 'v': case 'V':
@@ -280,23 +349,30 @@
switch (ext[5]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case '2':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case '3':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case '4':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'e': case 'E':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -307,8 +383,11 @@
switch (ext[5]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -316,16 +395,22 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'x': case 'X':
switch (ext[2]) {
case 'u': case 'U':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[1]) {
case 'e': case 'E':
@@ -334,15 +419,20 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'w': case 'W':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'o': case 'O':
switch (ext[1]) {
case 'g': case 'G':
@@ -351,19 +441,25 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[1]) {
case 'b': case 'B':
@@ -372,68 +468,88 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'c': case 'C':
switch (ext[2]) {
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'e': case 'E':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'l': case 'L':
switch (ext[2]) {
case 's': case 'S':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case 'd': case 'D':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'q': case 'Q':
switch (ext[1]) {
case 't': case 'T':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[1]) {
case 'a': case 'A':
@@ -443,30 +559,39 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 's': case 'S':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[2]) {
case 'b': case 'B':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[2]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'w': case 'W':
switch (ext[2]) {
case '2':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[1]) {
case 'd': case 'D':
@@ -475,21 +600,27 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'd': case 'D':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'w': case 'W':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case 'g': case 'G':
@@ -499,9 +630,13 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
case 't': case 'T':
switch (ext[1]) {
case 'i': case 'I':
@@ -513,13 +648,18 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[1]) {
case 'o': case 'O':
@@ -528,8 +668,11 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'w': case 'W':
switch (ext[1]) {
case 'a': case 'A':
@@ -538,11 +681,14 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'b': case 'B':
switch (ext[2]) {
case 'm': case 'M':
@@ -551,8 +697,11 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'e': case 'E':
switch (ext[2]) {
case 'b': case 'B':
@@ -561,12 +710,16 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'p': case 'P':
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -574,30 +727,39 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'v': case 'V':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'x': case 'X':
switch (ext[1]) {
case 'b': case 'B':
@@ -606,22 +768,29 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'w': case 'W':
switch (ext[2]) {
case 'd': case 'D':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
}
return 0;
diff --git a/cmds/installd/matchgen.py b/cmds/installd/matchgen.py
index 131487d..42ce82b 100644
--- a/cmds/installd/matchgen.py
+++ b/cmds/installd/matchgen.py
@@ -84,6 +84,8 @@
print "%scase '%s':" % (prefix, k)
dump(target[k], index + 1)
print "%s}" % (prefix)
+ if index > 0:
+ print "%sbreak;" % (prefix)
dump(trie, 0)
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 73098f8..28c7658 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -361,12 +361,11 @@
}
std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
- if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
- return PatchoatBootImage(isa_path, isa);
- } else {
+ if (access(preopted_boot_art_path.c_str(), F_OK) != 0) {
// No preopted boot image. Try to compile.
return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
}
+ return true;
}
static bool CreatePath(const std::string& path) {
@@ -431,29 +430,6 @@
CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
}
- bool PatchoatBootImage(const std::string& output_dir, const char* isa) const {
- // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
-
- std::vector<std::string> cmd;
- cmd.push_back("/system/bin/patchoat");
-
- cmd.push_back("--input-image-location=/system/framework/boot.art");
- cmd.push_back(StringPrintf("--output-image-directory=%s", output_dir.c_str()));
-
- cmd.push_back(StringPrintf("--instruction-set=%s", isa));
-
- int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
- art::GetImageMaxBaseAddressDelta());
- cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
-
- std::string error_msg;
- bool result = Exec(cmd, &error_msg);
- if (!result) {
- LOG(ERROR) << "Could not generate boot image: " << error_msg;
- }
- return result;
- }
-
bool Dex2oatBootImage(const std::string& boot_cp,
const std::string& art_path,
const std::string& oat_path,
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index bcdd03e..ad7a5ae 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
#include "InstalldNativeService.h"
+#include "MatchExtensionGen.h"
#include "globals.h"
#include "utils.h"
@@ -529,5 +530,19 @@
EXPECT_NE(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir//file"));
}
+TEST_F(UtilsTest, MatchExtension_Valid) {
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mpg"));
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mpeg"));
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mPeG"));
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("MPEG"));
+}
+
+TEST_F(UtilsTest, MatchExtension_Invalid) {
+ EXPECT_EQ(0, MatchExtension("log"));
+ EXPECT_EQ(0, MatchExtension("3amp"));
+ EXPECT_EQ(0, MatchExtension("fpe"));
+ EXPECT_EQ(0, MatchExtension("docx"));
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/lshal/PipeRelay.cpp b/cmds/lshal/PipeRelay.cpp
index 3a17e03..820679f 100644
--- a/cmds/lshal/PipeRelay.cpp
+++ b/cmds/lshal/PipeRelay.cpp
@@ -16,33 +16,75 @@
#include "PipeRelay.h"
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <atomic>
+
+#include <android-base/logging.h>
#include <utils/Thread.h>
namespace android {
namespace lshal {
+static constexpr struct timeval READ_TIMEOUT { .tv_sec = 1, .tv_usec = 0 };
+
struct PipeRelay::RelayThread : public Thread {
explicit RelayThread(int fd, std::ostream &os);
bool threadLoop() override;
+ void setFinished();
private:
int mFd;
std::ostream &mOutStream;
+ // If we were to use requestExit() and exitPending() instead, threadLoop()
+ // may not run at all by the time ~PipeRelay is called (i.e. debug() has
+ // returned from HAL). By using our own flag, we ensure that select() and
+ // read() are executed until data are drained.
+ std::atomic_bool mFinished;
+
DISALLOW_COPY_AND_ASSIGN(RelayThread);
};
////////////////////////////////////////////////////////////////////////////////
PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
- : mFd(fd),
- mOutStream(os) {
-}
+ : mFd(fd), mOutStream(os), mFinished(false) {}
bool PipeRelay::RelayThread::threadLoop() {
char buffer[1024];
- ssize_t n = read(mFd, buffer, sizeof(buffer));
+
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(mFd, &set);
+
+ struct timeval timeout = READ_TIMEOUT;
+
+ int res = TEMP_FAILURE_RETRY(select(mFd + 1, &set, nullptr, nullptr, &timeout));
+ if (res < 0) {
+ PLOG(INFO) << "select() failed";
+ return false;
+ }
+
+ if (res == 0 || !FD_ISSET(mFd, &set)) {
+ if (mFinished) {
+ LOG(WARNING) << "debug: timeout reading from pipe, output may be truncated.";
+ return false;
+ }
+ // timeout, but debug() has not returned, so wait for HAL to finish.
+ return true;
+ }
+
+ // FD_ISSET(mFd, &set) == true. Data available, start reading
+ ssize_t n = TEMP_FAILURE_RETRY(read(mFd, buffer, sizeof(buffer)));
+
+ if (n < 0) {
+ PLOG(ERROR) << "read() failed";
+ }
if (n <= 0) {
return false;
@@ -53,6 +95,10 @@
return true;
}
+void PipeRelay::RelayThread::setFinished() {
+ mFinished = true;
+}
+
////////////////////////////////////////////////////////////////////////////////
PipeRelay::PipeRelay(std::ostream &os)
@@ -77,12 +123,14 @@
PipeRelay::~PipeRelay() {
CloseFd(&mFds[1]);
- CloseFd(&mFds[0]);
if (mThread != nullptr) {
+ mThread->setFinished();
mThread->join();
mThread.clear();
}
+
+ CloseFd(&mFds[0]);
}
status_t PipeRelay::initCheck() const {
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index 0f336dd..0de3bb7 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -17,11 +17,37 @@
#ifndef _LIBINPUT_DISPLAY_VIEWPORT_H
#define _LIBINPUT_DISPLAY_VIEWPORT_H
+#include <android-base/stringprintf.h>
#include <ui/DisplayInfo.h>
#include <input/Input.h>
+using android::base::StringPrintf;
+
namespace android {
+/**
+ * Describes the different type of viewports supported by input flinger.
+ * Keep in sync with values in InputManagerService.java.
+ */
+enum class ViewportType : int32_t {
+ VIEWPORT_INTERNAL = 1,
+ VIEWPORT_EXTERNAL = 2,
+ VIEWPORT_VIRTUAL = 3,
+};
+
+static const char* viewportTypeToString(ViewportType type) {
+ switch(type) {
+ case ViewportType::VIEWPORT_INTERNAL:
+ return "INTERNAL";
+ case ViewportType::VIEWPORT_EXTERNAL:
+ return "EXTERNAL";
+ case ViewportType::VIEWPORT_VIRTUAL:
+ return "VIRTUAL";
+ default:
+ return "UNKNOWN";
+ }
+}
+
/*
* Describes how coordinates are mapped on a physical display.
* See com.android.server.display.DisplayViewport.
@@ -40,12 +66,13 @@
int32_t deviceWidth;
int32_t deviceHeight;
std::string uniqueId;
+ ViewportType type;
DisplayViewport() :
displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
- deviceWidth(0), deviceHeight(0), uniqueId() {
+ deviceWidth(0), deviceHeight(0), uniqueId(), type(ViewportType::VIEWPORT_INTERNAL) {
}
bool operator==(const DisplayViewport& other) const {
@@ -61,7 +88,8 @@
&& physicalBottom == other.physicalBottom
&& deviceWidth == other.deviceWidth
&& deviceHeight == other.deviceHeight
- && uniqueId == other.uniqueId;
+ && uniqueId == other.uniqueId
+ && type == other.type;
}
bool operator!=(const DisplayViewport& other) const {
@@ -86,17 +114,22 @@
deviceWidth = width;
deviceHeight = height;
uniqueId.clear();
+ type = ViewportType::VIEWPORT_INTERNAL;
}
-};
-/**
- * Describes the different type of viewports supported by input flinger.
- * Keep in sync with values in InputManagerService.java.
- */
-enum class ViewportType : int32_t {
- VIEWPORT_INTERNAL = 1,
- VIEWPORT_EXTERNAL = 2,
- VIEWPORT_VIRTUAL = 3,
+ std::string toString() const {
+ return StringPrintf("Viewport %s: displayId=%d, orientation=%d, "
+ "logicalFrame=[%d, %d, %d, %d], "
+ "physicalFrame=[%d, %d, %d, %d], "
+ "deviceSize=[%d, %d]",
+ viewportTypeToString(type),
+ displayId, orientation,
+ logicalLeft, logicalTop,
+ logicalRight, logicalBottom,
+ physicalLeft, physicalTop,
+ physicalRight, physicalBottom,
+ deviceWidth, deviceHeight);
+ }
};
} // namespace android
diff --git a/services/inputflinger/InputApplication.h b/include/input/InputApplication.h
similarity index 100%
rename from services/inputflinger/InputApplication.h
rename to include/input/InputApplication.h
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 5fd86b4..4782c9b 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -37,6 +37,7 @@
#include <utils/BitSet.h>
namespace android {
+class Parcel;
/*
* Intermediate representation used to send input events and related signals.
@@ -143,6 +144,7 @@
virtual ~InputChannel();
public:
+ InputChannel() = default;
InputChannel(const std::string& name, int fd);
/* Creates a pair of input channels.
@@ -183,9 +185,14 @@
/* Returns a new object that has a duplicate of this channel's fd. */
sp<InputChannel> dup() const;
+ status_t write(Parcel& out) const;
+ status_t read(const Parcel& from);
+
private:
+ void setFd(int fd);
+
std::string mName;
- int mFd;
+ int mFd = -1;
};
/*
diff --git a/services/inputflinger/InputWindow.h b/include/input/InputWindow.h
similarity index 97%
rename from services/inputflinger/InputWindow.h
rename to include/input/InputWindow.h
index c481853..7c284dd 100644
--- a/services/inputflinger/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -27,7 +27,7 @@
#include "InputApplication.h"
namespace android {
-
+class Parcel;
/*
* Describes the properties of a window that can receive input.
@@ -151,6 +151,9 @@
bool supportsSplitTouch() const;
bool overlaps(const InputWindowInfo* other) const;
+
+ status_t write(Parcel& output) const;
+ static InputWindowInfo read(const Parcel& from);
};
@@ -168,9 +171,7 @@
return mInfo;
}
- inline sp<InputChannel> getInputChannel() const {
- return mInfo ? mInfo->inputChannel : nullptr;
- }
+ sp<InputChannel> getInputChannel() const;
inline std::string getName() const {
return mInfo ? mInfo->name : "<invalid>";
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index b2a304a..aedf6b0 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -120,6 +120,7 @@
"liblog",
"libcutils",
"libutils",
+ "libbinderthreadstate",
],
header_libs: [
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index b2217b5..f052bcb 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "IPCThreadState"
#include <binder/IPCThreadState.h>
+#include <binderthreadstate/IPCThreadStateBase.h>
#include <binder/Binder.h>
#include <binder/BpBinder.h>
@@ -742,6 +743,7 @@
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
+ mIPCThreadStateBase = IPCThreadStateBase::self();
}
IPCThreadState::~IPCThreadState()
@@ -1082,6 +1084,9 @@
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
+ //Record the fact that we're in a binder call.
+ mIPCThreadStateBase->pushCurrentState(
+ IPCThreadStateBase::CallState::BINDER);
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1129,6 +1134,7 @@
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
+ mIPCThreadStateBase->popCurrentState();
//ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);
@@ -1192,6 +1198,10 @@
return result;
}
+bool IPCThreadState::isServingCall() const {
+ return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::BINDER;
+}
+
void IPCThreadState::threadDestructor(void *st)
{
IPCThreadState* const self = static_cast<IPCThreadState*>(st);
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index dce3f38..40b51ad 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -29,6 +29,8 @@
// ---------------------------------------------------------------------------
namespace android {
+class IPCThreadStateBase;
+
class IPCThreadState
{
public:
@@ -89,6 +91,33 @@
// the maximum number of binder threads threads allowed for this process.
void blockUntilThreadAvailable();
+
+ // Is this thread currently serving a binder call. This method
+ // returns true if while traversing backwards from the function call
+ // stack for this thread, we encounter a function serving a binder
+ // call before encountering a hwbinder call / hitting the end of the
+ // call stack.
+ // Eg: If thread T1 went through the following call pattern
+ // 1) T1 receives and executes hwbinder call H1.
+ // 2) While handling H1, T1 makes binder call B1.
+ // 3) The handler of B1, calls into T1 with a callback B2.
+ // If isServingCall() is called during H1 before 3), this method
+ // will return false, else true.
+ //
+ // ----
+ // | B2 | ---> While callback B2 is being handled, during 3).
+ // ----
+ // | H1 | ---> While H1 is being handled.
+ // ----
+ // Fig: Thread Call stack while handling B2
+ //
+ // This is since after 3), while traversing the thread call stack,
+ // we hit a binder call before a hwbinder call / end of stack. This
+ // method may be typically used to determine whether to use
+ // hardware::IPCThreadState methods or IPCThreadState methods to
+ // infer information about thread state.
+ bool isServingCall() const;
+
private:
IPCThreadState();
~IPCThreadState();
@@ -128,6 +157,7 @@
uid_t mCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
+ IPCThreadStateBase *mIPCThreadStateBase;
};
}; // namespace android
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
new file mode 100644
index 0000000..7106cbb
--- /dev/null
+++ b/libs/binderthreadstate/Android.bp
@@ -0,0 +1,44 @@
+// 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.
+
+cc_library {
+ name: "libbinderthreadstate",
+ recovery_available: true,
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ srcs: [
+ "IPCThreadStateBase.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libcutils",
+ "libutils",
+ ],
+
+ export_include_dirs: ["include"],
+
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/libs/binderthreadstate/IPCThreadStateBase.cpp b/libs/binderthreadstate/IPCThreadStateBase.cpp
new file mode 100644
index 0000000..fede151
--- /dev/null
+++ b/libs/binderthreadstate/IPCThreadStateBase.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "IPCThreadStateBase"
+
+#include <binderthreadstate/IPCThreadStateBase.h>
+#include <android-base/macros.h>
+
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <pthread.h>
+
+namespace android {
+
+static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gHaveTLS = false;
+static pthread_key_t gTLS = 0;
+
+IPCThreadStateBase::IPCThreadStateBase() {
+ pthread_setspecific(gTLS, this);
+}
+
+IPCThreadStateBase* IPCThreadStateBase::self()
+{
+ if (gHaveTLS) {
+restart:
+ const pthread_key_t k = gTLS;
+ IPCThreadStateBase* st = (IPCThreadStateBase*)pthread_getspecific(k);
+ if (st) return st;
+ return new IPCThreadStateBase;
+ }
+
+ pthread_mutex_lock(&gTLSMutex);
+ if (!gHaveTLS) {
+ int key_create_value = pthread_key_create(&gTLS, threadDestructor);
+ if (key_create_value != 0) {
+ pthread_mutex_unlock(&gTLSMutex);
+ ALOGW("IPCThreadStateBase::self() unable to create TLS key, expect a crash: %s\n",
+ strerror(key_create_value));
+ return nullptr;
+ }
+ gHaveTLS = true;
+ }
+ pthread_mutex_unlock(&gTLSMutex);
+ goto restart;
+}
+
+void IPCThreadStateBase::pushCurrentState(CallState callState) {
+ mCallStateStack.emplace(callState);
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::popCurrentState() {
+ ALOG_ASSERT(mCallStateStack.size > 0);
+ CallState val = mCallStateStack.top();
+ mCallStateStack.pop();
+ return val;
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::getCurrentBinderCallState() {
+ if (mCallStateStack.size() > 0) {
+ return mCallStateStack.top();
+ }
+ return CallState::NONE;
+}
+
+void IPCThreadStateBase::threadDestructor(void *st)
+{
+ IPCThreadStateBase* const self = static_cast<IPCThreadStateBase*>(st);
+ if (self) {
+ delete self;
+ }
+}
+
+}; // namespace android
diff --git a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
new file mode 100644
index 0000000..6fdcc84
--- /dev/null
+++ b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#ifndef BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+#define BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+
+#include <stack>
+namespace android {
+
+class IPCThreadStateBase {
+public:
+ enum CallState {
+ HWBINDER,
+ BINDER,
+ NONE,
+ };
+ static IPCThreadStateBase* self();
+ void pushCurrentState(CallState callState);
+ CallState popCurrentState();
+ CallState getCurrentBinderCallState();
+
+private:
+ IPCThreadStateBase();
+ static void threadDestructor(void *st);
+
+ std::stack<CallState> mCallStateStack;
+};
+
+}; // namespace android
+
+#endif // BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index a8ef7a0..2a7d76e 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -56,6 +56,35 @@
mDriverPath = path;
}
+void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
+ const std::string appPref, bool developerOptIn) {
+ if (!mAnglePath.empty()) {
+ ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(),
+ path.c_str());
+ } else {
+ ALOGV("setting ANGLE path to '%s'", path.c_str());
+ mAnglePath = path;
+ }
+
+ if (!mAngleAppName.empty()) {
+ ALOGV("ignoring attempt to change ANGLE app name from '%s' to '%s'", mAngleAppName.c_str(),
+ appName.c_str());
+ } else {
+ ALOGV("setting ANGLE app name to '%s'", appName.c_str());
+ mAngleAppName = appName;
+ }
+
+ if (!mAngleAppPref.empty()) {
+ ALOGV("ignoring attempt to change ANGLE application opt-in from '%s' to '%s'",
+ mAngleAppPref.c_str(), appPref.c_str());
+ } else {
+ ALOGV("setting ANGLE application opt-in to '%s'", appPref.c_str());
+ mAngleAppPref = appPref;
+ }
+
+ mAngleDeveloperOptIn = developerOptIn;
+}
+
void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
if (mLayerPaths.empty()) {
mLayerPaths = layerPaths;
@@ -70,6 +99,20 @@
return mAppNamespace;
}
+const char* GraphicsEnv::getAngleAppName() {
+ if (mAngleAppName.empty()) return nullptr;
+ return mAngleAppName.c_str();
+}
+
+bool GraphicsEnv::getAngleDeveloperOptIn() {
+ return mAngleDeveloperOptIn;
+}
+
+const char* GraphicsEnv::getAngleAppPref() {
+ if (mAngleAppPref.empty()) return nullptr;
+ return mAngleAppPref.c_str();
+}
+
const std::string GraphicsEnv::getLayerPaths(){
return mLayerPaths;
}
@@ -102,8 +145,40 @@
return mDriverNamespace;
}
+android_namespace_t* GraphicsEnv::getAngleNamespace() {
+ static std::once_flag once;
+ std::call_once(once, [this]() {
+ if (mAnglePath.empty()) return;
+
+ mAngleNamespace = android_create_namespace("ANGLE",
+ nullptr, // ld_library_path
+ mAnglePath.c_str(), // default_library_path
+ ANDROID_NAMESPACE_TYPE_SHARED |
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ nullptr);
+ if (!mAngleNamespace) ALOGD("Could not create ANGLE namespace from default");
+ });
+
+ return mAngleNamespace;
+}
+
} // namespace android
-extern "C" android_namespace_t* android_getDriverNamespace() {
+extern "C" {
+android_namespace_t* android_getDriverNamespace() {
return android::GraphicsEnv::getInstance().getDriverNamespace();
}
+android_namespace_t* android_getAngleNamespace() {
+ return android::GraphicsEnv::getInstance().getAngleNamespace();
+}
+const char* android_getAngleAppName() {
+ return android::GraphicsEnv::getInstance().getAngleAppName();
+}
+bool android_getAngleDeveloperOptIn() {
+ return android::GraphicsEnv::getInstance().getAngleDeveloperOptIn();
+}
+const char* android_getAngleAppPref() {
+ return android::GraphicsEnv::getInstance().getAngleAppPref();
+}
+}
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 17e8f6b..00e8fc0 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -37,8 +37,21 @@
void setDriverPath(const std::string path);
android_namespace_t* getDriverNamespace();
+ // Set a search path for loading ANGLE libraries. The path is a list of
+ // directories separated by ':'. A directory can be contained in a zip file
+ // (libraries must be stored uncompressed and page aligned); such elements
+ // in the search path must have a '!' after the zip filename, e.g.
+ // /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
+ void setAngleInfo(const std::string path, const std::string appName, const std::string appPref,
+ bool devOptIn);
+ android_namespace_t* getAngleNamespace();
+ const char* getAngleAppName();
+ const char* getAngleAppPref();
+ bool getAngleDeveloperOptIn();
+
void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths);
NativeLoaderNamespace* getAppNamespace();
+
const std::string getLayerPaths();
void setDebugLayers(const std::string layers);
@@ -47,9 +60,14 @@
private:
GraphicsEnv() = default;
std::string mDriverPath;
+ std::string mAnglePath;
+ std::string mAngleAppName;
+ std::string mAngleAppPref;
+ bool mAngleDeveloperOptIn;
std::string mDebugLayers;
std::string mLayerPaths;
android_namespace_t* mDriverNamespace = nullptr;
+ android_namespace_t* mAngleNamespace = nullptr;
NativeLoaderNamespace* mAppNamespace = nullptr;
};
@@ -66,6 +84,12 @@
* - the EGLsyncKHR synchronization in BufferQueue, which is deprecated and
* will be removed soon.
*/
-extern "C" android_namespace_t* android_getDriverNamespace();
+extern "C" {
+android_namespace_t* android_getDriverNamespace();
+android_namespace_t* android_getAngleNamespace();
+const char* android_getAngleAppName();
+const char* android_getAngleAppPref();
+bool android_getAngleDeveloperOptIn();
+}
#endif // ANDROID_UI_GRAPHICS_ENV_H
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index a379ad6..85ae433 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -621,7 +621,7 @@
// ============================================================================
FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
- FrameEventHistoryDelta&& src) {
+ FrameEventHistoryDelta&& src) noexcept {
mCompositorTiming = src.mCompositorTiming;
if (CC_UNLIKELY(!mDeltas.empty())) {
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 5a8d8db..2b0a461 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -77,6 +77,9 @@
output.writeBool(false);
}
+ memcpy(output.writeInplace(16 * sizeof(float)),
+ colorTransform.asArray(), 16 * sizeof(float));
+
return NO_ERROR;
}
@@ -130,6 +133,8 @@
sidebandStream = NativeHandle::create(input.readNativeHandle(), true);
}
+ colorTransform = mat4(static_cast<const float*>(input.readInplace(16 * sizeof(float))));
+
return NO_ERROR;
}
@@ -314,6 +319,10 @@
what |= eSidebandStreamChanged;
sidebandStream = other.sidebandStream;
}
+ if (other.what & eColorTransformChanged) {
+ what |= eColorTransformChanged;
+ colorTransform = other.colorTransform;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 09ea0f6..1ac9609 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -602,6 +602,18 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform(
+ const sp<SurfaceControl>& sc, const mat3& matrix, const vec3& translation) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eColorTransformChanged;
+ s->colorTransform = mat4(matrix, translation);
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index 9716be4..e06e40f 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -311,7 +311,7 @@
// Movable.
FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default;
- FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src);
+ FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src) noexcept;
// Not copyable.
FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete;
FrameEventHistoryDelta& operator=(
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 9a9f633..e06e2b1 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -23,6 +23,7 @@
#include <utils/Errors.h>
#include <gui/IGraphicBufferProducer.h>
+#include <math/mat4.h>
#include <math/vec3.h>
#include <ui/GraphicTypes.h>
#include <ui/Rect.h>
@@ -72,6 +73,7 @@
eSurfaceDamageRegionChanged = 0x02000000,
eApiChanged = 0x04000000,
eSidebandStreamChanged = 0x08000000,
+ eColorTransformChanged = 0x10000000,
};
layer_state_t()
@@ -94,7 +96,8 @@
crop(Rect::INVALID_RECT),
dataspace(ui::Dataspace::UNKNOWN),
surfaceDamageRegion(),
- api(-1) {
+ api(-1),
+ colorTransform(mat4()) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -150,6 +153,7 @@
Region surfaceDamageRegion;
int32_t api;
sp<NativeHandle> sidebandStream;
+ mat4 colorTransform;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 314b118..69a759f 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -269,6 +269,10 @@
Transaction& destroySurface(const sp<SurfaceControl>& sc);
+ // Set a color transform matrix on the given layer on the built-in display.
+ Transaction& setColorTransform(const sp<SurfaceControl>& sc, const mat3& matrix,
+ const vec3& translation);
+
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 02064c6..7ecadf8 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -44,6 +44,7 @@
"libgui",
"libhidlbase",
"libhidltransport",
+ "libinput",
"libui",
"libutils",
"libnativewindow"
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index a2d6a8a..72558a6 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -47,11 +47,14 @@
"InputTransport.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
+ "InputApplication.cpp",
+ "InputWindow.cpp"
],
shared_libs: [
"libutils",
"libbinder",
+ "libui"
],
sanitize: {
diff --git a/services/inputflinger/InputApplication.cpp b/libs/input/InputApplication.cpp
similarity index 96%
rename from services/inputflinger/InputApplication.cpp
rename to libs/input/InputApplication.cpp
index c56dfe6..a0d1668 100644
--- a/services/inputflinger/InputApplication.cpp
+++ b/libs/input/InputApplication.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "InputApplication"
-#include "InputApplication.h"
+#include <input/InputApplication.h>
#include <android/log.h>
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 770d483..32444f9 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -30,6 +30,7 @@
#include <cutils/properties.h>
#include <log/log.h>
+#include <binder/Parcel.h>
#include <input/InputTransport.h>
namespace android {
@@ -100,15 +101,13 @@
// --- InputChannel ---
InputChannel::InputChannel(const std::string& name, int fd) :
- mName(name), mFd(fd) {
+ mName(name) {
#if DEBUG_CHANNEL_LIFECYCLE
ALOGD("Input channel constructed: name='%s', fd=%d",
mName.c_str(), fd);
#endif
- int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
- "non-blocking. errno=%d", mName.c_str(), errno);
+ setFd(fd);
}
InputChannel::~InputChannel() {
@@ -120,6 +119,18 @@
::close(mFd);
}
+void InputChannel::setFd(int fd) {
+ if (mFd > 0) {
+ ::close(mFd);
+ }
+ mFd = fd;
+ if (mFd > 0) {
+ int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
+ LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
+ "non-blocking. errno=%d", mName.c_str(), errno);
+ }
+}
+
status_t InputChannel::openInputChannelPair(const std::string& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
@@ -230,6 +241,31 @@
}
+status_t InputChannel::write(Parcel& out) const {
+ status_t s = out.writeString8(String8(getName().c_str()));
+
+ if (s != OK) {
+ return s;
+ }
+
+ s = out.writeDupFileDescriptor(getFd());
+
+ return s;
+}
+
+status_t InputChannel::read(const Parcel& from) {
+ mName = from.readString8();
+
+ int rawFd = from.readFileDescriptor();
+ setFd(::dup(rawFd));
+
+ if (mFd < 0) {
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
// --- InputPublisher ---
InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
new file mode 100644
index 0000000..f94faba
--- /dev/null
+++ b/libs/input/InputWindow.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+#define LOG_NDEBUG 0
+
+#include <binder/Parcel.h>
+#include <input/InputWindow.h>
+#include <input/InputTransport.h>
+
+#include <log/log.h>
+
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+namespace android {
+
+// --- InputWindowInfo ---
+void InputWindowInfo::addTouchableRegion(const Rect& region) {
+ touchableRegion.orSelf(region);
+}
+
+bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+ return touchableRegion.contains(x,y);
+}
+
+bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
+ return x >= frameLeft && x < frameRight
+ && y >= frameTop && y < frameBottom;
+}
+
+bool InputWindowInfo::isTrustedOverlay() const {
+ return layoutParamsType == TYPE_INPUT_METHOD
+ || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+ || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
+ || layoutParamsType == TYPE_STATUS_BAR
+ || layoutParamsType == TYPE_NAVIGATION_BAR
+ || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
+ || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
+ || layoutParamsType == TYPE_DOCK_DIVIDER
+ || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
+ || layoutParamsType == TYPE_INPUT_CONSUMER;
+}
+
+bool InputWindowInfo::supportsSplitTouch() const {
+ return layoutParamsFlags & FLAG_SPLIT_TOUCH;
+}
+
+bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
+ return frameLeft < other->frameRight && frameRight > other->frameLeft
+ && frameTop < other->frameBottom && frameBottom > other->frameTop;
+}
+
+status_t InputWindowInfo::write(Parcel& output) const {
+ if (inputChannel == nullptr) {
+ output.writeInt32(0);
+ return OK;
+ }
+ output.writeInt32(1);
+ status_t s = inputChannel->write(output);
+ if (s != OK) return s;
+
+ output.writeString8(String8(name.c_str()));
+ output.writeInt32(layoutParamsFlags);
+ output.writeInt32(layoutParamsType);
+ output.writeInt64(dispatchingTimeout);
+ output.writeInt32(frameLeft);
+ output.writeInt32(frameTop);
+ output.writeInt32(frameRight);
+ output.writeInt32(frameBottom);
+ output.writeFloat(scaleFactor);
+ output.writeBool(visible);
+ output.writeBool(canReceiveKeys);
+ output.writeBool(hasFocus);
+ output.writeBool(hasWallpaper);
+ output.writeBool(paused);
+ output.writeInt32(layer);
+ output.writeInt32(ownerPid);
+ output.writeInt32(ownerUid);
+ output.writeInt32(inputFeatures);
+ output.writeInt32(displayId);
+ output.write(touchableRegion);
+
+ return OK;
+}
+
+InputWindowInfo InputWindowInfo::read(const Parcel& from) {
+ InputWindowInfo ret;
+
+ if (from.readInt32() == 0) {
+ return ret;
+
+ }
+ sp<InputChannel> inputChannel = new InputChannel();
+ status_t s = inputChannel->read(from);
+ if (s != OK) {
+ return ret;
+ }
+
+ ret.inputChannel = inputChannel;
+ ret.name = from.readString8().c_str();
+ ret.layoutParamsFlags = from.readInt32();
+ ret.layoutParamsType = from.readInt32();
+ ret.dispatchingTimeout = from.readInt64();
+ ret.frameLeft = from.readInt32();
+ ret.frameTop = from.readInt32();
+ ret.frameRight = from.readInt32();
+ ret.frameBottom = from.readInt32();
+ ret.scaleFactor = from.readFloat();
+ ret.visible = from.readBool();
+ ret.canReceiveKeys = from.readBool();
+ ret.hasFocus = from.readBool();
+ ret.hasWallpaper = from.readBool();
+ ret.paused = from.readBool();
+ ret.layer = from.readInt32();
+ ret.ownerPid = from.readInt32();
+ ret.ownerUid = from.readInt32();
+ ret.inputFeatures = from.readInt32();
+ ret.displayId = from.readInt32();
+ from.read(ret.touchableRegion);
+
+ return ret;
+}
+
+// --- InputWindowHandle ---
+
+InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+ inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) {
+}
+
+InputWindowHandle::~InputWindowHandle() {
+ delete mInfo;
+}
+
+void InputWindowHandle::releaseInfo() {
+ if (mInfo) {
+ delete mInfo;
+ mInfo = nullptr;
+ }
+}
+
+sp<InputChannel> InputWindowHandle::getInputChannel() const {
+ return mInfo ? mInfo->inputChannel : nullptr;
+}
+
+} // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index f06119f..fdd945e 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -6,6 +6,7 @@
"InputEvent_test.cpp",
"InputPublisherAndConsumer_test.cpp",
"VelocityTracker_test.cpp",
+ "InputWindow_test.cpp"
],
cflags: [
"-Wall",
@@ -34,4 +35,12 @@
"-Wall",
"-Werror",
],
+ shared_libs: [
+ "libinput",
+ "libcutils",
+ "libutils",
+ "libbinder",
+ "libui",
+ "libbase",
+ ]
}
diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
new file mode 100644
index 0000000..39ad26e
--- /dev/null
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 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 <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+
+#include <input/InputWindow.h>
+#include <input/InputTransport.h>
+
+namespace android {
+namespace test {
+
+TEST(InputWindowInfo, ParcellingWithoutChannel) {
+ InputWindowInfo i;
+ i.inputChannel = nullptr;
+
+ Parcel p;
+ ASSERT_EQ(OK, i.write(p));
+ p.setDataPosition(0);
+ InputWindowInfo i2 = InputWindowInfo::read(p);
+ ASSERT_TRUE(i2.inputChannel == nullptr);
+}
+
+TEST(InputWindowInfo, Parcelling) {
+ sp<InputChannel> channel, junkChannel;
+ status_t result = InputChannel::openInputChannelPair("name", channel, junkChannel);
+ ASSERT_EQ(OK, result) << "openInputChannelPair should have returned valid channels";
+
+ InputWindowInfo i;
+ i.inputChannel = channel;
+ i.name = "Foobar";
+ i.layoutParamsFlags = 7;
+ i.layoutParamsType = 39;
+ i.dispatchingTimeout = 12;
+ i.frameLeft = 93;
+ i.frameTop = 34;
+ i.frameRight = 16;
+ i.frameBottom = 19;
+ i.scaleFactor = 0.3;
+ i.visible = false;
+ i.canReceiveKeys = false;
+ i.hasFocus = false;
+ i.hasWallpaper = false;
+ i.paused = false;
+ i.layer = 7;
+ i.ownerPid = 19;
+ i.ownerUid = 24;
+ i.inputFeatures = 29;
+ i.displayId = 34;
+
+ Parcel p;
+ i.write(p);
+
+ p.setDataPosition(0);
+ InputWindowInfo i2 = InputWindowInfo::read(p);
+ ASSERT_EQ(i.inputChannel->getName(), i2.inputChannel->getName());
+ ASSERT_EQ(i.name, i2.name);
+ ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
+ ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
+ ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout);
+ ASSERT_EQ(i.frameLeft, i2.frameLeft);
+ ASSERT_EQ(i.frameTop, i2.frameTop);
+ ASSERT_EQ(i.frameRight, i2.frameRight);
+ ASSERT_EQ(i.frameBottom, i2.frameBottom);
+ ASSERT_EQ(i.scaleFactor, i2.scaleFactor);
+ ASSERT_EQ(i.visible, i2.visible);
+ ASSERT_EQ(i.canReceiveKeys, i2.canReceiveKeys);
+ ASSERT_EQ(i.hasFocus, i2.hasFocus);
+ ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper);
+ ASSERT_EQ(i.paused, i2.paused);
+ ASSERT_EQ(i.layer, i2.layer);
+ ASSERT_EQ(i.ownerPid, i2.ownerPid);
+ ASSERT_EQ(i.ownerUid, i2.ownerUid);
+ ASSERT_EQ(i.inputFeatures, i2.inputFeatures);
+ ASSERT_EQ(i.displayId, i2.displayId);
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 5242a18..af97c34 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "VelocityTracker_test"
+#include <array>
#include <math.h>
#include <android-base/stringprintf.h>
@@ -34,29 +35,35 @@
// here EV = expected value, tol = VELOCITY_TOLERANCE
constexpr float VELOCITY_TOLERANCE = 0.2;
+// estimate coefficients must be within 0.001% of the target value
+constexpr float COEFFICIENT_TOLERANCE = 0.00001;
+
// --- VelocityTrackerTest ---
class VelocityTrackerTest : public testing::Test { };
-static void checkVelocity(float Vactual, float Vtarget) {
- // Compare directions
- if ((Vactual > 0 && Vtarget <= 0) || (Vactual < 0 && Vtarget >= 0)) {
- FAIL() << StringPrintf("Velocity %f does not have the same direction"
- " as the target velocity %f", Vactual, Vtarget);
- }
+/*
+ * Similar to EXPECT_NEAR, but ensures that the difference between the two float values
+ * is at most a certain fraction of the target value.
+ * If fraction is zero, require exact match.
+ */
+static void EXPECT_NEAR_BY_FRACTION(float actual, float target, float fraction) {
+ float tolerance = fabsf(target * fraction);
- // Compare magnitudes
- const float Vlower = fabsf(Vtarget * (1 - VELOCITY_TOLERANCE));
- const float Vupper = fabsf(Vtarget * (1 + VELOCITY_TOLERANCE));
- if (fabsf(Vactual) < Vlower) {
- FAIL() << StringPrintf("Velocity %f is more than %.0f%% below target velocity %f",
- Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+ if (target == 0 && fraction != 0) {
+ // If target is zero, this would force actual == target, which is too harsh.
+ // Relax this requirement a little. The value is determined empirically from the
+ // coefficients computed by the quadratic least squares algorithms.
+ tolerance = 1E-6;
}
- if (fabsf(Vactual) > Vupper) {
- FAIL() << StringPrintf("Velocity %f is more than %.0f%% above target velocity %f",
- Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
- }
- SUCCEED() << StringPrintf("Velocity %f within %.0f%% of target %f)",
- Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+ EXPECT_NEAR(actual, target, tolerance);
+}
+
+static void checkVelocity(float Vactual, float Vtarget) {
+ EXPECT_NEAR_BY_FRACTION(Vactual, Vtarget, VELOCITY_TOLERANCE);
+}
+
+static void checkCoefficient(float actual, float target) {
+ EXPECT_NEAR_BY_FRACTION(actual, target, COEFFICIENT_TOLERANCE);
}
void failWithMessage(std::string message) {
@@ -125,6 +132,19 @@
delete event;
}
+static void computeAndCheckQuadraticEstimate(const Position* positions, size_t numSamples,
+ const std::array<float, 3>& coefficients) {
+ VelocityTracker vt("lsq2");
+ MotionEvent* event = createSimpleMotionEvent(positions, numSamples);
+ vt.addMovement(event);
+ VelocityTracker::Estimator estimator;
+ EXPECT_TRUE(vt.getEstimator(0, &estimator));
+ for (size_t i = 0; i< coefficients.size(); i++) {
+ checkCoefficient(estimator.xCoeff[i], coefficients[i]);
+ checkCoefficient(estimator.yCoeff[i], coefficients[i]);
+ }
+}
+
/*
* ================== VelocityTracker tests generated manually =====================================
*/
@@ -662,5 +682,114 @@
computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
}
+/*
+ * Special care must be taken when constructing tests for LeastSquaresVelocityTrackerStrategy
+ * getEstimator function. In particular:
+ * - inside the function, time gets converted from nanoseconds to seconds
+ * before being used in the fit.
+ * - any values that are older than 100 ms are being discarded.
+ * - the newest time gets subtracted from all of the other times before being used in the fit.
+ * So these tests have to be designed with those limitations in mind.
+ *
+ * General approach for the tests below:
+ * We only used timestamps in milliseconds, 0 ms, 1 ms, and 2 ms, to be sure that
+ * we are well within the HORIZON range.
+ * When specifying the expected values of the coefficients, we treat the x values as if
+ * they were in ms. Then, to adjust for the time units, the coefficients get progressively
+ * multiplied by powers of 1E3.
+ * For example:
+ * data: t(ms), x
+ * 1 ms, 1
+ * 2 ms, 4
+ * 3 ms, 9
+ * The coefficients are (0, 0, 1).
+ * In the test, we would convert these coefficients to (0*(1E3)^0, 0*(1E3)^1, 1*(1E3)^2).
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Constant) {
+ Position values[] = {
+ { 0000000, 1, 1 }, // 0 s
+ { 1000000, 1, 1 }, // 0.001 s
+ { 2000000, 1, 1 }, // 0.002 s
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 1
+ // -0.001, 1
+ // -0.000, 1
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({1, 0, 0}));
+}
+
+/*
+ * Straight line y = x :: the constant and quadratic coefficients are zero.
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Linear) {
+ Position values[] = {
+ { 0000000, -2, -2 },
+ { 1000000, -1, -1 },
+ { 2000000, -0, -0 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, -2
+ // -0.001, -1
+ // -0.000, 0
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 1E3, 0}));
+}
+
+/*
+ * Parabola
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic) {
+ Position values[] = {
+ { 0000000, 1, 1 },
+ { 1000000, 4, 4 },
+ { 2000000, 8, 8 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 1
+ // -0.001, 4
+ // -0.000, 8
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({8, 4.5E3, 0.5E6}));
+}
+
+/*
+ * Parabola
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic2) {
+ Position values[] = {
+ { 0000000, 1, 1 },
+ { 1000000, 4, 4 },
+ { 2000000, 9, 9 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 1
+ // -0.001, 4
+ // -0.000, 9
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({9, 6E3, 1E6}));
+}
+
+/*
+ * Parabola :: y = x^2 :: the constant and linear coefficients are zero.
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic3) {
+ Position values[] = {
+ { 0000000, 4, 4 },
+ { 1000000, 1, 1 },
+ { 2000000, 0, 0 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 4
+ // -0.001, 1
+ // -0.000, 0
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 0E3, 1E6}));
+}
} // namespace android
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index a36911d..a5b3e89 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -24,8 +24,8 @@
#endif
HdrCapabilities::~HdrCapabilities() = default;
-HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) = default;
-HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) = default;
+HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) noexcept = default;
+HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) noexcept = default;
size_t HdrCapabilities::getFlattenedSize() const {
return sizeof(mMaxLuminance) +
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 4e98c28..65ac26c 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -37,8 +37,8 @@
mMinLuminance(minLuminance) {}
// Make this move-constructable and move-assignable
- HdrCapabilities(HdrCapabilities&& other);
- HdrCapabilities& operator=(HdrCapabilities&& other);
+ HdrCapabilities(HdrCapabilities&& other) noexcept;
+ HdrCapabilities& operator=(HdrCapabilities&& other) noexcept;
HdrCapabilities()
: mSupportedHdrTypes(),
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 69b6422..93091e3 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -13,10 +13,14 @@
// limitations under the License.
sourceFiles = [
+ "buffer_hub_base.cpp",
"buffer_hub_client.cpp",
+ "buffer_hub_metadata.cpp",
"buffer_hub_rpc.cpp",
+ "consumer_buffer.cpp",
"detached_buffer.cpp",
"ion_buffer.cpp",
+ "producer_buffer.cpp",
]
localIncludeFiles = [
@@ -66,3 +70,10 @@
name: "buffer_hub-test",
}
+cc_test {
+ srcs: ["buffer_hub_metadata-test.cpp"],
+ static_libs: ["libbufferhub"],
+ shared_libs: sharedLibraries,
+ header_libs: headerLibraries,
+ name: "buffer_hub_metadata-test",
+}
diff --git a/libs/vr/libbufferhub/buffer_hub_base.cpp b/libs/vr/libbufferhub/buffer_hub_base.cpp
new file mode 100644
index 0000000..b2bcda7
--- /dev/null
+++ b/libs/vr/libbufferhub/buffer_hub_base.cpp
@@ -0,0 +1,224 @@
+#include <poll.h>
+#include <sys/epoll.h>
+
+#include <pdx/default_transport/client_channel.h>
+#include <pdx/default_transport/client_channel_factory.h>
+#include <private/dvr/buffer_hub_base.h>
+
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Status;
+using android::pdx::default_transport::ClientChannel;
+using android::pdx::default_transport::ClientChannelFactory;
+
+namespace android {
+namespace dvr {
+
+BufferHubBase::BufferHubBase(LocalChannelHandle channel_handle)
+ : Client{pdx::default_transport::ClientChannel::Create(
+ std::move(channel_handle))},
+ id_(-1),
+ cid_(-1) {}
+BufferHubBase::BufferHubBase(const std::string& endpoint_path)
+ : Client{pdx::default_transport::ClientChannelFactory::Create(
+ endpoint_path)},
+ id_(-1),
+ cid_(-1) {}
+
+BufferHubBase::~BufferHubBase() {
+ if (metadata_header_ != nullptr) {
+ metadata_buffer_.Unlock();
+ }
+}
+
+Status<LocalChannelHandle> BufferHubBase::CreateConsumer() {
+ Status<LocalChannelHandle> status =
+ InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
+ ALOGE_IF(!status,
+ "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
+ status.GetErrorMessage().c_str());
+ return status;
+}
+
+int BufferHubBase::ImportBuffer() {
+ ATRACE_NAME("BufferHubBase::ImportBuffer");
+
+ Status<BufferDescription<LocalHandle>> status =
+ InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
+ if (!status) {
+ ALOGE("BufferHubBase::ImportBuffer: Failed to get buffer: %s",
+ status.GetErrorMessage().c_str());
+ return -status.error();
+ } else if (status.get().id() < 0) {
+ ALOGE("BufferHubBase::ImportBuffer: Received an invalid id!");
+ return -EIO;
+ }
+
+ auto buffer_desc = status.take();
+
+ // Stash the buffer id to replace the value in id_.
+ const int new_id = buffer_desc.id();
+
+ // Import the buffer.
+ IonBuffer ion_buffer;
+ ALOGD_IF(TRACE, "BufferHubBase::ImportBuffer: id=%d.", buffer_desc.id());
+
+ if (const int ret = buffer_desc.ImportBuffer(&ion_buffer))
+ return ret;
+
+ // Import the metadata.
+ IonBuffer metadata_buffer;
+ if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
+ ALOGE("Failed to import metadata buffer, error=%d", ret);
+ return ret;
+ }
+ size_t metadata_buf_size = metadata_buffer.width();
+ if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
+ ALOGE("BufferHubBase::ImportBuffer: metadata buffer too small: %zu",
+ metadata_buf_size);
+ return -ENOMEM;
+ }
+
+ // If all imports succee, replace the previous buffer and id.
+ buffer_ = std::move(ion_buffer);
+ metadata_buffer_ = std::move(metadata_buffer);
+ metadata_buf_size_ = metadata_buf_size;
+ user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize;
+
+ void* metadata_ptr = nullptr;
+ if (const int ret =
+ metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
+ /*y=*/0, metadata_buf_size_,
+ /*height=*/1, &metadata_ptr)) {
+ ALOGE("BufferHubBase::ImportBuffer: Failed to lock metadata.");
+ return ret;
+ }
+
+ // Set up shared fences.
+ shared_acquire_fence_ = buffer_desc.take_acquire_fence();
+ shared_release_fence_ = buffer_desc.take_release_fence();
+ if (!shared_acquire_fence_ || !shared_release_fence_) {
+ ALOGE("BufferHubBase::ImportBuffer: Failed to import shared fences.");
+ return -EIO;
+ }
+
+ metadata_header_ =
+ reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
+ if (user_metadata_size_) {
+ user_metadata_ptr_ =
+ reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) +
+ BufferHubDefs::kMetadataHeaderSize);
+ } else {
+ user_metadata_ptr_ = nullptr;
+ }
+
+ 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
+ // object. The std::atomic's constructor will not be called so that the
+ // original value stored in the memory region will be preserved.
+ buffer_state_ = &metadata_header_->buffer_state;
+ ALOGD_IF(TRACE,
+ "BufferHubBase::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
+ id(), buffer_state_->load());
+ fence_state_ = &metadata_header_->fence_state;
+ ALOGD_IF(TRACE,
+ "BufferHubBase::ImportBuffer: id=%d, fence_state=%" PRIx64 ".", id(),
+ fence_state_->load());
+
+ return 0;
+}
+
+int BufferHubBase::CheckMetadata(size_t user_metadata_size) const {
+ if (user_metadata_size && !user_metadata_ptr_) {
+ ALOGE("BufferHubBase::CheckMetadata: doesn't support custom metadata.");
+ return -EINVAL;
+ }
+ if (user_metadata_size > user_metadata_size_) {
+ ALOGE("BufferHubBase::CheckMetadata: too big: %zu, maximum: %zu.",
+ user_metadata_size, user_metadata_size_);
+ return -E2BIG;
+ }
+ return 0;
+}
+
+int BufferHubBase::UpdateSharedFence(const LocalHandle& new_fence,
+ const LocalHandle& shared_fence) {
+ if (pending_fence_fd_.Get() != new_fence.Get()) {
+ // First, replace the old fd if there was already one. Skipping if the new
+ // one is the same as the old.
+ if (pending_fence_fd_.IsValid()) {
+ const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL,
+ pending_fence_fd_.Get(), nullptr);
+ ALOGW_IF(ret,
+ "BufferHubBase::UpdateSharedFence: failed to remove old fence "
+ "fd from epoll set, error: %s.",
+ strerror(errno));
+ }
+
+ if (new_fence.IsValid()) {
+ // If ready fence is valid, we put that into the epoll set.
+ epoll_event event;
+ event.events = EPOLLIN;
+ event.data.u64 = buffer_state_bit();
+ pending_fence_fd_ = new_fence.Duplicate();
+ if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(),
+ &event) < 0) {
+ const int error = errno;
+ ALOGE(
+ "BufferHubBase::UpdateSharedFence: failed to add new fence fd "
+ "into epoll set, error: %s.",
+ strerror(error));
+ return -error;
+ }
+ // Set bit in fence state to indicate that there is a fence from this
+ // producer or consumer.
+ fence_state_->fetch_or(buffer_state_bit());
+ } else {
+ // Unset bit in fence state to indicate that there is no fence, so that
+ // when consumer to acquire or producer to acquire, it knows no need to
+ // check fence for this buffer.
+ fence_state_->fetch_and(~buffer_state_bit());
+ }
+ }
+
+ return 0;
+}
+
+int BufferHubBase::Poll(int timeout_ms) {
+ ATRACE_NAME("BufferHubBase::Poll");
+ pollfd p = {event_fd(), POLLIN, 0};
+ return poll(&p, 1, timeout_ms);
+}
+
+int BufferHubBase::Lock(int usage, int x, int y, int width, int height,
+ void** address) {
+ return buffer_.Lock(usage, x, y, width, height, address);
+}
+
+int BufferHubBase::Unlock() { return buffer_.Unlock(); }
+
+int BufferHubBase::GetBlobReadWritePointer(size_t size, void** addr) {
+ int width = static_cast<int>(size);
+ int height = 1;
+ int ret = Lock(usage(), 0, 0, width, height, addr);
+ if (ret == 0)
+ Unlock();
+ return ret;
+}
+
+int BufferHubBase::GetBlobReadOnlyPointer(size_t size, void** addr) {
+ return GetBlobReadWritePointer(size, addr);
+}
+
+void BufferHubBase::GetBlobFds(int* fds, size_t* fds_count,
+ size_t max_fds_count) const {
+ size_t numFds = static_cast<size_t>(native_handle()->numFds);
+ *fds_count = std::min(max_fds_count, numFds);
+ std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 577cba9..3f20024 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -1,20 +1,12 @@
-#include <private/dvr/buffer_hub_client.h>
-
-#include <log/log.h>
-#include <poll.h>
-#include <sys/epoll.h>
-#include <utils/Trace.h>
-
#include <mutex>
+#include <log/log.h>
#include <pdx/default_transport/client_channel.h>
#include <pdx/default_transport/client_channel_factory.h>
-
-#include "include/private/dvr/bufferhub_rpc.h"
+#include <private/dvr/buffer_hub_client.h>
+#include <utils/Trace.h>
using android::pdx::LocalChannelHandle;
-using android::pdx::LocalHandle;
-using android::pdx::Status;
using android::pdx::default_transport::ClientChannel;
using android::pdx::default_transport::ClientChannelFactory;
@@ -39,615 +31,5 @@
}
}
-BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
- : Client{pdx::default_transport::ClientChannel::Create(
- std::move(channel_handle))},
- id_(-1),
- cid_(-1) {}
-BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
- : Client{pdx::default_transport::ClientChannelFactory::Create(
- endpoint_path)},
- id_(-1),
- cid_(-1) {}
-
-BufferHubBuffer::~BufferHubBuffer() {
- if (metadata_header_ != nullptr) {
- metadata_buffer_.Unlock();
- }
-}
-
-Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
- Status<LocalChannelHandle> status =
- InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
- ALOGE_IF(!status,
- "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
- status.GetErrorMessage().c_str());
- return status;
-}
-
-int BufferHubBuffer::ImportBuffer() {
- ATRACE_NAME("BufferHubBuffer::ImportBuffer");
-
- Status<BufferDescription<LocalHandle>> status =
- InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
- if (!status) {
- ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- } else if (status.get().id() < 0) {
- ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!");
- return -EIO;
- }
-
- auto buffer_desc = status.take();
-
- // Stash the buffer id to replace the value in id_.
- const int new_id = buffer_desc.id();
-
- // Import the buffer.
- IonBuffer ion_buffer;
- ALOGD_IF(TRACE, "BufferHubBuffer::ImportBuffer: id=%d.", buffer_desc.id());
-
- if (const int ret = buffer_desc.ImportBuffer(&ion_buffer))
- return ret;
-
- // Import the metadata.
- IonBuffer metadata_buffer;
- if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
- ALOGE("Failed to import metadata buffer, error=%d", ret);
- return ret;
- }
- size_t metadata_buf_size = metadata_buffer.width();
- if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
- ALOGE("BufferHubBuffer::ImportBuffer: metadata buffer too small: %zu",
- metadata_buf_size);
- return -ENOMEM;
- }
-
- // If all imports succee, replace the previous buffer and id.
- buffer_ = std::move(ion_buffer);
- metadata_buffer_ = std::move(metadata_buffer);
- metadata_buf_size_ = metadata_buf_size;
- user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize;
-
- void* metadata_ptr = nullptr;
- if (const int ret =
- metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
- /*y=*/0, metadata_buf_size_,
- /*height=*/1, &metadata_ptr)) {
- ALOGE("BufferHubBuffer::ImportBuffer: Failed to lock metadata.");
- return ret;
- }
-
- // Set up shared fences.
- shared_acquire_fence_ = buffer_desc.take_acquire_fence();
- shared_release_fence_ = buffer_desc.take_release_fence();
- if (!shared_acquire_fence_ || !shared_release_fence_) {
- ALOGE("BufferHubBuffer::ImportBuffer: Failed to import shared fences.");
- return -EIO;
- }
-
- metadata_header_ =
- reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
- if (user_metadata_size_) {
- user_metadata_ptr_ =
- reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) +
- BufferHubDefs::kMetadataHeaderSize);
- } else {
- user_metadata_ptr_ = nullptr;
- }
-
- 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
- // object. The std::atomic's constructor will not be called so that the
- // original value stored in the memory region will be preserved.
- buffer_state_ = &metadata_header_->buffer_state;
- ALOGD_IF(TRACE,
- "BufferHubBuffer::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
- id(), buffer_state_->load());
- fence_state_ = &metadata_header_->fence_state;
- ALOGD_IF(TRACE,
- "BufferHubBuffer::ImportBuffer: id=%d, fence_state=%" PRIx64 ".",
- id(), fence_state_->load());
-
- return 0;
-}
-
-inline int BufferHubBuffer::CheckMetadata(size_t user_metadata_size) const {
- if (user_metadata_size && !user_metadata_ptr_) {
- ALOGE("BufferHubBuffer::CheckMetadata: doesn't support custom metadata.");
- return -EINVAL;
- }
- if (user_metadata_size > user_metadata_size_) {
- ALOGE("BufferHubBuffer::CheckMetadata: too big: %zu, maximum: %zu.",
- user_metadata_size, user_metadata_size_);
- return -E2BIG;
- }
- return 0;
-}
-
-int BufferHubBuffer::UpdateSharedFence(const LocalHandle& new_fence,
- const LocalHandle& shared_fence) {
- if (pending_fence_fd_.Get() != new_fence.Get()) {
- // First, replace the old fd if there was already one. Skipping if the new
- // one is the same as the old.
- if (pending_fence_fd_.IsValid()) {
- const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL,
- pending_fence_fd_.Get(), nullptr);
- ALOGW_IF(ret,
- "BufferHubBuffer::UpdateSharedFence: failed to remove old fence "
- "fd from epoll set, error: %s.",
- strerror(errno));
- }
-
- if (new_fence.IsValid()) {
- // If ready fence is valid, we put that into the epoll set.
- epoll_event event;
- event.events = EPOLLIN;
- event.data.u64 = buffer_state_bit();
- pending_fence_fd_ = new_fence.Duplicate();
- if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(),
- &event) < 0) {
- const int error = errno;
- ALOGE(
- "BufferHubBuffer::UpdateSharedFence: failed to add new fence fd "
- "into epoll set, error: %s.",
- strerror(error));
- return -error;
- }
- // Set bit in fence state to indicate that there is a fence from this
- // producer or consumer.
- fence_state_->fetch_or(buffer_state_bit());
- } else {
- // Unset bit in fence state to indicate that there is no fence, so that
- // when consumer to acquire or producer to acquire, it knows no need to
- // check fence for this buffer.
- fence_state_->fetch_and(~buffer_state_bit());
- }
- }
-
- return 0;
-}
-
-int BufferHubBuffer::Poll(int timeout_ms) {
- ATRACE_NAME("BufferHubBuffer::Poll");
- pollfd p = {event_fd(), POLLIN, 0};
- return poll(&p, 1, timeout_ms);
-}
-
-int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height,
- void** address) {
- return buffer_.Lock(usage, x, y, width, height, address);
-}
-
-int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
-
-int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
- int width = static_cast<int>(size);
- int height = 1;
- int ret = Lock(usage(), 0, 0, width, height, addr);
- if (ret == 0)
- Unlock();
- return ret;
-}
-
-int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
- return GetBlobReadWritePointer(size, addr);
-}
-
-void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
- size_t max_fds_count) const {
- size_t numFds = static_cast<size_t>(native_handle()->numFds);
- *fds_count = std::min(max_fds_count, numFds);
- std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
-}
-
-BufferConsumer::BufferConsumer(LocalChannelHandle channel)
- : BASE(std::move(channel)) {
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-std::unique_ptr<BufferConsumer> BufferConsumer::Import(
- LocalChannelHandle channel) {
- ATRACE_NAME("BufferConsumer::Import");
- ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value());
- return BufferConsumer::Create(std::move(channel));
-}
-
-std::unique_ptr<BufferConsumer> BufferConsumer::Import(
- Status<LocalChannelHandle> status) {
- return Import(status ? status.take()
- : LocalChannelHandle{nullptr, -status.error()});
-}
-
-int BufferConsumer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
- LocalHandle* out_fence) {
- if (!out_meta)
- return -EINVAL;
-
- // Only check producer bit and this consumer buffer's particular consumer bit.
- // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
- // is not set.
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
- ALOGE("BufferConsumer::LocalAcquire: not posted, id=%d state=%" PRIx64
- " buffer_state_bit=%" PRIx64 ".",
- id(), buffer_state, buffer_state_bit());
- return -EBUSY;
- }
-
- // Copy the canonical metadata.
- void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
- memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
- // Fill in the user_metadata_ptr in address space of the local process.
- if (out_meta->user_metadata_size) {
- out_meta->user_metadata_ptr =
- reinterpret_cast<uint64_t>(user_metadata_ptr_);
- } else {
- out_meta->user_metadata_ptr = 0;
- }
-
- uint64_t fence_state = fence_state_->load();
- // If there is an acquire fence from producer, we need to return it.
- if (fence_state & BufferHubDefs::kProducerStateBit) {
- *out_fence = shared_acquire_fence_.Duplicate();
- }
-
- // Set the consumer bit unique to this consumer.
- BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
- return 0;
-}
-
-int BufferConsumer::Acquire(LocalHandle* ready_fence) {
- return Acquire(ready_fence, nullptr, 0);
-}
-
-int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
- size_t user_metadata_size) {
- ATRACE_NAME("BufferConsumer::Acquire");
-
- if (const int error = CheckMetadata(user_metadata_size))
- return error;
-
- DvrNativeBufferMetadata canonical_meta;
- if (const int error = LocalAcquire(&canonical_meta, ready_fence))
- return error;
-
- if (meta && user_metadata_size) {
- void* metadata_src =
- reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
- if (metadata_src) {
- memcpy(meta, metadata_src, user_metadata_size);
- } else {
- ALOGW("BufferConsumer::Acquire: no user-defined metadata.");
- }
- }
-
- auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
- if (!status)
- return -status.error();
- return 0;
-}
-
-int BufferConsumer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
- LocalHandle* out_fence) {
- ATRACE_NAME("BufferConsumer::AcquireAsync");
-
- if (const int error = LocalAcquire(out_meta, out_fence))
- return error;
-
- auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
- if (!status)
- return -status.error();
- return 0;
-}
-
-int BufferConsumer::LocalRelease(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence) {
- if (const int error = CheckMetadata(meta->user_metadata_size))
- return error;
-
- // Check invalid state transition.
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
- ALOGE("BufferConsumer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
- id(), buffer_state);
- return -EBUSY;
- }
-
- // On release, only the user requested metadata is copied back into the shared
- // memory for metadata. Since there are multiple consumers, it doesn't make
- // sense to send the canonical metadata back to the producer. However, one of
- // the consumer can still choose to write up to user_metadata_size bytes of
- // data into user_metadata_ptr.
- if (meta->user_metadata_ptr && meta->user_metadata_size) {
- void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
- memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
- }
-
- // Send out the release fence through the shared epoll fd. Note that during
- // releasing the producer is not expected to be polling on the fence.
- if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
- return error;
-
- // For release operation, the client don't need to change the state as it's
- // bufferhubd's job to flip the produer bit once all consumers are released.
- return 0;
-}
-
-int BufferConsumer::Release(const LocalHandle& release_fence) {
- ATRACE_NAME("BufferConsumer::Release");
-
- DvrNativeBufferMetadata meta;
- if (const int error = LocalRelease(&meta, release_fence))
- return error;
-
- return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
- BorrowedFence(release_fence.Borrow())));
-}
-
-int BufferConsumer::ReleaseAsync() {
- DvrNativeBufferMetadata meta;
- return ReleaseAsync(&meta, LocalHandle());
-}
-
-int BufferConsumer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence) {
- ATRACE_NAME("BufferConsumer::ReleaseAsync");
-
- if (const int error = LocalRelease(meta, release_fence))
- return error;
-
- return ReturnStatusOrError(
- SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
-}
-
-int BufferConsumer::Discard() { return Release(LocalHandle()); }
-
-int BufferConsumer::SetIgnore(bool ignore) {
- return ReturnStatusOrError(
- InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
-}
-
-BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint64_t usage, size_t user_metadata_size)
- : BASE(BufferHubRPC::kClientPath) {
- ATRACE_NAME("BufferProducer::BufferProducer");
- ALOGD_IF(TRACE,
- "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
- "usage=%" PRIx64 " user_metadata_size=%zu",
- event_fd(), width, height, format, usage, user_metadata_size);
-
- auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, user_metadata_size);
- if (!status) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
- status.GetErrorMessage().c_str());
- Close(-status.error());
- return;
- }
-
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-BufferProducer::BufferProducer(uint64_t usage, size_t size)
- : BASE(BufferHubRPC::kClientPath) {
- ATRACE_NAME("BufferProducer::BufferProducer");
- ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%" PRIx64 " size=%zu",
- usage, size);
- const int width = static_cast<int>(size);
- const int height = 1;
- const int format = HAL_PIXEL_FORMAT_BLOB;
- const size_t user_metadata_size = 0;
-
- auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, user_metadata_size);
- if (!status) {
- ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
- status.GetErrorMessage().c_str());
- Close(-status.error());
- return;
- }
-
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-BufferProducer::BufferProducer(LocalChannelHandle channel)
- : BASE(std::move(channel)) {
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-int BufferProducer::LocalPost(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence) {
- if (const int error = CheckMetadata(meta->user_metadata_size))
- return error;
-
- // Check invalid state transition.
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferGained(buffer_state)) {
- ALOGE("BufferProducer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
- id(), buffer_state);
- return -EBUSY;
- }
-
- // Copy the canonical metadata.
- void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
- memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
- // Copy extra user requested metadata.
- if (meta->user_metadata_ptr && meta->user_metadata_size) {
- void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
- memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
- }
-
- // Send out the acquire fence through the shared epoll fd. Note that during
- // posting no consumer is not expected to be polling on the fence.
- if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
- return error;
-
- // Set the producer bit atomically to transit into posted state.
- BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
- BufferHubDefs::kProducerStateBit);
- return 0;
-}
-
-int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
- size_t user_metadata_size) {
- ATRACE_NAME("BufferProducer::Post");
-
- // Populate cononical metadata for posting.
- DvrNativeBufferMetadata canonical_meta;
- canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
- canonical_meta.user_metadata_size = user_metadata_size;
-
- if (const int error = LocalPost(&canonical_meta, ready_fence))
- return error;
-
- return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
- BorrowedFence(ready_fence.Borrow())));
-}
-
-int BufferProducer::PostAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence) {
- ATRACE_NAME("BufferProducer::PostAsync");
-
- if (const int error = LocalPost(meta, ready_fence))
- return error;
-
- return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
-}
-
-int BufferProducer::LocalGain(DvrNativeBufferMetadata* out_meta,
- LocalHandle* out_fence) {
- uint64_t buffer_state = buffer_state_->load();
- ALOGD_IF(TRACE, "BufferProducer::LocalGain: buffer=%d, state=%" PRIx64 ".",
- id(), buffer_state);
-
- if (!out_meta)
- return -EINVAL;
-
- if (!BufferHubDefs::IsBufferReleased(buffer_state)) {
- if (BufferHubDefs::IsBufferGained(buffer_state)) {
- // We don't want to log error when gaining a newly allocated
- // buffer.
- ALOGI("BufferProducer::LocalGain: already gained id=%d.", id());
- return -EALREADY;
- }
- ALOGE("BufferProducer::LocalGain: not released id=%d state=%" PRIx64 ".",
- id(), buffer_state);
- return -EBUSY;
- }
-
- // Canonical metadata is undefined on Gain. Except for user_metadata and
- // release_fence_mask. Fill in the user_metadata_ptr in address space of the
- // local process.
- if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
- out_meta->user_metadata_size =
- metadata_header_->metadata.user_metadata_size;
- out_meta->user_metadata_ptr =
- reinterpret_cast<uint64_t>(user_metadata_ptr_);
- } else {
- out_meta->user_metadata_size = 0;
- out_meta->user_metadata_ptr = 0;
- }
-
- uint64_t fence_state = fence_state_->load();
- // If there is an release fence from consumer, we need to return it.
- if (fence_state & BufferHubDefs::kConsumerStateMask) {
- *out_fence = shared_release_fence_.Duplicate();
- out_meta->release_fence_mask =
- fence_state & BufferHubDefs::kConsumerStateMask;
- }
-
- // Clear out all bits and the buffer is now back to gained state.
- buffer_state_->store(0ULL);
- return 0;
-}
-
-int BufferProducer::Gain(LocalHandle* release_fence) {
- ATRACE_NAME("BufferProducer::Gain");
-
- DvrNativeBufferMetadata meta;
- if (const int error = LocalGain(&meta, release_fence))
- return error;
-
- auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
- if (!status)
- return -status.error();
- return 0;
-}
-
-int BufferProducer::GainAsync(DvrNativeBufferMetadata* out_meta,
- LocalHandle* release_fence) {
- ATRACE_NAME("BufferProducer::GainAsync");
-
- if (const int error = LocalGain(out_meta, release_fence))
- return error;
-
- return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
-}
-
-int BufferProducer::GainAsync() {
- DvrNativeBufferMetadata meta;
- LocalHandle fence;
- return GainAsync(&meta, &fence);
-}
-
-std::unique_ptr<BufferProducer> BufferProducer::Import(
- LocalChannelHandle channel) {
- ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
- return BufferProducer::Create(std::move(channel));
-}
-
-std::unique_ptr<BufferProducer> BufferProducer::Import(
- Status<LocalChannelHandle> status) {
- return Import(status ? status.take()
- : LocalChannelHandle{nullptr, -status.error()});
-}
-
-Status<LocalChannelHandle> BufferProducer::Detach() {
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferGained(buffer_state)) {
- // Can only detach a BufferProducer when it's in gained state.
- ALOGW("BufferProducer::Detach: The buffer (id=%d, state=0x%" PRIx64
- ") is not in gained state.",
- id(), buffer_state);
- return {};
- }
-
- Status<LocalChannelHandle> status =
- InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>();
- ALOGE_IF(!status,
- "BufferProducer::Detach: Failed to detach buffer (id=%d): %s.", id(),
- status.GetErrorMessage().c_str());
- return status;
-}
-
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub_metadata-test.cpp b/libs/vr/libbufferhub/buffer_hub_metadata-test.cpp
new file mode 100644
index 0000000..8c1c01c
--- /dev/null
+++ b/libs/vr/libbufferhub/buffer_hub_metadata-test.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <private/dvr/buffer_hub_metadata.h>
+
+using android::dvr::BufferHubDefs::IsBufferGained;
+
+namespace android {
+namespace dvr {
+
+constexpr size_t kEmptyUserMetadataSize = 0;
+
+class BufferHubMetadataTest : public ::testing::Test {};
+
+TEST_F(BufferHubMetadataTest, Create_UserMetdataSizeTooBig) {
+ BufferHubMetadata m1 =
+ BufferHubMetadata::Create(std::numeric_limits<uint32_t>::max());
+ EXPECT_FALSE(m1.IsValid());
+}
+
+TEST_F(BufferHubMetadataTest, Create_Success) {
+ BufferHubMetadata m1 = BufferHubMetadata::Create(kEmptyUserMetadataSize);
+ EXPECT_TRUE(m1.IsValid());
+ EXPECT_NE(m1.metadata_header(), nullptr);
+}
+
+TEST_F(BufferHubMetadataTest, Import_Success) {
+ BufferHubMetadata m1 = BufferHubMetadata::Create(kEmptyUserMetadataSize);
+ EXPECT_TRUE(m1.IsValid());
+ EXPECT_NE(m1.metadata_header(), nullptr);
+
+ pdx::LocalHandle h2 = m1.ashmem_handle().Duplicate();
+ EXPECT_TRUE(h2.IsValid());
+
+ BufferHubMetadata m2 = BufferHubMetadata::Import(std::move(h2));
+ EXPECT_FALSE(h2.IsValid());
+ EXPECT_TRUE(m1.IsValid());
+ BufferHubDefs::MetadataHeader* mh1 = m1.metadata_header();
+ EXPECT_NE(mh1, nullptr);
+
+ // TODO(b/111976433): Update this test once BufferHub state machine gets
+ // updated. In the old model, buffer starts in the gained state (i.e.
+ // valued 0). In the new model, buffer states in the released state.
+ EXPECT_TRUE(IsBufferGained(mh1->fence_state.load()));
+
+ EXPECT_TRUE(m2.IsValid());
+ BufferHubDefs::MetadataHeader* mh2 = m2.metadata_header();
+ EXPECT_NE(mh2, nullptr);
+
+ // TODO(b/111976433): Update this test once BufferHub state machine gets
+ // updated. In the old model, buffer starts in the gained state (i.e.
+ // valued 0). In the new model, buffer states in the released state.
+ EXPECT_TRUE(IsBufferGained(mh2->fence_state.load()));
+}
+
+TEST_F(BufferHubMetadataTest, MoveMetadataInvalidatesOldOne) {
+ BufferHubMetadata m1 = BufferHubMetadata::Create(sizeof(int));
+ EXPECT_TRUE(m1.IsValid());
+ EXPECT_NE(m1.metadata_header(), nullptr);
+ EXPECT_TRUE(m1.ashmem_handle().IsValid());
+ EXPECT_EQ(m1.user_metadata_size(), sizeof(int));
+
+ BufferHubMetadata m2 = std::move(m1);
+
+ // After the move, the metadata header (a raw pointer) should be reset in the
+ // older buffer.
+ EXPECT_EQ(m1.metadata_header(), nullptr);
+ EXPECT_NE(m2.metadata_header(), nullptr);
+
+ EXPECT_FALSE(m1.ashmem_handle().IsValid());
+ EXPECT_TRUE(m2.ashmem_handle().IsValid());
+
+ EXPECT_EQ(m1.user_metadata_size(), 0U);
+ EXPECT_EQ(m2.user_metadata_size(), sizeof(int));
+
+ BufferHubMetadata m3{std::move(m2)};
+
+ // After the move, the metadata header (a raw pointer) should be reset in the
+ // older buffer.
+ EXPECT_EQ(m2.metadata_header(), nullptr);
+ EXPECT_NE(m3.metadata_header(), nullptr);
+
+ EXPECT_FALSE(m2.ashmem_handle().IsValid());
+ EXPECT_TRUE(m3.ashmem_handle().IsValid());
+
+ EXPECT_EQ(m2.user_metadata_size(), 0U);
+ EXPECT_EQ(m3.user_metadata_size(), sizeof(int));
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub_metadata.cpp b/libs/vr/libbufferhub/buffer_hub_metadata.cpp
new file mode 100644
index 0000000..8243fc5
--- /dev/null
+++ b/libs/vr/libbufferhub/buffer_hub_metadata.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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 <errno.h>
+#include <sys/mman.h>
+
+#include <cutils/ashmem.h>
+#include <log/log.h>
+#include <private/dvr/buffer_hub_metadata.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+static const int kAshmemProt = PROT_READ | PROT_WRITE;
+
+} // namespace
+
+using BufferHubDefs::kMetadataHeaderSize;
+using BufferHubDefs::MetadataHeader;
+
+/* static */
+BufferHubMetadata BufferHubMetadata::Create(size_t 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() - kMetadataHeaderSize)) {
+ ALOGE("BufferHubMetadata::Create: metadata size too big: %zu.",
+ user_metadata_size);
+ return {};
+ }
+
+ const size_t metadata_size = user_metadata_size + kMetadataHeaderSize;
+ int fd = ashmem_create_region(/*name=*/"BufferHubMetadata", metadata_size);
+ if (fd < 0) {
+ ALOGE("BufferHubMetadata::Create: failed to create ashmem region.");
+ return {};
+ }
+
+ // Hand over the ownership of the fd to a pdx::LocalHandle immediately after
+ // the successful return of ashmem_create_region. The ashmem_handle is going
+ // to own the fd and to prevent fd leaks during error handling.
+ pdx::LocalHandle ashmem_handle{fd};
+
+ if (ashmem_set_prot_region(ashmem_handle.Get(), kAshmemProt) != 0) {
+ ALOGE("BufferHubMetadata::Create: failed to set protect region.");
+ return {};
+ }
+
+ return BufferHubMetadata::Import(std::move(ashmem_handle));
+}
+
+/* static */
+BufferHubMetadata BufferHubMetadata::Import(pdx::LocalHandle ashmem_handle) {
+ if (!ashmem_valid(ashmem_handle.Get())) {
+ ALOGE("BufferHubMetadata::Import: invalid ashmem fd.");
+ return {};
+ }
+
+ size_t metadata_size = ashmem_get_size_region(ashmem_handle.Get());
+ size_t user_metadata_size = metadata_size - kMetadataHeaderSize;
+
+ auto metadata_header = static_cast<MetadataHeader*>(
+ mmap(nullptr, metadata_size, kAshmemProt, MAP_SHARED, ashmem_handle.Get(),
+ /*offset=*/0));
+ if (metadata_header == nullptr) {
+ ALOGE("BufferHubMetadata::Import: failed to map region.");
+ return {};
+ }
+
+ return BufferHubMetadata(user_metadata_size, std::move(ashmem_handle),
+ metadata_header);
+}
+
+BufferHubMetadata::BufferHubMetadata(size_t user_metadata_size,
+ pdx::LocalHandle ashmem_handle,
+ MetadataHeader* metadata_header)
+ : user_metadata_size_(user_metadata_size),
+ ashmem_handle_(std::move(ashmem_handle)),
+ metadata_header_(metadata_header) {}
+
+BufferHubMetadata::~BufferHubMetadata() {
+ if (metadata_header_ != nullptr) {
+ int ret = munmap(metadata_header_, metadata_size());
+ ALOGE_IF(ret != 0,
+ "BufferHubMetadata::~BufferHubMetadata: failed to unmap ashmem, "
+ "error=%d.",
+ errno);
+ metadata_header_ = nullptr;
+ }
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
new file mode 100644
index 0000000..4e8c36b
--- /dev/null
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -0,0 +1,183 @@
+#include <private/dvr/consumer_buffer.h>
+
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Status;
+
+namespace android {
+namespace dvr {
+
+ConsumerBuffer::ConsumerBuffer(LocalChannelHandle channel)
+ : BASE(std::move(channel)) {
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE("ConsumerBuffer::ConsumerBuffer: Failed to import buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import(
+ LocalChannelHandle channel) {
+ ATRACE_NAME("ConsumerBuffer::Import");
+ ALOGD_IF(TRACE, "ConsumerBuffer::Import: channel=%d", channel.value());
+ return ConsumerBuffer::Create(std::move(channel));
+}
+
+std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import(
+ Status<LocalChannelHandle> status) {
+ return Import(status ? status.take()
+ : LocalChannelHandle{nullptr, -status.error()});
+}
+
+int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* out_fence) {
+ if (!out_meta)
+ return -EINVAL;
+
+ // Only check producer bit and this consumer buffer's particular consumer bit.
+ // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
+ // is not set.
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
+ ALOGE("ConsumerBuffer::LocalAcquire: not posted, id=%d state=%" PRIx64
+ " buffer_state_bit=%" PRIx64 ".",
+ id(), buffer_state, buffer_state_bit());
+ return -EBUSY;
+ }
+
+ // Copy the canonical metadata.
+ void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
+ memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
+ // Fill in the user_metadata_ptr in address space of the local process.
+ if (out_meta->user_metadata_size) {
+ out_meta->user_metadata_ptr =
+ reinterpret_cast<uint64_t>(user_metadata_ptr_);
+ } else {
+ out_meta->user_metadata_ptr = 0;
+ }
+
+ uint64_t fence_state = fence_state_->load();
+ // If there is an acquire fence from producer, we need to return it.
+ if (fence_state & BufferHubDefs::kProducerStateBit) {
+ *out_fence = shared_acquire_fence_.Duplicate();
+ }
+
+ // Set the consumer bit unique to this consumer.
+ BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
+ return 0;
+}
+
+int ConsumerBuffer::Acquire(LocalHandle* ready_fence) {
+ return Acquire(ready_fence, nullptr, 0);
+}
+
+int ConsumerBuffer::Acquire(LocalHandle* ready_fence, void* meta,
+ size_t user_metadata_size) {
+ ATRACE_NAME("ConsumerBuffer::Acquire");
+
+ if (const int error = CheckMetadata(user_metadata_size))
+ return error;
+
+ DvrNativeBufferMetadata canonical_meta;
+ if (const int error = LocalAcquire(&canonical_meta, ready_fence))
+ return error;
+
+ if (meta && user_metadata_size) {
+ void* metadata_src =
+ reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
+ if (metadata_src) {
+ memcpy(meta, metadata_src, user_metadata_size);
+ } else {
+ ALOGW("ConsumerBuffer::Acquire: no user-defined metadata.");
+ }
+ }
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
+ if (!status)
+ return -status.error();
+ return 0;
+}
+
+int ConsumerBuffer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* out_fence) {
+ ATRACE_NAME("ConsumerBuffer::AcquireAsync");
+
+ if (const int error = LocalAcquire(out_meta, out_fence))
+ return error;
+
+ auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
+ if (!status)
+ return -status.error();
+ return 0;
+}
+
+int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence) {
+ if (const int error = CheckMetadata(meta->user_metadata_size))
+ return error;
+
+ // Check invalid state transition.
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
+ ALOGE("ConsumerBuffer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
+ id(), buffer_state);
+ return -EBUSY;
+ }
+
+ // On release, only the user requested metadata is copied back into the shared
+ // memory for metadata. Since there are multiple consumers, it doesn't make
+ // sense to send the canonical metadata back to the producer. However, one of
+ // the consumer can still choose to write up to user_metadata_size bytes of
+ // data into user_metadata_ptr.
+ if (meta->user_metadata_ptr && meta->user_metadata_size) {
+ void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
+ memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
+ }
+
+ // Send out the release fence through the shared epoll fd. Note that during
+ // releasing the producer is not expected to be polling on the fence.
+ if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
+ return error;
+
+ // For release operation, the client don't need to change the state as it's
+ // bufferhubd's job to flip the produer bit once all consumers are released.
+ return 0;
+}
+
+int ConsumerBuffer::Release(const LocalHandle& release_fence) {
+ ATRACE_NAME("ConsumerBuffer::Release");
+
+ DvrNativeBufferMetadata meta;
+ if (const int error = LocalRelease(&meta, release_fence))
+ return error;
+
+ return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
+ BorrowedFence(release_fence.Borrow())));
+}
+
+int ConsumerBuffer::ReleaseAsync() {
+ DvrNativeBufferMetadata meta;
+ return ReleaseAsync(&meta, LocalHandle());
+}
+
+int ConsumerBuffer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence) {
+ ATRACE_NAME("ConsumerBuffer::ReleaseAsync");
+
+ if (const int error = LocalRelease(meta, release_fence))
+ return error;
+
+ return ReturnStatusOrError(
+ SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
+}
+
+int ConsumerBuffer::Discard() { return Release(LocalHandle()); }
+
+int ConsumerBuffer::SetIgnore(bool ignore) {
+ return ReturnStatusOrError(
+ InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
new file mode 100644
index 0000000..24db241
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -0,0 +1,172 @@
+#ifndef ANDROID_DVR_BUFFER_HUB_BASE_H_
+#define ANDROID_DVR_BUFFER_HUB_BASE_H_
+
+#include <vector>
+
+#include <private/dvr/bufferhub_rpc.h>
+
+namespace android {
+namespace dvr {
+
+// Base class of two types of BufferHub clients: dvr::ProducerBuffer and
+// dvr::ConsumerBuffer.
+class BufferHubBase : public pdx::Client {
+ public:
+ using LocalHandle = pdx::LocalHandle;
+ using LocalChannelHandle = pdx::LocalChannelHandle;
+ template <typename T>
+ using Status = pdx::Status<T>;
+
+ // Create a new consumer channel that is attached to the producer. Returns
+ // a file descriptor for the new channel or a negative error code.
+ Status<LocalChannelHandle> CreateConsumer();
+
+ // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
+ int Poll(int timeout_ms);
+
+ // Locks the area specified by (x, y, width, height) for a specific usage. If
+ // the usage is software then |addr| will be updated to point to the address
+ // of the buffer in virtual memory. The caller should only access/modify the
+ // pixels in the specified area. anything else is undefined behavior.
+ int Lock(int usage, int x, int y, int width, int height, void** addr);
+
+ // Must be called after Lock() when the caller has finished changing the
+ // buffer.
+ int Unlock();
+
+ // Gets a blob buffer that was created with ProducerBuffer::CreateBlob.
+ // Locking and Unlocking is handled internally. There's no need to Unlock
+ // after calling this method.
+ int GetBlobReadWritePointer(size_t size, void** addr);
+
+ // Gets a blob buffer that was created with ProducerBuffer::CreateBlob.
+ // Locking and Unlocking is handled internally. There's no need to Unlock
+ // after calling this method.
+ int GetBlobReadOnlyPointer(size_t size, void** addr);
+
+ // Returns a dup'd file descriptor for accessing the blob shared memory. The
+ // caller takes ownership of the file descriptor and must close it or pass on
+ // ownership. Some GPU API extensions can take file descriptors to bind shared
+ // memory gralloc buffers to GPU buffer objects.
+ LocalHandle GetBlobFd() const {
+ // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
+ // vendors and this is the wrong fd, late-latching and EDS will very clearly
+ // stop working and we will need to correct this. The alternative is to use
+ // a GL context in the pose service to allocate this buffer or to use the
+ // ION API directly instead of gralloc.
+ return LocalHandle(dup(native_handle()->data[0]));
+ }
+
+ // Get up to |max_fds_count| file descriptors for accessing the blob shared
+ // memory. |fds_count| will contain the actual number of file descriptors.
+ void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
+
+ using Client::event_fd;
+
+ Status<int> GetEventMask(int events) {
+ if (auto* client_channel = GetChannel()) {
+ return client_channel->GetEventMask(events);
+ } else {
+ return pdx::ErrorStatus(EINVAL);
+ }
+ }
+
+ std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
+ if (auto* client_channel = GetChannel()) {
+ return client_channel->GetEventSources();
+ } else {
+ return {};
+ }
+ }
+
+ native_handle_t* native_handle() const {
+ return const_cast<native_handle_t*>(buffer_.handle());
+ }
+
+ IonBuffer* buffer() { return &buffer_; }
+ const IonBuffer* buffer() const { return &buffer_; }
+
+ // Gets ID of the buffer client. All BufferHub 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 BufferHub 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(); };
+
+ // A state mask which is unique to a buffer hub client among all its siblings
+ // sharing the same concrete graphic buffer.
+ uint64_t buffer_state_bit() const { return buffer_state_bit_; }
+
+ // The following methods return settings of the first buffer. Currently,
+ // it is only possible to create multi-buffer BufferHubBases with the same
+ // settings.
+ uint32_t width() const { return buffer_.width(); }
+ uint32_t height() const { return buffer_.height(); }
+ uint32_t stride() const { return buffer_.stride(); }
+ uint32_t format() const { return buffer_.format(); }
+ uint32_t usage() const { return buffer_.usage(); }
+ uint32_t layer_count() const { return buffer_.layer_count(); }
+
+ uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
+ void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
+
+ protected:
+ explicit BufferHubBase(LocalChannelHandle channel);
+ explicit BufferHubBase(const std::string& endpoint_path);
+ virtual ~BufferHubBase();
+
+ // Initialization helper.
+ int ImportBuffer();
+
+ // Check invalid metadata operation. Returns 0 if requested metadata is valid.
+ int CheckMetadata(size_t user_metadata_size) const;
+
+ // Send out the new fence by updating the shared fence (shared_release_fence
+ // for producer and shared_acquire_fence for consumer). Note that during this
+ // should only be used in LocalPost() or LocalRelease, and the shared fence
+ // shouldn't be poll'ed by the other end.
+ int UpdateSharedFence(const LocalHandle& new_fence,
+ const LocalHandle& shared_fence);
+
+ // IonBuffer that is shared between bufferhubd, producer, and consumers.
+ size_t metadata_buf_size_{0};
+ size_t user_metadata_size_{0};
+ BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
+ void* user_metadata_ptr_{nullptr};
+ std::atomic<uint64_t>* buffer_state_{nullptr};
+ std::atomic<uint64_t>* fence_state_{nullptr};
+
+ LocalHandle shared_acquire_fence_;
+ LocalHandle shared_release_fence_;
+
+ // A local fence fd that holds the ownership of the fence fd on Post (for
+ // producer) and Release (for consumer).
+ LocalHandle pending_fence_fd_;
+
+ private:
+ BufferHubBase(const BufferHubBase&) = delete;
+ void operator=(const BufferHubBase&) = delete;
+
+ // Global id for the buffer that is consistent across processes. It is meant
+ // for logging and debugging purposes only and should not be used for lookup
+ // or any other functional purpose as a security precaution.
+ int id_;
+
+ // Channel id.
+ int cid_;
+
+ // Client bit mask which indicates the locations of this client object in the
+ // buffer_state_.
+ uint64_t buffer_state_bit_{0ULL};
+ IonBuffer buffer_;
+ IonBuffer metadata_buffer_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_BUFFER_HUB_BASE_H_
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 0b2666a..7b317d1 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -1,17 +1,10 @@
#ifndef ANDROID_DVR_BUFFER_HUB_CLIENT_H_
#define ANDROID_DVR_BUFFER_HUB_CLIENT_H_
-#include <hardware/gralloc.h>
#include <pdx/channel_handle.h>
#include <pdx/client.h>
-#include <pdx/file_handle.h>
-#include <pdx/status.h>
-
-#include <vector>
-
-#include <private/dvr/ion_buffer.h>
-
-#include "bufferhub_rpc.h"
+#include <private/dvr/consumer_buffer.h>
+#include <private/dvr/producer_buffer.h>
namespace android {
namespace dvr {
@@ -31,322 +24,6 @@
using pdx::Client::event_fd;
};
-class BufferHubBuffer : public pdx::Client {
- public:
- using LocalHandle = pdx::LocalHandle;
- using LocalChannelHandle = pdx::LocalChannelHandle;
- template <typename T>
- using Status = pdx::Status<T>;
-
- // Create a new consumer channel that is attached to the producer. Returns
- // a file descriptor for the new channel or a negative error code.
- Status<LocalChannelHandle> CreateConsumer();
-
- // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
- int Poll(int timeout_ms);
-
- // Locks the area specified by (x, y, width, height) for a specific usage. If
- // the usage is software then |addr| will be updated to point to the address
- // of the buffer in virtual memory. The caller should only access/modify the
- // pixels in the specified area. anything else is undefined behavior.
- int Lock(int usage, int x, int y, int width, int height, void** addr);
-
- // Must be called after Lock() when the caller has finished changing the
- // buffer.
- int Unlock();
-
- // Gets a blob buffer that was created with BufferProducer::CreateBlob.
- // Locking and Unlocking is handled internally. There's no need to Unlock
- // after calling this method.
- int GetBlobReadWritePointer(size_t size, void** addr);
-
- // Gets a blob buffer that was created with BufferProducer::CreateBlob.
- // Locking and Unlocking is handled internally. There's no need to Unlock
- // after calling this method.
- int GetBlobReadOnlyPointer(size_t size, void** addr);
-
- // Returns a dup'd file descriptor for accessing the blob shared memory. The
- // caller takes ownership of the file descriptor and must close it or pass on
- // ownership. Some GPU API extensions can take file descriptors to bind shared
- // memory gralloc buffers to GPU buffer objects.
- LocalHandle GetBlobFd() const {
- // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
- // vendors and this is the wrong fd, late-latching and EDS will very clearly
- // stop working and we will need to correct this. The alternative is to use
- // a GL context in the pose service to allocate this buffer or to use the
- // ION API directly instead of gralloc.
- return LocalHandle(dup(native_handle()->data[0]));
- }
-
- // Get up to |max_fds_count| file descriptors for accessing the blob shared
- // memory. |fds_count| will contain the actual number of file descriptors.
- void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
-
- using Client::event_fd;
-
- Status<int> GetEventMask(int events) {
- if (auto* client_channel = GetChannel()) {
- return client_channel->GetEventMask(events);
- } else {
- return pdx::ErrorStatus(EINVAL);
- }
- }
-
- std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
- if (auto* client_channel = GetChannel()) {
- return client_channel->GetEventSources();
- } else {
- return {};
- }
- }
-
- native_handle_t* native_handle() const {
- return const_cast<native_handle_t*>(buffer_.handle());
- }
-
- 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(); };
-
- // A state mask which is unique to a buffer hub client among all its siblings
- // sharing the same concrete graphic buffer.
- uint64_t buffer_state_bit() const { return buffer_state_bit_; }
-
- // The following methods return settings of the first buffer. Currently,
- // it is only possible to create multi-buffer BufferHubBuffers with the same
- // settings.
- uint32_t width() const { return buffer_.width(); }
- uint32_t height() const { return buffer_.height(); }
- uint32_t stride() const { return buffer_.stride(); }
- uint32_t format() const { return buffer_.format(); }
- uint32_t usage() const { return buffer_.usage(); }
- uint32_t layer_count() const { return buffer_.layer_count(); }
-
- uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
- void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
-
- protected:
- explicit BufferHubBuffer(LocalChannelHandle channel);
- explicit BufferHubBuffer(const std::string& endpoint_path);
- virtual ~BufferHubBuffer();
-
- // Initialization helper.
- int ImportBuffer();
-
- // Check invalid metadata operation. Returns 0 if requested metadata is valid.
- int CheckMetadata(size_t user_metadata_size) const;
-
- // Send out the new fence by updating the shared fence (shared_release_fence
- // for producer and shared_acquire_fence for consumer). Note that during this
- // should only be used in LocalPost() or LocalRelease, and the shared fence
- // shouldn't be poll'ed by the other end.
- int UpdateSharedFence(const LocalHandle& new_fence,
- const LocalHandle& shared_fence);
-
- // IonBuffer that is shared between bufferhubd, producer, and consumers.
- size_t metadata_buf_size_{0};
- size_t user_metadata_size_{0};
- BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
- void* user_metadata_ptr_{nullptr};
- std::atomic<uint64_t>* buffer_state_{nullptr};
- std::atomic<uint64_t>* fence_state_{nullptr};
-
- LocalHandle shared_acquire_fence_;
- LocalHandle shared_release_fence_;
-
- // A local fence fd that holds the ownership of the fence fd on Post (for
- // producer) and Release (for consumer).
- LocalHandle pending_fence_fd_;
-
- private:
- BufferHubBuffer(const BufferHubBuffer&) = delete;
- void operator=(const BufferHubBuffer&) = delete;
-
- // Global id for the buffer that is consistent across processes. It is meant
- // 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_;
-};
-
-// This represents a writable buffer. Calling Post notifies all clients and
-// makes the buffer read-only. Call Gain to acquire write access. A buffer
-// may have many consumers.
-//
-// The user of BufferProducer is responsible with making sure that the Post() is
-// done with the correct metadata type and size. The user is also responsible
-// for making sure that remote ends (BufferConsumers) are also using the correct
-// metadata when acquiring the buffer. The API guarantees that a Post() with a
-// metadata of wrong size will fail. However, it currently does not do any
-// type checking.
-// The API also assumes that metadata is a serializable type (plain old data).
-class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
- public:
- // Imports a bufferhub producer channel, assuming ownership of its handle.
- static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel);
- static std::unique_ptr<BufferProducer> Import(
- Status<LocalChannelHandle> status);
-
- // Asynchronously posts a buffer. The fence and metadata are passed to
- // consumer via shared fd and shared memory.
- int PostAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence);
-
- // Post this buffer, passing |ready_fence| to the consumers. The bytes in
- // |meta| are passed unaltered to the consumers. The producer must not modify
- // the buffer until it is re-gained.
- // This returns zero or a negative unix error code.
- int Post(const LocalHandle& ready_fence, const void* meta,
- size_t user_metadata_size);
-
- int Post(const LocalHandle& ready_fence) {
- return Post(ready_fence, nullptr, 0);
- }
-
- template <typename Meta, typename = typename std::enable_if<
- !std::is_void<Meta>::value>::type>
- int Post(const LocalHandle& ready_fence, const Meta& meta) {
- return Post(ready_fence, &meta, sizeof(meta));
- }
-
- // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
- // must be waited on before using the buffer. If it is not valid then the
- // buffer is free for immediate use. This call will only succeed if the buffer
- // is in the released state.
- // This returns zero or a negative unix error code.
- int Gain(LocalHandle* release_fence);
- int GainAsync();
-
- // Asynchronously marks a released buffer as gained. This method is similar to
- // the synchronous version above, except that it does not wait for BufferHub
- // to acknowledge success or failure. Because of the asynchronous nature of
- // the underlying message, no error is returned if this method is called when
- // the buffer is in an incorrect state. Returns zero if sending the message
- // succeeded, or a negative errno code if local error check fails.
- int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
-
- // Detaches a ProducerBuffer from an existing producer/consumer set. Can only
- // be called when a producer buffer has exclusive access to the buffer (i.e.
- // in the gain'ed state). On the successful return of the IPC call, a new
- // LocalChannelHandle representing a detached buffer will be returned and all
- // existing producer and consumer channels will be closed. Further IPCs
- // towards those channels will return error.
- Status<LocalChannelHandle> Detach();
-
- private:
- friend BASE;
-
- // Constructors are automatically exposed through BufferProducer::Create(...)
- // static template methods inherited from ClientBase, which take the same
- // arguments as the constructors.
-
- // Constructs a buffer with the given geometry and parameters.
- BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint64_t usage, size_t metadata_size = 0);
-
- // Constructs a blob (flat) buffer with the given usage flags.
- BufferProducer(uint64_t usage, size_t size);
-
- // Imports the given file handle to a producer channel, taking ownership.
- explicit BufferProducer(LocalChannelHandle channel);
-
- // Local state transition helpers.
- int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
- int LocalPost(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence);
-};
-
-// This is a connection to a producer buffer, which can be located in another
-// application. When that buffer is Post()ed, this fd will be signaled and
-// Acquire allows read access. The user is responsible for making sure that
-// Acquire is called with the correct metadata structure. The only guarantee the
-// API currently provides is that an Acquire() with metadata of the wrong size
-// will fail.
-class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
- public:
- // This call assumes ownership of |fd|.
- static std::unique_ptr<BufferConsumer> Import(LocalChannelHandle channel);
- static std::unique_ptr<BufferConsumer> Import(
- Status<LocalChannelHandle> status);
-
- // Attempt to retrieve a post event from buffer hub. If successful,
- // |ready_fence| will be set to a fence to wait on until the buffer is ready.
- // This call will only succeed after the fd is signalled. This call may be
- // performed as an alternative to the Acquire() with metadata. In such cases
- // the metadata is not read.
- //
- // This returns zero or negative unix error code.
- int Acquire(LocalHandle* ready_fence);
-
- // Attempt to retrieve a post event from buffer hub. If successful,
- // |ready_fence| is set to a fence signaling that the contents of the buffer
- // are available. This call will only succeed if the buffer is in the posted
- // state.
- // Returns zero on success, or a negative errno code otherwise.
- int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
-
- // Attempt to retrieve a post event from buffer hub. If successful,
- // |ready_fence| is set to a fence to wait on until the buffer is ready. This
- // call will only succeed after the fd is signaled. This returns zero or a
- // negative unix error code.
- template <typename Meta>
- int Acquire(LocalHandle* ready_fence, Meta* meta) {
- return Acquire(ready_fence, meta, sizeof(*meta));
- }
-
- // Asynchronously acquires a bufer.
- int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
-
- // This should be called after a successful Acquire call. If the fence is
- // valid the fence determines the buffer usage, otherwise the buffer is
- // released immediately.
- // This returns zero or a negative unix error code.
- int Release(const LocalHandle& release_fence);
- int ReleaseAsync();
-
- // Asynchronously releases a buffer. Similar to the synchronous version above,
- // except that it does not wait for BufferHub to reply with success or error.
- // The fence and metadata are passed to consumer via shared fd and shared
- // memory.
- int ReleaseAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence);
-
- // May be called after or instead of Acquire to indicate that the consumer
- // does not need to access the buffer this cycle. This returns zero or a
- // negative unix error code.
- int Discard();
-
- // When set, this consumer is no longer notified when this buffer is
- // available. The system behaves as if Discard() is immediately called
- // whenever the buffer is posted. If ignore is set to true while a buffer is
- // pending, it will act as if Discard() was also called.
- // This returns zero or a negative unix error code.
- int SetIgnore(bool ignore);
-
- private:
- friend BASE;
-
- explicit BufferConsumer(LocalChannelHandle channel);
-
- // Local state transition helpers.
- int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
- int LocalRelease(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence);
-};
-
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_metadata.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_metadata.h
new file mode 100644
index 0000000..980ade7
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_metadata.h
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_DVR_BUFFER_HUB_METADATA_H_
+#define ANDROID_DVR_BUFFER_HUB_METADATA_H_
+
+#include <pdx/file_handle.h>
+#include <private/dvr/buffer_hub_defs.h>
+
+namespace android {
+namespace dvr {
+
+class BufferHubMetadata {
+ public:
+ // Creates a new BufferHubMetadata backed by an ashmem region.
+ //
+ // @param user_metadata_size Size in bytes of the user defined metadata. The
+ // entire metadata shared memory region to be allocated is the size of
+ // canonical BufferHubDefs::MetadataHeader plus user_metadata_size.
+ static BufferHubMetadata Create(size_t user_metadata_size);
+
+ // Imports an existing BufferHubMetadata from an ashmem FD.
+ //
+ // TODO(b/112338294): Refactor BufferHub to use Binder as its internal IPC
+ // backend instead of UDS.
+ //
+ // @param ashmem_handle Ashmem file handle representing an ashmem region.
+ static BufferHubMetadata Import(pdx::LocalHandle ashmem_handle);
+
+ BufferHubMetadata() = default;
+
+ BufferHubMetadata(BufferHubMetadata&& other) { *this = std::move(other); }
+
+ ~BufferHubMetadata();
+
+ BufferHubMetadata& operator=(BufferHubMetadata&& other) {
+ if (this != &other) {
+ user_metadata_size_ = other.user_metadata_size_;
+ other.user_metadata_size_ = 0;
+
+ ashmem_handle_ = std::move(other.ashmem_handle_);
+
+ // The old raw metadata_header_ pointer must be cleared, otherwise the
+ // destructor will automatically mummap() the shared memory.
+ metadata_header_ = other.metadata_header_;
+ other.metadata_header_ = nullptr;
+ }
+ return *this;
+ }
+
+ // Returns true if the metadata is valid, i.e. the metadata has a valid ashmem
+ // fd and the ashmem has been mapped into virtual address space.
+ bool IsValid() const {
+ return ashmem_handle_.IsValid() && metadata_header_ != nullptr;
+ }
+
+ size_t user_metadata_size() const { return user_metadata_size_; }
+ size_t metadata_size() const {
+ return user_metadata_size_ + BufferHubDefs::kMetadataHeaderSize;
+ }
+
+ const pdx::LocalHandle& ashmem_handle() const { return ashmem_handle_; }
+ BufferHubDefs::MetadataHeader* metadata_header() { return metadata_header_; }
+
+ private:
+ BufferHubMetadata(size_t user_metadata_size, pdx::LocalHandle ashmem_handle,
+ BufferHubDefs::MetadataHeader* metadata_header);
+
+ BufferHubMetadata(const BufferHubMetadata&) = delete;
+ void operator=(const BufferHubMetadata&) = delete;
+
+ size_t user_metadata_size_ = 0;
+ pdx::LocalHandle ashmem_handle_;
+ BufferHubDefs::MetadataHeader* metadata_header_ = nullptr;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_BUFFER_HUB_METADATA_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index e163216..1483e16 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -38,8 +38,8 @@
opaque_ints_.push_back(buffer.handle()->data[fd_count + i]);
}
}
- NativeBufferHandle(NativeBufferHandle&& other) = default;
- NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
+ NativeBufferHandle(NativeBufferHandle&& other) noexcept = default;
+ NativeBufferHandle& operator=(NativeBufferHandle&& other) noexcept = default;
// Imports the native handle into the given IonBuffer instance.
int Import(IonBuffer* buffer) {
@@ -110,16 +110,18 @@
acquire_fence_fd_(acquire_fence_fd.Borrow()),
release_fence_fd_(release_fence_fd.Borrow()) {}
- BufferDescription(BufferDescription&& other) = default;
- BufferDescription& operator=(BufferDescription&& other) = default;
+ BufferDescription(BufferDescription&& other) noexcept = default;
+ BufferDescription& operator=(BufferDescription&& other) noexcept = default;
- // ID of the buffer client. All BufferHubBuffer clients derived from the same
- // buffer in bufferhubd share the same buffer id.
+ // ID of the buffer client. All BufferHub 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
+
+ // Channel ID of the buffer client. Each BufferHub 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
+
+ // State mask of the buffer client. Each BufferHub 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
// must be one of the kConsumerStateMask.
@@ -159,8 +161,8 @@
FenceHandle() = default;
explicit FenceHandle(int fence) : fence_{fence} {}
explicit FenceHandle(FileHandleType&& fence) : fence_{std::move(fence)} {}
- FenceHandle(FenceHandle&&) = default;
- FenceHandle& operator=(FenceHandle&&) = default;
+ FenceHandle(FenceHandle&&) noexcept = default;
+ FenceHandle& operator=(FenceHandle&&) noexcept = default;
explicit operator bool() const { return fence_.IsValid(); }
diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
new file mode 100644
index 0000000..089eff8
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
@@ -0,0 +1,100 @@
+#ifndef ANDROID_DVR_CONSUMER_BUFFER_H_
+#define ANDROID_DVR_CONSUMER_BUFFER_H_
+
+#include <private/dvr/buffer_hub_base.h>
+
+namespace android {
+namespace dvr {
+
+// BufferConsumer was originally poorly named and gets easily confused with
+// IGraphicBufferConsumer. Actually, BufferConsumer is a single buffer that can
+// consume (i.e. read) data from a buffer, but it doesn't consume buffer. On
+// the other hand, IGraphicBufferConsumer is the consumer end of a BufferQueue
+// and it is used to consume buffers.
+//
+// TODO(b/116855254): Remove this typedef once rename is complete in other
+// projects and/or branches.
+typedef class ConsumerBuffer BufferConsumer;
+
+// This is a connection to a producer buffer, which can be located in another
+// application. When that buffer is Post()ed, this fd will be signaled and
+// Acquire allows read access. The user is responsible for making sure that
+// Acquire is called with the correct metadata structure. The only guarantee the
+// API currently provides is that an Acquire() with metadata of the wrong size
+// will fail.
+class ConsumerBuffer : public pdx::ClientBase<ConsumerBuffer, BufferHubBase> {
+ public:
+ // This call assumes ownership of |fd|.
+ static std::unique_ptr<ConsumerBuffer> Import(LocalChannelHandle channel);
+ static std::unique_ptr<ConsumerBuffer> Import(
+ Status<LocalChannelHandle> status);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| will be set to a fence to wait on until the buffer is ready.
+ // This call will only succeed after the fd is signalled. This call may be
+ // performed as an alternative to the Acquire() with metadata. In such cases
+ // the metadata is not read.
+ //
+ // This returns zero or negative unix error code.
+ int Acquire(LocalHandle* ready_fence);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| is set to a fence signaling that the contents of the buffer
+ // are available. This call will only succeed if the buffer is in the posted
+ // state.
+ // Returns zero on success, or a negative errno code otherwise.
+ int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| is set to a fence to wait on until the buffer is ready. This
+ // call will only succeed after the fd is signaled. This returns zero or a
+ // negative unix error code.
+ template <typename Meta>
+ int Acquire(LocalHandle* ready_fence, Meta* meta) {
+ return Acquire(ready_fence, meta, sizeof(*meta));
+ }
+
+ // Asynchronously acquires a bufer.
+ int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+
+ // This should be called after a successful Acquire call. If the fence is
+ // valid the fence determines the buffer usage, otherwise the buffer is
+ // released immediately.
+ // This returns zero or a negative unix error code.
+ int Release(const LocalHandle& release_fence);
+ int ReleaseAsync();
+
+ // Asynchronously releases a buffer. Similar to the synchronous version above,
+ // except that it does not wait for BufferHub to reply with success or error.
+ // The fence and metadata are passed to consumer via shared fd and shared
+ // memory.
+ int ReleaseAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence);
+
+ // May be called after or instead of Acquire to indicate that the consumer
+ // does not need to access the buffer this cycle. This returns zero or a
+ // negative unix error code.
+ int Discard();
+
+ // When set, this consumer is no longer notified when this buffer is
+ // available. The system behaves as if Discard() is immediately called
+ // whenever the buffer is posted. If ignore is set to true while a buffer is
+ // pending, it will act as if Discard() was also called.
+ // This returns zero or a negative unix error code.
+ int SetIgnore(bool ignore);
+
+ private:
+ friend BASE;
+
+ explicit ConsumerBuffer(LocalChannelHandle channel);
+
+ // Local state transition helpers.
+ int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+ int LocalRelease(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence);
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_CONSUMER_BUFFER_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index f6bc547..860f08a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -20,8 +20,8 @@
uint64_t usage);
~IonBuffer();
- IonBuffer(IonBuffer&& other);
- IonBuffer& operator=(IonBuffer&& other);
+ IonBuffer(IonBuffer&& other) noexcept;
+ IonBuffer& operator=(IonBuffer&& other) noexcept;
// Returns check this IonBuffer holds a valid Gralloc buffer.
bool IsValid() const { return buffer_ && buffer_->initCheck() == NO_ERROR; }
diff --git a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
new file mode 100644
index 0000000..b5e1c5b
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
@@ -0,0 +1,109 @@
+#ifndef ANDROID_DVR_PRODUCER_BUFFER_H_
+#define ANDROID_DVR_PRODUCER_BUFFER_H_
+
+#include <private/dvr/buffer_hub_base.h>
+
+namespace android {
+namespace dvr {
+
+// BufferProducer was originally poorly named and gets easily confused with
+// IGraphicBufferProducer. Actually, BufferProducer is a single buffer that can
+// produce (i.e. write) data into a buffer, but it doesn't produce buffer. On
+// the other hand, IGraphicBufferProducer is the producer end of a BufferQueue
+// and it is used to produce buffers.
+//
+// TODO(b/116855254): Remove this typedef once rename is complete in other
+// projects and/or branches.
+typedef class ProducerBuffer BufferProducer;
+
+// This represents a writable buffer. Calling Post notifies all clients and
+// makes the buffer read-only. Call Gain to acquire write access. A buffer
+// may have many consumers.
+//
+// The user of ProducerBuffer is responsible with making sure that the Post() is
+// done with the correct metadata type and size. The user is also responsible
+// for making sure that remote ends (BufferConsumers) are also using the correct
+// metadata when acquiring the buffer. The API guarantees that a Post() with a
+// metadata of wrong size will fail. However, it currently does not do any
+// type checking.
+// The API also assumes that metadata is a serializable type (plain old data).
+class ProducerBuffer : public pdx::ClientBase<ProducerBuffer, BufferHubBase> {
+ public:
+ // Imports a bufferhub producer channel, assuming ownership of its handle.
+ static std::unique_ptr<ProducerBuffer> Import(LocalChannelHandle channel);
+ static std::unique_ptr<ProducerBuffer> Import(
+ Status<LocalChannelHandle> status);
+
+ // Asynchronously posts a buffer. The fence and metadata are passed to
+ // consumer via shared fd and shared memory.
+ int PostAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence);
+
+ // Post this buffer, passing |ready_fence| to the consumers. The bytes in
+ // |meta| are passed unaltered to the consumers. The producer must not modify
+ // the buffer until it is re-gained.
+ // This returns zero or a negative unix error code.
+ int Post(const LocalHandle& ready_fence, const void* meta,
+ size_t user_metadata_size);
+
+ int Post(const LocalHandle& ready_fence) {
+ return Post(ready_fence, nullptr, 0);
+ }
+
+ template <typename Meta, typename = typename std::enable_if<
+ !std::is_void<Meta>::value>::type>
+ int Post(const LocalHandle& ready_fence, const Meta& meta) {
+ return Post(ready_fence, &meta, sizeof(meta));
+ }
+
+ // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
+ // must be waited on before using the buffer. If it is not valid then the
+ // buffer is free for immediate use. This call will only succeed if the buffer
+ // is in the released state.
+ // This returns zero or a negative unix error code.
+ int Gain(LocalHandle* release_fence);
+ int GainAsync();
+
+ // Asynchronously marks a released buffer as gained. This method is similar to
+ // the synchronous version above, except that it does not wait for BufferHub
+ // to acknowledge success or failure. Because of the asynchronous nature of
+ // the underlying message, no error is returned if this method is called when
+ // the buffer is in an incorrect state. Returns zero if sending the message
+ // succeeded, or a negative errno code if local error check fails.
+ int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+
+ // Detaches a ProducerBuffer from an existing producer/consumer set. Can only
+ // be called when a producer buffer has exclusive access to the buffer (i.e.
+ // in the gain'ed state). On the successful return of the IPC call, a new
+ // LocalChannelHandle representing a detached buffer will be returned and all
+ // existing producer and consumer channels will be closed. Further IPCs
+ // towards those channels will return error.
+ Status<LocalChannelHandle> Detach();
+
+ private:
+ friend BASE;
+
+ // Constructors are automatically exposed through ProducerBuffer::Create(...)
+ // static template methods inherited from ClientBase, which take the same
+ // arguments as the constructors.
+
+ // Constructs a buffer with the given geometry and parameters.
+ ProducerBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t usage, size_t metadata_size = 0);
+
+ // Constructs a blob (flat) buffer with the given usage flags.
+ ProducerBuffer(uint64_t usage, size_t size);
+
+ // Imports the given file handle to a producer channel, taking ownership.
+ explicit ProducerBuffer(LocalChannelHandle channel);
+
+ // Local state transition helpers.
+ int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+ int LocalPost(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence);
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_PRODUCER_BUFFER_H_
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index cbaa24a..1295531 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -49,11 +49,11 @@
FreeHandle();
}
-IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
+IonBuffer::IonBuffer(IonBuffer&& other) noexcept : IonBuffer() {
*this = std::move(other);
}
-IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
+IonBuffer& IonBuffer::operator=(IonBuffer&& other) noexcept {
ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
other.handle());
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
new file mode 100644
index 0000000..c4f1a3b
--- /dev/null
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -0,0 +1,243 @@
+#include <private/dvr/producer_buffer.h>
+
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Status;
+
+namespace android {
+namespace dvr {
+
+ProducerBuffer::ProducerBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t usage, size_t user_metadata_size)
+ : BASE(BufferHubRPC::kClientPath) {
+ ATRACE_NAME("ProducerBuffer::ProducerBuffer");
+ ALOGD_IF(TRACE,
+ "ProducerBuffer::ProducerBuffer: fd=%d width=%u height=%u format=%u "
+ "usage=%" PRIx64 " user_metadata_size=%zu",
+ event_fd(), width, height, format, usage, user_metadata_size);
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
+ width, height, format, usage, user_metadata_size);
+ if (!status) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to create producer buffer: %s",
+ status.GetErrorMessage().c_str());
+ Close(-status.error());
+ return;
+ }
+
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+ProducerBuffer::ProducerBuffer(uint64_t usage, size_t size)
+ : BASE(BufferHubRPC::kClientPath) {
+ ATRACE_NAME("ProducerBuffer::ProducerBuffer");
+ ALOGD_IF(TRACE, "ProducerBuffer::ProducerBuffer: usage=%" PRIx64 " size=%zu",
+ usage, size);
+ const int width = static_cast<int>(size);
+ const int height = 1;
+ const int format = HAL_PIXEL_FORMAT_BLOB;
+ const size_t user_metadata_size = 0;
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
+ width, height, format, usage, user_metadata_size);
+ if (!status) {
+ ALOGE("ProducerBuffer::ProducerBuffer: Failed to create blob: %s",
+ status.GetErrorMessage().c_str());
+ Close(-status.error());
+ return;
+ }
+
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+ProducerBuffer::ProducerBuffer(LocalChannelHandle channel)
+ : BASE(std::move(channel)) {
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence) {
+ if (const int error = CheckMetadata(meta->user_metadata_size))
+ return error;
+
+ // Check invalid state transition.
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferGained(buffer_state)) {
+ ALOGE("ProducerBuffer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
+ id(), buffer_state);
+ return -EBUSY;
+ }
+
+ // Copy the canonical metadata.
+ void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
+ memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
+ // Copy extra user requested metadata.
+ if (meta->user_metadata_ptr && meta->user_metadata_size) {
+ void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
+ memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
+ }
+
+ // Send out the acquire fence through the shared epoll fd. Note that during
+ // posting no consumer is not expected to be polling on the fence.
+ if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
+ return error;
+
+ // Set the producer bit atomically to transit into posted state.
+ BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
+ BufferHubDefs::kProducerStateBit);
+ return 0;
+}
+
+int ProducerBuffer::Post(const LocalHandle& ready_fence, const void* meta,
+ size_t user_metadata_size) {
+ ATRACE_NAME("ProducerBuffer::Post");
+
+ // Populate cononical metadata for posting.
+ DvrNativeBufferMetadata canonical_meta;
+ canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
+ canonical_meta.user_metadata_size = user_metadata_size;
+
+ if (const int error = LocalPost(&canonical_meta, ready_fence))
+ return error;
+
+ return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
+ BorrowedFence(ready_fence.Borrow())));
+}
+
+int ProducerBuffer::PostAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence) {
+ ATRACE_NAME("ProducerBuffer::PostAsync");
+
+ if (const int error = LocalPost(meta, ready_fence))
+ return error;
+
+ return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
+}
+
+int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* out_fence) {
+ uint64_t buffer_state = buffer_state_->load();
+ ALOGD_IF(TRACE, "ProducerBuffer::LocalGain: buffer=%d, state=%" PRIx64 ".",
+ id(), buffer_state);
+
+ if (!out_meta)
+ return -EINVAL;
+
+ if (!BufferHubDefs::IsBufferReleased(buffer_state)) {
+ if (BufferHubDefs::IsBufferGained(buffer_state)) {
+ // We don't want to log error when gaining a newly allocated
+ // buffer.
+ ALOGI("ProducerBuffer::LocalGain: already gained id=%d.", id());
+ return -EALREADY;
+ }
+ ALOGE("ProducerBuffer::LocalGain: not released id=%d state=%" PRIx64 ".",
+ id(), buffer_state);
+ return -EBUSY;
+ }
+
+ // Canonical metadata is undefined on Gain. Except for user_metadata and
+ // release_fence_mask. Fill in the user_metadata_ptr in address space of the
+ // local process.
+ if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
+ out_meta->user_metadata_size =
+ metadata_header_->metadata.user_metadata_size;
+ out_meta->user_metadata_ptr =
+ reinterpret_cast<uint64_t>(user_metadata_ptr_);
+ } else {
+ out_meta->user_metadata_size = 0;
+ out_meta->user_metadata_ptr = 0;
+ }
+
+ uint64_t fence_state = fence_state_->load();
+ // If there is an release fence from consumer, we need to return it.
+ if (fence_state & BufferHubDefs::kConsumerStateMask) {
+ *out_fence = shared_release_fence_.Duplicate();
+ out_meta->release_fence_mask =
+ fence_state & BufferHubDefs::kConsumerStateMask;
+ }
+
+ // Clear out all bits and the buffer is now back to gained state.
+ buffer_state_->store(0ULL);
+ return 0;
+}
+
+int ProducerBuffer::Gain(LocalHandle* release_fence) {
+ ATRACE_NAME("ProducerBuffer::Gain");
+
+ DvrNativeBufferMetadata meta;
+ if (const int error = LocalGain(&meta, release_fence))
+ return error;
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
+ if (!status)
+ return -status.error();
+ return 0;
+}
+
+int ProducerBuffer::GainAsync(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* release_fence) {
+ ATRACE_NAME("ProducerBuffer::GainAsync");
+
+ if (const int error = LocalGain(out_meta, release_fence))
+ return error;
+
+ return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
+}
+
+int ProducerBuffer::GainAsync() {
+ DvrNativeBufferMetadata meta;
+ LocalHandle fence;
+ return GainAsync(&meta, &fence);
+}
+
+std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
+ LocalChannelHandle channel) {
+ ALOGD_IF(TRACE, "ProducerBuffer::Import: channel=%d", channel.value());
+ return ProducerBuffer::Create(std::move(channel));
+}
+
+std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
+ Status<LocalChannelHandle> status) {
+ return Import(status ? status.take()
+ : LocalChannelHandle{nullptr, -status.error()});
+}
+
+Status<LocalChannelHandle> ProducerBuffer::Detach() {
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferGained(buffer_state)) {
+ // Can only detach a ProducerBuffer when it's in gained state.
+ ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx64
+ ") is not in gained state.",
+ id(), buffer_state);
+ return {};
+ }
+
+ Status<LocalChannelHandle> status =
+ InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>();
+ ALOGE_IF(!status,
+ "ProducerBuffer::Detach: Failed to detach buffer (id=%d): %s.", id(),
+ status.GetErrorMessage().c_str());
+ return status;
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 44276ba..e1c1aa9 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -278,7 +278,7 @@
}
Status<void> BufferHubQueue::AddBuffer(
- const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+ const std::shared_ptr<BufferHubBase>& buffer, size_t slot) {
ALOGD_IF(TRACE, "BufferHubQueue::AddBuffer: buffer_id=%d slot=%zu",
buffer->id(), slot);
@@ -356,8 +356,8 @@
}
}
-Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(int timeout,
- size_t* slot) {
+Status<std::shared_ptr<BufferHubBase>> BufferHubQueue::Dequeue(int timeout,
+ size_t* slot) {
ALOGD_IF(TRACE, "BufferHubQueue::Dequeue: count=%zu, timeout=%d", count(),
timeout);
@@ -372,7 +372,7 @@
PDX_TRACE_FORMAT("buffer|buffer_id=%d;slot=%zu|", entry.buffer->id(),
entry.slot);
- std::shared_ptr<BufferHubBuffer> buffer = std::move(entry.buffer);
+ std::shared_ptr<BufferHubBase> buffer = std::move(entry.buffer);
*slot = entry.slot;
available_buffers_.pop();
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 df500b4..c69002d 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
@@ -31,13 +31,13 @@
class ConsumerQueue;
-// |BufferHubQueue| manages a queue of |BufferHubBuffer|s. Buffers are
+// |BufferHubQueue| manages a queue of |BufferHubBase|s. Buffers are
// automatically re-requeued when released by the remote side.
class BufferHubQueue : public pdx::Client {
public:
using BufferAvailableCallback = std::function<void()>;
using BufferRemovedCallback =
- std::function<void(const std::shared_ptr<BufferHubBuffer>&)>;
+ std::function<void(const std::shared_ptr<BufferHubBase>&)>;
virtual ~BufferHubQueue() {}
@@ -93,7 +93,7 @@
: -1;
}
- std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
+ std::shared_ptr<BufferHubBase> GetBuffer(size_t slot) const {
return buffers_[slot];
}
@@ -142,7 +142,7 @@
// Register a buffer for management by the queue. Used by subclasses to add a
// buffer to internal bookkeeping.
- pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
+ pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBase>& buffer,
size_t slot);
// Called by ProducerQueue::RemoveBuffer and ConsumerQueue::RemoveBuffer only
@@ -158,8 +158,8 @@
// block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
// while specifying a timeout equal to zero cause Dequeue() to return
// immediately, even if no buffers are available.
- pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
- size_t* slot);
+ pdx::Status<std::shared_ptr<BufferHubBase>> Dequeue(int timeout,
+ size_t* slot);
// Waits for buffers to become available and adds them to the available queue.
bool WaitForBuffers(int timeout);
@@ -172,10 +172,10 @@
// per-buffer data.
struct Entry {
Entry() : slot(0) {}
- Entry(const std::shared_ptr<BufferHubBuffer>& in_buffer, size_t in_slot,
+ Entry(const std::shared_ptr<BufferHubBase>& in_buffer, size_t in_slot,
uint64_t in_index)
: buffer(in_buffer), slot(in_slot), index(in_index) {}
- Entry(const std::shared_ptr<BufferHubBuffer>& in_buffer,
+ Entry(const std::shared_ptr<BufferHubBase>& in_buffer,
std::unique_ptr<uint8_t[]> in_metadata, pdx::LocalHandle in_fence,
size_t in_slot)
: buffer(in_buffer),
@@ -185,7 +185,7 @@
Entry(Entry&&) = default;
Entry& operator=(Entry&&) = default;
- std::shared_ptr<BufferHubBuffer> buffer;
+ std::shared_ptr<BufferHubBase> buffer;
std::unique_ptr<uint8_t[]> metadata;
pdx::LocalHandle fence;
size_t slot;
@@ -250,7 +250,7 @@
// Tracks the buffers belonging to this queue. Buffers are stored according to
// "slot" in this vector. Each slot is a logical id of the buffer within this
// queue regardless of its queue position or presence in the ring buffer.
- std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
+ std::array<std::shared_ptr<BufferHubBase>, kMaxQueueCapacity> buffers_;
// Buffers and related data that are available for dequeue.
std::priority_queue<Entry, std::vector<Entry>, EntryComparator>
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
index 4dea9b2..ad3f56b 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
@@ -28,8 +28,8 @@
public:
BufferHubQueueParcelable() = default;
- BufferHubQueueParcelable(BufferHubQueueParcelable&& other) = default;
- BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) {
+ BufferHubQueueParcelable(BufferHubQueueParcelable&& other) noexcept = default;
+ BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) noexcept {
channel_parcelable_ = std::move(other.channel_parcelable_);
return *this;
}
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 571558a..f4c6600 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -9,7 +9,7 @@
using namespace android;
using android::dvr::BufferConsumer;
-using android::dvr::BufferHubBuffer;
+using android::dvr::BufferHubBase;
using android::dvr::BufferProducer;
using android::dvr::ConsumerQueue;
using android::dvr::ProducerQueue;
@@ -439,7 +439,7 @@
consumer_queue_->SetBufferRemovedCallback(nullptr);
} else {
consumer_queue_->SetBufferRemovedCallback(
- [callback, context](const std::shared_ptr<BufferHubBuffer>& buffer) {
+ [callback, context](const std::shared_ptr<BufferHubBase>& buffer) {
// When buffer is removed from the queue, the slot is already invalid.
auto read_buffer = std::make_unique<DvrReadBuffer>();
read_buffer->read_buffer =
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index de8bb96..df8125a 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -16,8 +16,11 @@
namespace android {
namespace dvr {
-class BufferProducer;
-class BufferConsumer;
+// TODO(b/116855254): Remove this typedef once rename is complete in libdvr.
+// Note that the dvr::BufferProducer and dvr::BufferConsumer were poorly named,
+// they should really be named as ProducerBuffer and ConsumerBuffer.
+typedef class ProducerBuffer BufferProducer;
+typedef class ConsumerBuffer BufferConsumer;
class IonBuffer;
DvrBuffer* CreateDvrBufferFromIonBuffer(
diff --git a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h b/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
index 44485a7..1824241 100644
--- a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
+++ b/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
@@ -23,9 +23,9 @@
explicit RingBuffer(size_t capacity) { Reset(capacity); }
RingBuffer(const RingBuffer& other) = default;
- RingBuffer(RingBuffer&& other) = default;
+ RingBuffer(RingBuffer&& other) noexcept = default;
RingBuffer& operator=(const RingBuffer& other) = default;
- RingBuffer& operator=(RingBuffer&& other) = default;
+ RingBuffer& operator=(RingBuffer&& other) noexcept = default;
void Append(const T& val) {
if (IsFull())
diff --git a/libs/vr/libpdx/private/pdx/channel_handle.h b/libs/vr/libpdx/private/pdx/channel_handle.h
index 1e62d25..daa08f4 100644
--- a/libs/vr/libpdx/private/pdx/channel_handle.h
+++ b/libs/vr/libpdx/private/pdx/channel_handle.h
@@ -50,14 +50,14 @@
public:
ChannelHandle() = default;
using ChannelHandleBase::ChannelHandleBase;
- ChannelHandle(ChannelHandle&& other) : ChannelHandleBase{other.value_} {
+ ChannelHandle(ChannelHandle&& other) noexcept : ChannelHandleBase{other.value_} {
other.value_ = kEmptyHandle;
}
~ChannelHandle() = default;
ChannelHandle Duplicate() const { return ChannelHandle{value_}; }
- ChannelHandle& operator=(ChannelHandle&& other) {
+ ChannelHandle& operator=(ChannelHandle&& other) noexcept {
value_ = other.value_;
other.value_ = kEmptyHandle;
return *this;
@@ -74,13 +74,13 @@
ChannelHandle(const ChannelHandle&) = delete;
ChannelHandle& operator=(const ChannelHandle&) = delete;
- ChannelHandle(ChannelHandle&& other)
+ ChannelHandle(ChannelHandle&& other) noexcept
: ChannelHandleBase{other.value_}, manager_{other.manager_} {
other.manager_ = nullptr;
other.value_ = kEmptyHandle;
}
- ChannelHandle& operator=(ChannelHandle&& other) {
+ ChannelHandle& operator=(ChannelHandle&& other) noexcept {
value_ = other.value_;
manager_ = other.manager_;
other.value_ = kEmptyHandle;
diff --git a/libs/vr/libpdx/private/pdx/file_handle.h b/libs/vr/libpdx/private/pdx/file_handle.h
index b3c3ad7..fed1529 100644
--- a/libs/vr/libpdx/private/pdx/file_handle.h
+++ b/libs/vr/libpdx/private/pdx/file_handle.h
@@ -43,7 +43,7 @@
// Move constructor that assumes ownership of the file descriptor, leaving the
// other FileHandle object empty.
- FileHandle(FileHandle&& other) {
+ FileHandle(FileHandle&& other) noexcept {
fd_ = other.fd_;
other.fd_ = kEmptyFileHandle;
}
@@ -62,7 +62,7 @@
// Move assignment operator that assumes ownership of the underlying file
// descriptor, leaving the other FileHandle object empty.
- FileHandle& operator=(FileHandle&& other) {
+ FileHandle& operator=(FileHandle&& other) noexcept {
if (this != &other) {
Reset(other.fd_);
other.fd_ = kEmptyFileHandle;
diff --git a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
index 93d87f3..d835c57 100644
--- a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
@@ -39,7 +39,7 @@
ArrayWrapper(const ArrayWrapper& other) { *this = other; }
- ArrayWrapper(ArrayWrapper&& other) { *this = std::move(other); }
+ ArrayWrapper(ArrayWrapper&& other) noexcept { *this = std::move(other); }
ArrayWrapper& operator=(const ArrayWrapper& other) {
if (&other == this) {
@@ -53,7 +53,7 @@
return *this;
}
- ArrayWrapper& operator=(ArrayWrapper&& other) {
+ ArrayWrapper& operator=(ArrayWrapper&& other) noexcept {
if (&other == this) {
return *this;
} else {
diff --git a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
index aa86531..0421220 100644
--- a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
@@ -39,7 +39,7 @@
BufferWrapper(const BufferWrapper& other) { *this = other; }
- BufferWrapper(BufferWrapper&& other) { *this = std::move(other); }
+ BufferWrapper(BufferWrapper&& other) noexcept { *this = std::move(other); }
BufferWrapper& operator=(const BufferWrapper& other) {
if (&other == this) {
@@ -53,7 +53,7 @@
return *this;
}
- BufferWrapper& operator=(BufferWrapper&& other) {
+ BufferWrapper& operator=(BufferWrapper&& other) noexcept {
if (&other == this) {
return *this;
} else {
@@ -117,9 +117,9 @@
BufferWrapper(BufferType&& buffer, const Allocator& allocator)
: buffer_(std::move(buffer), allocator) {}
BufferWrapper(const BufferWrapper&) = default;
- BufferWrapper(BufferWrapper&&) = default;
+ BufferWrapper(BufferWrapper&&) noexcept = default;
BufferWrapper& operator=(const BufferWrapper&) = default;
- BufferWrapper& operator=(BufferWrapper&&) = default;
+ BufferWrapper& operator=(BufferWrapper&&) noexcept = default;
pointer data() { return buffer_.data(); }
const_pointer data() const { return buffer_.data(); }
diff --git a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
index d496719..1cb85de 100644
--- a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
@@ -15,9 +15,9 @@
PointerWrapper(T* pointer) : pointer_(pointer) {}
PointerWrapper(const PointerWrapper&) = default;
- PointerWrapper(PointerWrapper&&) = default;
+ PointerWrapper(PointerWrapper&&) noexcept = default;
PointerWrapper& operator=(const PointerWrapper&) = default;
- PointerWrapper& operator=(PointerWrapper&&) = default;
+ PointerWrapper& operator=(PointerWrapper&&) noexcept = default;
T& Dereference() { return *pointer_; }
const T& Dereference() const { return *pointer_; }
diff --git a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
index 19fc4c1..2d0a4ea 100644
--- a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
@@ -44,7 +44,7 @@
StringWrapper(const StringWrapper& other) { *this = other; }
- StringWrapper(StringWrapper&& other) { *this = std::move(other); }
+ StringWrapper(StringWrapper&& other) noexcept { *this = std::move(other); }
StringWrapper& operator=(const StringWrapper& other) {
if (&other == this) {
@@ -58,7 +58,7 @@
return *this;
}
- StringWrapper& operator=(StringWrapper&& other) {
+ StringWrapper& operator=(StringWrapper&& other) noexcept {
if (&other == this) {
return *this;
} else {
diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h
index 0a4802e..a1292b0 100644
--- a/libs/vr/libpdx/private/pdx/rpc/variant.h
+++ b/libs/vr/libpdx/private/pdx/rpc/variant.h
@@ -447,7 +447,7 @@
Variant(const Variant& other)
: index_{other.index_}, value_{other.value_, other.index_} {}
- Variant(Variant&& other)
+ Variant(Variant&& other) noexcept
: index_{other.index_}, value_{std::move(other.value_), other.index_} {}
// Recent Clang versions has a regression that produces bogus
@@ -472,7 +472,7 @@
other.Visit([this](const auto& value) { *this = value; });
return *this;
}
- Variant& operator=(Variant&& other) {
+ Variant& operator=(Variant&& other) noexcept {
other.Visit([this](auto&& value) { *this = std::move(value); });
return *this;
}
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 15fa327..d38b174 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -101,8 +101,8 @@
/*
* Message objects support move construction and assignment.
*/
- Message(Message&& other);
- Message& operator=(Message&& other);
+ Message(Message&& other) noexcept;
+ Message& operator=(Message&& other) noexcept;
/*
* Read/write payload, in either single buffer or iovec form.
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index 067fe25..7e51a52 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -41,14 +41,14 @@
// Copy/move constructors. Move constructor leaves |other| object in empty
// state.
Status(const Status& other) = default;
- Status(Status&& other)
+ Status(Status&& other) noexcept
: value_{std::move(other.value_)}, error_{other.error_} {
other.error_ = -1;
}
// Assignment operators.
Status& operator=(const Status& other) = default;
- Status& operator=(Status&& other) {
+ Status& operator=(Status&& other) noexcept {
error_ = other.error_;
value_ = std::move(other.value_);
other.error_ = -1;
diff --git a/libs/vr/libpdx/private/pdx/utility.h b/libs/vr/libpdx/private/pdx/utility.h
index 08fcaea..c9a0c21 100644
--- a/libs/vr/libpdx/private/pdx/utility.h
+++ b/libs/vr/libpdx/private/pdx/utility.h
@@ -33,7 +33,7 @@
return *this;
}
- ByteBuffer& operator=(ByteBuffer&& other) {
+ ByteBuffer& operator=(ByteBuffer&& other) noexcept {
std::swap(data_, other.data_);
std::swap(size_, other.size_);
std::swap(capacity_, other.capacity_);
diff --git a/libs/vr/libpdx/service.cpp b/libs/vr/libpdx/service.cpp
index 1d3b62a..68b8dd7 100644
--- a/libs/vr/libpdx/service.cpp
+++ b/libs/vr/libpdx/service.cpp
@@ -31,9 +31,9 @@
// C++11 specifies the move semantics for shared_ptr but not weak_ptr. This
// means we have to manually implement the desired move semantics for Message.
-Message::Message(Message&& other) { *this = std::move(other); }
+Message::Message(Message&& other) noexcept { *this = std::move(other); }
-Message& Message::operator=(Message&& other) {
+Message& Message::operator=(Message&& other) noexcept {
Destroy();
auto base = reinterpret_cast<std::uint8_t*>(&info_);
std::fill(&base[0], &base[sizeof(info_)], 0);
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 9614c6d..5d873d1 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -31,13 +31,13 @@
}
}
-AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) {
+AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) noexcept {
*this = std::move(other);
}
AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
-AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) {
+AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) noexcept {
if (this != &other) {
Release();
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 32e912a..1a200aa 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -31,7 +31,7 @@
AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer, int* error);
// Move constructor. Behaves similarly to the move assignment operator below.
- AcquiredBuffer(AcquiredBuffer&& other);
+ AcquiredBuffer(AcquiredBuffer&& other) noexcept;
~AcquiredBuffer();
@@ -39,7 +39,7 @@
// |other| into this instance after RELEASING the current BufferConsumer and
// closing the acquire fence. After the move |other| is left in the empty
// state.
- AcquiredBuffer& operator=(AcquiredBuffer&& other);
+ AcquiredBuffer& operator=(AcquiredBuffer&& other) noexcept;
// Accessors for the underlying BufferConsumer, the acquire fence, and the
// use-case specific sequence value from the acquisition (see
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index e98d592..5f6455c 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1338,9 +1338,9 @@
Layer::~Layer() { Reset(); }
-Layer::Layer(Layer&& other) { *this = std::move(other); }
+Layer::Layer(Layer&& other) noexcept { *this = std::move(other); }
-Layer& Layer::operator=(Layer&& other) {
+Layer& Layer::operator=(Layer&& other) noexcept {
if (this != &other) {
Reset();
using std::swap;
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 80fa7ac..94a2337 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -87,8 +87,8 @@
const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
HWC::Composition composition_type, size_t z_order);
- Layer(Layer&&);
- Layer& operator=(Layer&&);
+ Layer(Layer&&) noexcept;
+ Layer& operator=(Layer&&) noexcept;
~Layer();
diff --git a/opengl/include/EGL/Platform.h b/opengl/include/EGL/Platform.h
new file mode 100644
index 0000000..624d31f
--- /dev/null
+++ b/opengl/include/EGL/Platform.h
@@ -0,0 +1,329 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Platform.h: The public interface ANGLE exposes to the API layer, for
+// doing platform-specific tasks like gathering data, or for tracing.
+
+#ifndef ANGLE_PLATFORM_H
+#define ANGLE_PLATFORM_H
+
+#include <stdint.h>
+#include <array>
+
+#define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x3482
+
+#if defined(_WIN32)
+# if !defined(LIBANGLE_IMPLEMENTATION)
+# define ANGLE_PLATFORM_EXPORT __declspec(dllimport)
+# else
+# define ANGLE_PLATFORM_EXPORT __declspec(dllexport)
+# endif
+#elif defined(__GNUC__) || defined(__clang__)
+# define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default")))
+#endif
+#if !defined(ANGLE_PLATFORM_EXPORT)
+# define ANGLE_PLATFORM_EXPORT
+#endif
+
+#if defined(_WIN32)
+# define ANGLE_APIENTRY __stdcall
+#else
+# define ANGLE_APIENTRY
+#endif
+
+namespace angle
+{
+struct WorkaroundsD3D;
+using TraceEventHandle = uint64_t;
+using EGLDisplayType = void *;
+struct PlatformMethods;
+
+// Use a C-like API to not trigger undefined calling behaviour.
+// Avoid using decltype here to work around sanitizer limitations.
+// TODO(jmadill): Use decltype here if/when UBSAN is fixed.
+
+// System --------------------------------------------------------------
+
+// Wall clock time in seconds since the epoch.
+// TODO(jmadill): investigate using an ANGLE internal time library
+using CurrentTimeFunc = double (*)(PlatformMethods *platform);
+inline double DefaultCurrentTime(PlatformMethods *platform)
+{
+ return 0.0;
+}
+
+// Monotonically increasing time in seconds from an arbitrary fixed point in the past.
+// This function is expected to return at least millisecond-precision values. For this reason,
+// it is recommended that the fixed point be no further in the past than the epoch.
+using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform);
+inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform)
+{
+ return 0.0;
+}
+
+// Logging ------------------------------------------------------------
+
+// Log an error message within the platform implementation.
+using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage);
+inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage)
+{
+}
+
+// Log a warning message within the platform implementation.
+using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage);
+inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage)
+{
+}
+
+// Log an info message within the platform implementation.
+using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage);
+inline void DefaultLogInfo(PlatformMethods *platform, const char *infoMessage)
+{
+}
+
+// Tracing --------
+
+// Get a pointer to the enabled state of the given trace category. The
+// embedder can dynamically change the enabled state as trace event
+// recording is started and stopped by the application. Only long-lived
+// literal strings should be given as the category name. The implementation
+// expects the returned pointer to be held permanently in a local static. If
+// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
+// addTraceEvent is expected to be called by the trace event macros.
+using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform,
+ const char *categoryName);
+inline const unsigned char *DefaultGetTraceCategoryEnabledFlag(PlatformMethods *platform,
+ const char *categoryName)
+{
+ return nullptr;
+}
+
+//
+// Add a trace event to the platform tracing system. Depending on the actual
+// enabled state, this event may be recorded or dropped.
+// - phase specifies the type of event:
+// - BEGIN ('B'): Marks the beginning of a scoped event.
+// - END ('E'): Marks the end of a scoped event.
+// - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
+// need a matching END event. Instead, at the end of the scope,
+// updateTraceEventDuration() must be called with the TraceEventHandle
+// returned from addTraceEvent().
+// - INSTANT ('I'): Standalone, instantaneous event.
+// - START ('S'): Marks the beginning of an asynchronous event (the end
+// event can occur in a different scope or thread). The id parameter is
+// used to match START/FINISH pairs.
+// - FINISH ('F'): Marks the end of an asynchronous event.
+// - COUNTER ('C'): Used to trace integer quantities that change over
+// time. The argument values are expected to be of type int.
+// - METADATA ('M'): Reserved for internal use.
+// - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
+// - name is the name of the event. Also used to match BEGIN/END and
+// START/FINISH pairs.
+// - id optionally allows events of the same name to be distinguished from
+// each other. For example, to trace the construction and destruction of
+// objects, specify the pointer as the id parameter.
+// - timestamp should be a time value returned from monotonicallyIncreasingTime.
+// - numArgs specifies the number of elements in argNames, argTypes, and
+// argValues.
+// - argNames is the array of argument names. Use long-lived literal strings
+// or specify the COPY flag.
+// - argTypes is the array of argument types:
+// - BOOL (1): bool
+// - UINT (2): unsigned long long
+// - INT (3): long long
+// - DOUBLE (4): double
+// - POINTER (5): void*
+// - STRING (6): char* (long-lived null-terminated char* string)
+// - COPY_STRING (7): char* (temporary null-terminated char* string)
+// - CONVERTABLE (8): WebConvertableToTraceFormat
+// - argValues is the array of argument values. Each value is the unsigned
+// long long member of a union of all supported types.
+// - flags can be 0 or one or more of the following, ORed together:
+// - COPY (0x1): treat all strings (name, argNames and argValues of type
+// string) as temporary so that they will be copied by addTraceEvent.
+// - HAS_ID (0x2): use the id argument to uniquely identify the event for
+// matching with other events of the same name.
+// - MANGLE_ID (0x4): specify this flag if the id parameter is the value
+// of a pointer.
+using AddTraceEventFunc = angle::TraceEventHandle (*)(PlatformMethods *platform,
+ char phase,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ unsigned long long id,
+ double timestamp,
+ int numArgs,
+ const char **argNames,
+ const unsigned char *argTypes,
+ const unsigned long long *argValues,
+ unsigned char flags);
+inline angle::TraceEventHandle DefaultAddTraceEvent(PlatformMethods *platform,
+ char phase,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ unsigned long long id,
+ double timestamp,
+ int numArgs,
+ const char **argNames,
+ const unsigned char *argTypes,
+ const unsigned long long *argValues,
+ unsigned char flags)
+{
+ return 0;
+}
+
+// Set the duration field of a COMPLETE trace event.
+using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ angle::TraceEventHandle eventHandle);
+inline void DefaultUpdateTraceEventDuration(PlatformMethods *platform,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ angle::TraceEventHandle eventHandle)
+{
+}
+
+// Callbacks for reporting histogram data.
+// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50
+// would do.
+using HistogramCustomCountsFunc = void (*)(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int min,
+ int max,
+ int bucketCount);
+inline void DefaultHistogramCustomCounts(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int min,
+ int max,
+ int bucketCount)
+{
+}
+// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample
+// value.
+using HistogramEnumerationFunc = void (*)(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int boundaryValue);
+inline void DefaultHistogramEnumeration(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int boundaryValue)
+{
+}
+// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
+using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample);
+inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample)
+{
+}
+// Boolean histograms track two-state variables.
+using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample);
+inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample)
+{
+}
+
+// Allows us to programatically override ANGLE's default workarounds for testing purposes.
+using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform,
+ angle::WorkaroundsD3D *workaroundsD3D);
+inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform,
+ angle::WorkaroundsD3D *workaroundsD3D)
+{
+}
+
+// Callback on a successful program link with the program binary. Can be used to store
+// shaders to disk. Keys are a 160-bit SHA-1 hash.
+using ProgramKeyType = std::array<uint8_t, 20>;
+using CacheProgramFunc = void (*)(PlatformMethods *platform,
+ const ProgramKeyType &key,
+ size_t programSize,
+ const uint8_t *programBytes);
+inline void DefaultCacheProgram(PlatformMethods *platform,
+ const ProgramKeyType &key,
+ size_t programSize,
+ const uint8_t *programBytes)
+{
+}
+
+// Platform methods are enumerated here once.
+#define ANGLE_PLATFORM_OP(OP) \
+ OP(currentTime, CurrentTime) \
+ OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \
+ OP(logError, LogError) \
+ OP(logWarning, LogWarning) \
+ OP(logInfo, LogInfo) \
+ OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \
+ OP(addTraceEvent, AddTraceEvent) \
+ OP(updateTraceEventDuration, UpdateTraceEventDuration) \
+ OP(histogramCustomCounts, HistogramCustomCounts) \
+ OP(histogramEnumeration, HistogramEnumeration) \
+ OP(histogramSparse, HistogramSparse) \
+ OP(histogramBoolean, HistogramBoolean) \
+ OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \
+ OP(cacheProgram, CacheProgram)
+
+#define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
+
+struct ANGLE_PLATFORM_EXPORT PlatformMethods
+{
+ PlatformMethods() {}
+
+ // User data pointer for any implementation specific members. Put it at the start of the
+ // platform structure so it doesn't become overwritten if one version of the platform
+ // adds or removes new members.
+ void *context = 0;
+
+ ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF);
+};
+
+#undef ANGLE_PLATFORM_METHOD_DEF
+
+// Subtract one to account for the context pointer.
+constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1;
+
+#define ANGLE_PLATFORM_METHOD_STRING(Name) #Name
+#define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name),
+
+constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = {
+ ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)};
+
+#undef ANGLE_PLATFORM_METHOD_STRING2
+#undef ANGLE_PLATFORM_METHOD_STRING
+
+} // namespace angle
+
+extern "C" {
+
+// Gets the platform methods on the passed-in EGL display. If the method name signature does not
+// match the compiled signature for this ANGLE, false is returned. On success true is returned.
+// The application should set any platform methods it cares about on the returned pointer.
+// If display is not valid, behaviour is undefined.
+
+ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
+ const char *const methodNames[],
+ unsigned int methodNameCount,
+ void *context,
+ void *platformMethodsOut);
+
+// Sets the platform methods back to their defaults.
+// If display is not valid, behaviour is undefined.
+ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display);
+
+} // extern "C"
+
+namespace angle
+{
+typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType,
+ const char *const *,
+ unsigned int,
+ void *,
+ void *);
+typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType);
+} // namespace angle
+
+// This function is not exported
+angle::PlatformMethods *ANGLEPlatformCurrent();
+
+#endif // ANGLE_PLATFORM_H
diff --git a/opengl/include/EGL/eglext_angle.h b/opengl/include/EGL/eglext_angle.h
new file mode 100644
index 0000000..0556ea1
--- /dev/null
+++ b/opengl/include/EGL/eglext_angle.h
@@ -0,0 +1,191 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// eglext_angle.h: ANGLE modifications to the eglext.h header file.
+// Currently we don't include this file directly, we patch eglext.h
+// to include it implicitly so it is visible throughout our code.
+
+#ifndef INCLUDE_EGL_EGLEXT_ANGLE_
+#define INCLUDE_EGL_EGLEXT_ANGLE_
+
+// clang-format off
+
+#ifndef EGL_ANGLE_robust_resource_initialization
+#define EGL_ANGLE_robust_resource_initialization 1
+#define EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453
+#endif /* EGL_ANGLE_robust_resource_initialization */
+
+#ifndef EGL_ANGLE_keyed_mutex
+#define EGL_ANGLE_keyed_mutex 1
+#define EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2
+#endif /* EGL_ANGLE_keyed_mutex */
+
+#ifndef EGL_ANGLE_d3d_texture_client_buffer
+#define EGL_ANGLE_d3d_texture_client_buffer 1
+#define EGL_D3D_TEXTURE_ANGLE 0x33A3
+#endif /* EGL_ANGLE_d3d_texture_client_buffer */
+
+#ifndef EGL_ANGLE_software_display
+#define EGL_ANGLE_software_display 1
+#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
+#endif /* EGL_ANGLE_software_display */
+
+#ifndef EGL_ANGLE_direct3d_display
+#define EGL_ANGLE_direct3d_display 1
+#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
+#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
+#endif /* EGL_ANGLE_direct3d_display */
+
+#ifndef EGL_ANGLE_direct_composition
+#define EGL_ANGLE_direct_composition 1
+#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
+#endif /* EGL_ANGLE_direct_composition */
+
+#ifndef EGL_ANGLE_platform_angle
+#define EGL_ANGLE_platform_angle 1
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
+#define EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE 0x3451
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x345E
+#endif /* EGL_ANGLE_platform_angle */
+
+#ifndef EGL_ANGLE_platform_angle_d3d
+#define EGL_ANGLE_platform_angle_d3d 1
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE 0x320B
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE 0x320C
+#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
+#endif /* EGL_ANGLE_platform_angle_d3d */
+
+#ifndef EGL_ANGLE_platform_angle_opengl
+#define EGL_ANGLE_platform_angle_opengl 1
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
+#define EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE 0x3480
+#endif /* EGL_ANGLE_platform_angle_opengl */
+
+#ifndef EGL_ANGLE_platform_angle_null
+#define EGL_ANGLE_platform_angle_null 1
+#define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE
+#endif /* EGL_ANGLE_platform_angle_null */
+
+#ifndef EGL_ANGLE_platform_angle_vulkan
+#define EGL_ANGLE_platform_angle_vulkan 1
+#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
+#endif /* EGL_ANGLE_platform_angle_vulkan */
+
+#ifndef EGL_ANGLE_platform_angle_context_virtualization
+#define EGL_ANGLE_platform_angle_context_virtualization 1
+#define EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481
+#endif /* EGL_ANGLE_platform_angle_context_virtualization */
+
+#ifndef EGL_ANGLE_x11_visual
+#define EGL_ANGLE_x11_visual
+#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
+#endif /* EGL_ANGLE_x11_visual */
+
+#ifndef EGL_ANGLE_flexible_surface_compatibility
+#define EGL_ANGLE_flexible_surface_compatibility 1
+#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
+#endif /* EGL_ANGLE_flexible_surface_compatibility */
+
+#ifndef EGL_ANGLE_surface_orientation
+#define EGL_ANGLE_surface_orientation
+#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
+#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
+#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
+#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
+#endif /* EGL_ANGLE_surface_orientation */
+
+#ifndef EGL_ANGLE_experimental_present_path
+#define EGL_ANGLE_experimental_present_path
+#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
+#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
+#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
+#endif /* EGL_ANGLE_experimental_present_path */
+
+#ifndef EGL_ANGLE_stream_producer_d3d_texture
+#define EGL_ANGLE_stream_producer_d3d_texture
+#define EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglCreateStreamProducerD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_ANGLE_stream_producer_d3d_texture */
+
+#ifndef EGL_ANGLE_create_context_webgl_compatibility
+#define EGL_ANGLE_create_context_webgl_compatibility 1
+#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x33AC
+#endif /* EGL_ANGLE_create_context_webgl_compatibility */
+
+#ifndef EGL_ANGLE_display_texture_share_group
+#define EGL_ANGLE_display_texture_share_group 1
+#define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF
+#endif /* EGL_ANGLE_display_texture_share_group */
+
+#ifndef EGL_CHROMIUM_create_context_bind_generates_resource
+#define EGL_CHROMIUM_create_context_bind_generates_resource 1
+#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x33AD
+#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
+
+#ifndef EGL_ANGLE_create_context_client_arrays
+#define EGL_ANGLE_create_context_client_arrays 1
+#define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
+#endif /* EGL_ANGLE_create_context_client_arrays */
+
+#ifndef EGL_ANGLE_device_creation
+#define EGL_ANGLE_device_creation 1
+typedef EGLDeviceEXT(EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE(EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE(EGLDeviceEXT device);
+#endif
+#endif /* EGL_ANGLE_device_creation */
+
+#ifndef EGL_ANGLE_program_cache_control
+#define EGL_ANGLE_program_cache_control 1
+#define EGL_PROGRAM_CACHE_SIZE_ANGLE 0x3455
+#define EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE 0x3456
+#define EGL_PROGRAM_CACHE_RESIZE_ANGLE 0x3457
+#define EGL_PROGRAM_CACHE_TRIM_ANGLE 0x3458
+#define EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE 0x3459
+typedef EGLint (EGLAPIENTRYP PFNEGLPROGRAMCACHEGETATTRIBANGLEPROC) (EGLDisplay dpy, EGLenum attrib);
+typedef void (EGLAPIENTRYP PFNEGLPROGRAMCACHEQUERYANGLEPROC) (EGLDisplay dpy, EGLint index, void *key, EGLint *keysize, void *binary, EGLint *binarysize);
+typedef void (EGLAPIENTRYP PFNEGPROGRAMCACHELPOPULATEANGLEPROC) (EGLDisplay dpy, const void *key, EGLint keysize, const void *binary, EGLint binarysize);
+typedef EGLint (EGLAPIENTRYP PFNEGLPROGRAMCACHERESIZEANGLEPROC) (EGLDisplay dpy, EGLint limit, EGLenum mode);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib);
+EGLAPI void EGLAPIENTRY eglProgramCacheQueryANGLE(EGLDisplay dpy, EGLint index, void *key, EGLint *keysize, void *binary, EGLint *binarysize);
+EGLAPI void EGLAPIENTRY eglProgramCachePopulateANGLE(EGLDisplay dpy, const void *key, EGLint keysize, const void *binary, EGLint binarysize);
+EGLAPI EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode);
+#endif
+#endif /* EGL_ANGLE_program_cache_control */
+
+#ifndef EGL_ANGLE_iosurface_client_buffer
+#define EGL_ANGLE_iosurface_client_buffer 1
+#define EGL_IOSURFACE_ANGLE 0x3454
+#define EGL_IOSURFACE_PLANE_ANGLE 0x345A
+#define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
+#define EGL_TEXTURE_TYPE_ANGLE 0x345C
+#define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
+#endif /* EGL_ANGLE_iosurface_client_buffer */
+
+#ifndef EGL_ANGLE_create_context_extensions_enabled
+#define EGL_ANGLE_create_context_extensions_enabled 1
+#define EGL_EXTENSIONS_ENABLED_ANGLE 0x345F
+#endif /* EGL_ANGLE_create_context_extensions_enabled */
+
+// clang-format on
+
+#endif // INCLUDE_EGL_EGLEXT_ANGLE_
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index d43c164..2a6dee4 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -143,6 +143,7 @@
"EGL/egl.cpp",
"EGL/eglApi.cpp",
"EGL/Loader.cpp",
+ "EGL/egl_angle_platform.cpp",
],
shared_libs: [
"libvndksupport",
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e954b4f..1421a48 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -38,6 +38,18 @@
extern "C" {
android_namespace_t* android_get_exported_namespace(const char*);
+
+ // TODO(ianelliott@): Get this from an ANGLE header:
+ typedef enum ANGLEPreference {
+ ANGLE_NO_PREFERENCE = 0,
+ ANGLE_PREFER_NATIVE = 1,
+ ANGLE_PREFER_ANGLE = 2,
+ } ANGLEPreference;
+
+ // TODO(ianelliott@): Get this from an ANGLE header:
+ typedef bool (*fpANGLEUseForApplication)(const char* appName, const char* deviceMfr,
+ const char* deviceModel, ANGLEPreference developerOption,
+ ANGLEPreference appPreference);
}
// ----------------------------------------------------------------------------
@@ -455,6 +467,114 @@
return dso;
}
+static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = ns,
+ };
+
+ std::string name = std::string("lib") + kind + "_angle.so";
+
+ void* so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+
+ if (so) {
+ ALOGD("dlopen_ext from APK (%s) success at %p", name.c_str(), so);
+ return so;
+ } else {
+ ALOGE("dlopen_ext(\"%s\") failed: %s", name.c_str(), dlerror());
+ }
+
+ return nullptr;
+}
+
+static ANGLEPreference getAnglePref(const char* app_pref) {
+ if (app_pref == nullptr)
+ return ANGLE_NO_PREFERENCE;
+
+ if (strcmp(app_pref, "angle") == 0) {
+ return ANGLE_PREFER_ANGLE;
+ } else if (strcmp(app_pref, "native") == 0) {
+ return ANGLE_PREFER_NATIVE;
+ }
+ return ANGLE_NO_PREFERENCE;
+}
+
+static void* load_angle(const char* kind, egl_connection_t* cnx) {
+ // Only attempt to load ANGLE libs
+ if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0)
+ return nullptr;
+
+ void* so = nullptr;
+ std::string name;
+ char prop[PROPERTY_VALUE_MAX];
+
+ android_namespace_t* ns = android_getAngleNamespace();
+ const char* app_name = android_getAngleAppName();
+ const char* app_pref = android_getAngleAppPref();
+ bool developer_opt_in = android_getAngleDeveloperOptIn();
+
+ // Determine whether or not to use ANGLE:
+ ANGLEPreference developer_option = developer_opt_in ? ANGLE_PREFER_ANGLE : ANGLE_NO_PREFERENCE;
+ bool use_angle = (developer_option == ANGLE_PREFER_ANGLE);
+
+ if (use_angle) {
+ ALOGV("User set \"Developer Options\" to force the use of ANGLE");
+ } else {
+ // The "Developer Options" value wasn't set to force the use of ANGLE. Need to temporarily
+ // load ANGLE and call the updatable opt-in/out logic:
+ std::string app_name_str = app_name ? app_name : "";
+ char manufacturer[PROPERTY_VALUE_MAX];
+ char model[PROPERTY_VALUE_MAX];
+ property_get("ro.product.manufacturer", manufacturer, "UNSET");
+ property_get("ro.product.model", model, "UNSET");
+ ANGLEPreference app_preference = getAnglePref(android_getAngleAppPref());
+
+ so = load_angle_from_namespace("GLESv2", ns);
+ if (so) {
+ ALOGV("Temporarily loaded ANGLE's opt-in/out logic from namespace");
+ fpANGLEUseForApplication fp =
+ (fpANGLEUseForApplication)dlsym(so, "ANGLEUseForApplication");
+ if (fp) {
+ use_angle = (fp)(app_name_str.c_str(), manufacturer, model, developer_option,
+ app_preference);
+ ALOGV("Result of opt-in/out logic is %s", use_angle ? "true" : "false");
+ }
+
+ ALOGV("Close temporarily-loaded ANGLE opt-in/out logic");
+ dlclose(so);
+ so = nullptr;
+ } else {
+ // We weren't able to load and call the updateable opt-in/out logic.
+ // If we can't load the library, there is no ANGLE available.
+ use_angle = false;
+ ALOGV("Could not temporarily-load the ANGLE opt-in/out logic, cannot use ANGLE.");
+ }
+ }
+ if (use_angle) {
+ so = load_angle_from_namespace(kind, ns);
+ }
+
+ if (so) {
+ ALOGV("Loaded ANGLE %s library for %s (instead of native)",
+ kind, app_name ? app_name : "nullptr");
+ property_get("debug.angle.backend", prop, "UNSET");
+ ALOGV("ANGLE's backend set to %s", prop);
+ property_get("debug.hwui.renderer", prop, "UNSET");
+ ALOGV("Skia's renderer set to %s", prop);
+ cnx->useAngle = true;
+ // Find and load vendor libEGL for ANGLE
+ if (!cnx->vendorEGL) {
+ cnx->vendorEGL = load_system_driver("EGL");
+ }
+ return so;
+ } else {
+ ALOGV("Loaded native %s library for %s (instead of ANGLE)",
+ kind, app_name ? app_name : "nullptr");
+ }
+
+ return nullptr;
+}
+
static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
"ro.hardware.egl",
"ro.board.platform",
@@ -486,10 +606,13 @@
ATRACE_CALL();
void* dso = nullptr;
+ dso = load_angle(kind, cnx);
#ifndef __ANDROID_VNDK__
- android_namespace_t* ns = android_getDriverNamespace();
- if (ns) {
- dso = load_updated_driver(kind, ns);
+ if (!dso) {
+ android_namespace_t* ns = android_getDriverNamespace();
+ if (ns) {
+ dso = load_updated_driver(kind, ns);
+ }
}
#endif
if (!dso) {
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index c361ab0..1ed9850 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -25,6 +25,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include <EGL/eglext_angle.h>
#include <android/hardware_buffer.h>
#include <private/android/AHardwareBufferHelpers.h>
@@ -711,12 +712,16 @@
return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
- int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
- if (result < 0) {
- ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
- "failed (%#x) (already connected to another API?)",
- window, result);
- return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ // NOTE: When using Vulkan backend, the Vulkan runtime makes all the
+ // native_window_* calls, so don't do them here.
+ if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+ if (result < 0) {
+ ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
+ "failed (%#x) (already connected to another API?)",
+ window, result);
+ return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
}
EGLDisplay iDpy = dp->disp.dpy;
@@ -733,7 +738,7 @@
}
attrib_list = strippedAttribList.data();
- {
+ if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
int err = native_window_set_buffers_format(window, format);
if (err != 0) {
ALOGE("error setting native window pixel format: %s (%d)",
@@ -741,16 +746,16 @@
native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
- }
- android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace);
- if (dataSpace != HAL_DATASPACE_UNKNOWN) {
- int err = native_window_set_buffers_data_space(window, dataSpace);
- if (err != 0) {
- ALOGE("error setting native window pixel dataSpace: %s (%d)",
- strerror(-err), err);
- native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
- return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace);
+ if (dataSpace != HAL_DATASPACE_UNKNOWN) {
+ err = native_window_set_buffers_data_space(window, dataSpace);
+ if (err != 0) {
+ ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err),
+ err);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
}
}
@@ -769,8 +774,10 @@
}
// EGLSurface creation failed
- native_window_set_buffers_format(window, 0);
- native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ native_window_set_buffers_format(window, 0);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ }
}
return EGL_NO_SURFACE;
}
@@ -1362,9 +1369,11 @@
}
}
- if (!sendSurfaceMetadata(s)) {
- native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
- return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
+ if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ if (!sendSurfaceMetadata(s)) {
+ native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
+ return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
+ }
}
if (n_rects == 0) {
@@ -1385,7 +1394,10 @@
androidRect.bottom = y;
androidRects.push_back(androidRect);
}
- native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
+ if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(),
+ androidRects.size());
+ }
if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
new file mode 100644
index 0000000..7e0175a
--- /dev/null
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#if defined(__ANDROID__)
+
+#include "egl_angle_platform.h"
+#include <time.h>
+
+#include <log/log.h>
+
+namespace angle {
+
+GetDisplayPlatformFunc AnglePlatformImpl::angleGetDisplayPlatform = nullptr;
+ResetDisplayPlatformFunc AnglePlatformImpl::angleResetDisplayPlatform = nullptr;
+// Initialize start time
+time_t AnglePlatformImpl::startTime = time(nullptr);
+
+void AnglePlatformImpl::assignAnglePlatformMethods(PlatformMethods* platformMethods) {
+ platformMethods->addTraceEvent = addTraceEvent;
+ platformMethods->getTraceCategoryEnabledFlag = getTraceCategoryEnabledFlag;
+ platformMethods->monotonicallyIncreasingTime = monotonicallyIncreasingTime;
+ platformMethods->logError = logError;
+ platformMethods->logWarning = logWarning;
+ platformMethods->logInfo = logInfo;
+}
+
+const unsigned char* AnglePlatformImpl::getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/,
+ const char* /*categoryName*/) {
+ // Returning ptr to 'g' (non-zero) to ALWAYS enable tracing initially.
+ // This ptr is what will be passed into "category_group_enabled" of addTraceEvent
+ static const unsigned char traceEnabled = 'g';
+ return &traceEnabled;
+}
+
+double AnglePlatformImpl::monotonicallyIncreasingTime(PlatformMethods* /*platform*/) {
+ return difftime(time(nullptr), startTime);
+}
+
+void AnglePlatformImpl::logError(PlatformMethods* /*platform*/, const char* errorMessage) {
+ ALOGE("ANGLE Error:%s", errorMessage);
+}
+
+void AnglePlatformImpl::logWarning(PlatformMethods* /*platform*/, const char* warningMessage) {
+ ALOGW("ANGLE Warn:%s", warningMessage);
+}
+
+void AnglePlatformImpl::logInfo(PlatformMethods* /*platform*/, const char* infoMessage) {
+ ALOGD("ANGLE Info:%s", infoMessage);
+}
+
+TraceEventHandle AnglePlatformImpl::addTraceEvent(
+ PlatformMethods* /**platform*/, char phase, const unsigned char* /*category_group_enabled*/,
+ const char* name, unsigned long long /*id*/, double /*timestamp*/, int /*num_args*/,
+ const char** /*arg_names*/, const unsigned char* /*arg_types*/,
+ const unsigned long long* /*arg_values*/, unsigned char /*flags*/) {
+ switch (phase) {
+ case 'B': {
+ ATRACE_BEGIN(name);
+ break;
+ }
+ case 'E': {
+ ATRACE_END();
+ break;
+ }
+ case 'I': {
+ ATRACE_NAME(name);
+ break;
+ }
+ default:
+ // Could handle other event types here
+ break;
+ }
+ // Return any non-zero handle to avoid assert in ANGLE
+ TraceEventHandle result = 1.0;
+ return result;
+}
+
+}; // namespace angle
+
+#endif // __ANDROID__
diff --git a/opengl/libs/EGL/egl_angle_platform.h b/opengl/libs/EGL/egl_angle_platform.h
new file mode 100644
index 0000000..7c6c8ed
--- /dev/null
+++ b/opengl/libs/EGL/egl_angle_platform.h
@@ -0,0 +1,58 @@
+/*
+ * 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
+
+#if defined(__ANDROID__)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include <EGL/Platform.h>
+#pragma GCC diagnostic pop
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "egl_trace.h"
+
+namespace angle {
+
+class AnglePlatformImpl {
+public:
+ static void assignAnglePlatformMethods(PlatformMethods* platformMethods);
+ static GetDisplayPlatformFunc angleGetDisplayPlatform;
+ static ResetDisplayPlatformFunc angleResetDisplayPlatform;
+
+private:
+ static time_t startTime;
+ static const unsigned char* getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/,
+ const char* /*categoryName*/);
+ static double monotonicallyIncreasingTime(PlatformMethods* /*platform*/);
+ static void logError(PlatformMethods* /*platform*/, const char* errorMessage);
+ static void logWarning(PlatformMethods* /*platform*/, const char* warningMessage);
+ static void logInfo(PlatformMethods* /*platform*/, const char* infoMessage);
+ static TraceEventHandle addTraceEvent(PlatformMethods* /**platform*/, char phase,
+ const unsigned char* /*category_group_enabled*/,
+ const char* name, unsigned long long /*id*/,
+ double /*timestamp*/, int /*num_args*/,
+ const char** /*arg_names*/,
+ const unsigned char* /*arg_types*/,
+ const unsigned long long* /*arg_values*/,
+ unsigned char /*flags*/);
+};
+
+}; // namespace angle
+
+#endif // __ANDROID__
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index d16d33a..d452a6c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -21,14 +21,19 @@
#include "../egl_impl.h"
+#include <EGL/eglext_angle.h>
#include <private/EGL/display.h>
+#include <cutils/properties.h>
+#include "Loader.h"
+#include "egl_angle_platform.h"
#include "egl_cache.h"
#include "egl_object.h"
#include "egl_tls.h"
-#include "egl_trace.h"
-#include "Loader.h"
-#include <cutils/properties.h>
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+#include <graphicsenv/GraphicsEnv.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <configstore/Utils.h>
@@ -121,6 +126,150 @@
return sDisplay[uintptr_t(disp)].getDisplay(disp);
}
+static void addAnglePlatformAttributes(egl_connection_t* const cnx, const EGLAttrib* attrib_list,
+ std::vector<EGLAttrib>& attrs) {
+ intptr_t vendorEGL = (intptr_t)cnx->vendorEGL;
+
+ EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+ if (attrib_list) {
+ while (*attrib_list != EGL_NONE) {
+ EGLAttrib attr = *attrib_list++;
+ EGLAttrib value = *attrib_list++;
+ if (attr == EGL_PLATFORM_ANGLE_TYPE_ANGLE) {
+ switch (value) {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+ angleBackendDefault = value;
+ break;
+ default:
+ ALOGW("Invalid EGL_PLATFORM_ANGLE_TYPE_ANGLE attribute: 0x%" PRIxPTR,
+ value);
+ break;
+ }
+ }
+ }
+ }
+
+ cnx->angleBackend = angleBackendDefault;
+
+ // Allow debug property to override application's
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("debug.angle.backend", prop, "0");
+ switch (atoi(prop)) {
+ case 1:
+ ALOGV("addAnglePlatformAttributes: Requesting OpenGLES back-end");
+ cnx->angleBackend = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
+ break;
+ case 2:
+ ALOGV("addAnglePlatformAttributes: Requesting Vulkan back-end");
+ cnx->angleBackend = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+ break;
+ default:
+ break;
+ }
+
+ attrs.reserve(4 * 2);
+
+ attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+ attrs.push_back(cnx->angleBackend);
+
+ switch (cnx->angleBackend) {
+ case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+ ALOGV("%s: Requesting Vulkan ANGLE back-end", __FUNCTION__);
+ property_get("debug.angle.validation", prop, "0");
+ attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
+ attrs.push_back(atoi(prop));
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ ALOGV("%s: Requesting Default ANGLE back-end", __FUNCTION__);
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+ ALOGV("%s: Requesting OpenGL ES ANGLE back-end", __FUNCTION__);
+ // NOTE: This is only valid if the backend is OpenGL
+ attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE);
+ attrs.push_back(vendorEGL);
+ break;
+ default:
+ ALOGV("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
+ break;
+ }
+ attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
+ attrs.push_back(EGL_FALSE);
+}
+
+// Initialize function ptrs for ANGLE PlatformMethods struct, used for systrace
+bool initializeAnglePlatform(EGLDisplay dpy) {
+ // Since we're inside libEGL, use dlsym to lookup fptr for ANGLEGetDisplayPlatform
+ android_namespace_t* ns = android_getAngleNamespace();
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = ns,
+ };
+ void* so = android_dlopen_ext("libEGL_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ angle::AnglePlatformImpl::angleGetDisplayPlatform =
+ reinterpret_cast<angle::GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
+
+ if (!angle::AnglePlatformImpl::angleGetDisplayPlatform) {
+ ALOGE("dlsym lookup of ANGLEGetDisplayPlatform in libEGL_angle failed!");
+ return false;
+ }
+
+ angle::AnglePlatformImpl::angleResetDisplayPlatform =
+ reinterpret_cast<angle::ResetDisplayPlatformFunc>(
+ eglGetProcAddress("ANGLEResetDisplayPlatform"));
+
+ angle::PlatformMethods* platformMethods = nullptr;
+ if (!((angle::AnglePlatformImpl::angleGetDisplayPlatform)(dpy, angle::g_PlatformMethodNames,
+ angle::g_NumPlatformMethods, nullptr,
+ &platformMethods))) {
+ ALOGE("ANGLEGetDisplayPlatform call failed!");
+ return false;
+ }
+ if (platformMethods) {
+ angle::AnglePlatformImpl::assignAnglePlatformMethods(platformMethods);
+ } else {
+ ALOGE("In initializeAnglePlatform() platformMethods struct ptr is NULL. Not assigning "
+ "tracing function ptrs!");
+ }
+ return true;
+}
+
+static EGLDisplay getDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx) {
+ EGLDisplay dpy = EGL_NO_DISPLAY;
+
+ // Locally define this until EGL 1.5 is supported
+ typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform, void* native_display,
+ const EGLAttrib* attrib_list);
+
+ PFNEGLGETPLATFORMDISPLAYPROC eglGetPlatformDisplay =
+ reinterpret_cast<PFNEGLGETPLATFORMDISPLAYPROC>(
+ cnx->egl.eglGetProcAddress("eglGetPlatformDisplay"));
+
+ if (eglGetPlatformDisplay) {
+ std::vector<EGLAttrib> attrs;
+ addAnglePlatformAttributes(cnx, nullptr, attrs);
+ attrs.push_back(EGL_NONE);
+
+ dpy = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
+ reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), attrs.data());
+ if (dpy == EGL_NO_DISPLAY) {
+ ALOGE("eglGetPlatformDisplay failed!");
+ } else {
+ if (!initializeAnglePlatform(dpy)) {
+ ALOGE("initializeAnglePlatform failed!");
+ }
+ }
+ } else {
+ ALOGE("eglGetDisplay(%p) failed: Unable to look up eglGetPlatformDisplay from ANGLE",
+ display);
+ }
+
+ return dpy;
+}
+
EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
std::lock_guard<std::mutex> _l(lock);
@@ -131,7 +280,15 @@
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
- EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
+ EGLDisplay dpy = EGL_NO_DISPLAY;
+
+ if (cnx->useAngle) {
+ dpy = getDisplayAngle(display, cnx);
+ }
+ if (dpy == EGL_NO_DISPLAY) {
+ dpy = cnx->egl.eglGetDisplay(display);
+ }
+
disp.dpy = dpy;
if (dpy == EGL_NO_DISPLAY) {
loader.close(cnx->dso);
@@ -305,6 +462,10 @@
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
+ // If we're using ANGLE reset any custom DisplayPlatform
+ if (cnx->useAngle && angle::AnglePlatformImpl::angleResetDisplayPlatform) {
+ (angle::AnglePlatformImpl::angleResetDisplayPlatform)(disp.dpy);
+ }
if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 299d8f7..4990af6 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -47,6 +47,10 @@
void* libEgl;
void* libGles1;
void* libGles2;
+
+ bool useAngle;
+ EGLint angleBackend;
+ void* vendorEGL;
};
// ----------------------------------------------------------------------------
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 45efb9f..9a65452 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -19,12 +19,10 @@
srcs: [
"EventHub.cpp",
- "InputApplication.cpp",
"InputDispatcher.cpp",
"InputListener.cpp",
"InputManager.cpp",
"InputReader.cpp",
- "InputWindow.cpp",
],
shared_libs: [
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index af33fbe..aedad2f 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -18,7 +18,9 @@
#define _UI_INPUT_DISPATCHER_H
#include <input/Input.h>
+#include <input/InputApplication.h>
#include <input/InputTransport.h>
+#include <input/InputWindow.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
#include <utils/threads.h>
@@ -33,8 +35,6 @@
#include <limits.h>
#include <unordered_map>
-#include "InputWindow.h"
-#include "InputApplication.h"
#include "InputListener.h"
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8f12129..57fc17f 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -258,64 +258,31 @@
bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType,
const std::string& uniqueDisplayId, DisplayViewport* outViewport) const {
- const DisplayViewport* viewport = nullptr;
- if (viewportType == ViewportType::VIEWPORT_VIRTUAL && !uniqueDisplayId.empty()) {
-
- for (const DisplayViewport& currentViewport : mVirtualDisplays) {
- if (currentViewport.uniqueId == uniqueDisplayId) {
- viewport = ¤tViewport;
- break;
+ for (const DisplayViewport& currentViewport : mDisplays) {
+ if (currentViewport.type == viewportType) {
+ if (uniqueDisplayId.empty() ||
+ (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) {
+ *outViewport = currentViewport;
+ return true;
}
}
- } else if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
- viewport = &mExternalDisplay;
- } else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
- viewport = &mInternalDisplay;
- }
-
- if (viewport != nullptr && viewport->displayId >= 0) {
- *outViewport = *viewport;
- return true;
}
return false;
}
-void InputReaderConfiguration::setPhysicalDisplayViewport(ViewportType viewportType,
- const DisplayViewport& viewport) {
- if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
- mExternalDisplay = viewport;
- } else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
- mInternalDisplay = viewport;
- }
-}
-
-void InputReaderConfiguration::setVirtualDisplayViewports(
- const Vector<DisplayViewport>& viewports) {
- mVirtualDisplays = viewports;
+void InputReaderConfiguration::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
+ mDisplays = viewports;
}
void InputReaderConfiguration::dump(std::string& dump) const {
- dump += INDENT4 "ViewportInternal:\n";
- dumpViewport(dump, mInternalDisplay);
- dump += INDENT4 "ViewportExternal:\n";
- dumpViewport(dump, mExternalDisplay);
- dump += INDENT4 "ViewportVirtual:\n";
- for (const DisplayViewport& viewport : mVirtualDisplays) {
+ for (const DisplayViewport& viewport : mDisplays) {
dumpViewport(dump, viewport);
}
}
-void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport) const {
- dump += StringPrintf(INDENT5 "Viewport: displayId=%d, orientation=%d, uniqueId='%s', "
- "logicalFrame=[%d, %d, %d, %d], "
- "physicalFrame=[%d, %d, %d, %d], "
- "deviceSize=[%d, %d]\n",
- viewport.displayId, viewport.orientation, viewport.uniqueId.c_str(),
- viewport.logicalLeft, viewport.logicalTop,
- viewport.logicalRight, viewport.logicalBottom,
- viewport.physicalLeft, viewport.physicalTop,
- viewport.physicalRight, viewport.physicalBottom,
- viewport.deviceWidth, viewport.deviceHeight);
+void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport)
+ const {
+ dump += StringPrintf(INDENT4 "%s\n", viewport.toString().c_str());
}
@@ -3600,6 +3567,12 @@
break;
}
+ if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
+ ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
+ naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
+ naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
+ }
+
mPhysicalWidth = naturalPhysicalWidth;
mPhysicalHeight = naturalPhysicalHeight;
mPhysicalLeft = naturalPhysicalLeft;
@@ -3913,17 +3886,7 @@
}
void TouchInputMapper::dumpSurface(std::string& dump) {
- dump += StringPrintf(INDENT3 "Viewport: displayId=%d, orientation=%d, "
- "logicalFrame=[%d, %d, %d, %d], "
- "physicalFrame=[%d, %d, %d, %d], "
- "deviceSize=[%d, %d]\n",
- mViewport.displayId, mViewport.orientation,
- mViewport.logicalLeft, mViewport.logicalTop,
- mViewport.logicalRight, mViewport.logicalBottom,
- mViewport.physicalLeft, mViewport.physicalTop,
- mViewport.physicalRight, mViewport.physicalBottom,
- mViewport.deviceWidth, mViewport.deviceHeight);
-
+ dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index c06168d..74668b7 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -38,6 +38,7 @@
#include <optional>
#include <stddef.h>
#include <unistd.h>
+#include <vector>
// Maximum supported size of a vibration pattern.
// Must be at least 2.
@@ -203,17 +204,14 @@
bool getDisplayViewport(ViewportType viewportType, const std::string& uniqueDisplayId,
DisplayViewport* outViewport) const;
- void setPhysicalDisplayViewport(ViewportType viewportType, const DisplayViewport& viewport);
- void setVirtualDisplayViewports(const Vector<DisplayViewport>& viewports);
+ void setDisplayViewports(const std::vector<DisplayViewport>& viewports);
void dump(std::string& dump) const;
void dumpViewport(std::string& dump, const DisplayViewport& viewport) const;
private:
- DisplayViewport mInternalDisplay;
- DisplayViewport mExternalDisplay;
- Vector<DisplayViewport> mVirtualDisplays;
+ std::vector<DisplayViewport> mDisplays;
};
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
deleted file mode 100644
index 0d1dfdd..0000000
--- a/services/inputflinger/InputWindow.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputWindow"
-#define LOG_NDEBUG 0
-
-#include "InputWindow.h"
-
-#include <log/log.h>
-
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
-namespace android {
-
-// --- InputWindowInfo ---
-void InputWindowInfo::addTouchableRegion(const Rect& region) {
- touchableRegion.orSelf(region);
-}
-
-bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
- return touchableRegion.contains(x,y);
-}
-
-bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x < frameRight
- && y >= frameTop && y < frameBottom;
-}
-
-bool InputWindowInfo::isTrustedOverlay() const {
- return layoutParamsType == TYPE_INPUT_METHOD
- || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
- || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
- || layoutParamsType == TYPE_STATUS_BAR
- || layoutParamsType == TYPE_NAVIGATION_BAR
- || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
- || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
- || layoutParamsType == TYPE_DOCK_DIVIDER
- || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
- || layoutParamsType == TYPE_INPUT_CONSUMER;
-}
-
-bool InputWindowInfo::supportsSplitTouch() const {
- return layoutParamsFlags & FLAG_SPLIT_TOUCH;
-}
-
-bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
- return frameLeft < other->frameRight && frameRight > other->frameLeft
- && frameTop < other->frameBottom && frameBottom > other->frameTop;
-}
-
-
-// --- InputWindowHandle ---
-
-InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
- inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) {
-}
-
-InputWindowHandle::~InputWindowHandle() {
- delete mInfo;
-}
-
-void InputWindowHandle::releaseInfo() {
- if (mInfo) {
- delete mInfo;
- mInfo = nullptr;
- }
-}
-
-} // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 9b985dc..b70ee09 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -132,6 +132,7 @@
InputReaderConfiguration mConfig;
KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
Vector<InputDeviceInfo> mInputDevices;
+ std::vector<DisplayViewport> mViewports;
TouchAffineTransformation transform;
protected:
@@ -143,17 +144,20 @@
void setDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
const std::string& uniqueId) {
- DisplayViewport v = createDisplayViewport(displayId, width, height, orientation, uniqueId);
+ mViewports.clear();
// Set the size of both the internal and external display at the same time.
- mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL, v);
- mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_EXTERNAL, v);
+ mViewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId,
+ ViewportType::VIEWPORT_INTERNAL));
+ mViewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId,
+ ViewportType::VIEWPORT_EXTERNAL));
+ mConfig.setDisplayViewports(mViewports);
}
void setVirtualDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
const std::string& uniqueId) {
- Vector<DisplayViewport> viewports;
- viewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId));
- mConfig.setVirtualDisplayViewports(viewports);
+ mViewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId,
+ ViewportType::VIEWPORT_VIRTUAL));
+ mConfig.setDisplayViewports(mViewports);
}
void addExcludedDeviceName(const std::string& deviceName) {
@@ -203,7 +207,7 @@
private:
DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, const std::string& uniqueId) {
+ int32_t orientation, const std::string& uniqueId, ViewportType type) {
bool isRotated = (orientation == DISPLAY_ORIENTATION_90
|| orientation == DISPLAY_ORIENTATION_270);
DisplayViewport v;
@@ -220,6 +224,7 @@
v.deviceWidth = isRotated ? height : width;
v.deviceHeight = isRotated ? width : height;
v.uniqueId = uniqueId;
+ v.type = type;
return v;
}
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index ebc7eb1..f813fe5 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -16,6 +16,7 @@
#include "SensorDevice.h"
+#include "android/hardware/sensors/2.0/ISensorsCallback.h"
#include "android/hardware/sensors/2.0/types.h"
#include "SensorService.h"
@@ -32,6 +33,7 @@
using namespace android::hardware::sensors;
using namespace android::hardware::sensors::V1_0;
using namespace android::hardware::sensors::V1_0::implementation;
+using android::hardware::sensors::V2_0::ISensorsCallback;
using android::hardware::sensors::V2_0::EventQueueFlagBits;
using android::hardware::hidl_vec;
using android::hardware::Return;
@@ -57,6 +59,27 @@
}
}
+void SensorsHalDeathReceivier::serviceDied(
+ uint64_t /* cookie */,
+ const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
+ ALOGW("Sensors HAL died, attempting to reconnect.");
+ // TODO: Attempt reconnect
+}
+
+struct SensorsCallback : public ISensorsCallback {
+ using Result = ::android::hardware::sensors::V1_0::Result;
+ Return<void> onDynamicSensorsConnected(
+ const hidl_vec<SensorInfo> &dynamicSensorsAdded) override {
+ return SensorDevice::getInstance().onDynamicSensorsConnected(dynamicSensorsAdded);
+ }
+
+ Return<void> onDynamicSensorsDisconnected(
+ const hidl_vec<int32_t> &dynamicSensorHandlesRemoved) override {
+ return SensorDevice::getInstance().onDynamicSensorsDisconnected(
+ dynamicSensorHandlesRemoved);
+ }
+};
+
SensorDevice::SensorDevice()
: mHidlTransportErrors(20), mRestartWaiter(new HidlServiceRegistrationWaiter()) {
if (!connectHidlService()) {
@@ -166,13 +189,15 @@
status_t status = StatusFromResult(checkReturn(mSensors->initialize(
*mEventQueue->getDesc(),
*mWakeLockQueue->getDesc(),
- this)));
+ new SensorsCallback())));
if (status != NO_ERROR) {
connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
ALOGE("Failed to initialize Sensors HAL (%s)", strerror(-status));
} else {
connectionStatus = HalConnectionStatus::CONNECTED;
+ mSensorsHalDeathReceiver = new SensorsHalDeathReceivier();
+ sensors->linkToDeath(mSensorsHalDeathReceiver, 0 /* cookie */);
}
}
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 282550f..2da60b6 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -42,9 +42,12 @@
namespace android {
// ---------------------------------------------------------------------------
+class SensorsHalDeathReceivier : public android::hardware::hidl_death_recipient {
+ virtual void serviceDied(uint64_t cookie,
+ const wp<::android::hidl::base::V1_0::IBase>& service) override;
+};
class SensorDevice : public Singleton<SensorDevice>,
- public android::hardware::sensors::V2_0::ISensorsCallback,
public SensorServiceUtil::Dumpable {
public:
class HidlTransportErrorLog {
@@ -107,9 +110,9 @@
using Result = ::android::hardware::sensors::V1_0::Result;
hardware::Return<void> onDynamicSensorsConnected(
- const hardware::hidl_vec<hardware::sensors::V1_0::SensorInfo> &dynamicSensorsAdded) override;
+ const hardware::hidl_vec<hardware::sensors::V1_0::SensorInfo> &dynamicSensorsAdded);
hardware::Return<void> onDynamicSensorsDisconnected(
- const hardware::hidl_vec<int32_t> &dynamicSensorHandlesRemoved) override;
+ const hardware::hidl_vec<int32_t> &dynamicSensorHandlesRemoved);
// Dumpable
virtual std::string dump() const;
@@ -223,6 +226,8 @@
hardware::EventFlag* mEventQueueFlag;
std::array<Event, SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
+
+ sp<SensorsHalDeathReceivier> mSensorsHalDeathReceiver;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 4f12d3e..339f83b 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -138,6 +138,7 @@
"LayerStats.cpp",
"LayerVector.cpp",
"MonitoredProducer.cpp",
+ "NativeWindowSurface.cpp",
"RenderArea.cpp",
"Scheduler/DispSync.cpp",
"Scheduler/DispSyncSource.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 89394cd..cafe26b 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -49,24 +49,16 @@
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),
- mTextureName(mFlinger->getNewTexture()),
- mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mBufferLatched(false),
- mRefreshPending(false) {
- ALOGV("Creating Layer %s", name.string());
+BufferLayer::BufferLayer(const LayerCreationArgs& args)
+ : Layer(args), mTextureName(args.flinger->getNewTexture()) {
+ ALOGV("Creating Layer %s", args.name.string());
mTexture.init(renderengine::Texture::TEXTURE_EXTERNAL, mTextureName);
- mPremultipliedAlpha = !(flags & ISurfaceComposerClient::eNonPremultiplied);
+ mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
- mPotentialCursor = flags & ISurfaceComposerClient::eCursorWindow;
- mProtectedByApp = flags & ISurfaceComposerClient::eProtectedByApp;
-
- // drawing state & current state are identical
- mDrawingState = mCurrentState;
+ mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
+ mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp;
}
BufferLayer::~BufferLayer() {
@@ -266,6 +258,7 @@
getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata();
getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata();
+ getBE().compositionInfo.hwc.colorTransform = getColorTransform();
setHwcLayerBuffer(display);
}
@@ -327,7 +320,8 @@
return true;
}
-Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) {
ATRACE_CALL();
std::optional<Region> sidebandStreamDirtyRegion = latchSidebandStream(recomputeVisibleRegions);
@@ -368,7 +362,7 @@
return dirtyRegion;
}
- status_t err = updateTexImage(recomputeVisibleRegions, latchTime);
+ status_t err = updateTexImage(recomputeVisibleRegions, latchTime, releaseFence);
if (err != NO_ERROR) {
return dirtyRegion;
}
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 45906ff..a294793 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -39,6 +39,8 @@
#include <utils/String8.h>
#include <utils/Timers.h>
+#include <system/window.h> // For NATIVE_WINDOW_SCALING_MODE_FREEZE
+
#include <stdint.h>
#include <sys/types.h>
#include <list>
@@ -47,9 +49,7 @@
class BufferLayer : public Layer {
public:
- BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
- uint32_t h, uint32_t flags);
-
+ explicit BufferLayer(const LayerCreationArgs& args);
~BufferLayer() override;
// -----------------------------------------------------------------------
@@ -91,7 +91,11 @@
// 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;
+ // If there was a GL composition step rendering the previous frame, then
+ // releaseFence will be populated with a native fence that fires when
+ // composition has completed.
+ Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) override;
bool isBufferLatched() const override { return mRefreshPending; }
@@ -135,7 +139,8 @@
virtual void setFilteringEnabled(bool enabled) = 0;
virtual status_t bindTextureImage() const = 0;
- virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
+ virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& flushFence) = 0;
virtual status_t updateActiveBuffer() = 0;
virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
@@ -172,15 +177,15 @@
uint64_t getHeadFrameNumber() const;
- uint32_t mCurrentScalingMode;
+ uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
// main thread.
- bool mBufferLatched; // TODO: Use mActiveBuffer?
+ bool mBufferLatched{false}; // TODO: Use mActiveBuffer?
// The texture used to draw the layer in GLES composition mode
mutable renderengine::Texture mTexture;
- bool mRefreshPending;
+ bool mRefreshPending{false};
};
} // namespace android
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index fa181ad..f499f06 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -147,7 +147,8 @@
status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
bool* autoRefresh, bool* queuedBuffer,
- uint64_t maxFrameNumber) {
+ uint64_t maxFrameNumber,
+ const sp<Fence>& releaseFence) {
ATRACE_CALL();
BLC_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex);
@@ -198,12 +199,12 @@
}
// Release the previous buffer.
- err = updateAndReleaseLocked(item, &mPendingRelease);
+ err = updateAndReleaseLocked(item, &mPendingRelease, releaseFence);
if (err != NO_ERROR) {
return err;
}
- if (mRE.useNativeFenceSync()) {
+ if (!mRE.useNativeFenceSync()) {
// Bind the new buffer to the GL texture.
//
// Older devices require the "implicit" synchronization provided
@@ -278,14 +279,15 @@
}
status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease) {
+ PendingRelease* pendingRelease,
+ const sp<Fence>& releaseFence) {
status_t err = NO_ERROR;
int slot = item.mSlot;
// Do whatever sync ops we need to do before releasing the old slot.
if (slot != mCurrentTexture) {
- err = syncForReleaseLocked();
+ err = syncForReleaseLocked(releaseFence);
if (err != NO_ERROR) {
// Release the buffer we just acquired. It's not safe to
// release the old buffer, so instead we just drop the new frame.
@@ -367,19 +369,19 @@
return doFenceWaitLocked();
}
-status_t BufferLayerConsumer::syncForReleaseLocked() {
+status_t BufferLayerConsumer::syncForReleaseLocked(const sp<Fence>& releaseFence) {
BLC_LOGV("syncForReleaseLocked");
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- if (mRE.useNativeFenceSync()) {
- base::unique_fd fenceFd = mRE.flush();
- if (fenceFd == -1) {
+ if (mRE.useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
+ // TODO(alecmouri): fail further upstream if the fence is invalid
+ if (!releaseFence->isValid()) {
BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine");
return UNKNOWN_ERROR;
}
- sp<Fence> fence(new Fence(std::move(fenceFd)));
- status_t err = addReleaseFenceLocked(mCurrentTexture,
- mCurrentTextureImage->graphicBuffer(), fence);
+ status_t err =
+ addReleaseFenceLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
+ releaseFence);
if (err != OK) {
BLC_LOGE("syncForReleaseLocked: error adding release fence: "
"%s (%d)",
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 257a4e5..dc00487 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -94,7 +94,8 @@
// used to reject the newly acquired buffer. It also does not bind the
// RenderEngine texture until bindTextureImage is called.
status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync, bool* autoRefresh,
- bool* queuedBuffer, uint64_t maxFrameNumber);
+ bool* queuedBuffer, uint64_t maxFrameNumber,
+ const sp<Fence>& releaseFence);
// See BufferLayerConsumer::bindTextureImageLocked().
status_t bindTextureImage();
@@ -208,7 +209,8 @@
// completion of the method will instead be returned to the caller, so that
// it may call releaseBufferLocked itself later.
status_t updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease = nullptr);
+ PendingRelease* pendingRelease = nullptr,
+ const sp<Fence>& releaseFence = Fence::NO_FENCE);
// Binds mTexName and the current buffer to TEXTURE_EXTERNAL target. Uses
// mCurrentTexture if it's set, mCurrentTextureImage if not. If the
@@ -282,7 +284,7 @@
// current slot from RenderEngine. If needed it will set the current
// slot's fence to guard against a producer accessing the buffer before
// the outstanding accesses have completed.
- status_t syncForReleaseLocked();
+ status_t syncForReleaseLocked(const sp<Fence>& releaseFence);
// The default consumer usage flags that BufferLayerConsumer always sets on its
// BufferQueue instance; these will be OR:d with any additional flags passed
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 521cdbf..6822298 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -21,24 +21,9 @@
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;
-}
+BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
+
+BufferQueueLayer::~BufferQueueLayer() = default;
// -----------------------------------------------------------------------
// Interface implementation for Layer
@@ -236,7 +221,8 @@
return mConsumer->bindTextureImage();
}
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) {
// 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
@@ -247,7 +233,7 @@
getTransformToDisplayInverse(), mFreezeGeometryUpdates);
status_t updateResult =
mConsumer->updateTexImage(&r, *mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived);
+ mLastFrameNumberReceived, releaseFence);
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.
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 400f412..dcf39ee 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -31,8 +31,8 @@
*/
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);
+ explicit BufferQueueLayer(const LayerCreationArgs&);
+ ~BufferQueueLayer() override;
// -----------------------------------------------------------------------
// Interface implementation for Layer
@@ -90,7 +90,8 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() const override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
@@ -121,20 +122,20 @@
sp<BufferLayerConsumer> mConsumer;
sp<IGraphicBufferProducer> mProducer;
- PixelFormat mFormat;
+ PixelFormat mFormat{PIXEL_FORMAT_NONE};
// Only accessed on the main thread.
- uint64_t mPreviousFrameNumber;
- bool mUpdateTexImageFailed;
+ uint64_t mPreviousFrameNumber{0};
+ bool mUpdateTexImageFailed{false};
// Local copy of the queued contents of the incoming BufferQueue
mutable Mutex mQueueItemLock;
Condition mQueueItemCondition;
Vector<BufferItem> mQueueItems;
- std::atomic<uint64_t> mLastFrameNumberReceived;
+ std::atomic<uint64_t> mLastFrameNumberReceived{0};
- bool mAutoRefresh;
- int mActiveBufferSlot;
+ bool mAutoRefresh{false};
+ int mActiveBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
// thread-safe
std::atomic<int32_t> mQueuedFrames{0};
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index da9dcfb..2ecf71c 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -26,18 +26,17 @@
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};
+// clang-format off
+const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+};
+// clang-format on
-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;
-}
+BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
+BufferStateLayer::~BufferStateLayer() = default;
// -----------------------------------------------------------------------
// Interface implementation for Layer
@@ -378,7 +377,8 @@
return NO_ERROR;
}
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) {
const State& s(getDrawingState());
if (!s.buffer) {
@@ -420,16 +420,13 @@
}
// Handle sync fences
- if (SyncFeatures::getInstance().useNativeFenceSync()) {
- base::unique_fd fenceFd = engine.flush();
- if (fenceFd == -1) {
- ALOGE("failed to flush RenderEngine");
+ if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
+ // TODO(alecmouri): Fail somewhere upstream if the fence is invalid.
+ if (!releaseFence->isValid()) {
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.
@@ -440,10 +437,10 @@
return BAD_VALUE;
}
- auto incomingStatus = fence->getStatus();
+ auto incomingStatus = releaseFence->getStatus();
if (incomingStatus == Fence::Status::Invalid) {
ALOGE("New fence has invalid state");
- mDrawingState.acquireFence = fence;
+ mDrawingState.acquireFence = releaseFence;
mTimeStats.clearLayerRecord(getName().c_str());
return BAD_VALUE;
}
@@ -453,12 +450,13 @@
if (currentStatus == incomingStatus) {
char fenceName[32] = {};
snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber);
- sp<Fence> mergedFence = Fence::merge(fenceName, mDrawingState.acquireFence, fence);
+ sp<Fence> mergedFence =
+ Fence::merge(fenceName, mDrawingState.acquireFence, releaseFence);
if (!mergedFence.get()) {
ALOGE("failed to merge release fences");
// synchronization is broken, the best we can do is hope fences
// signal in order so the new fence will act like a union
- mDrawingState.acquireFence = fence;
+ mDrawingState.acquireFence = releaseFence;
mTimeStats.clearLayerRecord(getName().c_str());
return BAD_VALUE;
}
@@ -471,7 +469,7 @@
// 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;
+ mDrawingState.acquireFence = releaseFence;
}
} else {
// Bind the new buffer to the GL texture.
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index ac3aad1..db11110 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -29,8 +29,8 @@
class BufferStateLayer : public BufferLayer {
public:
- BufferStateLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
- uint32_t w, uint32_t h, uint32_t flags);
+ explicit BufferStateLayer(const LayerCreationArgs&);
+ ~BufferStateLayer() override;
// -----------------------------------------------------------------------
// Interface implementation for Layer
@@ -115,7 +115,8 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() const override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
@@ -125,13 +126,15 @@
private:
void onFirstRef() override;
+ static const std::array<float, 16> IDENTITY_MATRIX;
+
std::unique_ptr<renderengine::Image> mTextureImage;
- std::array<float, 16> mTransformMatrix;
+ std::array<float, 16> mTransformMatrix{IDENTITY_MATRIX};
- std::atomic<bool> mSidebandStreamChanged;
+ std::atomic<bool> mSidebandStreamChanged{false};
- uint32_t mFrameNumber;
+ uint32_t mFrameNumber{0};
// TODO(marissaw): support sticky transform for LEGACY camera mode
};
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 9bf75e8..3a554c9 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -34,12 +34,9 @@
namespace android {
// ---------------------------------------------------------------------------
-ColorLayer::ColorLayer(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) {
- // drawing state & current state are identical
- mDrawingState = mCurrentState;
-}
+ColorLayer::ColorLayer(const LayerCreationArgs& args) : Layer(args) {}
+
+ColorLayer::~ColorLayer() = default;
void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
bool useIdentityTransform) {
@@ -72,12 +69,13 @@
getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
half4 color = getColor();
- getBE().compositionInfo.hwc.color = { static_cast<uint8_t>(std::round(255.0f * color.r)),
- static_cast<uint8_t>(std::round(255.0f * color.g)),
- static_cast<uint8_t>(std::round(255.0f * color.b)), 255 };
+ getBE().compositionInfo.hwc.color = {static_cast<uint8_t>(std::round(255.0f * color.r)),
+ static_cast<uint8_t>(std::round(255.0f * color.g)),
+ static_cast<uint8_t>(std::round(255.0f * color.b)), 255};
// Clear out the transform, because it doesn't make sense absent a source buffer
getBE().compositionInfo.hwc.transform = HWC2::Transform::None;
+ getBE().compositionInfo.hwc.colorTransform = getColorTransform();
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index aa6b049..2c10357 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -25,9 +25,8 @@
class ColorLayer : public Layer {
public:
- ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
- uint32_t h, uint32_t flags);
- virtual ~ColorLayer() = default;
+ explicit ColorLayer(const LayerCreationArgs&);
+ ~ColorLayer() override;
virtual const char* getTypeId() const { return "ColorLayer"; }
virtual void onDraw(const RenderArea& renderArea, const Region& clip,
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index e9f3059..44e843e 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -22,11 +22,9 @@
namespace android {
-ContainerLayer::ContainerLayer(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) {
- mDrawingState = mCurrentState;
-}
+ContainerLayer::ContainerLayer(const LayerCreationArgs& args) : Layer(args) {}
+
+ContainerLayer::~ContainerLayer() = default;
void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) {}
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 0b4a181..8eddc7f 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -25,9 +25,8 @@
class ContainerLayer : public Layer {
public:
- ContainerLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
- uint32_t w, uint32_t h, uint32_t flags);
- virtual ~ContainerLayer() = default;
+ explicit ContainerLayer(const LayerCreationArgs&);
+ ~ContainerLayer() override;
const char* getTypeId() const override { return "ContainerLayer"; }
void onDraw(const RenderArea& renderArea, const Region& clip,
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 4becfab..341dfd5 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -206,54 +206,46 @@
} // anonymous namespace
-// clang-format off
-DisplayDevice::DisplayDevice(
- const sp<SurfaceFlinger>& flinger,
- DisplayType type,
- int32_t id,
- bool isSecure,
- const wp<IBinder>& displayToken,
- const sp<ANativeWindow>& nativeWindow,
- const sp<DisplaySurface>& displaySurface,
- std::unique_ptr<renderengine::Surface> renderSurface,
- int displayWidth,
- int displayHeight,
- int displayInstallOrientation,
- bool hasWideColorGamut,
- const HdrCapabilities& hdrCapabilities,
- const int32_t supportedPerFrameMetadata,
- const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
- int initialPowerMode)
- : lastCompositionHadVisibleLayers(false),
- mFlinger(flinger),
- mType(type),
- mId(id),
- mDisplayToken(displayToken),
- mNativeWindow(nativeWindow),
- mDisplaySurface(displaySurface),
- mSurface{std::move(renderSurface)},
- mDisplayWidth(displayWidth),
- mDisplayHeight(displayHeight),
- mDisplayInstallOrientation(displayInstallOrientation),
- mPageFlipCount(0),
- mIsSecure(isSecure),
- mLayerStack(NO_LAYER_STACK),
- mOrientation(),
- mViewport(Rect::INVALID_RECT),
- mFrame(Rect::INVALID_RECT),
- mPowerMode(initialPowerMode),
- mActiveConfig(0),
- mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
- mHasWideColorGamut(hasWideColorGamut),
- mHasHdr10(false),
- mHasHLG(false),
- mHasDolbyVision(false),
- mSupportedPerFrameMetadata(supportedPerFrameMetadata)
-{
- // clang-format on
- populateColorModes(hwcColorModes);
+DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(const sp<SurfaceFlinger>& flinger,
+ const wp<IBinder>& displayToken,
+ DisplayDevice::DisplayType type, int32_t id)
+ : flinger(flinger), displayToken(displayToken), type(type), id(id) {}
- std::vector<Hdr> types = hdrCapabilities.getSupportedHdrTypes();
+DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args)
+ : lastCompositionHadVisibleLayers(false),
+ mFlinger(args.flinger),
+ mType(args.type),
+ mId(args.id),
+ mDisplayToken(args.displayToken),
+ mNativeWindow(args.nativeWindow),
+ mDisplaySurface(args.displaySurface),
+ mSurface{std::move(args.renderSurface)},
+ mDisplayWidth(args.displayWidth),
+ mDisplayHeight(args.displayHeight),
+ mDisplayInstallOrientation(args.displayInstallOrientation),
+ mPageFlipCount(0),
+ mIsSecure(args.isSecure),
+ mLayerStack(NO_LAYER_STACK),
+ mOrientation(),
+ mViewport(Rect::INVALID_RECT),
+ mFrame(Rect::INVALID_RECT),
+ mPowerMode(args.initialPowerMode),
+ mActiveConfig(0),
+ mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
+ mHasWideColorGamut(args.hasWideColorGamut),
+ mHasHdr10(false),
+ mHasHLG(false),
+ mHasDolbyVision(false),
+ mSupportedPerFrameMetadata(args.supportedPerFrameMetadata) {
+ populateColorModes(args.hwcColorModes);
+
+ ALOGE_IF(!mNativeWindow, "No native window was set for display");
+ ALOGE_IF(!mDisplaySurface, "No display surface was set for display");
+ ALOGE_IF(!mSurface, "No render surface was set for display");
+ ALOGE_IF(mDisplayWidth <= 0 || mDisplayHeight <= 0,
+ "Invalid dimensions of %d x %d were set for display", mDisplayWidth, mDisplayHeight);
+
+ std::vector<Hdr> types = args.hdrCapabilities.getSupportedHdrTypes();
for (Hdr hdrType : types) {
switch (hdrType) {
case Hdr::HDR10:
@@ -270,9 +262,9 @@
}
}
- float minLuminance = hdrCapabilities.getDesiredMinLuminance();
- float maxLuminance = hdrCapabilities.getDesiredMaxLuminance();
- float maxAverageLuminance = hdrCapabilities.getDesiredMaxAverageLuminance();
+ float minLuminance = args.hdrCapabilities.getDesiredMinLuminance();
+ float maxLuminance = args.hdrCapabilities.getDesiredMaxLuminance();
+ float maxAverageLuminance = args.hdrCapabilities.getDesiredMaxAverageLuminance();
minLuminance = minLuminance <= 0.0 ? sDefaultMinLumiance : minLuminance;
maxLuminance = maxLuminance <= 0.0 ? sDefaultMaxLumiance : maxLuminance;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index ed73671..38482c9 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -43,14 +43,16 @@
namespace android {
-struct DisplayInfo;
class DisplaySurface;
class Fence;
+class HWComposer;
class IGraphicBufferProducer;
class Layer;
class SurfaceFlinger;
-class HWComposer;
+
struct CompositionInfo;
+struct DisplayDeviceCreationArgs;
+struct DisplayInfo;
class DisplayDevice : public LightRefBase<DisplayDevice>
{
@@ -76,25 +78,7 @@
NO_LAYER_STACK = 0xFFFFFFFF,
};
- // clang-format off
- DisplayDevice(
- const sp<SurfaceFlinger>& flinger,
- DisplayType type,
- int32_t id,
- bool isSecure,
- const wp<IBinder>& displayToken,
- const sp<ANativeWindow>& nativeWindow,
- const sp<DisplaySurface>& displaySurface,
- std::unique_ptr<renderengine::Surface> renderSurface,
- int displayWidth,
- int displayHeight,
- int displayInstallOrientation,
- bool hasWideColorGamut,
- const HdrCapabilities& hdrCapabilities,
- const int32_t supportedPerFrameMetadata,
- const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>>& hwcColorModes,
- int initialPowerMode);
- // clang-format on
+ explicit DisplayDevice(DisplayDeviceCreationArgs&& args);
~DisplayDevice();
@@ -335,6 +319,31 @@
static std::atomic<int32_t> sNextSequenceId;
};
+struct DisplayDeviceCreationArgs {
+ // We use a constructor to ensure some of the values are set, without
+ // assuming a default value.
+ DisplayDeviceCreationArgs(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& displayToken,
+ DisplayDevice::DisplayType type, int32_t id);
+
+ const sp<SurfaceFlinger> flinger;
+ const wp<IBinder> displayToken;
+ const DisplayDevice::DisplayType type;
+ const int32_t id;
+
+ bool isSecure{false};
+ sp<ANativeWindow> nativeWindow;
+ sp<DisplaySurface> displaySurface;
+ std::unique_ptr<renderengine::Surface> renderSurface;
+ int displayWidth{0};
+ int displayHeight{0};
+ int displayInstallOrientation{DisplayState::eOrientationDefault};
+ bool hasWideColorGamut{false};
+ HdrCapabilities hdrCapabilities;
+ int32_t supportedPerFrameMetadata{0};
+ std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hwcColorModes;
+ int initialPowerMode{HWC_POWER_MODE_NORMAL};
+};
+
class DisplayRenderArea : public RenderArea {
public:
DisplayRenderArea(const sp<const DisplayDevice> device,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 19c84d0..9be18fb 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -64,40 +64,22 @@
std::atomic<int32_t> Layer::sSequence{1};
-Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
- uint32_t h, uint32_t flags)
- : contentDirty(false),
- mFlinger(flinger),
- mPremultipliedAlpha(true),
- mName(name),
- mTransactionFlags(0),
- mPendingStateMutex(),
- mPendingStates(),
- mCurrentTransform(0),
- mOverrideScalingMode(-1),
- mCurrentFrameNumber(0),
- mFrameLatencyNeeded(false),
- mNeedsFiltering(false),
- mProtectedByApp(false),
- mClientRef(client),
- mPotentialCursor(false),
- mFreezeGeometryUpdates(false),
- mCurrentChildren(LayerVector::StateSet::Current),
- mDrawingChildren(LayerVector::StateSet::Drawing),
- mBE{this, name.string()} {
-
+Layer::Layer(const LayerCreationArgs& args)
+ : mFlinger(args.flinger),
+ mName(args.name),
+ mClientRef(args.client),
+ mBE{this, args.name.string()} {
mCurrentCrop.makeInvalid();
uint32_t layerFlags = 0;
- if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
- if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
- if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
+ if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
+ if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
+ if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
- mName = name;
mTransactionName = String8("TX - ") + mName;
- mCurrentState.active_legacy.w = w;
- mCurrentState.active_legacy.h = h;
+ mCurrentState.active_legacy.w = args.w;
+ mCurrentState.active_legacy.h = args.h;
mCurrentState.flags = layerFlags;
mCurrentState.active_legacy.transform.set(0, 0);
mCurrentState.crop_legacy.makeInvalid();
@@ -125,7 +107,7 @@
mDrawingState = mCurrentState;
CompositorTiming compositorTiming;
- flinger->getCompositorTiming(&compositorTiming);
+ args.flinger->getCompositorTiming(&compositorTiming);
mFrameEventHistory.initializeCompositorTiming(compositorTiming);
mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval);
}
@@ -136,12 +118,6 @@
c->detachLayer(this);
}
- for (auto& point : mRemoteSyncPoints) {
- point->setTransactionApplied();
- }
- for (auto& point : mLocalSyncPoints) {
- point->setFrameAvailable();
- }
mFrameTracker.logAndResetStats(mName);
}
@@ -159,8 +135,6 @@
void Layer::onRemovedFromCurrentState() {
// the layer is removed from SF mCurrentState to mLayersPendingRemoval
- mPendingRemoval = true;
-
if (mCurrentState.zOrderRelativeOf != nullptr) {
sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
if (strongRelative != nullptr) {
@@ -169,7 +143,7 @@
}
mCurrentState.zOrderRelativeOf = nullptr;
}
-
+
for (const auto& child : mCurrentChildren) {
child->onRemovedFromCurrentState();
}
@@ -181,8 +155,13 @@
destroyAllHwcLayers();
- for (const auto& child : mCurrentChildren) {
- child->onRemoved();
+ mRemoved = true;
+
+ for (auto& point : mRemoteSyncPoints) {
+ point->setTransactionApplied();
+ }
+ for (auto& point : mLocalSyncPoints) {
+ point->setFrameAvailable();
}
}
@@ -1564,6 +1543,25 @@
return true;
}
+bool Layer::setColorTransform(const mat4& matrix) {
+ if (mCurrentState.colorTransform == matrix) {
+ return false;
+ }
+ ++mCurrentState.sequence;
+ mCurrentState.colorTransform = matrix;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+const mat4& Layer::getColorTransform() const {
+ return getDrawingState().colorTransform;
+}
+
+bool Layer::hasColorTransform() const {
+ static const mat4 identityMatrix = mat4();
+ return getDrawingState().colorTransform != identityMatrix;
+}
+
bool Layer::isLegacyDataSpace() const {
// return true when no higher bits are set
return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK |
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 74f0a63..f2cda03 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -72,6 +72,19 @@
// ---------------------------------------------------------------------------
+struct LayerCreationArgs {
+ LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags)
+ : flinger(flinger), client(client), name(name), w(w), h(h), flags(flags) {}
+
+ SurfaceFlinger* flinger;
+ const sp<Client>& client;
+ const String8& name;
+ uint32_t w;
+ uint32_t h;
+ uint32_t flags;
+};
+
class Layer : public virtual RefBase {
static std::atomic<int32_t> sSequence;
@@ -79,7 +92,7 @@
friend class LayerBE;
LayerBE& getBE() { return mBE; }
LayerBE& getBE() const { return mBE; }
- mutable bool contentDirty;
+ mutable bool contentDirty{false};
// regions below are in window-manager space
Region visibleRegion;
Region coveredRegion;
@@ -168,10 +181,10 @@
int32_t api;
sp<NativeHandle> sidebandStream;
+ mat4 colorTransform;
};
- Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
- uint32_t h, uint32_t flags);
+ explicit Layer(const LayerCreationArgs& args);
virtual ~Layer();
void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; }
@@ -243,6 +256,9 @@
virtual void setChildrenDrawingParent(const sp<Layer>& layer);
virtual bool reparent(const sp<IBinder>& newParentHandle);
virtual bool detachChildren();
+ virtual bool setColorTransform(const mat4& matrix);
+ virtual const mat4& getColorTransform() const;
+ virtual bool hasColorTransform() const;
// Used only to set BufferStateLayer state
virtual bool setTransform(uint32_t /*transform*/) { return false; };
@@ -329,7 +345,7 @@
virtual bool isCreatedFromMainThread() const { return false; }
- bool isPendingRemoval() const { return mPendingRemoval; }
+ bool isRemoved() const { return mRemoved; }
void writeToProto(LayerProto* layerInfo,
LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
@@ -445,7 +461,8 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) {
+ virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
+ const sp<Fence>& /*releaseFence*/) {
return {};
}
@@ -577,12 +594,12 @@
*/
class LayerCleaner {
sp<SurfaceFlinger> mFlinger;
- wp<Layer> mLayer;
+ sp<Layer> mLayer;
protected:
~LayerCleaner() {
// destroy client resources
- mFlinger->onLayerDestroyed(mLayer);
+ mFlinger->removeLayer(mLayer, true);
}
public:
@@ -688,7 +705,7 @@
// -----------------------------------------------------------------------
bool usingRelativeZ(LayerVector::StateSet stateSet);
- bool mPremultipliedAlpha;
+ bool mPremultipliedAlpha{true};
String8 mName;
String8 mTransactionName; // A cached version of "TX - " + mName for systraces
@@ -719,18 +736,18 @@
sp<GraphicBuffer> mActiveBuffer;
ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN;
Rect mCurrentCrop;
- uint32_t mCurrentTransform;
+ uint32_t mCurrentTransform{0};
// We encode unset as -1.
- int32_t mOverrideScalingMode;
- std::atomic<uint64_t> mCurrentFrameNumber;
- bool mFrameLatencyNeeded;
+ int32_t mOverrideScalingMode{-1};
+ std::atomic<uint64_t> mCurrentFrameNumber{0};
+ bool mFrameLatencyNeeded{false};
// Whether filtering is needed b/c of the drawingstate
- bool mNeedsFiltering;
+ bool mNeedsFiltering{false};
- bool mPendingRemoval = false;
+ bool mRemoved{false};
// page-flip thread (currently main thread)
- bool mProtectedByApp; // application requires protected path to external sink
+ bool mProtectedByApp{false}; // application requires protected path to external sink
// protected by mLock
mutable Mutex mLock;
@@ -738,14 +755,14 @@
const wp<Client> mClientRef;
// This layer can be a cursor on some displays.
- bool mPotentialCursor;
+ bool mPotentialCursor{false};
- bool mFreezeGeometryUpdates;
+ bool mFreezeGeometryUpdates{false};
// Child list about to be committed/used for editing.
- LayerVector mCurrentChildren;
+ LayerVector mCurrentChildren{LayerVector::StateSet::Current};
// Child list used for rendering.
- LayerVector mDrawingChildren;
+ LayerVector mDrawingChildren{LayerVector::StateSet::Drawing};
wp<Layer> mCurrentParent;
wp<Layer> mDrawingParent;
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index ef017aa..c9b7933 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -112,6 +112,20 @@
hwc.surfaceDamage.dump(regionString, "surfaceDamage");
result += regionString.string();
}
+
+ result += base::StringPrintf("\tcolor transform matrix:\n"
+ "\t\t[%f, %f, %f, %f,\n"
+ "\t\t %f, %f, %f, %f,\n"
+ "\t\t %f, %f, %f, %f,\n"
+ "\t\t %f, %f, %f, %f]\n",
+ hwc.colorTransform[0][0], hwc.colorTransform[1][0],
+ hwc.colorTransform[2][0], hwc.colorTransform[3][0],
+ hwc.colorTransform[0][1], hwc.colorTransform[1][1],
+ hwc.colorTransform[2][1], hwc.colorTransform[3][1],
+ hwc.colorTransform[0][2], hwc.colorTransform[1][2],
+ hwc.colorTransform[2][2], hwc.colorTransform[3][2],
+ hwc.colorTransform[0][3], hwc.colorTransform[1][3],
+ hwc.colorTransform[2][3], hwc.colorTransform[3][3]);
}
void CompositionInfo::dumpRe(std::string& result, const char* tag) const {
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 2722b01..d63d16f 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -60,6 +60,7 @@
bool clearClientTarget = false;
bool supportedPerFrameMetadata = false;
HdrMetadata hdrMetadata;
+ mat4 colorTransform;
} hwc;
struct {
bool blackoutLayer = false;
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index 9c2d312..c0174ae 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -68,7 +68,7 @@
base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
base::StringAppendF(&key, ",%d", layer->isProtected);
base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
- base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
+ base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
base::StringAppendF(&key, ",%s",
destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0],
@@ -162,8 +162,8 @@
return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
}
-const char* LayerStats::layerPixelFormat(int32_t pixelFormat) {
- return decodePixelFormat(pixelFormat).c_str();
+std::string LayerStats::layerPixelFormat(int32_t pixelFormat) {
+ return decodePixelFormat(pixelFormat);
}
std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 944073b..9de9cce 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -50,7 +50,7 @@
// Return the name of the composition type
static const char* layerCompositionType(int32_t compositionType);
// Return the name of the pixel format
- static const char* layerPixelFormat(int32_t pixelFormat);
+ static std::string layerPixelFormat(int32_t pixelFormat);
// Calculate scale ratios of layer's width/height with rotation information
static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
// Calculate scale ratio from source to destination and convert to string
diff --git a/services/surfaceflinger/NativeWindowSurface.cpp b/services/surfaceflinger/NativeWindowSurface.cpp
new file mode 100644
index 0000000..3fff928
--- /dev/null
+++ b/services/surfaceflinger/NativeWindowSurface.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 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 "NativeWindowSurface.h"
+
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+
+namespace android::surfaceflinger {
+
+NativeWindowSurface::~NativeWindowSurface() = default;
+
+namespace impl {
+
+std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
+ const sp<IGraphicBufferProducer>& producer) {
+ class NativeWindowSurface final : public surfaceflinger::NativeWindowSurface {
+ public:
+ explicit NativeWindowSurface(const sp<IGraphicBufferProducer>& producer)
+ : mSurface(new Surface(producer, /* controlledByApp */ false)) {}
+
+ ~NativeWindowSurface() override = default;
+
+ sp<ANativeWindow> getNativeWindow() const override { return mSurface; }
+
+ void preallocateBuffers() override { mSurface->allocateBuffers(); }
+
+ private:
+ sp<Surface> mSurface;
+ };
+
+ return std::make_unique<NativeWindowSurface>(producer);
+}
+
+} // namespace impl
+} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/NativeWindowSurface.h b/services/surfaceflinger/NativeWindowSurface.h
new file mode 100644
index 0000000..f34a45a
--- /dev/null
+++ b/services/surfaceflinger/NativeWindowSurface.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 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 <memory>
+
+#include <utils/StrongPointer.h>
+
+struct ANativeWindow;
+
+namespace android {
+
+class IGraphicBufferProducer;
+
+namespace surfaceflinger {
+
+// A thin interface to abstract creating instances of Surface (gui/Surface.h) to
+// use as a NativeWindow.
+class NativeWindowSurface {
+public:
+ virtual ~NativeWindowSurface();
+
+ // Gets the NativeWindow to use for the surface.
+ virtual sp<ANativeWindow> getNativeWindow() const = 0;
+
+ // Indicates that the surface should allocate its buffers now.
+ virtual void preallocateBuffers() = 0;
+};
+
+namespace impl {
+
+std::unique_ptr<NativeWindowSurface> createNativeWindowSurface(const sp<IGraphicBufferProducer>&);
+
+} // namespace impl
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index 813c9e6..1b0a539 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -743,7 +743,7 @@
mState.textureEnabled = true;
}
-void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) {
+void GLES20RenderEngine::setColorTransform(const mat4& colorTransform) {
mState.colorMatrix = colorTransform;
}
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
index fa01410..4f03a90 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -86,7 +86,7 @@
void setupLayerTexturing(const Texture& texture) override;
void setupLayerBlackedOut() override;
void setupFillWithColor(float r, float g, float b, float a) override;
- void setupColorTransform(const mat4& colorTransform) override;
+ void setColorTransform(const mat4& colorTransform) override;
void disableTexturing() override;
void disableBlending() override;
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 05668f8..122271f 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -115,7 +115,9 @@
virtual void setupLayerTexturing(const Texture& texture) = 0;
virtual void setupLayerBlackedOut() = 0;
virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
- virtual void setupColorTransform(const mat4& /* colorTransform */) = 0;
+
+ // Set a color transform matrix that is applied in linear space right before OETF.
+ virtual void setColorTransform(const mat4& /* colorTransform */) = 0;
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
@@ -163,7 +165,6 @@
bool useNativeFenceSync() const override;
bool useWaitSync() const override;
- void setupColorTransform(const mat4& /* colorTransform */) override {}
protected:
RenderEngine(uint32_t featureFlags);
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
index efab8ff..911bb7a 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
@@ -68,6 +68,8 @@
// projection matrix
mat4 projectionMatrix;
+
+ // The color matrix will be applied in linear space right before OETF.
mat4 colorMatrix;
mat4 inputTransformMatrix;
mat4 outputTransformMatrix;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index fa2b0a6..9bee9a3 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -111,14 +111,28 @@
status_t EventThread::registerDisplayEventConnection(
const sp<EventThread::Connection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
- mDisplayEventConnections.add(connection);
+
+ // this should never happen
+ auto it = std::find(mDisplayEventConnections.cbegin(),
+ mDisplayEventConnections.cend(), connection);
+ if (it != mDisplayEventConnections.cend()) {
+ ALOGW("DisplayEventConnection %p already exists", connection.get());
+ mCondition.notify_all();
+ return ALREADY_EXISTS;
+ }
+
+ mDisplayEventConnections.push_back(connection);
mCondition.notify_all();
return NO_ERROR;
}
void EventThread::removeDisplayEventConnectionLocked(
const wp<EventThread::Connection>& connection) {
- mDisplayEventConnections.remove(connection);
+ auto it = std::find(mDisplayEventConnections.cbegin(),
+ mDisplayEventConnections.cend(), connection);
+ if (it != mDisplayEventConnections.cend()) {
+ mDisplayEventConnections.erase(it);
+ }
}
void EventThread::setVsyncRate(uint32_t count, const sp<EventThread::Connection>& connection) {
@@ -181,7 +195,7 @@
event.header.timestamp = systemTime();
event.hotplug.connected = connected;
- mPendingEvents.add(event);
+ mPendingEvents.push(event);
mCondition.notify_all();
}
@@ -189,13 +203,11 @@
std::unique_lock<std::mutex> lock(mMutex);
while (mKeepRunning) {
DisplayEventReceiver::Event event;
- Vector<sp<EventThread::Connection> > signalConnections;
+ std::vector<sp<EventThread::Connection>> signalConnections;
signalConnections = waitForEventLocked(&lock, &event);
// dispatch events to listeners...
- const size_t count = signalConnections.size();
- for (size_t i = 0; i < count; i++) {
- const sp<Connection>& conn(signalConnections[i]);
+ for (const sp<Connection>& conn : signalConnections) {
// now see if we still need to report this event
status_t err = conn->postEvent(event);
if (err == -EAGAIN || err == -EWOULDBLOCK) {
@@ -210,7 +222,7 @@
// handle any other error on the pipe as fatal. the only
// reasonable thing to do is to clean-up this connection.
// The most common error we'll get here is -EPIPE.
- removeDisplayEventConnectionLocked(signalConnections[i]);
+ removeDisplayEventConnectionLocked(conn);
}
}
}
@@ -218,11 +230,11 @@
// 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::vector<sp<EventThread::Connection>> EventThread::waitForEventLocked(
std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* outEvent) {
- Vector<sp<EventThread::Connection> > signalConnections;
+ std::vector<sp<EventThread::Connection>> signalConnections;
- while (signalConnections.isEmpty() && mKeepRunning) {
+ while (signalConnections.empty() && mKeepRunning) {
bool eventPending = false;
bool waitForVSync = false;
@@ -244,18 +256,18 @@
if (!timestamp) {
// no vsync event, see if there are some other event
- eventPending = !mPendingEvents.isEmpty();
+ eventPending = !mPendingEvents.empty();
if (eventPending) {
// we have some other event to dispatch
- *outEvent = mPendingEvents[0];
- mPendingEvents.removeAt(0);
+ *outEvent = mPendingEvents.front();
+ mPendingEvents.pop();
}
}
// find out connections waiting for events
- size_t count = mDisplayEventConnections.size();
- for (size_t i = 0; i < count;) {
- sp<Connection> connection(mDisplayEventConnections[i].promote());
+ auto it = mDisplayEventConnections.begin();
+ while (it != mDisplayEventConnections.end()) {
+ sp<Connection> connection(it->promote());
if (connection != nullptr) {
bool added = false;
if (connection->count >= 0) {
@@ -268,12 +280,12 @@
if (connection->count == 0) {
// fired this time around
connection->count = -1;
- signalConnections.add(connection);
+ signalConnections.push_back(connection);
added = true;
} else if (connection->count == 1 ||
(vsyncCount % connection->count) == 0) {
// continuous event, and time to report it
- signalConnections.add(connection);
+ signalConnections.push_back(connection);
added = true;
}
}
@@ -283,14 +295,13 @@
// we don't have a vsync event to process
// (timestamp==0), but we have some pending
// messages.
- signalConnections.add(connection);
+ signalConnections.push_back(connection);
}
- ++i;
+ ++it;
} else {
// we couldn't promote this reference, the connection has
// died, so clean-up!
- mDisplayEventConnections.removeAt(i);
- --count;
+ it = mDisplayEventConnections.erase(it);
}
}
@@ -379,11 +390,12 @@
result.appendFormat(" soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled");
result.appendFormat(" numListeners=%zu,\n events-delivered: %u\n",
mDisplayEventConnections.size(), mVSyncEvent[0].vsync.count);
- for (size_t i = 0; i < mDisplayEventConnections.size(); i++) {
- sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote();
+ for (const wp<Connection>& weak : mDisplayEventConnections) {
+ sp<Connection> connection = weak.promote();
result.appendFormat(" %p: count=%d\n", connection.get(),
connection != nullptr ? connection->count : 0);
}
+ result.appendFormat(" other-events-pending: %zu\n", mPendingEvents.size());
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 127891e..5e7ed13 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -22,7 +22,9 @@
#include <condition_variable>
#include <cstdint>
#include <mutex>
+#include <queue>
#include <thread>
+#include <vector>
#include <android-base/thread_annotations.h>
@@ -31,7 +33,6 @@
#include <private/gui/BitTube.h>
#include <utils/Errors.h>
-#include <utils/SortedVector.h>
// ---------------------------------------------------------------------------
namespace android {
@@ -117,7 +118,6 @@
~EventThread();
sp<BnDisplayEventConnection> createEventConnection() const override;
- status_t registerDisplayEventConnection(const sp<Connection>& connection);
void setVsyncRate(uint32_t count, const sp<Connection>& connection);
void requestNextVsync(const sp<Connection>& connection);
@@ -143,9 +143,11 @@
ResyncWithRateLimitCallback resyncWithRateLimitCallback,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
+ status_t registerDisplayEventConnection(const sp<Connection>& connection);
+
void threadMain();
- Vector<sp<EventThread::Connection>> waitForEventLocked(std::unique_lock<std::mutex>* lock,
- DisplayEventReceiver::Event* event)
+ std::vector<sp<EventThread::Connection>> waitForEventLocked(std::unique_lock<std::mutex>* lock,
+ DisplayEventReceiver::Event* event)
REQUIRES(mMutex);
void removeDisplayEventConnectionLocked(const wp<Connection>& connection) REQUIRES(mMutex);
@@ -167,8 +169,8 @@
mutable std::condition_variable mCondition;
// protected by mLock
- SortedVector<wp<Connection>> mDisplayEventConnections GUARDED_BY(mMutex);
- Vector<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
+ std::vector<wp<Connection>> mDisplayEventConnections GUARDED_BY(mMutex);
+ std::queue<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
std::array<DisplayEventReceiver::Event, 2> mVSyncEvent GUARDED_BY(mMutex);
bool mUseSoftwareVSync GUARDED_BY(mMutex) = false;
bool mVsyncEnabled GUARDED_BY(mMutex) = false;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 157cbea..2199ce1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -74,6 +74,7 @@
#include "Layer.h"
#include "LayerVector.h"
#include "MonitoredProducer.h"
+#include "NativeWindowSurface.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/ComposerHal.h"
@@ -222,32 +223,6 @@
}
}
-NativeWindowSurface::~NativeWindowSurface() = default;
-
-namespace impl {
-
-class NativeWindowSurface final : public android::NativeWindowSurface {
-public:
- static std::unique_ptr<android::NativeWindowSurface> create(
- const sp<IGraphicBufferProducer>& producer) {
- return std::make_unique<NativeWindowSurface>(producer);
- }
-
- explicit NativeWindowSurface(const sp<IGraphicBufferProducer>& producer)
- : surface(new Surface(producer, false)) {}
-
- ~NativeWindowSurface() override = default;
-
-private:
- sp<ANativeWindow> getNativeWindow() const override { return surface; }
-
- void preallocateBuffers() override { surface->allocateBuffers(); }
-
- sp<Surface> surface;
-};
-
-} // namespace impl
-
SurfaceFlingerBE::SurfaceFlingerBE()
: mHwcServiceName(getHwcServiceName()),
mRenderEngine(nullptr),
@@ -284,7 +259,7 @@
mVrFlingerRequestsDisplay(false),
mMainThreadId(std::this_thread::get_id()),
mCreateBufferQueue(&BufferQueue::createBufferQueue),
- mCreateNativeWindowSurface(&impl::NativeWindowSurface::create) {}
+ mCreateNativeWindowSurface(&surfaceflinger::impl::createNativeWindowSurface) {}
SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
@@ -1553,6 +1528,18 @@
getBE().mHwc->hasClientComposition(display->getId());
}
+ // Setup RenderEngine sync fences if native sync is supported.
+ if (getBE().mRenderEngine->useNativeFenceSync()) {
+ if (mHadClientComposition) {
+ base::unique_fd flushFence(getRenderEngine().flush());
+ ALOGE_IF(flushFence < 0, "Failed to flush RenderEngine!");
+ getBE().flushFence = new Fence(std::move(flushFence));
+ } else {
+ // Cleanup for hygiene.
+ getBE().flushFence = Fence::NO_FENCE;
+ }
+ }
+
mVsyncModulator.onRefreshed(mHadClientComposition);
getBE().mEndOfFrameCompositionInfo = std::move(getBE().mCompositionInfo);
@@ -1629,6 +1616,11 @@
layer->forceClientComposition(displayId);
}
+ // TODO(b/111562338) remove when composer 2.3 is shipped.
+ if (layer->hasColorTransform()) {
+ layer->forceClientComposition(displayId);
+ }
+
if (layer->getForceClientComposition(displayId)) {
ALOGV("[%s] Requesting Client composition", layer->getName().string());
layer->setCompositionType(displayId, HWC2::Composition::Client);
@@ -2166,6 +2158,8 @@
ALOGE_IF(error != HWC2::Error::None,
"[SF] Failed to set surface damage: %s (%d)",
to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (compositionInfo.hwc.hwcLayer)->setColorTransform(compositionInfo.hwc.colorTransform);
}
void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const
@@ -2452,31 +2446,34 @@
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
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;
+ DisplayDeviceCreationArgs creationArgs(this, displayToken, state.type, displayId);
+ creationArgs.isSecure = state.isSecure;
+ creationArgs.displaySurface = dispSurface;
+ creationArgs.hasWideColorGamut = false;
+ creationArgs.supportedPerFrameMetadata = 0;
if (useColorManagement && displayId >= 0) {
std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId);
for (ColorMode colorMode : modes) {
if (isWideColorMode(colorMode)) {
- hasWideColorGamut = true;
+ creationArgs.hasWideColorGamut = true;
}
std::vector<RenderIntent> renderIntents =
getHwComposer().getRenderIntents(displayId, colorMode);
- hwcColorModes.emplace(colorMode, renderIntents);
+ creationArgs.hwcColorModes.emplace(colorMode, renderIntents);
}
}
if (displayId >= 0) {
- getHwComposer().getHdrCapabilities(displayId, &hdrCapabilities);
- supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(displayId);
+ getHwComposer().getHdrCapabilities(displayId, &creationArgs.hdrCapabilities);
+ creationArgs.supportedPerFrameMetadata =
+ getHwComposer().getSupportedPerFrameMetadata(displayId);
}
auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
auto nativeWindow = nativeWindowSurface->getNativeWindow();
+ creationArgs.nativeWindow = nativeWindow;
/*
* Create our display's surface
@@ -2485,8 +2482,9 @@
renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
renderSurface->setAsync(state.isVirtual());
renderSurface->setNativeWindow(nativeWindow.get());
- const int displayWidth = renderSurface->getWidth();
- const int displayHeight = renderSurface->getHeight();
+ creationArgs.displayWidth = renderSurface->getWidth();
+ creationArgs.displayHeight = renderSurface->getHeight();
+ creationArgs.renderSurface = std::move(renderSurface);
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough. We have to do this
@@ -2499,18 +2497,14 @@
nativeWindow->setSwapInterval(nativeWindow.get(), 0);
}
- const int displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY ?
- primaryDisplayOrientation : DisplayState::eOrientationDefault;
+ creationArgs.displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY
+ ? primaryDisplayOrientation
+ : DisplayState::eOrientationDefault;
// virtual displays are always considered enabled
- auto initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
+ creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
- sp<DisplayDevice> display =
- new DisplayDevice(this, state.type, displayId, state.isSecure, displayToken,
- nativeWindow, dispSurface, std::move(renderSurface), displayWidth,
- displayHeight, displayInstallOrientation, hasWideColorGamut,
- hdrCapabilities, supportedPerFrameMetadata, hwcColorModes,
- initialPowerMode);
+ sp<DisplayDevice> display = new DisplayDevice(std::move(creationArgs));
if (maxFrameBufferAcquiredBuffers >= 3) {
nativeWindowSurface->preallocateBuffers();
@@ -2518,7 +2512,7 @@
ColorMode defaultColorMode = ColorMode::NATIVE;
Dataspace defaultDataSpace = Dataspace::UNKNOWN;
- if (hasWideColorGamut) {
+ if (display->hasWideColorGamut()) {
defaultColorMode = ColorMode::SRGB;
defaultDataSpace = Dataspace::SRGB;
}
@@ -2858,6 +2852,7 @@
recordBufferingStats(l->getName().string(),
l->getOccupancyHistory(true));
l->onRemoved();
+ mNumLayers -= 1;
}
mLayersPendingRemoval.clear();
}
@@ -3056,7 +3051,7 @@
});
for (auto& layer : mLayersWithQueuedFrames) {
- const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
+ const Region dirty(layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence));
layer->useSurfaceDamage();
invalidateLayerStack(layer, dirty);
if (layer->isBufferLatched()) {
@@ -3064,6 +3059,11 @@
}
}
+ // Clear the renderengine fence here...
+ // downstream code assumes that a cleared fence == NO_FENCE, so reassign to
+ // clear instead of sp::clear.
+ getBE().flushFence = Fence::NO_FENCE;
+
mVisibleRegionsDirty |= visibleRegions;
// If we will need to wake up at some time in the future to deal with a
@@ -3116,6 +3116,7 @@
const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId);
ATRACE_INT("hasClientComposition", hasClientComposition);
+ mat4 colorMatrix;
bool applyColorMatrix = false;
bool needsEnhancedColorMatrix = false;
@@ -3134,7 +3135,7 @@
const bool skipClientColorTransform = getBE().mHwc->hasCapability(
HWC2::Capability::SkipClientColorTransform);
- mat4 colorMatrix;
+ // Compute the global color transform matrix.
applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
if (applyColorMatrix) {
colorMatrix = mDrawingState.colorMatrix;
@@ -3150,8 +3151,6 @@
colorMatrix *= mEnhancedSaturationMatrix;
}
- getRenderEngine().setupColorTransform(colorMatrix);
-
if (!display->makeCurrent()) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
display->getDisplayName().c_str());
@@ -3230,6 +3229,19 @@
break;
}
case HWC2::Composition::Client: {
+ if (layer->hasColorTransform()) {
+ mat4 tmpMatrix;
+ if (applyColorMatrix) {
+ tmpMatrix = mDrawingState.colorMatrix;
+ }
+ tmpMatrix *= layer->getColorTransform();
+ if (needsEnhancedColorMatrix) {
+ tmpMatrix *= mEnhancedSaturationMatrix;
+ }
+ getRenderEngine().setColorTransform(tmpMatrix);
+ } else {
+ getRenderEngine().setColorTransform(colorMatrix);
+ }
layer->draw(renderArea, clip);
break;
}
@@ -3242,9 +3254,8 @@
firstLayer = false;
}
- if (applyColorMatrix || needsEnhancedColorMatrix) {
- getRenderEngine().setupColorTransform(mat4());
- }
+ // Clear color transform matrix at the end of the frame.
+ getRenderEngine().setColorTransform(mat4());
// disable scissor at the end of the frame
getBE().mRenderEngine->disableScissor();
@@ -3273,7 +3284,7 @@
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
- if (parent->isPendingRemoval()) {
+ if (parent->isRemoved()) {
ALOGE("addClientLayer called with a removed parent");
return NAME_NOT_FOUND;
}
@@ -3305,7 +3316,7 @@
status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp<Layer>& layer,
bool topLevelOnly) {
- if (layer->isPendingRemoval()) {
+ if (layer->isRemoved()) {
return NO_ERROR;
}
@@ -3315,39 +3326,14 @@
if (topLevelOnly) {
return NO_ERROR;
}
-
- sp<Layer> ancestor = p;
- while (ancestor->getParent() != nullptr) {
- ancestor = ancestor->getParent();
- }
- if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
- ALOGE("removeLayer called with a layer whose parent has been removed");
- return NAME_NOT_FOUND;
- }
-
index = p->removeChild(layer);
} else {
index = mCurrentState.layersSortedByZ.remove(layer);
}
- // As a matter of normal operation, the LayerCleaner will produce a second
- // attempt to remove the surface. The Layer will be kept alive in mDrawingState
- // so we will succeed in promoting it, but it's already been removed
- // from mCurrentState. As long as we can find it in mDrawingState we have no problem
- // otherwise something has gone wrong and we are leaking the layer.
- if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
- ALOGE("Failed to find layer (%s) in layer parent (%s).",
- layer->getName().string(),
- (p != nullptr) ? p->getName().string() : "no-parent");
- return BAD_VALUE;
- } else if (index < 0) {
- return NO_ERROR;
- }
-
layer->onRemovedFromCurrentState();
mLayersPendingRemoval.add(layer);
mLayersRemoved = true;
- mNumLayers -= 1 + layer->getChildrenCount();
setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}
@@ -3550,7 +3536,7 @@
return 0;
}
- if (layer->isPendingRemoval()) {
+ if (layer->isRemoved()) {
ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
return 0;
}
@@ -3621,6 +3607,11 @@
if (layer->setColor(s.color))
flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eColorTransformChanged) {
+ if (layer->setColorTransform(s.colorTransform)) {
+ flags |= eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eMatrixChanged) {
// TODO: b/109894387
//
@@ -3753,7 +3744,7 @@
return;
}
- if (layer->isPendingRemoval()) {
+ if (layer->isRemoved()) {
ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string());
return;
}
@@ -3873,7 +3864,8 @@
break;
}
- sp<BufferQueueLayer> layer = new BufferQueueLayer(this, client, name, w, h, flags);
+ sp<BufferQueueLayer> layer =
+ new BufferQueueLayer(LayerCreationArgs(this, client, name, w, h, flags));
status_t err = layer->setDefaultBufferProperties(w, h, format);
if (err == NO_ERROR) {
*handle = layer->getHandle();
@@ -3888,7 +3880,8 @@
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);
+ sp<BufferStateLayer> layer =
+ new BufferStateLayer(LayerCreationArgs(this, client, name, w, h, flags));
*handle = layer->getHandle();
*outLayer = layer;
@@ -3899,7 +3892,7 @@
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
sp<IBinder>* handle, sp<Layer>* outLayer)
{
- *outLayer = new ColorLayer(this, client, name, w, h, flags);
+ *outLayer = new ColorLayer(LayerCreationArgs(this, client, name, w, h, flags));
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
@@ -3908,7 +3901,7 @@
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
sp<IBinder>* handle, sp<Layer>* outLayer)
{
- *outLayer = new ContainerLayer(this, client, name, w, h, flags);
+ *outLayer = new ContainerLayer(LayerCreationArgs(this, client, name, w, h, flags));
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
@@ -3928,19 +3921,6 @@
return err;
}
-status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
-{
- // called by ~LayerCleaner() when all references to the IBinder (handle)
- // are gone
- sp<Layer> l = layer.promote();
- if (l == nullptr) {
- // The layer has already been removed, carry on
- return NO_ERROR;
- }
- // If we have a parent, then we can continue to live as long as it does.
- return removeLayer(l, true);
-}
-
// ---------------------------------------------------------------------------
void SurfaceFlinger::onInitializeDisplays() {
@@ -5288,9 +5268,9 @@
drawLayers();
} else {
Rect bounds = getBounds();
- screenshotParentLayer =
- new ContainerLayer(mFlinger, nullptr, String8("Screenshot Parent"),
- bounds.getWidth(), bounds.getHeight(), 0);
+ screenshotParentLayer = new ContainerLayer(
+ LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"),
+ bounds.getWidth(), bounds.getHeight(), 0));
ReparentForDrawing reparent(mLayer, screenshotParentLayer);
drawLayers();
@@ -5314,7 +5294,7 @@
auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
auto parent = layerHandle->owner.promote();
- if (parent == nullptr || parent->isPendingRemoval()) {
+ if (parent == nullptr || parent->isRemoved()) {
ALOGE("captureLayers called with a removed parent");
return NAME_NOT_FOUND;
}
@@ -5464,7 +5444,9 @@
engine.clearWithColor(0, 0, 0, alpha);
traverseLayers([&](Layer* layer) {
+ engine.setColorTransform(layer->getColorTransform());
layer->draw(renderArea, useIdentityTransform);
+ engine.setColorTransform(mat4());
});
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e2be544..9f6eb21 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -117,6 +117,10 @@
class VrFlinger;
} // namespace dvr
+namespace surfaceflinger {
+class NativeWindowSurface;
+} // namespace surfaceflinger
+
// ---------------------------------------------------------------------------
enum {
@@ -133,18 +137,6 @@
ENHANCED = 2,
};
-// A thin interface to abstract creating instances of Surface (gui/Surface.h) to
-// use as a NativeWindow.
-class NativeWindowSurface {
-public:
- virtual ~NativeWindowSurface();
-
- // Gets the NativeWindow to use for the surface.
- virtual sp<ANativeWindow> getNativeWindow() const = 0;
-
- // Indicates that the surface should allocate its buffers now.
- virtual void preallocateBuffers() = 0;
-};
class SurfaceFlingerBE
{
@@ -199,6 +191,9 @@
nsecs_t mTotalTime;
std::atomic<nsecs_t> mLastSwapTime;
+ // Synchronization fence from a GL composition.
+ sp<Fence> flushFence = Fence::NO_FENCE;
+
// Double- vs. triple-buffering stats
struct BufferingStats {
BufferingStats()
@@ -462,7 +457,6 @@
status_t getCompositionPreference(ui::Dataspace* outDataSpace,
ui::PixelFormat* outPixelFormat) const override;
-
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
@@ -567,11 +561,6 @@
// ISurfaceComposerClient::destroySurface()
status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
- // called when all clients have released all their references to
- // this layer meaning it is entirely safe to destroy all
- // resources associated to this layer.
- status_t onLayerDestroyed(const wp<Layer>& layer);
-
// remove a layer from SurfaceFlinger immediately
status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
@@ -938,7 +927,8 @@
CreateBufferQueueFunction mCreateBufferQueue;
using CreateNativeWindowSurfaceFunction =
- std::function<std::unique_ptr<NativeWindowSurface>(const sp<IGraphicBufferProducer>&)>;
+ std::function<std::unique_ptr<surfaceflinger::NativeWindowSurface>(
+ const sp<IGraphicBufferProducer>&)>;
CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
SurfaceFlingerBE mBE;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index d77a324..0bc1c0a 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -32,11 +32,8 @@
namespace android {
TimeStats& TimeStats::getInstance() {
- static std::unique_ptr<TimeStats> sInstance;
- static std::once_flag sOnceFlag;
-
- std::call_once(sOnceFlag, [] { sInstance.reset(new TimeStats); });
- return *sInstance.get();
+ static TimeStats sInstance;
+ return sInstance;
}
void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, size_t& index,
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 3af98e5..0bf54d5 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2064,6 +2064,34 @@
Transaction().setSidebandStream(layer, nullptr).apply();
}
+TEST_F(LayerTransactionTest, SetColorTransformBasic) {
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(
+ colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+ Transaction().setLayer(colorLayer, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("default color");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
+ const Color expected = {90, 90, 90, 255};
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+ mat3 matrix;
+ matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11;
+ matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11;
+ matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11;
+ Transaction().setColor(colorLayer, color)
+ .setColorTransform(colorLayer, matrix, vec3()).apply();
+ {
+ SCOPED_TRACE("new color");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), expected, tolerance);
+ }
+}
+
class LayerUpdateTest : public LayerTransactionTest {
protected:
virtual void SetUp() {
@@ -2554,6 +2582,37 @@
}
}
+TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
+ sp<SurfaceControl> mGrandChild =
+ mClient->createSurface(String8("Grand Child"), 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+ fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
+
+ {
+ SCOPED_TRACE("Grandchild visible");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 111, 111, 111);
+ }
+
+ mChild->clear();
+
+ {
+ SCOPED_TRACE("After destroying child");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->expectFGColor(64, 64);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.reparent(mGrandChild, mFGSurfaceControl->getHandle());
+ });
+
+ {
+ SCOPED_TRACE("After reparenting grandchild");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 111, 111, 111);
+ }
+}
+
TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
sp<SurfaceControl> mChildNewClient =
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index d52f0d8..7b79fbd 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -325,7 +325,7 @@
EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(ui::Dataspace::UNKNOWN)).Times(1);
EXPECT_CALL(*test->mRenderEngine, setDisplayMaxLuminance(DEFAULT_DISPLAY_MAX_LUMINANCE))
.Times(1);
- EXPECT_CALL(*test->mRenderEngine, setupColorTransform(_)).Times(2);
+ EXPECT_CALL(*test->mRenderEngine, setColorTransform(_)).Times(2);
// These expectations retire on saturation as the code path these
// expectations are for appears to make an extra call to them.
// TODO: Investigate this extra call
@@ -478,11 +478,8 @@
EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
EXPECT_CALL(*test->mRenderEngine, createImage())
.WillOnce(Return(ByMove(std::unique_ptr<renderengine::Image>(test->mReImage))));
- EXPECT_CALL(*test->mRenderEngine, bindExternalTextureImage(DEFAULT_TEXTURE_ID, _)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, checkErrors()).Times(1);
- EXPECT_CALL(*test->mReImage, setNativeWindowBuffer(_, false)).WillOnce(Return(true));
bool ignoredRecomputeVisibleRegions;
- layer->latchBuffer(ignoredRecomputeVisibleRegions, 0);
+ layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, Fence::NO_FENCE);
Mock::VerifyAndClear(test->mRenderEngine);
Mock::VerifyAndClear(test->mReImage);
}
@@ -774,9 +771,10 @@
static FlingerLayerType createLayer(CompositionTest* test) {
FlingerLayerType layer = Base::template createLayerWithFactory<ColorLayer>(test, [test]() {
- return new ColorLayer(test->mFlinger.mFlinger.get(), sp<Client>(),
- String8("test-layer"), LayerProperties::WIDTH,
- LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS);
+ return new ColorLayer(LayerCreationArgs(test->mFlinger.mFlinger.get(), sp<Client>(),
+ String8("test-layer"), LayerProperties::WIDTH,
+ LayerProperties::HEIGHT,
+ LayerProperties::LAYER_FLAGS));
});
return layer;
}
@@ -811,10 +809,11 @@
FlingerLayerType layer =
Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
- return new BufferQueueLayer(test->mFlinger.mFlinger.get(), sp<Client>(),
- String8("test-layer"), LayerProperties::WIDTH,
- LayerProperties::HEIGHT,
- LayerProperties::LAYER_FLAGS);
+ return new BufferQueueLayer(
+ LayerCreationArgs(test->mFlinger.mFlinger.get(), sp<Client>(),
+ String8("test-layer"), LayerProperties::WIDTH,
+ LayerProperties::HEIGHT,
+ LayerProperties::LAYER_FLAGS));
});
LayerProperties::setupLayerState(test, layer);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index cc46043..b474e42 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -125,7 +125,7 @@
// These mocks are created only when expected to be created via a factory.
sp<mock::GraphicBufferConsumer> mConsumer;
sp<mock::GraphicBufferProducer> mProducer;
- mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
+ surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
sp<mock::NativeWindow> mNativeWindow;
renderengine::mock::Surface* mRenderSurface = nullptr;
};
@@ -195,11 +195,12 @@
// This setup is only expected once per test.
ASSERT_TRUE(mNativeWindowSurface == nullptr);
- mNativeWindowSurface = new mock::NativeWindowSurface();
+ mNativeWindowSurface = new surfaceflinger::mock::NativeWindowSurface();
mNativeWindow = new mock::NativeWindow();
- mFlinger.setCreateNativeWindowSurface(
- [this](auto) { return std::unique_ptr<NativeWindowSurface>(mNativeWindowSurface); });
+ mFlinger.setCreateNativeWindowSurface([this](auto) {
+ return std::unique_ptr<surfaceflinger::NativeWindowSurface>(mNativeWindowSurface);
+ });
}
bool DisplayTransactionTest::hasHwcDisplay(hwc2_display_t displayId) {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index f367275..2046439 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -192,7 +192,7 @@
public:
FakePowerAdvisor() = default;
~FakePowerAdvisor() override = default;
- void setExpensiveRenderingExpected(hwc2_display_t, bool) override { }
+ void setExpensiveRenderingExpected(hwc2_display_t, bool) override {}
};
struct HWC2Display : public HWC2::Display {
@@ -315,7 +315,8 @@
public:
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, DisplayDevice::DisplayType type,
int32_t displayId)
- : mFlinger(flinger), mType(type), mDisplayId(displayId) {}
+ : mFlinger(flinger),
+ mCreationArgs(flinger.mFlinger.get(), mDisplayToken, type, displayId) {}
sp<IBinder> token() const { return mDisplayToken; }
@@ -338,54 +339,49 @@
auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
- mNativeWindow = nativeWindow;
+ mCreationArgs.nativeWindow = nativeWindow;
return *this;
}
auto& setDisplaySurface(const sp<DisplaySurface>& displaySurface) {
- mDisplaySurface = displaySurface;
+ mCreationArgs.displaySurface = displaySurface;
return *this;
}
auto& setRenderSurface(std::unique_ptr<renderengine::Surface> renderSurface) {
- mRenderSurface = std::move(renderSurface);
+ mCreationArgs.renderSurface = std::move(renderSurface);
return *this;
}
auto& setSecure(bool secure) {
- mSecure = secure;
+ mCreationArgs.isSecure = secure;
return *this;
}
auto& setDisplaySize(int width, int height) {
- mWidth = width;
- mHeight = height;
+ mCreationArgs.displayWidth = width;
+ mCreationArgs.displayHeight = height;
return *this;
}
auto& setPowerMode(int mode) {
- mPowerMode = mode;
+ mCreationArgs.initialPowerMode = mode;
return *this;
}
sp<DisplayDevice> inject() {
- std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hdrAndRenderIntents;
- sp<DisplayDevice> device =
- new DisplayDevice(mFlinger.mFlinger.get(), mType, mDisplayId, mSecure,
- mDisplayToken, mNativeWindow, mDisplaySurface,
- std::move(mRenderSurface), mWidth, mHeight,
- DisplayState::eOrientationDefault, false, HdrCapabilities(),
- 0, hdrAndRenderIntents, mPowerMode);
- mFlinger.mutableDisplays().emplace(mDisplayToken, device);
-
DisplayDeviceState state;
- state.type = mType;
- state.isSecure = mSecure;
+ state.type = mCreationArgs.type;
+ state.isSecure = mCreationArgs.isSecure;
+
+ sp<DisplayDevice> device = new DisplayDevice(std::move(mCreationArgs));
+ mFlinger.mutableDisplays().emplace(mDisplayToken, device);
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
- if (mType >= DisplayDevice::DISPLAY_PRIMARY && mType < DisplayDevice::DISPLAY_VIRTUAL) {
- mFlinger.mutableDisplayTokens()[mType] = mDisplayToken;
+ if (state.type >= DisplayDevice::DISPLAY_PRIMARY &&
+ state.type < DisplayDevice::DISPLAY_VIRTUAL) {
+ mFlinger.mutableDisplayTokens()[state.type] = mDisplayToken;
}
return device;
@@ -394,15 +390,7 @@
private:
TestableSurfaceFlinger& mFlinger;
sp<BBinder> mDisplayToken = new BBinder();
- DisplayDevice::DisplayType mType;
- const int32_t mDisplayId;
- sp<ANativeWindow> mNativeWindow;
- sp<DisplaySurface> mDisplaySurface;
- std::unique_ptr<renderengine::Surface> mRenderSurface;
- bool mSecure = false;
- int mWidth = 0;
- int mHeight = 0;
- int mPowerMode = HWC_POWER_MODE_NORMAL;
+ DisplayDeviceCreationArgs mCreationArgs;
};
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(SurfaceFlinger::SkipInitialization);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.cpp b/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.cpp
index 25ff39b..9cc6d38 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
- *
+ * Copyright 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
@@ -16,12 +16,10 @@
#include "mock/MockNativeWindowSurface.h"
-namespace android {
-namespace mock {
+namespace android::surfaceflinger::mock {
// Explicit default instantiation is recommended.
NativeWindowSurface::NativeWindowSurface() = default;
NativeWindowSurface::~NativeWindowSurface() = default;
-} // namespace mock
-} // namespace android
+} // namespace android::surfaceflinger::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.h b/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.h
index 88d1a9f..7bc1151 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockNativeWindowSurface.h
@@ -20,19 +20,17 @@
#include <system/window.h> // for ANativeWindow
-#include "SurfaceFlinger.h" // for base NativeWindowSurface
+#include "NativeWindowSurface.h"
-namespace android {
-namespace mock {
+namespace android::surfaceflinger::mock {
-class NativeWindowSurface : public android::NativeWindowSurface {
+class NativeWindowSurface : public surfaceflinger::NativeWindowSurface {
public:
NativeWindowSurface();
- ~NativeWindowSurface();
+ ~NativeWindowSurface() override;
MOCK_CONST_METHOD0(getNativeWindow, sp<ANativeWindow>());
MOCK_METHOD0(preallocateBuffers, void());
};
-} // namespace mock
-} // namespace android
+} // namespace android::surfaceflinger::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index c29452c..6813cda 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -62,7 +62,7 @@
MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
MOCK_METHOD0(setupLayerBlackedOut, void());
MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
- MOCK_METHOD1(setupColorTransform, void(const mat4&));
+ MOCK_METHOD1(setColorTransform, void(const mat4&));
MOCK_METHOD1(setSaturationMatrix, void(const mat4&));
MOCK_METHOD0(disableTexturing, void());
MOCK_METHOD0(disableBlending, void());
diff --git a/services/vr/bufferhubd/buffer_hub_binder.cpp b/services/vr/bufferhubd/buffer_hub_binder.cpp
index def15f1..4ff9890 100644
--- a/services/vr/bufferhubd/buffer_hub_binder.cpp
+++ b/services/vr/bufferhubd/buffer_hub_binder.cpp
@@ -1,28 +1,58 @@
#include <stdio.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
#include <log/log.h>
#include <private/dvr/buffer_hub_binder.h>
namespace android {
namespace dvr {
-status_t BufferHubBinderService::start() {
- ProcessState::self()->startThreadPool();
+status_t BufferHubBinderService::start(
+ const std::shared_ptr<BufferHubService> &pdx_service) {
IPCThreadState::self()->disableBackgroundScheduling(true);
- status_t result = BinderService<BufferHubBinderService>::publish();
- if (result != OK) {
+
+ BufferHubBinderService* service = new BufferHubBinderService();
+ service->pdx_service_ = pdx_service;
+
+ // Not using BinderService::publish because need to get an instance of this
+ // class (above). Following code is the same as
+ // BinderService::publishAndJoinThreadPool
+ sp<IServiceManager> sm = defaultServiceManager();
+ status_t result = sm->addService(String16(getServiceName()), service,
+ /*allowIsolated =*/ false,
+ /*dump flags =*/ IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+ if (result != NO_ERROR) {
ALOGE("Publishing bufferhubd failed with error %d", result);
return result;
}
+ sp<ProcessState> process_self(ProcessState::self());
+ process_self->startThreadPool();
+ process_self->giveThreadPoolName();
+ IPCThreadState::self()->joinThreadPool();
+
return result;
}
-status_t BufferHubBinderService::dump(int fd, const Vector<String16> & /* args */) {
- // TODO(b/115435506): not implemented yet
+status_t BufferHubBinderService::dump(int fd, const Vector<String16> &args) {
FILE *out = fdopen(dup(fd), "w");
- fprintf(out, "BufferHubBinderService::dump(): Not Implemented.\n");
+ // Currently not supporting args, so notify the user.
+ if (!args.isEmpty()){
+ fprintf(out, "Note: dumpsys bufferhubd currently does not support args."
+ "Input arguments are ignored.\n");
+ }
+
+ // TODO(b/116526156): output real data in this class once we have it
+ if (pdx_service_){
+ // BufferHubService::Dumpstate(size_t) is not actually using the param
+ // So just using 0 as the length
+ fprintf(out, "%s", pdx_service_->DumpState(0).c_str());
+ } else {
+ fprintf(out, "PDX service not registered or died.\n");
+ }
fclose(out);
return NO_ERROR;
@@ -30,4 +60,4 @@
} // namespace dvr
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index 0ca7edc..3e10b26 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -10,7 +10,7 @@
int main(int, char**) {
int ret = -1;
- std::shared_ptr<android::pdx::Service> service;
+ std::shared_ptr<android::dvr::BufferHubService> pdx_service;
std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher;
// We need to be able to create endpoints with full perms.
@@ -33,15 +33,16 @@
else
ALOGI("New nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
- CHECK_ERROR(android::dvr::BufferHubBinderService::start() != android::OK,
- error, "Failed to create bufferhub binder service\n");
-
dispatcher = android::pdx::ServiceDispatcher::Create();
CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n");
- service = android::dvr::BufferHubService::Create();
- CHECK_ERROR(!service, error, "Failed to create bufferhubd service\n");
- dispatcher->AddService(service);
+ pdx_service = android::dvr::BufferHubService::Create();
+ CHECK_ERROR(!pdx_service, error, "Failed to create bufferhub pdx service\n");
+ dispatcher->AddService(pdx_service);
+
+ ret = android::dvr::BufferHubBinderService::start(pdx_service);
+ CHECK_ERROR(ret != android::NO_ERROR, error,
+ "Failed to create bufferhub binder service\n");
ret = dvrSetSchedulerClass(0, "graphics");
CHECK_ERROR(ret < 0, error, "Failed to set thread priority");
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
index c0281fd..07f05cc 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
@@ -2,6 +2,7 @@
#define ANDROID_DVR_BUFFER_HUB_BINDER_H
#include <binder/BinderService.h>
+#include <private/dvr/buffer_hub.h>
#include "android/dvr/BnBufferHub.h"
@@ -10,14 +11,17 @@
class BufferHubBinderService : public BinderService<BufferHubBinderService>, public BnBufferHub {
public:
- static status_t start();
+ static status_t start(const std::shared_ptr<BufferHubService> &pdx_service);
static const char* getServiceName() { return "bufferhubd"; }
// Dump bufferhub related information to given fd (usually stdout)
// usage: adb shell dumpsys bufferhubd
virtual status_t dump(int fd, const Vector<String16> &args) override;
+
+ private:
+ std::shared_ptr<BufferHubService> pdx_service_;
};
} // namespace dvr
} // namespace android
-#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
\ No newline at end of file
+#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
index 4d1d43f..92bda78 100644
--- a/services/vr/bufferhubd/tests/Android.bp
+++ b/services/vr/bufferhubd/tests/Android.bp
@@ -6,11 +6,18 @@
"-DTRACE=0",
"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
- static_libs: ["libbufferhubd"],
+ header_libs: ["libdvr_headers"],
+ static_libs: [
+ "libbufferhub",
+ "libbufferhubd",
+ "libgmock",
+ ],
shared_libs: [
"libbase",
"libbinder",
"liblog",
+ "libpdx_default_transport",
+ "libui",
"libutils",
],
}
\ No newline at end of file
diff --git a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
index e3f2825..0b64cf0 100644
--- a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
+++ b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
@@ -1,6 +1,7 @@
-#include <private/dvr/buffer_hub_binder.h>
-
+#include <binder/IServiceManager.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <private/dvr/buffer_hub_binder.h>
namespace android {
namespace dvr {
@@ -12,8 +13,12 @@
};
TEST_F(BufferHubBinderServiceTest, TestInitialize) {
- // Test if start binder server returns OK
- EXPECT_EQ(BufferHubBinderService::start(), OK);
+ // Create a new service will kill the current one.
+ // So just check if Binder service is running
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> service = sm->checkService(
+ String16(BufferHubBinderService::getServiceName()));
+ EXPECT_THAT(service, ::testing::Ne(nullptr));
}
} // namespace
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index fa63fbd..5722810 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
// API version (major.minor.patch)
define VERSION_MAJOR 1
define VERSION_MINOR 1
-define VERSION_PATCH 85
+define VERSION_PATCH 86
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -45,6 +45,10 @@
define VK_QUEUE_FAMILY_EXTERNAL -2
@extension("VK_EXT_queue_family_foreign")
define VK_QUEUE_FAMILY_FOREIGN_EXT -3
+@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
+define VK_MAX_DRIVER_NAME_SIZE_KHR 256
+@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
+define VK_MAX_DRIVER_INFO_SIZE_KHR 256
// API keywords
define VK_TRUE 1
@@ -545,6 +549,10 @@
@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
+// 181
+@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
+@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
+
// 186
@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
@@ -553,6 +561,10 @@
@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
+// 197
+@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
+@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
+
// 199
@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
@@ -1763,6 +1775,12 @@
VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002,
+ //@extension("VK_KHR_shader_atomic_int64") // 181
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000,
+
+ //@extension("VK_KHR_driver_properties") // 197
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
+
//@extension("VK_AMD_shader_core_properties") // 186
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
@@ -2264,6 +2282,19 @@
VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024,
}
+@extension("VK_KHR_driver_properties") // 197
+enum VkDriverIdKHR {
+ VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1,
+ VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = 2,
+ VK_DRIVER_ID_MESA_RADV_KHR = 3,
+ VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = 4,
+ VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = 5,
+ VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = 6,
+ VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
+ VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
+ VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+}
+
/////////////////
// Bitfields //
/////////////////
@@ -7214,6 +7245,14 @@
VkDeviceSize minImportedHostPointerAlignment
}
+@extension("VK_KHR_shader_atomic_int64") // 181
+class VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 shaderBufferInt64Atomics
+ VkBool32 shaderSharedInt64Atomics
+}
+
@extension("VK_AMD_shader_core_properties") // 186
class VkPhysicalDeviceShaderCorePropertiesAMD {
VkStructureType sType
@@ -7263,6 +7302,24 @@
VkBool32 vertexAttributeInstanceRateZeroDivisor
}
+@extension("VK_KHR_driver_properties") // 197
+class VkConformanceVersionKHR {
+ u8 major
+ u8 minor
+ u8 subminor
+ u8 patch
+}
+
+@extension("VK_KHR_driver_properties") // 197
+class VkPhysicalDeviceDriverPropertiesKHR {
+ VkStructureType sType
+ void* pNext
+ u32 driverID
+ char[VK_MAX_DRIVER_NAME_SIZE_KHR] driverName
+ char[VK_MAX_DRIVER_INFO_SIZE_KHR] driverInfo
+ VkConformanceVersionKHR conformanceVersion
+}
+
@extension("VK_NV_compute_shader_derivatives") // 202
class VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
VkStructureType sType
@@ -11168,42 +11225,42 @@
@extension("VK_NVX_raytracing") // 166
cmd void vkCmdBuildAccelerationStructureNVX(
- VkCommandBuffer cmdBuf,
- VkAccelerationStructureTypeNVX type,
- u32 instanceCount,
- VkBuffer instanceData,
- VkDeviceSize instanceOffset,
- u32 geometryCount,
- const VkGeometryNVX* pGeometries,
- VkBuildAccelerationStructureFlagsNVX flags,
- VkBool32 update,
- VkAccelerationStructureNVX dst,
- VkAccelerationStructureNVX src,
- VkBuffer scratch,
- VkDeviceSize scratchOffset) {
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureTypeNVX type,
+ u32 instanceCount,
+ VkBuffer instanceData,
+ VkDeviceSize instanceOffset,
+ u32 geometryCount,
+ const VkGeometryNVX* pGeometries,
+ VkBuildAccelerationStructureFlagsNVX flags,
+ VkBool32 update,
+ VkAccelerationStructureNVX dst,
+ VkAccelerationStructureNVX src,
+ VkBuffer scratch,
+ VkDeviceSize scratchOffset) {
}
@extension("VK_NVX_raytracing") // 166
cmd void vkCmdCopyAccelerationStructureNVX(
- VkCommandBuffer cmdBuf,
- VkAccelerationStructureNVX dst,
- VkAccelerationStructureNVX src,
- VkCopyAccelerationStructureModeNVX mode) {
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNVX dst,
+ VkAccelerationStructureNVX src,
+ VkCopyAccelerationStructureModeNVX mode) {
}
@extension("VK_NVX_raytracing") // 166
cmd void vkCmdTraceRaysNVX(
- VkCommandBuffer cmdBuf,
- VkBuffer raygenShaderBindingTableBuffer,
- VkDeviceSize raygenShaderBindingOffset,
- VkBuffer missShaderBindingTableBuffer,
- VkDeviceSize missShaderBindingOffset,
- VkDeviceSize missShaderBindingStride,
- VkBuffer hitShaderBindingTableBuffer,
- VkDeviceSize hitShaderBindingOffset,
- VkDeviceSize hitShaderBindingStride,
- u32 width,
- u32 height) {
+ VkCommandBuffer commandBuffer,
+ VkBuffer raygenShaderBindingTableBuffer,
+ VkDeviceSize raygenShaderBindingOffset,
+ VkBuffer missShaderBindingTableBuffer,
+ VkDeviceSize missShaderBindingOffset,
+ VkDeviceSize missShaderBindingStride,
+ VkBuffer hitShaderBindingTableBuffer,
+ VkDeviceSize hitShaderBindingOffset,
+ VkDeviceSize hitShaderBindingStride,
+ u32 width,
+ u32 height) {
}
@extension("VK_NVX_raytracing") // 166
@@ -11219,38 +11276,38 @@
@extension("VK_NVX_raytracing") // 166
cmd VkResult vkGetRaytracingShaderHandlesNVX(
- VkDevice device,
- VkPipeline pipeline,
- u32 firstGroup,
- u32 groupCount,
- platform.size_t dataSize,
- void* pData) {
+ VkDevice device,
+ VkPipeline pipeline,
+ u32 firstGroup,
+ u32 groupCount,
+ platform.size_t dataSize,
+ void* pData) {
return ?
}
@extension("VK_NVX_raytracing") // 166
cmd VkResult vkGetAccelerationStructureHandleNVX(
- VkDevice device,
- VkAccelerationStructureNVX accelerationStructure,
- platform.size_t dataSize,
- void* pData) {
+ VkDevice device,
+ VkAccelerationStructureNVX accelerationStructure,
+ platform.size_t dataSize,
+ void* pData) {
return ?
}
@extension("VK_NVX_raytracing") // 166
cmd void vkCmdWriteAccelerationStructurePropertiesNVX(
- VkCommandBuffer cmdBuf,
- VkAccelerationStructureNVX accelerationStructure,
- VkQueryType queryType,
- VkQueryPool queryPool,
- u32 query) {
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNVX accelerationStructure,
+ VkQueryType queryType,
+ VkQueryPool queryPool,
+ u32 query) {
}
@extension("VK_NVX_raytracing") // 166
cmd VkResult vkCompileDeferredNVX(
- VkDevice device,
- VkPipeline pipeline,
- u32 shader) {
+ VkDevice device,
+ VkPipeline pipeline,
+ u32 shader) {
return ?
}
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index 2d1b3f5..39f4dc6 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,7 +43,7 @@
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 85
+#define VK_HEADER_VERSION 86
#define VK_NULL_HANDLE 0
@@ -427,10 +427,12 @@
VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000,
VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001,
@@ -6044,6 +6046,60 @@
+#define VK_KHR_shader_atomic_int64 1
+#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
+#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
+
+typedef struct VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderBufferInt64Atomics;
+ VkBool32 shaderSharedInt64Atomics;
+} VkPhysicalDeviceShaderAtomicInt64FeaturesKHR;
+
+
+
+#define VK_KHR_driver_properties 1
+#define VK_MAX_DRIVER_NAME_SIZE_KHR 256
+#define VK_MAX_DRIVER_INFO_SIZE_KHR 256
+#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
+#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
+
+
+typedef enum VkDriverIdKHR {
+ VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1,
+ VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = 2,
+ VK_DRIVER_ID_MESA_RADV_KHR = 3,
+ VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = 4,
+ VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = 5,
+ VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = 6,
+ VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
+ VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
+ VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+ VK_DRIVER_ID_BEGIN_RANGE_KHR = VK_DRIVER_ID_AMD_PROPRIETARY_KHR,
+ VK_DRIVER_ID_END_RANGE_KHR = VK_DRIVER_ID_ARM_PROPRIETARY_KHR,
+ VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_ARM_PROPRIETARY_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1),
+ VK_DRIVER_ID_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDriverIdKHR;
+
+typedef struct VkConformanceVersionKHR {
+ uint8_t major;
+ uint8_t minor;
+ uint8_t subminor;
+ uint8_t patch;
+} VkConformanceVersionKHR;
+
+typedef struct VkPhysicalDeviceDriverPropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t driverID;
+ char driverName[VK_MAX_DRIVER_NAME_SIZE_KHR];
+ char driverInfo[VK_MAX_DRIVER_INFO_SIZE_KHR];
+ VkConformanceVersionKHR conformanceVersion;
+} VkPhysicalDeviceDriverPropertiesKHR;
+
+
+
#define VK_KHR_vulkan_memory_model 1
#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
@@ -8044,13 +8100,13 @@
typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureScratchMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNVX)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos);
-typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNVX)(VkCommandBuffer cmdBuf, VkAccelerationStructureTypeNVX type, uint32_t instanceCount, VkBuffer instanceData, VkDeviceSize instanceOffset, uint32_t geometryCount, const VkGeometryNVX* pGeometries, VkBuildAccelerationStructureFlagsNVX flags, VkBool32 update, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkBuffer scratch, VkDeviceSize scratchOffset);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNVX)(VkCommandBuffer cmdBuf, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkCopyAccelerationStructureModeNVX mode);
-typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNVX)(VkCommandBuffer cmdBuf, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, uint32_t width, uint32_t height);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureTypeNVX type, uint32_t instanceCount, VkBuffer instanceData, VkDeviceSize instanceOffset, uint32_t geometryCount, const VkGeometryNVX* pGeometries, VkBuildAccelerationStructureFlagsNVX flags, VkBool32 update, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkBuffer scratch, VkDeviceSize scratchOffset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkCopyAccelerationStructureModeNVX mode);
+typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNVX)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, uint32_t width, uint32_t height);
typedef VkResult (VKAPI_PTR *PFN_vkCreateRaytracingPipelinesNVX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRaytracingPipelineCreateInfoNVX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
typedef VkResult (VKAPI_PTR *PFN_vkGetRaytracingShaderHandlesNVX)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNVX)(VkDevice device, VkAccelerationStructureNVX accelerationStructure, size_t dataSize, void* pData);
-typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructurePropertiesNVX)(VkCommandBuffer cmdBuf, VkAccelerationStructureNVX accelerationStructure, VkQueryType queryType, VkQueryPool queryPool, uint32_t query);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructurePropertiesNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX accelerationStructure, VkQueryType queryType, VkQueryPool queryPool, uint32_t query);
typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNVX)(VkDevice device, VkPipeline pipeline, uint32_t shader);
#ifndef VK_NO_PROTOTYPES
@@ -8081,7 +8137,7 @@
const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos);
VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNVX(
- VkCommandBuffer cmdBuf,
+ VkCommandBuffer commandBuffer,
VkAccelerationStructureTypeNVX type,
uint32_t instanceCount,
VkBuffer instanceData,
@@ -8096,13 +8152,13 @@
VkDeviceSize scratchOffset);
VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNVX(
- VkCommandBuffer cmdBuf,
+ VkCommandBuffer commandBuffer,
VkAccelerationStructureNVX dst,
VkAccelerationStructureNVX src,
VkCopyAccelerationStructureModeNVX mode);
VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNVX(
- VkCommandBuffer cmdBuf,
+ VkCommandBuffer commandBuffer,
VkBuffer raygenShaderBindingTableBuffer,
VkDeviceSize raygenShaderBindingOffset,
VkBuffer missShaderBindingTableBuffer,
@@ -8137,7 +8193,7 @@
void* pData);
VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructurePropertiesNVX(
- VkCommandBuffer cmdBuf,
+ VkCommandBuffer commandBuffer,
VkAccelerationStructureNVX accelerationStructure,
VkQueryType queryType,
VkQueryPool queryPool,
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index b32977a..009b257 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -78,7 +78,7 @@
native_bridge_(false),
refcount_(0) {}
- LayerLibrary(LayerLibrary&& other)
+ LayerLibrary(LayerLibrary&& other) noexcept
: path_(std::move(other.path_)),
filename_(std::move(other.filename_)),
dlhandle_(other.dlhandle_),
@@ -545,7 +545,7 @@
}
}
-LayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
+LayerRef::LayerRef(LayerRef&& other) noexcept : layer_(other.layer_) {
other.layer_ = nullptr;
}
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
index 07ac1a3..1dae456 100644
--- a/vulkan/libvulkan/layers_extensions.h
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -27,7 +27,7 @@
class LayerRef {
public:
explicit LayerRef(const Layer* layer);
- LayerRef(LayerRef&& other);
+ LayerRef(LayerRef&& other) noexcept;
~LayerRef();
LayerRef(const LayerRef&) = delete;
LayerRef& operator=(const LayerRef&) = delete;