Merge "Add AC-4 support in OpenMAX definition"
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 0ee6c3a..f2678eb 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -137,6 +137,7 @@
dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str());
dprintf(fd, "version: %s\n", ds_.version_.c_str());
dprintf(fd, "bugreport_dir: %s\n", ds_.bugreport_dir_.c_str());
+ dprintf(fd, "bugreport_internal_dir_: %s\n", ds_.bugreport_internal_dir_.c_str());
dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str());
dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str());
dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str());
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index df80651..be10232 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -82,6 +82,7 @@
using android::TIMED_OUT;
using android::UNKNOWN_ERROR;
using android::Vector;
+using android::base::StringPrintf;
using android::os::dumpstate::CommandOptions;
using android::os::dumpstate::DumpFileToFd;
using android::os::dumpstate::DumpstateSectionReporter;
@@ -121,6 +122,69 @@
// TODO: temporary variables and functions used during C++ refactoring
static Dumpstate& ds = Dumpstate::GetInstance();
+
+namespace android {
+namespace os {
+namespace {
+
+static int Open(std::string path, int flags, mode_t mode = 0) {
+ int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
+ if (fd == -1) {
+ MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
+ }
+ return fd;
+}
+
+static int OpenForWrite(std::string path) {
+ return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+}
+
+static int OpenForRead(std::string path) {
+ return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+}
+
+bool CopyFile(int in_fd, int out_fd) {
+ char buf[4096];
+ ssize_t byte_count;
+ while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
+ if (!android::base::WriteFully(out_fd, buf, byte_count)) {
+ return false;
+ }
+ }
+ return (byte_count != -1);
+}
+
+static bool CopyFileToFd(const std::string& input_file, int out_fd) {
+ MYLOGD("Going to copy bugreport file (%s) to %d\n", ds.path_.c_str(), out_fd);
+
+ // Obtain a handle to the source file.
+ android::base::unique_fd in_fd(OpenForRead(input_file));
+ if (out_fd != -1 && in_fd.get() != -1) {
+ if (CopyFile(in_fd.get(), out_fd)) {
+ return true;
+ }
+ MYLOGE("Failed to copy zip file: %s\n", strerror(errno));
+ }
+ return false;
+}
+
+static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
+ if (input_file == output_file) {
+ MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
+ output_file.c_str());
+ return false;
+ }
+
+ MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
+ android::base::unique_fd out_fd(OpenForWrite(output_file));
+ return CopyFileToFd(input_file, out_fd.get());
+}
+
+} // namespace
+} // namespace os
+} // namespace android
+
static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
const CommandOptions& options = CommandOptions::DEFAULT) {
return ds.RunCommand(title, fullCommand, options);
@@ -137,8 +201,6 @@
// Relative directory (inside the zip) for all files copied as-is into the bugreport.
static const std::string ZIP_ROOT_DIR = "FS";
-// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
-static const std::string kDumpstateBoardPath = "/bugreports/";
static const std::string kProtoPath = "proto/";
static const std::string kProtoExt = ".proto";
static const std::string kDumpstateBoardFiles[] = {
@@ -1145,7 +1207,7 @@
return !isalnum(c) &&
std::string("@-_:.").find(c) == std::string::npos;
}, '_');
- const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
+ const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
{
auto fd = android::base::unique_fd(
@@ -1529,7 +1591,8 @@
std::vector<std::string> paths;
std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
for (int i = 0; i < NUM_OF_DUMPS; i++) {
- paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
+ paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
+ kDumpstateBoardFiles[i].c_str()));
remover.emplace_back(android::base::make_scope_guard(std::bind(
[](std::string path) {
if (remove(path.c_str()) != 0 && errno != ENOENT) {
@@ -1687,7 +1750,8 @@
MYLOGE("Failed to add dumpstate log to .zip file\n");
return false;
}
- // ... and re-opens it for further logging.
+ // TODO: Should truncate the existing file.
+ // ... and re-open it for further logging.
redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
fprintf(stderr, "\n");
@@ -1770,17 +1834,30 @@
// clang-format on
}
+static void MaybeResolveSymlink(std::string* path) {
+ std::string resolved_path;
+ if (android::base::Readlink(*path, &resolved_path)) {
+ *path = resolved_path;
+ }
+}
+
/*
* 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() {
- ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
+ MaybeResolveSymlink(&ds.bugreport_internal_dir_);
+
+ std::string base_name_part1 = "bugreport";
+ if (!ds.options_->use_outfile.empty()) {
+ ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
+ base_name_part1 = basename(ds.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(ds.options_->use_outfile.c_str()),
- device_name.c_str(), build_id.c_str());
+ StringPrintf("%s-%s-%s", base_name_part1.c_str(), device_name.c_str(), build_id.c_str());
if (ds.options_->do_add_date) {
char date[80];
strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
@@ -1801,15 +1878,18 @@
ds.tmp_path_ = ds.GetPath(".tmp");
ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
+ std::string destination = ds.options_->fd != -1 ? StringPrintf("[fd:%d]", ds.options_->fd)
+ : ds.bugreport_dir_.c_str();
MYLOGD(
"Bugreport dir: %s\n"
+ "Internal 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());
+ destination.c_str(), ds.bugreport_internal_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 (ds.options_->do_zip_file) {
ds.path_ = ds.GetPath(".zip");
@@ -1875,6 +1955,19 @@
ds.path_ = new_path;
}
}
+ // The zip file lives in an internal directory. Copy it over to output.
+ bool copy_succeeded = false;
+ if (ds.options_->fd != -1) {
+ copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->fd);
+ } else {
+ ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip");
+ copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_);
+ }
+ if (copy_succeeded) {
+ if (remove(ds.path_.c_str())) {
+ MYLOGE("remove(%s): %s", ds.path_.c_str(), strerror(errno));
+ }
+ }
}
}
if (do_text_file) {
@@ -1899,8 +1992,9 @@
/* Broadcasts that we are done with the bugreport */
static void SendBugreportFinishedBroadcast() {
- if (!ds.path_.empty()) {
- MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
+ // TODO(b/111441001): use callback instead of broadcast.
+ if (!ds.final_path_.empty()) {
+ MYLOGI("Final bugreport path: %s\n", ds.final_path_.c_str());
// clang-format off
std::vector<std::string> am_args = {
@@ -1908,7 +2002,7 @@
"--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.BUGREPORT", ds.final_path_,
"--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
};
// clang-format on
@@ -1930,7 +2024,7 @@
if (ds.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_));
+ am_args.push_back(SHA256_file_hash(ds.final_path_));
SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
} else {
SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
@@ -2060,6 +2154,7 @@
MYLOGI("telephony_only: %d\n", options.telephony_only);
MYLOGI("wifi_only: %d\n", options.wifi_only);
MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
+ MYLOGI("fd: %d\n", options.fd);
MYLOGI("use_outfile: %s\n", options.use_outfile.c_str());
MYLOGI("extra_options: %s\n", options.extra_options.c_str());
MYLOGI("args: %s\n", options.args.c_str());
@@ -2125,8 +2220,13 @@
}
bool Dumpstate::DumpOptions::ValidateOptions() const {
- if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast)
- && use_outfile.empty()) {
+ if (fd != -1 && !do_zip_file) {
+ return false;
+ }
+
+ bool has_out_file_options = !use_outfile.empty() || fd != -1;
+ if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) &&
+ !has_out_file_options) {
return false;
}
@@ -2148,10 +2248,31 @@
options_ = std::move(options);
}
+/*
+ * Dumps relevant information to a bugreport based on the given options.
+ *
+ * The bugreport can be dumped to a file or streamed to a socket.
+ *
+ * How dumping to file works:
+ * stdout is redirected to a temporary file. This will later become the main bugreport entry.
+ * stderr is redirected a log file.
+ *
+ * The temporary bugreport is then populated via printfs, dumping contents of files and
+ * output of commands to stdout.
+ *
+ * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
+ * text file.
+ *
+ * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
+ * gets added to the archive.
+ *
+ * Bugreports are first generated in a local directory and later copied to the caller's fd or
+ * directory.
+ */
Dumpstate::RunStatus Dumpstate::Run() {
+ LogDumpOptions(*options_);
if (!options_->ValidateOptions()) {
MYLOGE("Invalid options specified\n");
- LogDumpOptions(*options_);
return RunStatus::INVALID_INPUT;
}
/* set as high priority, and protect from OOM killer */
@@ -2191,9 +2312,9 @@
// TODO: temporarily set progress until it's part of the Dumpstate constructor
std::string stats_path =
- is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt",
- dirname(options_->use_outfile.c_str()))
- : "";
+ is_redirecting
+ ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
+ : "";
progress_.reset(new Progress(stats_path));
/* gets the sequential id */
@@ -2289,13 +2410,18 @@
int dup_stdout_fd;
int dup_stderr_fd;
if (is_redirecting) {
+ // Redirect stderr to log_path_ for debugging.
TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()));
if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
strerror(errno));
}
+
+ // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
+ // moved into zip file later, if zipping.
TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
+ // TODO: why not write to a file instead of stdout to overcome this problem?
/* TODO: rather than generating a text file now and zipping it later,
it would be more efficient to redirect stdout to the zip entry
directly, but the libziparchive doesn't support that option yet. */
@@ -2370,7 +2496,7 @@
return RunStatus::OK;
}
-/* Main entry point for dumpstate. */
+/* Main entry point for dumpstate binary. */
int run_main(int argc, char* argv[]) {
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
Dumpstate::RunStatus status = options->Initialize(argc, argv);
@@ -2382,7 +2508,7 @@
switch (status) {
case Dumpstate::RunStatus::OK:
return 0;
- break;
+ // TODO(b/111441001): Exit directly in the following cases.
case Dumpstate::RunStatus::HELP:
ShowUsageAndExit(0 /* exit code */);
break;
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 35cbdb1..94e3191 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -142,7 +142,7 @@
float growth_factor_;
int32_t n_runs_;
int32_t average_max_;
- const std::string& path_;
+ std::string path_;
};
/*
@@ -164,6 +164,11 @@
static std::string VERSION_DEFAULT = "default";
/*
+ * Directory used by Dumpstate binary to keep its local files.
+ */
+static const std::string DUMPSTATE_DIRECTORY = "/bugreports";
+
+/*
* Structure that contains the information of an open dump file.
*/
struct DumpData {
@@ -300,7 +305,11 @@
*/
bool FinishZipFile();
- /* Gets the path of a bugreport file with the given suffix. */
+ /* Constructs a full path inside directory with file name formatted using the given suffix. */
+ std::string GetPath(const std::string& directory, const std::string& suffix) const;
+
+ /* Constructs a full path inside bugreport_internal_dir_ with file name formatted using the
+ * given suffix. */
std::string GetPath(const std::string& suffix) const;
/* Returns true if the current version supports priority dump feature. */
@@ -314,7 +323,6 @@
/* Sets runtime options. */
void SetOptions(std::unique_ptr<DumpOptions> options);
- // TODO: add other options from DumpState.
/*
* Structure to hold options that determine the behavior of dumpstate.
*/
@@ -333,6 +341,10 @@
bool wifi_only = false;
// Whether progress updates should be published.
bool do_progress_updates = false;
+ // File descriptor to output zip file. -1 indicates not set. Takes precedence over
+ // use_outfile.
+ int fd = -1;
+ // Partial path to output file.
std::string use_outfile;
// TODO: rename to MODE.
// Extra options passed as system property.
@@ -381,12 +393,6 @@
// Bugreport format version;
std::string version_ = VERSION_CURRENT;
- // Full path of the directory where the bugreport files will be written.
- std::string bugreport_dir_;
-
- // Full path of the temporary file containing the screenshot (when requested).
- std::string screenshot_path_;
-
time_t now_;
// Base name (without suffix or extensions) of the bugreport files, typically
@@ -397,15 +403,30 @@
// `-d`), but it could be changed by the user..
std::string name_;
- // Full path of the temporary file containing the bugreport.
+ std::string bugreport_internal_dir_ = DUMPSTATE_DIRECTORY;
+
+ // Full path of the temporary file containing the bugreport, inside bugreport_internal_dir_.
+ // At the very end this file is pulled into the zip file.
std::string tmp_path_;
- // Full path of the file containing the dumpstate logs.
+ // Full path of the file containing the dumpstate logs, inside bugreport_internal_dir_.
+ // This is useful for debugging.
std::string log_path_;
- // Pointer to the actual path, be it zip or text.
+ // Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_.
std::string path_;
+ // TODO: If temporary this should be removed at the end.
+ // Full path of the temporary file containing the screenshot (when requested).
+ std::string screenshot_path_;
+
+ // TODO(b/111441001): remove when obsolete.
+ // Full path of the final zip file inside the caller-specified directory, if available.
+ std::string final_path_;
+
+ // The caller-specified directory, if available.
+ std::string bugreport_dir_;
+
// Pointer to the zipped file.
std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose};
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 6cbb691..d97ffbf 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -229,7 +229,11 @@
}
std::string Dumpstate::GetPath(const std::string& suffix) const {
- return android::base::StringPrintf("%s/%s-%s%s", bugreport_dir_.c_str(), base_name_.c_str(),
+ return GetPath(bugreport_internal_dir_, suffix);
+}
+
+std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
+ return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
name_.c_str(), suffix.c_str());
}
diff --git a/data/etc/android.software.ipsec_tunnels.xml b/data/etc/android.software.ipsec_tunnels.xml
new file mode 100644
index 0000000..f7ffc02
--- /dev/null
+++ b/data/etc/android.software.ipsec_tunnels.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+ This is the feature indicating that the device has support for multinetworking-capable IPsec
+ tunnels
+-->
+
+<permissions>
+ <feature name="android.software.ipsec_tunnels" />
+</permissions>
diff --git a/headers/media_plugin/media/cas/DescramblerAPI.h b/headers/media_plugin/media/cas/DescramblerAPI.h
index 033c8ce..c57f606 100644
--- a/headers/media_plugin/media/cas/DescramblerAPI.h
+++ b/headers/media_plugin/media/cas/DescramblerAPI.h
@@ -72,12 +72,12 @@
// associated MediaCas session is used to load decryption keys
// into the crypto/cas plugin. The keys are then referenced by key-id
// in the 'key' parameter to the decrypt() method.
- // Should return NO_ERROR on success, ERROR_DRM_SESSION_NOT_OPENED if
+ // Should return NO_ERROR on success, ERROR_CAS_SESSION_NOT_OPENED if
// the session is not opened and a code from MediaErrors.h otherwise.
virtual status_t setMediaCasSession(const CasSessionId& sessionId) = 0;
// If the error returned falls into the range
- // ERROR_DRM_VENDOR_MIN..ERROR_DRM_VENDOR_MAX, errorDetailMsg should be
+ // ERROR_CAS_VENDOR_MIN..ERROR_CAS_VENDOR_MAX, errorDetailMsg should be
// filled in with an appropriate string.
// At the java level these special errors will then trigger a
// MediaCodec.CryptoException that gives clients access to both
diff --git a/include/android/trace.h b/include/android/trace.h
index aa24995..bb7ff28 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -33,6 +33,7 @@
#define ANDROID_NATIVE_TRACE_H
#include <stdbool.h>
+#include <stdint.h>
#include <sys/cdefs.h>
#ifdef __cplusplus
@@ -73,6 +74,40 @@
#endif /* __ANDROID_API__ >= 23 */
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+
+/**
+ * Writes a trace message to indicate that a given section of code has
+ * begun. Must be followed by a call to {@link ATrace_endAsyncSection} with the same
+ * methodName and cookie. Unlike {@link ATrace_beginSection} and {@link ATrace_endSection},
+ * asynchronous events do not need to be nested. The name and cookie used to
+ * begin an event must be used to end it.
+ *
+ * \param sectionName The method name to appear in the trace.
+ * \param cookie Unique identifier for distinguishing simultaneous events
+ */
+void ATrace_beginAsyncSection(const char* sectionName, int32_t cookie) __INTRODUCED_IN(29);
+
+/**
+ * Writes a trace message to indicate that the current method has ended.
+ * Must be called exactly once for each call to {@link ATrace_beginAsyncSection}
+ * using the same name and cookie.
+ *
+ * \param methodName The method name to appear in the trace.
+ * \param cookie Unique identifier for distinguishing simultaneous events
+ */
+void ATrace_endAsyncSection(const char* sectionName, int32_t cookie) __INTRODUCED_IN(29);
+
+/**
+ * Writes trace message to indicate the value of a given counter.
+ *
+ * \param counterName The counter name to appear in the trace.
+ * \param counterValue The counter value.
+ */
+void ATrace_setCounter(const char* counterName, int64_t counterValue) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
#ifdef __cplusplus
};
#endif
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a0a634a..ab94719 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -467,7 +467,6 @@
status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
{
- const sp<ProcessState> proc(ProcessState::self());
status_t err;
const uint8_t *data = parcel->mData;
const binder_size_t *objects = parcel->mObjects;
@@ -520,6 +519,7 @@
err = NO_ERROR;
if (numObjects > 0) {
+ const sp<ProcessState> proc(ProcessState::self());
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
size_t newSize = ((mObjectsSize + numObjects)*3)/2;
@@ -2559,8 +2559,11 @@
void Parcel::releaseObjects()
{
- const sp<ProcessState> proc(ProcessState::self());
size_t i = mObjectsSize;
+ if (i == 0) {
+ return;
+ }
+ sp<ProcessState> proc(ProcessState::self());
uint8_t* const data = mData;
binder_size_t* const objects = mObjects;
while (i > 0) {
@@ -2573,8 +2576,11 @@
void Parcel::acquireObjects()
{
- const sp<ProcessState> proc(ProcessState::self());
size_t i = mObjectsSize;
+ if (i == 0) {
+ return;
+ }
+ const sp<ProcessState> proc(ProcessState::self());
uint8_t* const data = mData;
binder_size_t* const objects = mObjects;
while (i > 0) {
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index d799c5f..dc4e000 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -40,6 +40,10 @@
],
version_script: "libbinder_ndk.map.txt",
+ stubs: {
+ symbol_file: "libbinder_ndk.map.txt",
+ versions: ["29"],
+ },
}
ndk_headers {
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index c2a6764..dfdda0c 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -135,8 +135,8 @@
}
void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
- bool developerOptIn, const int rulesFd, const long rulesOffset,
- const long rulesLength) {
+ const std::string developerOptIn, const int rulesFd,
+ const long rulesOffset, const long rulesLength) {
if (!mAnglePath.empty()) {
ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(),
path.c_str());
@@ -153,7 +153,13 @@
mAngleAppName = appName;
}
- mAngleDeveloperOptIn = developerOptIn;
+ if (!mAngleDeveloperOptIn.empty()) {
+ ALOGV("ignoring attempt to change ANGLE application opt-in from '%s' to '%s'",
+ mAngleDeveloperOptIn.c_str(), developerOptIn.c_str());
+ } else {
+ ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
+ mAngleDeveloperOptIn = developerOptIn;
+ }
ALOGV("setting ANGLE rules file descriptor to '%i'", rulesFd);
mAngleRulesFd = rulesFd;
@@ -182,8 +188,8 @@
return mAngleAppName.c_str();
}
-bool GraphicsEnv::getAngleDeveloperOptIn() {
- return mAngleDeveloperOptIn;
+const char* GraphicsEnv::getAngleDeveloperOptIn() {
+ return mAngleDeveloperOptIn.c_str();
}
int GraphicsEnv::getAngleRulesFd() {
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 20e4d66..4ec53f1 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -44,12 +44,12 @@
// (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, bool devOptIn,
+ void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn,
const int rulesFd, const long rulesOffset, const long rulesLength);
android_namespace_t* getAngleNamespace();
const char* getAngleAppName();
const char* getAngleAppPref();
- bool getAngleDeveloperOptIn();
+ const char* getAngleDeveloperOptIn();
int getAngleRulesFd();
long getAngleRulesOffset();
long getAngleRulesLength();
@@ -69,7 +69,7 @@
std::string mDriverPath;
std::string mAnglePath;
std::string mAngleAppName;
- bool mAngleDeveloperOptIn;
+ std::string mAngleDeveloperOptIn;
int mAngleRulesFd;
long mAngleRulesOffset;
long mAngleRulesLength;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 127fcd6..d1c732b 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -31,7 +31,6 @@
"-Werror",
],
cppflags: [
- "-std=c++1z",
"-Weverything",
// The static constructors and destructors in this library have not been noted to
@@ -123,6 +122,7 @@
shared_libs: [
"android.hardware.graphics.common@1.1",
+ "libbase",
"libsync",
"libbinder",
"libbufferhub",
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 85ae433..96e9a85 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -18,10 +18,10 @@
#define LOG_TAG "FrameEvents"
+#include <android-base/stringprintf.h>
#include <cutils/compiler.h> // For CC_[UN]LIKELY
#include <inttypes.h>
#include <utils/Log.h>
-#include <utils/String8.h>
#include <algorithm>
#include <limits>
@@ -29,6 +29,7 @@
namespace android {
+using base::StringAppendF;
// ============================================================================
// FrameEvents
@@ -86,50 +87,49 @@
releaseFence->getSignalTime();
}
-static void dumpFenceTime(String8& outString, const char* name,
- bool pending, const FenceTime& fenceTime) {
- outString.appendFormat("--- %s", name);
+static void dumpFenceTime(std::string& outString, const char* name, bool pending,
+ const FenceTime& fenceTime) {
+ StringAppendF(&outString, "--- %s", name);
nsecs_t signalTime = fenceTime.getCachedSignalTime();
if (Fence::isValidTimestamp(signalTime)) {
- outString.appendFormat("%" PRId64 "\n", signalTime);
+ StringAppendF(&outString, "%" PRId64 "\n", signalTime);
} else if (pending || signalTime == Fence::SIGNAL_TIME_PENDING) {
- outString.appendFormat("Pending\n");
+ outString.append("Pending\n");
} else if (&fenceTime == FenceTime::NO_FENCE.get()){
- outString.appendFormat("N/A\n");
+ outString.append("N/A\n");
} else {
- outString.appendFormat("Error\n");
+ outString.append("Error\n");
}
}
-void FrameEvents::dump(String8& outString) const
-{
+void FrameEvents::dump(std::string& outString) const {
if (!valid) {
return;
}
- outString.appendFormat("-- Frame %" PRIu64 "\n", frameNumber);
- outString.appendFormat("--- Posted \t%" PRId64 "\n", postedTime);
- outString.appendFormat("--- Req. Present\t%" PRId64 "\n", requestedPresentTime);
+ StringAppendF(&outString, "-- Frame %" PRIu64 "\n", frameNumber);
+ StringAppendF(&outString, "--- Posted \t%" PRId64 "\n", postedTime);
+ StringAppendF(&outString, "--- Req. Present\t%" PRId64 "\n", requestedPresentTime);
- outString.appendFormat("--- Latched \t");
+ outString.append("--- Latched \t");
if (FrameEvents::isValidTimestamp(latchTime)) {
- outString.appendFormat("%" PRId64 "\n", latchTime);
+ StringAppendF(&outString, "%" PRId64 "\n", latchTime);
} else {
- outString.appendFormat("Pending\n");
+ outString.append("Pending\n");
}
- outString.appendFormat("--- Refresh (First)\t");
+ outString.append("--- Refresh (First)\t");
if (FrameEvents::isValidTimestamp(firstRefreshStartTime)) {
- outString.appendFormat("%" PRId64 "\n", firstRefreshStartTime);
+ StringAppendF(&outString, "%" PRId64 "\n", firstRefreshStartTime);
} else {
- outString.appendFormat("Pending\n");
+ outString.append("Pending\n");
}
- outString.appendFormat("--- Refresh (Last)\t");
+ outString.append("--- Refresh (Last)\t");
if (FrameEvents::isValidTimestamp(lastRefreshStartTime)) {
- outString.appendFormat("%" PRId64 "\n", lastRefreshStartTime);
+ StringAppendF(&outString, "%" PRId64 "\n", lastRefreshStartTime);
} else {
- outString.appendFormat("Pending\n");
+ outString.append("Pending\n");
}
dumpFenceTime(outString, "Acquire \t",
@@ -139,11 +139,11 @@
dumpFenceTime(outString, "Display Present \t",
!addPostCompositeCalled, *displayPresentFence);
- outString.appendFormat("--- DequeueReady \t");
+ outString.append("--- DequeueReady \t");
if (FrameEvents::isValidTimestamp(dequeueReadyTime)) {
- outString.appendFormat("%" PRId64 "\n", dequeueReadyTime);
+ StringAppendF(&outString, "%" PRId64 "\n", dequeueReadyTime);
} else {
- outString.appendFormat("Pending\n");
+ outString.append("Pending\n");
}
dumpFenceTime(outString, "Release \t",
@@ -206,11 +206,11 @@
return lhs.valid;
}
-void FrameEventHistory::dump(String8& outString) const {
+void FrameEventHistory::dump(std::string& outString) const {
auto earliestFrame = std::min_element(
mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
if (!earliestFrame->valid) {
- outString.appendFormat("-- N/A\n");
+ outString.append("-- N/A\n");
return;
}
for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
diff --git a/libs/gui/GuiConfig.cpp b/libs/gui/GuiConfig.cpp
index bc0c83c..3ec20ee 100644
--- a/libs/gui/GuiConfig.cpp
+++ b/libs/gui/GuiConfig.cpp
@@ -18,8 +18,7 @@
namespace android {
-void appendGuiConfigString(String8& configStr)
-{
+void appendGuiConfigString(std::string& configStr) {
static const char* config =
" [libgui"
#ifdef DONT_USE_FENCE_SYNC
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 7d26151..f1fefcc 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -651,6 +651,49 @@
&reply);
return result;
}
+
+ virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ uint64_t timestamp,
+ DisplayedFrameStats* outStats) const {
+ if (!outStats) return BAD_VALUE;
+
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ data.writeStrongBinder(display);
+ data.writeUint64(maxFrames);
+ data.writeUint64(timestamp);
+
+ status_t result =
+ remote()->transact(BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLE, data, &reply);
+
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ result = reply.readUint64(&outStats->numFrames);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ result = reply.readInt64Vector(
+ reinterpret_cast<std::vector<int64_t>*>(&outStats->component_0_sample));
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt64Vector(
+ reinterpret_cast<std::vector<int64_t>*>(&outStats->component_1_sample));
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt64Vector(
+ reinterpret_cast<std::vector<int64_t>*>(&outStats->component_2_sample));
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt64Vector(
+ reinterpret_cast<std::vector<int64_t>*>(&outStats->component_3_sample));
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -1055,6 +1098,40 @@
return setDisplayContentSamplingEnabled(display, enable,
static_cast<uint8_t>(componentMask), maxFrames);
}
+ case GET_DISPLAYED_CONTENT_SAMPLE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+
+ sp<IBinder> display = data.readStrongBinder();
+ uint64_t maxFrames = 0;
+ uint64_t timestamp = 0;
+
+ status_t result = data.readUint64(&maxFrames);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayedContentSample failure in reading max frames: %d", result);
+ return result;
+ }
+
+ result = data.readUint64(×tamp);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayedContentSample failure in reading timestamp: %d", result);
+ return result;
+ }
+
+ DisplayedFrameStats stats;
+ result = getDisplayedContentSample(display, maxFrames, timestamp, &stats);
+ if (result == NO_ERROR) {
+ reply->writeUint64(stats.numFrames);
+ reply->writeInt64Vector(
+ *reinterpret_cast<std::vector<int64_t>*>(&stats.component_0_sample));
+ reply->writeInt64Vector(
+ *reinterpret_cast<std::vector<int64_t>*>(&stats.component_1_sample));
+ reply->writeInt64Vector(
+ *reinterpret_cast<std::vector<int64_t>*>(&stats.component_2_sample));
+ reply->writeInt64Vector(
+ *reinterpret_cast<std::vector<int64_t>*>(&stats.component_3_sample));
+ }
+ return result;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index ccde9e0..cdde9a2 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -16,13 +16,14 @@
#include <gui/LayerDebugInfo.h>
+#include <android-base/stringprintf.h>
+
#include <ui/DebugUtils.h>
#include <binder/Parcel.h>
-#include <utils/String8.h>
-
using namespace android;
+using android::base::StringAppendF;
#define RETURN_ON_ERROR(X) do {status_t res = (X); if (res != NO_ERROR) return res;} while(false)
@@ -108,38 +109,37 @@
}
std::string to_string(const LayerDebugInfo& info) {
- String8 result;
+ std::string result;
- result.appendFormat("+ %s (%s)\n", info.mType.c_str(), info.mName.c_str());
+ StringAppendF(&result, "+ %s (%s)\n", info.mType.c_str(), info.mName.c_str());
info.mTransparentRegion.dump(result, "TransparentRegion");
info.mVisibleRegion.dump(result, "VisibleRegion");
info.mSurfaceDamageRegion.dump(result, "SurfaceDamageRegion");
- result.appendFormat(" layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ",
- info.mLayerStack, info.mZ, static_cast<double>(info.mX), static_cast<double>(info.mY),
- info.mWidth, info.mHeight);
+ StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ",
+ info.mLayerStack, info.mZ, static_cast<double>(info.mX),
+ static_cast<double>(info.mY), info.mWidth, info.mHeight);
- result.appendFormat("crop=%s, ", to_string(info.mCrop).c_str());
- result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty);
- result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str());
- result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str());
- result.appendFormat("color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
- static_cast<double>(info.mColor.r), static_cast<double>(info.mColor.g),
- static_cast<double>(info.mColor.b), static_cast<double>(info.mColor.a),
- info.mFlags);
- result.appendFormat("tr=[%.2f, %.2f][%.2f, %.2f]",
- static_cast<double>(info.mMatrix[0][0]), static_cast<double>(info.mMatrix[0][1]),
- static_cast<double>(info.mMatrix[1][0]), static_cast<double>(info.mMatrix[1][1]));
+ StringAppendF(&result, "crop=%s, ", to_string(info.mCrop).c_str());
+ StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty);
+ StringAppendF(&result, "dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str());
+ StringAppendF(&result, "pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str());
+ StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+ static_cast<double>(info.mColor.r), static_cast<double>(info.mColor.g),
+ static_cast<double>(info.mColor.b), static_cast<double>(info.mColor.a),
+ info.mFlags);
+ StringAppendF(&result, "tr=[%.2f, %.2f][%.2f, %.2f]", static_cast<double>(info.mMatrix[0][0]),
+ static_cast<double>(info.mMatrix[0][1]), static_cast<double>(info.mMatrix[1][0]),
+ static_cast<double>(info.mMatrix[1][1]));
result.append("\n");
- result.appendFormat(" parent=%s\n", info.mParentName.c_str());
- result.appendFormat(" activeBuffer=[%4ux%4u:%4u,%s],",
- info.mActiveBufferWidth, info.mActiveBufferHeight,
- info.mActiveBufferStride,
- decodePixelFormat(info.mActiveBufferFormat).c_str());
- result.appendFormat(" queued-frames=%d, mRefreshPending=%d",
- info.mNumQueuedFrames, info.mRefreshPending);
+ StringAppendF(&result, " parent=%s\n", info.mParentName.c_str());
+ StringAppendF(&result, " activeBuffer=[%4ux%4u:%4u,%s],", info.mActiveBufferWidth,
+ info.mActiveBufferHeight, info.mActiveBufferStride,
+ decodePixelFormat(info.mActiveBufferFormat).c_str());
+ StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", info.mNumQueuedFrames,
+ info.mRefreshPending);
result.append("\n");
- return std::string(result.c_str());
+ return result;
}
} // android
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 407eecb..35ce6e3 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "LayerState"
+#include <inttypes.h>
+
#include <utils/Errors.h>
#include <binder/Parcel.h>
#include <gui/ISurfaceComposerClient.h>
@@ -27,7 +29,7 @@
status_t layer_state_t::write(Parcel& output) const
{
output.writeStrongBinder(surface);
- output.writeUint32(what);
+ output.writeUint64(what);
output.writeFloat(x);
output.writeFloat(y);
output.writeInt32(z);
@@ -57,6 +59,7 @@
output.writeUint32(transform);
output.writeBool(transformToDisplayInverse);
output.write(crop);
+ output.write(frame);
if (buffer) {
output.writeBool(true);
output.write(*buffer);
@@ -97,7 +100,7 @@
status_t layer_state_t::read(const Parcel& input)
{
surface = input.readStrongBinder();
- what = input.readUint32();
+ what = input.readUint64();
x = input.readFloat();
y = input.readFloat();
z = input.readInt32();
@@ -133,6 +136,7 @@
transform = input.readUint32();
transformToDisplayInverse = input.readBool();
input.read(crop);
+ input.read(frame);
buffer = new GraphicBuffer();
if (input.readBool()) {
input.read(*buffer);
@@ -320,6 +324,10 @@
what |= eCropChanged;
crop = other.crop;
}
+ if (other.what & eFrameChanged) {
+ what |= eFrameChanged;
+ frame = other.frame;
+ }
if (other.what & eBufferChanged) {
what |= eBufferChanged;
buffer = other.buffer;
@@ -366,7 +374,7 @@
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
- "other.what=0x%X what=0x%X",
+ "other.what=0x%" PRIu64 " what=0x%" PRIu64,
other.what, what);
}
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 405d228..9586219 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -609,6 +609,20 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame(
+ const sp<SurfaceControl>& sc, const Rect& frame) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eFrameChanged;
+ s->frame = frame;
+
+ registerSurfaceControlForCallback(sc);
+ return *this;
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer(
const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer) {
layer_state_t* s = getLayerState(sc);
@@ -1106,6 +1120,12 @@
maxFrames);
}
+status_t SurfaceComposerClient::getDisplayedContentSample(const sp<IBinder>& display,
+ uint64_t maxFrames, uint64_t timestamp,
+ DisplayedFrameStats* outStats) {
+ return ComposerService::getComposerService()->getDisplayedContentSample(display, maxFrames,
+ timestamp, outStats);
+}
// ----------------------------------------------------------------------------
status_t ScreenshotClient::capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace,
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index e06e40f..df02494 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -30,7 +30,6 @@
struct FrameEvents;
class FrameEventHistoryDelta;
-class String8;
// Identifiers for all the events that may be recorded or reported.
@@ -72,7 +71,7 @@
bool hasDequeueReadyInfo() const;
void checkFencesForCompletion();
- void dump(String8& outString) const;
+ void dump(std::string& outString) const;
bool valid{false};
int connectId{0};
@@ -112,7 +111,7 @@
FrameEvents* getFrame(uint64_t frameNumber);
FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint);
void checkFencesForCompletion();
- void dump(String8& outString) const;
+ void dump(std::string& outString) const;
static constexpr size_t MAX_FRAME_HISTORY = 8;
diff --git a/libs/gui/include/gui/GuiConfig.h b/libs/gui/include/gui/GuiConfig.h
index b020ed9..7aa5432 100644
--- a/libs/gui/include/gui/GuiConfig.h
+++ b/libs/gui/include/gui/GuiConfig.h
@@ -17,12 +17,12 @@
#ifndef ANDROID_GUI_CONFIG_H
#define ANDROID_GUI_CONFIG_H
-#include <utils/String8.h>
+#include <string>
namespace android {
// Append the libgui configuration details to configStr.
-void appendGuiConfigString(String8& configStr);
+void appendGuiConfigString(std::string& configStr);
}; // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 41369c8..3052c0b 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -27,10 +27,11 @@
#include <binder/IInterface.h>
+#include <ui/DisplayedFrameStats.h>
#include <ui/FrameStats.h>
-#include <ui/PixelFormat.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
+#include <ui/PixelFormat.h>
#include <vector>
@@ -308,6 +309,14 @@
virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
uint8_t componentMask,
uint64_t maxFrames) const = 0;
+
+ /* Returns statistics on the color profile of the last frame displayed for a given display
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ uint64_t timestamp,
+ DisplayedFrameStats* outStats) const = 0;
};
// ----------------------------------------------------------------------------
@@ -349,6 +358,7 @@
GET_COLOR_MANAGEMENT,
GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
+ GET_DISPLAYED_CONTENT_SAMPLE,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 3cfee9e..02c6be2 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -83,6 +83,7 @@
eListenerCallbacksChanged = 0x20000000,
eInputInfoChanged = 0x40000000,
eCornerRadiusChanged = 0x80000000,
+ eFrameChanged = 0x1'00000000,
};
layer_state_t()
@@ -104,6 +105,7 @@
transform(0),
transformToDisplayInverse(false),
crop(Rect::INVALID_RECT),
+ frame(Rect::INVALID_RECT),
dataspace(ui::Dataspace::UNKNOWN),
surfaceDamageRegion(),
api(-1),
@@ -124,7 +126,7 @@
float dsdy{0};
};
sp<IBinder> surface;
- uint32_t what;
+ uint64_t what;
float x;
float y;
int32_t z;
@@ -157,6 +159,7 @@
uint32_t transform;
bool transformToDisplayInverse;
Rect crop;
+ Rect frame;
sp<GraphicBuffer> buffer;
sp<Fence> acquireFence;
ui::Dataspace dataspace;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index ba943a0..8e3ba78 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -30,6 +30,7 @@
#include <utils/SortedVector.h>
#include <utils/threads.h>
+#include <ui/DisplayedFrameStats.h>
#include <ui/FrameStats.h>
#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
@@ -295,6 +296,7 @@
Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc,
bool transformToDisplayInverse);
Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop);
+ Transaction& setFrame(const sp<SurfaceControl>& sc, const Rect& frame);
Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer);
Transaction& setAcquireFence(const sp<SurfaceControl>& sc, const sp<Fence>& fence);
Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
@@ -389,6 +391,9 @@
static status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
uint8_t componentMask, uint64_t maxFrames);
+ static status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ uint64_t timestamp, DisplayedFrameStats* outStats);
+
private:
virtual void onFirstRef();
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 6de641d..f020a40 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -37,6 +37,7 @@
shared_libs: [
"android.hardware.configstore@1.0",
"android.hardware.configstore-utils",
+ "libbase",
"liblog",
"libEGL",
"libGLESv1_CM",
diff --git a/libs/gui/tests/DisplayedContentSampling_test.cpp b/libs/gui/tests/DisplayedContentSampling_test.cpp
index f9d5dd6..5443812 100644
--- a/libs/gui/tests/DisplayedContentSampling_test.cpp
+++ b/libs/gui/tests/DisplayedContentSampling_test.cpp
@@ -104,4 +104,19 @@
0);
EXPECT_EQ(OK, status);
}
+
+TEST_F(DisplayedContentSamplingTest, SampleCollectionCoherentWithSupportMask) {
+ if (shouldSkipTest()) return;
+
+ DisplayedFrameStats stats;
+ status_t status = mComposerClient->getDisplayedContentSample(mDisplayToken, 0, 0, &stats);
+ EXPECT_EQ(OK, status);
+ if (stats.numFrames <= 0) return;
+
+ if (componentMask & (0x1 << 0)) EXPECT_NE(0, stats.component_0_sample.size());
+ if (componentMask & (0x1 << 1)) EXPECT_NE(0, stats.component_1_sample.size());
+ if (componentMask & (0x1 << 2)) EXPECT_NE(0, stats.component_2_sample.size());
+ if (componentMask & (0x1 << 3)) EXPECT_NE(0, stats.component_3_sample.size());
+}
+
} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index cb1756f..d37b810 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -652,6 +652,11 @@
uint64_t /*maxFrames*/) const override {
return NO_ERROR;
}
+ status_t getDisplayedContentSample(const sp<IBinder>& /*display*/, uint64_t /*maxFrames*/,
+ uint64_t /*timestamp*/,
+ DisplayedFrameStats* /*outStats*/) const override {
+ return NO_ERROR;
+ }
virtual status_t getColorManagement(bool* /*outGetColorManagement*/) const { return NO_ERROR; }
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index beaf9ee..d872f02 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -8,7 +8,6 @@
"-Wunused",
"-Wunreachable-code",
],
- cppflags: ["-std=c++1z"],
}
cc_defaults {
@@ -19,6 +18,7 @@
"-DEGL_EGLEXT_PROTOTYPES",
],
shared_libs: [
+ "libbase",
"libcutils",
"libEGL",
"libGLESv1_CM",
@@ -46,7 +46,7 @@
filegroup {
name: "librenderengine_gl_sources",
srcs: [
- "gl/GLES20RenderEngine.cpp",
+ "gl/GLESRenderEngine.cpp",
"gl/GLExtensions.cpp",
"gl/GLFramebuffer.cpp",
"gl/GLImage.cpp",
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index 8be1c3c..6dd7283 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -19,7 +19,7 @@
#include <cutils/properties.h>
#include <log/log.h>
#include <private/gui/SyncFeatures.h>
-#include "gl/GLES20RenderEngine.h"
+#include "gl/GLESRenderEngine.h"
namespace android {
namespace renderengine {
@@ -29,10 +29,10 @@
property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles");
if (strcmp(prop, "gles") == 0) {
ALOGD("RenderEngine GLES Backend");
- return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+ return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags);
}
ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop);
- return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+ return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags);
}
RenderEngine::~RenderEngine() = default;
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
similarity index 84%
rename from libs/renderengine/gl/GLES20RenderEngine.cpp
rename to libs/renderengine/gl/GLESRenderEngine.cpp
index 7adda83..1395551 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -19,7 +19,7 @@
#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include "GLES20RenderEngine.h"
+#include "GLESRenderEngine.h"
#include <math.h>
#include <fstream>
@@ -27,6 +27,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <android-base/stringprintf.h>
#include <cutils/compiler.h>
#include <renderengine/Mesh.h>
#include <renderengine/Texture.h>
@@ -36,7 +37,6 @@
#include <ui/Rect.h>
#include <ui/Region.h>
#include <utils/KeyedVector.h>
-#include <utils/String8.h>
#include <utils/Trace.h>
#include "GLExtensions.h"
#include "GLFramebuffer.h"
@@ -109,6 +109,7 @@
namespace renderengine {
namespace gl {
+using base::StringAppendF;
using ui::Dataspace;
static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
@@ -221,8 +222,7 @@
return err;
}
-std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat,
- uint32_t featureFlags) {
+std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32_t featureFlags) {
// initialize EGL for the default display
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!eglInitialize(display, nullptr, nullptr)) {
@@ -263,7 +263,7 @@
GlesVersion version = parseGlesVersion(extensions.getVersion());
// initialize the renderer while GL is current
- std::unique_ptr<GLES20RenderEngine> engine;
+ std::unique_ptr<GLESRenderEngine> engine;
switch (version) {
case GLES_VERSION_1_0:
case GLES_VERSION_1_1:
@@ -271,8 +271,7 @@
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- engine = std::make_unique<GLES20RenderEngine>(featureFlags, display, config, ctxt,
- dummy);
+ engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy);
break;
}
@@ -287,17 +286,17 @@
return engine;
}
-EGLConfig GLES20RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
+EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
status_t err;
EGLConfig config;
- // First try to get an ES2 config
- err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
+ // First try to get an ES3 config
+ err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config);
if (err != NO_ERROR) {
- // If ES2 fails, try ES1
- err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
+ // If ES3 fails, try to get an ES2 config
+ err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
if (err != NO_ERROR) {
- // still didn't work, probably because we're on the emulator...
+ // If ES2 still doesn't work, probably because we're on the emulator.
// try a simplified query
ALOGW("no suitable EGLConfig found, trying a simpler query");
err = selectEGLConfig(display, format, 0, &config);
@@ -326,8 +325,8 @@
return config;
}
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
- EGLContext ctxt, EGLSurface dummy)
+GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
+ EGLContext ctxt, EGLSurface dummy)
: renderengine::impl::RenderEngine(featureFlags),
mEGLDisplay(display),
mEGLConfig(config),
@@ -382,28 +381,28 @@
}
}
-GLES20RenderEngine::~GLES20RenderEngine() {
+GLESRenderEngine::~GLESRenderEngine() {
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mEGLDisplay);
}
-std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() {
+std::unique_ptr<Framebuffer> GLESRenderEngine::createFramebuffer() {
return std::make_unique<GLFramebuffer>(*this);
}
-std::unique_ptr<Image> GLES20RenderEngine::createImage() {
+std::unique_ptr<Image> GLESRenderEngine::createImage() {
return std::make_unique<GLImage>(*this);
}
-void GLES20RenderEngine::primeCache() const {
+void GLESRenderEngine::primeCache() const {
ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT);
}
-bool GLES20RenderEngine::isCurrent() const {
+bool GLESRenderEngine::isCurrent() const {
return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
}
-base::unique_fd GLES20RenderEngine::flush() {
+base::unique_fd GLESRenderEngine::flush() {
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
}
@@ -427,7 +426,7 @@
return fenceFd;
}
-bool GLES20RenderEngine::finish() {
+bool GLESRenderEngine::finish() {
if (!GLExtensions::getInstance().hasFenceSync()) {
ALOGW("no synchronization support");
return false;
@@ -455,7 +454,7 @@
return true;
}
-bool GLES20RenderEngine::waitFence(base::unique_fd fenceFd) {
+bool GLESRenderEngine::waitFence(base::unique_fd fenceFd) {
if (!GLExtensions::getInstance().hasNativeFenceSync() ||
!GLExtensions::getInstance().hasWaitSync()) {
return false;
@@ -485,13 +484,13 @@
return true;
}
-void GLES20RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+void GLESRenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
glClearColor(red, green, blue, alpha);
glClear(GL_COLOR_BUFFER_BIT);
}
-void GLES20RenderEngine::fillRegionWithColor(const Region& region, float red, float green,
- float blue, float alpha) {
+void GLESRenderEngine::fillRegionWithColor(const Region& region, float red, float green, float blue,
+ float alpha) {
size_t c;
Rect const* r = region.getArray(&c);
Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
@@ -514,7 +513,7 @@
drawMesh(mesh);
}
-void GLES20RenderEngine::setScissor(const Rect& region) {
+void GLESRenderEngine::setScissor(const Rect& region) {
// Invert y-coordinate to map to GL-space.
int32_t canvasHeight = mFboHeight;
int32_t glBottom = canvasHeight - region.bottom;
@@ -523,19 +522,19 @@
glEnable(GL_SCISSOR_TEST);
}
-void GLES20RenderEngine::disableScissor() {
+void GLESRenderEngine::disableScissor() {
glDisable(GL_SCISSOR_TEST);
}
-void GLES20RenderEngine::genTextures(size_t count, uint32_t* names) {
+void GLESRenderEngine::genTextures(size_t count, uint32_t* names) {
glGenTextures(count, names);
}
-void GLES20RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
+void GLESRenderEngine::deleteTextures(size_t count, uint32_t const* names) {
glDeleteTextures(count, names);
}
-void GLES20RenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
+void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
const GLImage& glImage = static_cast<const GLImage&>(image);
const GLenum target = GL_TEXTURE_EXTERNAL_OES;
@@ -545,7 +544,7 @@
}
}
-status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
+status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
EGLImageKHR eglImage = glFramebuffer->getEGLImage();
uint32_t textureName = glFramebuffer->getTextureName();
@@ -569,14 +568,14 @@
return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}
-void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
mFboHeight = 0;
// back to main framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-void GLES20RenderEngine::checkErrors() const {
+void GLESRenderEngine::checkErrors() const {
do {
// there could be more than one error flag
GLenum error = glGetError();
@@ -585,15 +584,15 @@
} while (true);
}
-status_t GLES20RenderEngine::drawLayers(const DisplaySettings& /*settings*/,
- const std::vector<LayerSettings>& /*layers*/,
- ANativeWindowBuffer* const /*buffer*/,
- base::unique_fd* /*displayFence*/) const {
+status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/,
+ const std::vector<LayerSettings>& /*layers*/,
+ ANativeWindowBuffer* const /*buffer*/,
+ base::unique_fd* /*displayFence*/) const {
return NO_ERROR;
}
-void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
- ui::Transform::orientation_flags rotation) {
+void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
+ ui::Transform::orientation_flags rotation) {
int32_t l = sourceCrop.left;
int32_t r = sourceCrop.right;
int32_t b = sourceCrop.bottom;
@@ -625,9 +624,8 @@
mVpHeight = vph;
}
-void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque,
- bool disableTexture, const half4& color,
- float cornerRadius) {
+void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+ const half4& color, float cornerRadius) {
mState.isPremultipliedAlpha = premultipliedAlpha;
mState.isOpaque = opaque;
mState.color = color;
@@ -645,23 +643,23 @@
}
}
-void GLES20RenderEngine::setSourceY410BT2020(bool enable) {
+void GLESRenderEngine::setSourceY410BT2020(bool enable) {
mState.isY410BT2020 = enable;
}
-void GLES20RenderEngine::setSourceDataSpace(Dataspace source) {
+void GLESRenderEngine::setSourceDataSpace(Dataspace source) {
mDataSpace = source;
}
-void GLES20RenderEngine::setOutputDataSpace(Dataspace dataspace) {
+void GLESRenderEngine::setOutputDataSpace(Dataspace dataspace) {
mOutputDataSpace = dataspace;
}
-void GLES20RenderEngine::setDisplayMaxLuminance(const float maxLuminance) {
+void GLESRenderEngine::setDisplayMaxLuminance(const float maxLuminance) {
mState.displayMaxLuminance = maxLuminance;
}
-void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
+void GLESRenderEngine::setupLayerTexturing(const Texture& texture) {
GLuint target = texture.getTextureTarget();
glBindTexture(target, texture.getTextureName());
GLenum filter = GL_NEAREST;
@@ -677,7 +675,7 @@
mState.textureEnabled = true;
}
-void GLES20RenderEngine::setupLayerBlackedOut() {
+void GLESRenderEngine::setupLayerBlackedOut() {
glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
Texture texture(Texture::TEXTURE_2D, mProtectedTexName);
texture.setDimensions(1, 1); // FIXME: we should get that from somewhere
@@ -685,19 +683,19 @@
mState.textureEnabled = true;
}
-void GLES20RenderEngine::setColorTransform(const mat4& colorTransform) {
+void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
mState.colorMatrix = colorTransform;
}
-void GLES20RenderEngine::disableTexturing() {
+void GLESRenderEngine::disableTexturing() {
mState.textureEnabled = false;
}
-void GLES20RenderEngine::disableBlending() {
+void GLESRenderEngine::disableBlending() {
glDisable(GL_BLEND);
}
-void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
+void GLESRenderEngine::setupFillWithColor(float r, float g, float b, float a) {
mState.isPremultipliedAlpha = true;
mState.isOpaque = false;
mState.color = half4(r, g, b, a);
@@ -705,11 +703,11 @@
glDisable(GL_BLEND);
}
-void GLES20RenderEngine::setupCornerRadiusCropSize(float width, float height) {
+void GLESRenderEngine::setupCornerRadiusCropSize(float width, float height) {
mState.cropSize = half2(width, height);
}
-void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
+void GLESRenderEngine::drawMesh(const Mesh& mesh) {
ATRACE_CALL();
if (mesh.getTexCoordsSize()) {
glEnableVertexAttribArray(Program::texCoords);
@@ -849,33 +847,33 @@
}
}
-size_t GLES20RenderEngine::getMaxTextureSize() const {
+size_t GLESRenderEngine::getMaxTextureSize() const {
return mMaxTextureSize;
}
-size_t GLES20RenderEngine::getMaxViewportDims() const {
+size_t GLESRenderEngine::getMaxViewportDims() const {
return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
}
-void GLES20RenderEngine::dump(String8& result) {
+void GLESRenderEngine::dump(std::string& result) {
const GLExtensions& extensions = GLExtensions::getInstance();
- result.appendFormat("EGL implementation : %s\n", extensions.getEGLVersion());
- result.appendFormat("%s\n", extensions.getEGLExtensions());
+ StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
+ StringAppendF(&result, "%s\n", extensions.getEGLExtensions());
- result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
- extensions.getVersion());
- result.appendFormat("%s\n", extensions.getExtensions());
+ StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
+ extensions.getVersion());
+ StringAppendF(&result, "%s\n", extensions.getExtensions());
- result.appendFormat("RenderEngine program cache size: %zu\n",
- ProgramCache::getInstance().getSize());
+ StringAppendF(&result, "RenderEngine program cache size: %zu\n",
+ ProgramCache::getInstance().getSize());
- result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n",
- dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
- dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
+ StringAppendF(&result, "RenderEngine last dataspace conversion: (%s) to (%s)\n",
+ dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
+ dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
}
-GLES20RenderEngine::GlesVersion GLES20RenderEngine::parseGlesVersion(const char* str) {
+GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str) {
int major, minor;
if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
@@ -893,16 +891,18 @@
return GLES_VERSION_1_0;
}
-EGLContext GLES20RenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
- EGLContext shareContext, bool useContextPriority) {
+EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
+ EGLContext shareContext, bool useContextPriority) {
EGLint renderableType = 0;
if (config == EGL_NO_CONFIG) {
- renderableType = EGL_OPENGL_ES2_BIT;
+ renderableType = EGL_OPENGL_ES3_BIT;
} else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
}
EGLint contextClientVersion = 0;
- if (renderableType & EGL_OPENGL_ES2_BIT) {
+ if (renderableType & EGL_OPENGL_ES3_BIT) {
+ contextClientVersion = 3;
+ } else if (renderableType & EGL_OPENGL_ES2_BIT) {
contextClientVersion = 2;
} else if (renderableType & EGL_OPENGL_ES_BIT) {
contextClientVersion = 1;
@@ -920,11 +920,25 @@
}
contextAttributes.push_back(EGL_NONE);
- return eglCreateContext(display, config, shareContext, contextAttributes.data());
+ EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
+
+ if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
+ // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
+ // EGL_NO_CONTEXT so that we can abort.
+ if (config != EGL_NO_CONFIG) {
+ return context;
+ }
+ // If |config| is EGL_NO_CONFIG, we speculatively try to create GLES 3 context, so we should
+ // try to fall back to GLES 2.
+ contextAttributes[1] = 2;
+ context = eglCreateContext(display, config, shareContext, contextAttributes.data());
+ }
+
+ return context;
}
-EGLSurface GLES20RenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
- int hwcFormat) {
+EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
+ int hwcFormat) {
EGLConfig dummyConfig = config;
if (dummyConfig == EGL_NO_CONFIG) {
dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
@@ -940,7 +954,7 @@
return eglCreatePbufferSurface(display, dummyConfig, attributes.data());
}
-bool GLES20RenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
+bool GLESRenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
const Dataspace standard = static_cast<Dataspace>(dataSpace & Dataspace::STANDARD_MASK);
const Dataspace transfer = static_cast<Dataspace>(dataSpace & Dataspace::TRANSFER_MASK);
return standard == Dataspace::STANDARD_BT2020 &&
@@ -957,7 +971,7 @@
// input data space or output data space is HDR data space, and the input transfer function
// doesn't match the output transfer function, we would enable an intermediate transfrom to
// XYZ color space.
-bool GLES20RenderEngine::needsXYZTransformMatrix() const {
+bool GLESRenderEngine::needsXYZTransformMatrix() const {
const bool isInputHdrDataSpace = isHdrDataSpace(mDataSpace);
const bool isOutputHdrDataSpace = isHdrDataSpace(mOutputDataSpace);
const Dataspace inputTransfer = static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK);
diff --git a/libs/renderengine/gl/GLES20RenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
similarity index 91%
rename from libs/renderengine/gl/GLES20RenderEngine.h
rename to libs/renderengine/gl/GLESRenderEngine.h
index a9f8cad..21d5b81 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SF_GLES20RENDERENGINE_H_
-#define SF_GLES20RENDERENGINE_H_
+#ifndef SF_GLESRENDERENGINE_H_
+#define SF_GLESRENDERENGINE_H_
#include <stdint.h>
#include <sys/types.h>
@@ -30,8 +30,6 @@
namespace android {
-class String8;
-
namespace renderengine {
class Mesh;
@@ -41,14 +39,14 @@
class GLImage;
-class GLES20RenderEngine : public impl::RenderEngine {
+class GLESRenderEngine : public impl::RenderEngine {
public:
- static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+ static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags);
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
- GLES20RenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
- EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
- ~GLES20RenderEngine() override;
+ GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
+ EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
+ ~GLESRenderEngine() override;
std::unique_ptr<Framebuffer> createFramebuffer() override;
std::unique_ptr<Image> createImage() override;
@@ -79,7 +77,7 @@
EGLConfig getEGLConfig() const { return mEGLConfig; }
protected:
- void dump(String8& result) override;
+ void dump(std::string& result) override;
void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
ui::Transform::orientation_flags rotation) override;
void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
@@ -165,4 +163,4 @@
} // namespace renderengine
} // namespace android
-#endif /* SF_GLES20RENDERENGINE_H_ */
+#endif /* SF_GLESRENDERENGINE_H_ */
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 2bd4e7f..f4de91a 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -21,13 +21,13 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <nativebase/nativebase.h>
-#include "GLES20RenderEngine.h"
+#include "GLESRenderEngine.h"
namespace android {
namespace renderengine {
namespace gl {
-GLFramebuffer::GLFramebuffer(const GLES20RenderEngine& engine)
+GLFramebuffer::GLFramebuffer(const GLESRenderEngine& engine)
: mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
glGenTextures(1, &mTextureName);
glGenFramebuffers(1, &mFramebufferName);
diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h
index 90c6f4a..358ab47 100644
--- a/libs/renderengine/gl/GLFramebuffer.h
+++ b/libs/renderengine/gl/GLFramebuffer.h
@@ -28,11 +28,11 @@
namespace renderengine {
namespace gl {
-class GLES20RenderEngine;
+class GLESRenderEngine;
class GLFramebuffer : public renderengine::Framebuffer {
public:
- explicit GLFramebuffer(const GLES20RenderEngine& engine);
+ explicit GLFramebuffer(const GLESRenderEngine& engine);
~GLFramebuffer() override;
bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) override;
diff --git a/libs/renderengine/gl/GLImage.cpp b/libs/renderengine/gl/GLImage.cpp
index 5a92093..a9529a7 100644
--- a/libs/renderengine/gl/GLImage.cpp
+++ b/libs/renderengine/gl/GLImage.cpp
@@ -19,7 +19,7 @@
#include <vector>
#include <log/log.h>
-#include "GLES20RenderEngine.h"
+#include "GLESRenderEngine.h"
#include "GLExtensions.h"
namespace android {
@@ -43,7 +43,7 @@
return attrs;
}
-GLImage::GLImage(const GLES20RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
+GLImage::GLImage(const GLESRenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
GLImage::~GLImage() {
setNativeWindowBuffer(nullptr, false);
diff --git a/libs/renderengine/gl/GLImage.h b/libs/renderengine/gl/GLImage.h
index 0e451f8..c897d8e 100644
--- a/libs/renderengine/gl/GLImage.h
+++ b/libs/renderengine/gl/GLImage.h
@@ -29,11 +29,11 @@
namespace renderengine {
namespace gl {
-class GLES20RenderEngine;
+class GLESRenderEngine;
class GLImage : public renderengine::Image {
public:
- explicit GLImage(const GLES20RenderEngine& engine);
+ explicit GLImage(const GLESRenderEngine& engine);
~GLImage() override;
bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override;
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index d0916ad..41870d2 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -215,7 +215,7 @@
const highp float c2 = (2413.0 / 4096.0) * 32.0;
const highp float c3 = (2392.0 / 4096.0) * 32.0;
- highp vec3 tmp = pow(color, 1.0 / vec3(m2));
+ highp vec3 tmp = pow(clamp(color, 0.0, 1.0), 1.0 / vec3(m2));
tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp);
return pow(tmp, 1.0 / vec3(m1));
}
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index 5941cdf..aa4e319 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -29,32 +29,32 @@
struct DisplaySettings {
// Rectangle describing the physical display. We will project from the
// logical clip onto this rectangle.
- Rect physicalDisplay;
+ Rect physicalDisplay = Rect::INVALID_RECT;
// Rectangle bounded by the x,y- clipping planes in the logical display, so
// that the orthographic projection matrix can be computed. When
// constructing this matrix, z-coordinate bound are assumed to be at z=0 and
// z=1.
- Rect clip;
+ Rect clip = Rect::INVALID_RECT;
// Global transform to apply to all layers.
- mat4 globalTransform;
+ mat4 globalTransform = mat4();
// Maximum luminance pulled from the display's HDR capabilities.
- float maxLuminence;
+ float maxLuminence = 1.0f;
// Output dataspace that will be populated if wide color gamut is used, or
// DataSpace::UNKNOWN otherwise.
- ui::Dataspace outputDataspace;
+ ui::Dataspace outputDataspace = ui::Dataspace::UNKNOWN;
// Additional color transform to apply in linear space after transforming
// to the output dataspace.
- mat4 colorTransform;
+ mat4 colorTransform = mat4();
// Region that will be cleared to (0, 0, 0, 0) prior to rendering.
// clearRegion will first be transformed by globalTransform so that it will
// be in the same coordinate space as the rendered layers.
- Region clearRegion;
+ Region clearRegion = Region::INVALID_REGION;
};
} // namespace renderengine
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index facea21..38dee40 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -34,58 +34,58 @@
// Buffer containing the image that we will render.
// If buffer == nullptr, then the rest of the fields in this struct will be
// ignored.
- sp<GraphicBuffer> buffer;
+ sp<GraphicBuffer> buffer = nullptr;
// Texture identifier to bind the external texture to.
// TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
- uint32_t textureName;
+ uint32_t textureName = 0;
// Whether to use filtering when rendering the texture.
- bool useTextureFiltering;
+ bool useTextureFiltering = false;
// Transform matrix to apply to texture coordinates.
- mat4 textureTransform;
+ mat4 textureTransform = mat4();
// Wheteher to use pre-multiplied alpha
- bool usePremultipliedAlpha;
+ bool usePremultipliedAlpha = true;
// HDR color-space setting for Y410.
- bool isY410BT2020;
+ bool isY410BT2020 = false;
};
// Metadata describing the layer geometry.
struct Geometry {
// Boundaries of the layer.
- FloatRect boundaries;
+ FloatRect boundaries = FloatRect();
// Transform matrix to apply to mesh coordinates.
- mat4 positionTransform;
+ mat4 positionTransform = mat4();
};
// Descriptor of the source pixels for this layer.
struct PixelSource {
// Source buffer
- Buffer buffer;
+ Buffer buffer = Buffer();
// The solid color with which to fill the layer.
// This should only be populated if we don't render from an application
// buffer.
- half3 solidColor;
+ half3 solidColor = half3(0.0f, 0.0f, 0.0f);
};
// The settings that RenderEngine requires for correctly rendering a Layer.
struct LayerSettings {
// Geometry information
- Geometry geometry;
+ Geometry geometry = Geometry();
// Source pixels for this layer.
- PixelSource source;
+ PixelSource source = PixelSource();
// Alpha option to apply to the source pixels
- half alpha;
+ half alpha = half(0.0);
// Color space describing how the source pixels should be interpreted.
- ui::Dataspace sourceDataspace;
+ ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN;
};
} // namespace renderengine
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index bb7f4df..8eaa2d2 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -39,7 +39,6 @@
namespace android {
-class String8;
class Rect;
class Region;
@@ -76,7 +75,7 @@
virtual void primeCache() const = 0;
// dump the extension strings. always call the base class.
- virtual void dump(String8& result) = 0;
+ virtual void dump(std::string& result) = 0;
virtual bool useNativeFenceSync() const = 0;
virtual bool useWaitSync() const = 0;
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index 65b7c82..051b8b6 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -24,6 +24,7 @@
"librenderengine",
],
shared_libs: [
+ "libbase",
"libcutils",
"libEGL",
"libGLESv2",
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index a4d0dd1..956465c 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -26,7 +26,6 @@
"-Werror",
],
cppflags: [
- "-std=c++1z",
"-Weverything",
// The static constructors and destructors in this library have not been noted to
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index e747ee1..3816c1b 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -61,6 +61,16 @@
// to use Binder.
static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
+using dvr::BufferHubDefs::AnyClientAcquired;
+using dvr::BufferHubDefs::AnyClientGained;
+using dvr::BufferHubDefs::AnyClientPosted;
+using dvr::BufferHubDefs::IsClientAcquired;
+using dvr::BufferHubDefs::IsClientGained;
+using dvr::BufferHubDefs::IsClientPosted;
+using dvr::BufferHubDefs::IsClientReleased;
+using dvr::BufferHubDefs::kHighBitsMask;
+using dvr::BufferHubDefs::kMetadataHeaderSize;
+
} // namespace
BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
@@ -71,7 +81,7 @@
BufferHubClient::~BufferHubClient() {}
bool BufferHubClient::IsValid() const {
- return IsConnected() && GetChannelHandle().valid();
+ return IsConnected() && GetChannelHandle().valid();
}
LocalChannelHandle BufferHubClient::TakeChannelHandle() {
@@ -151,11 +161,17 @@
}
size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
- if (metadataSize < dvr::BufferHubDefs::kMetadataHeaderSize) {
+ if (metadataSize < kMetadataHeaderSize) {
ALOGE("BufferHubBuffer::ImportGraphicBuffer: metadata too small: %zu", metadataSize);
return -EINVAL;
}
+ // Populate shortcuts to the atomics in metadata.
+ auto metadata_header = mMetadata.metadata_header();
+ buffer_state_ = &metadata_header->buffer_state;
+ fence_state_ = &metadata_header->fence_state;
+ active_clients_bit_mask_ = &metadata_header->active_clients_bit_mask;
+
// Import the buffer: We only need to hold on the native_handle_t here so that
// GraphicBuffer instance can be created in future.
mBufferHandle = bufferTraits.take_buffer_handle();
@@ -176,7 +192,93 @@
// TODO(b/112012161) Set up shared fences.
ALOGD("BufferHubBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64 ".", id(),
- mMetadata.metadata_header()->buffer_state.load(std::memory_order_acquire));
+ buffer_state_->load(std::memory_order_acquire));
+ return 0;
+}
+
+int BufferHubBuffer::Gain() {
+ uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+ if (IsClientGained(current_buffer_state, mClientStateMask)) {
+ ALOGV("%s: Buffer is already gained by this client %" PRIx64 ".", __FUNCTION__,
+ mClientStateMask);
+ return 0;
+ }
+ do {
+ if (AnyClientGained(current_buffer_state & (~mClientStateMask)) ||
+ AnyClientAcquired(current_buffer_state)) {
+ ALOGE("%s: Buffer is in use, id=%d mClientStateMask=%" PRIx64 " state=%" PRIx64 ".",
+ __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+ return -EBUSY;
+ }
+ // Change the buffer state to gained state, whose value happens to be the same as
+ // mClientStateMask.
+ } while (!buffer_state_->compare_exchange_weak(current_buffer_state, mClientStateMask,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
+ // TODO(b/119837586): Update fence state and return GPU fence.
+ return 0;
+}
+
+int BufferHubBuffer::Post() {
+ uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+ uint64_t current_active_clients_bit_mask = 0ULL;
+ uint64_t updated_buffer_state = 0ULL;
+ do {
+ if (!IsClientGained(current_buffer_state, mClientStateMask)) {
+ ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
+ "mClientStateMask=%" PRIx64 " state=%" PRIx64 ".",
+ __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+ return -EBUSY;
+ }
+ // Set the producer client buffer state to released, other clients' buffer state to posted.
+ current_active_clients_bit_mask = active_clients_bit_mask_->load(std::memory_order_acquire);
+ updated_buffer_state =
+ current_active_clients_bit_mask & (~mClientStateMask) & kHighBitsMask;
+ } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
+ // TODO(b/119837586): Update fence state and return GPU fence if needed.
+ return 0;
+}
+
+int BufferHubBuffer::Acquire() {
+ uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+ if (IsClientAcquired(current_buffer_state, mClientStateMask)) {
+ ALOGV("%s: Buffer is already acquired by this client %" PRIx64 ".", __FUNCTION__,
+ mClientStateMask);
+ return 0;
+ }
+ uint64_t updated_buffer_state = 0ULL;
+ do {
+ if (!IsClientPosted(current_buffer_state, mClientStateMask)) {
+ ALOGE("%s: Cannot acquire a buffer that is not in posted state. buffer_id=%d "
+ "mClientStateMask=%" PRIx64 " state=%" PRIx64 ".",
+ __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+ return -EBUSY;
+ }
+ // Change the buffer state for this consumer from posted to acquired.
+ updated_buffer_state = current_buffer_state ^ mClientStateMask;
+ } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
+ // TODO(b/119837586): Update fence state and return GPU fence.
+ return 0;
+}
+
+int BufferHubBuffer::Release() {
+ uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+ if (IsClientReleased(current_buffer_state, mClientStateMask)) {
+ ALOGV("%s: Buffer is already released by this client %" PRIx64 ".", __FUNCTION__,
+ mClientStateMask);
+ return 0;
+ }
+ uint64_t updated_buffer_state = 0ULL;
+ do {
+ updated_buffer_state = current_buffer_state & (~mClientStateMask);
+ } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
+ // TODO(b/119837586): Update fence state and return GPU fence if needed.
return 0;
}
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 37cf617..20f27c5 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -42,9 +42,6 @@
for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
bits = bits | bit;
}
- // TODO(b/72323293, b/72703005): Remove these additional bits
- bits = bits | (1 << 10) | (1 << 13);
-
return bits;
}();
return valid10UsageBits;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index eaba1ed..f56e6b9 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -24,9 +24,9 @@
#include <grallocusage/GrallocUsageConversion.h>
+#include <android-base/stringprintf.h>
#include <log/log.h>
#include <utils/Singleton.h>
-#include <utils/String8.h>
#include <utils/Trace.h>
#include <ui/Gralloc2.h>
@@ -35,6 +35,8 @@
namespace android {
// ---------------------------------------------------------------------------
+using base::StringAppendF;
+
ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator )
Mutex GraphicBufferAllocator::sLock;
@@ -50,46 +52,37 @@
GraphicBufferAllocator::~GraphicBufferAllocator() {}
-void GraphicBufferAllocator::dump(String8& result) const
-{
+void GraphicBufferAllocator::dump(std::string& result) const {
Mutex::Autolock _l(sLock);
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
size_t total = 0;
- const size_t SIZE = 4096;
- char buffer[SIZE];
- snprintf(buffer, SIZE, "Allocated buffers:\n");
- result.append(buffer);
+ result.append("Allocated buffers:\n");
const size_t c = list.size();
for (size_t i=0 ; i<c ; i++) {
const alloc_rec_t& rec(list.valueAt(i));
if (rec.size) {
- snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64
- " | %s\n",
- list.keyAt(i), rec.size/1024.0,
- rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
- rec.usage, rec.requestorName.c_str());
+ StringAppendF(&result,
+ "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 " | %s\n",
+ list.keyAt(i), rec.size / 1024.0, rec.width, rec.stride, rec.height,
+ rec.layerCount, rec.format, rec.usage, rec.requestorName.c_str());
} else {
- snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64
- " | %s\n",
- list.keyAt(i),
- rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
- rec.usage, rec.requestorName.c_str());
+ StringAppendF(&result,
+ "%10p: unknown | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 " | %s\n",
+ list.keyAt(i), rec.width, rec.stride, rec.height, rec.layerCount,
+ rec.format, rec.usage, rec.requestorName.c_str());
}
- result.append(buffer);
total += rec.size;
}
- snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0);
- result.append(buffer);
+ StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", total / 1024.0);
- std::string deviceDump = mAllocator->dumpDebugInfo();
- result.append(deviceDump.c_str(), deviceDump.size());
+ result.append(mAllocator->dumpDebugInfo());
}
void GraphicBufferAllocator::dumpToSystemLog()
{
- String8 s;
+ std::string s;
GraphicBufferAllocator::getInstance().dump(s);
- ALOGD("%s", s.string());
+ ALOGD("%s", s.c_str());
}
status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
@@ -108,6 +101,9 @@
if (layerCount < 1)
layerCount = 1;
+ // TODO(b/72323293, b/72703005): Remove these invalid bits from callers
+ usage &= ~static_cast<uint64_t>((1 << 10) | (1 << 13));
+
Gralloc2::IMapper::BufferDescriptorInfo info = {};
info.width = width;
info.height = height;
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index 045db31..13fed3a 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -72,11 +72,11 @@
return *this;
}
-Rect& Rect::inset(int32_t left, int32_t top, int32_t right, int32_t bottom) {
- this->left += left;
- this->top += top;
- this->right -= right;
- this->bottom -= bottom;
+Rect& Rect::inset(int32_t _left, int32_t _top, int32_t _right, int32_t _bottom) {
+ this->left += _left;
+ this->top += _top;
+ this->right -= _right;
+ this->bottom -= _bottom;
return *this;
}
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 618c7d6..3bd3748 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -19,8 +19,9 @@
#include <inttypes.h>
#include <limits.h>
+#include <android-base/stringprintf.h>
+
#include <utils/Log.h>
-#include <utils/String8.h>
#include <utils/CallStack.h>
#include <ui/Rect.h>
@@ -41,6 +42,8 @@
namespace android {
// ----------------------------------------------------------------------------
+using base::StringAppendF;
+
enum {
op_nand = region_operator<Rect>::op_nand,
op_and = region_operator<Rect>::op_and,
@@ -868,16 +871,14 @@
// ----------------------------------------------------------------------------
-void Region::dump(String8& out, const char* what, uint32_t /* flags */) const
-{
+void Region::dump(std::string& out, const char* what, uint32_t /* flags */) const {
const_iterator head = begin();
const_iterator const tail = end();
- out.appendFormat(" Region %s (this=%p, count=%" PRIdPTR ")\n",
- what, this, tail - head);
+ StringAppendF(&out, " Region %s (this=%p, count=%" PRIdPTR ")\n", what, this, tail - head);
while (head != tail) {
- out.appendFormat(" [%3d, %3d, %3d, %3d]\n", head->left, head->top,
- head->right, head->bottom);
+ StringAppendF(&out, " [%3d, %3d, %3d, %3d]\n", head->left, head->top, head->right,
+ head->bottom);
++head;
}
}
diff --git a/libs/ui/UiConfig.cpp b/libs/ui/UiConfig.cpp
index 7730690..0ac863d 100644
--- a/libs/ui/UiConfig.cpp
+++ b/libs/ui/UiConfig.cpp
@@ -18,8 +18,7 @@
namespace android {
-void appendUiConfigString(String8& configStr)
-{
+void appendUiConfigString(std::string& configStr) {
static const char* config =
" [libui]";
configStr.append(config);
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 6850b43..03d10e7 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -103,6 +103,27 @@
// to read from and/or write into.
bool IsValid() const { return mBufferHandle.IsValid(); }
+ // Gains the buffer for exclusive write permission. Read permission is implied once a buffer is
+ // gained.
+ // The buffer can be gained as long as there is no other client in acquired or gained state.
+ int Gain();
+
+ // Posts the gained buffer for other buffer clients to use the buffer.
+ // The buffer can be posted iff the buffer state for this client is gained.
+ // After posting the buffer, this client is put to released state and does not have access to
+ // the buffer for this cycle of the usage of the buffer.
+ int Post();
+
+ // Acquires the buffer for shared read permission.
+ // The buffer can be acquired iff the buffer state for this client is posted.
+ int Acquire();
+
+ // Releases the buffer.
+ // The buffer can be released from any buffer state.
+ // After releasing the buffer, this client no longer have any permissions to the buffer for the
+ // current cycle of the usage of the buffer.
+ int Release();
+
// Returns the event mask for all the events that are pending on this buffer (see sys/poll.h for
// all possible bits).
pdx::Status<int> GetEventMask(int events) {
@@ -130,6 +151,9 @@
// Global id for the buffer that is consistent across processes.
int mId = -1;
+
+ // Client state mask of this BufferHubBuffer object. It is unique amoung all
+ // clients/users of the buffer.
uint64_t mClientStateMask = 0;
// Stores ground truth of the buffer.
@@ -141,6 +165,10 @@
// An ashmem-based metadata object. The same shared memory are mapped to the
// bufferhubd daemon and all buffer clients.
BufferHubMetadata mMetadata;
+ // Shortcuts to the atomics inside the header of mMetadata.
+ std::atomic<uint64_t>* buffer_state_{nullptr};
+ std::atomic<uint64_t>* fence_state_{nullptr};
+ std::atomic<uint64_t>* active_clients_bit_mask_{nullptr};
// PDX backend.
BufferHubClient mClient;
diff --git a/libs/ui/include/ui/DisplayedFrameStats.h b/libs/ui/include/ui/DisplayedFrameStats.h
new file mode 100644
index 0000000..7a70ea1
--- /dev/null
+++ b/libs/ui/include/ui/DisplayedFrameStats.h
@@ -0,0 +1,41 @@
+/*
+ * 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 <vector>
+
+namespace android {
+
+struct DisplayedFrameStats {
+ /* The number of frames represented by this sample. */
+ uint64_t numFrames = 0;
+ /* A histogram counting how many times a pixel of a given value was displayed onscreen for
+ * FORMAT_COMPONENT_0. The buckets of the histogram are evenly weighted, the number of buckets
+ * is device specific. eg, for RGBA_8888, if sampleComponent0 is {10, 6, 4, 1} this means that
+ * 10 red pixels were displayed onscreen in range 0x00->0x3F, 6 red pixels
+ * were displayed onscreen in range 0x40->0x7F, etc.
+ */
+ std::vector<uint64_t> component_0_sample = {};
+ /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_1. */
+ std::vector<uint64_t> component_1_sample = {};
+ /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_2. */
+ std::vector<uint64_t> component_2_sample = {};
+ /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_3. */
+ std::vector<uint64_t> component_3_sample = {};
+};
+
+} // namespace android
diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
index 14a865e..7e2b230 100644
--- a/libs/ui/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -39,7 +39,6 @@
}
class GraphicBufferMapper;
-class String8;
class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
{
@@ -53,7 +52,7 @@
status_t free(buffer_handle_t handle);
- void dump(String8& res) const;
+ void dump(std::string& res) const;
static void dumpToSystemLog();
private:
diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h
index 9edb510..e9da087 100644
--- a/libs/ui/include/ui/Rect.h
+++ b/libs/ui/include/ui/Rect.h
@@ -178,7 +178,7 @@
/**
* Insets the rectangle on all sides specified by the insets.
*/
- Rect& inset(int32_t left, int32_t top, int32_t right, int32_t bottom);
+ Rect& inset(int32_t _left, int32_t _top, int32_t _right, int32_t _bottom);
bool intersect(const Rect& with, Rect* result) const;
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 0a09960..79642ae 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -27,12 +27,11 @@
#include <android-base/macros.h>
+#include <string>
+
namespace android {
// ---------------------------------------------------------------------------
-class String8;
-
-// ---------------------------------------------------------------------------
class Region : public LightFlattenable<Region>
{
public:
@@ -144,8 +143,8 @@
status_t flatten(void* buffer, size_t size) const;
status_t unflatten(void const* buffer, size_t size);
- void dump(String8& out, const char* what, uint32_t flags=0) const;
- void dump(const char* what, uint32_t flags=0) const;
+ void dump(std::string& out, const char* what, uint32_t flags=0) const;
+ void dump(const char* what, uint32_t flags=0) const;
private:
class rasterizer;
diff --git a/libs/ui/include/ui/UiConfig.h b/libs/ui/include/ui/UiConfig.h
index fcf8ed5..d1d6014 100644
--- a/libs/ui/include/ui/UiConfig.h
+++ b/libs/ui/include/ui/UiConfig.h
@@ -17,12 +17,12 @@
#ifndef ANDROID_UI_CONFIG_H
#define ANDROID_UI_CONFIG_H
-#include <utils/String8.h>
+#include <string>
namespace android {
// Append the libui configuration details to configStr.
-void appendUiConfigString(String8& configStr);
+void appendUiConfigString(std::string& configStr);
}; // namespace android
diff --git a/libs/ui/include_vndk/ui/DisplayedFrameStats.h b/libs/ui/include_vndk/ui/DisplayedFrameStats.h
new file mode 120000
index 0000000..6014e19
--- /dev/null
+++ b/libs/ui/include_vndk/ui/DisplayedFrameStats.h
@@ -0,0 +1 @@
+../../include/ui/DisplayedFrameStats.h
\ No newline at end of file
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index fcc6d37..18bbb3e 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -74,7 +74,12 @@
cc_test {
name: "BufferHubMetadata_test",
header_libs: ["libbufferhub_headers", "libdvr_headers"],
- shared_libs: ["libpdx_default_transport", "libui", "libutils"],
+ shared_libs: [
+ "libbase",
+ "libpdx_default_transport",
+ "libui",
+ "libutils",
+ ],
srcs: ["BufferHubMetadata_test.cpp"],
cflags: ["-Wall", "-Werror"],
}
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 6c7d06b..e33acf6 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -36,7 +36,14 @@
const int kUsage = 0;
const size_t kUserMetadataSize = 0;
+using dvr::BufferHubDefs::AnyClientAcquired;
+using dvr::BufferHubDefs::AnyClientGained;
+using dvr::BufferHubDefs::AnyClientPosted;
using dvr::BufferHubDefs::IsBufferReleased;
+using dvr::BufferHubDefs::IsClientAcquired;
+using dvr::BufferHubDefs::IsClientGained;
+using dvr::BufferHubDefs::IsClientPosted;
+using dvr::BufferHubDefs::IsClientReleased;
using dvr::BufferHubDefs::kFirstClientBitMask;
using dvr::BufferHubDefs::kMetadataHeaderSize;
using frameworks::bufferhub::V1_0::BufferHubStatus;
@@ -48,9 +55,40 @@
using pdx::LocalChannelHandle;
class BufferHubBufferTest : public ::testing::Test {
+protected:
void SetUp() override { android::hardware::ProcessState::self()->startThreadPool(); }
};
+class BufferHubBufferStateTransitionTest : public BufferHubBufferTest {
+protected:
+ void SetUp() override {
+ BufferHubBufferTest::SetUp();
+ CreateTwoClientsOfABuffer();
+ }
+
+ std::unique_ptr<BufferHubBuffer> b1;
+ uint64_t b1ClientMask = 0ULL;
+ std::unique_ptr<BufferHubBuffer> b2;
+ uint64_t b2ClientMask = 0ULL;
+
+private:
+ // Creates b1 and b2 as the clients of the same buffer for testing.
+ void CreateTwoClientsOfABuffer();
+};
+
+void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() {
+ b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
+ b1ClientMask = b1->client_state_mask();
+ ASSERT_NE(b1ClientMask, 0ULL);
+ auto statusOrHandle = b1->Duplicate();
+ ASSERT_TRUE(statusOrHandle);
+ LocalChannelHandle h2 = statusOrHandle.take();
+ b2 = BufferHubBuffer::Import(std::move(h2));
+ b2ClientMask = b2->client_state_mask();
+ ASSERT_NE(b2ClientMask, 0ULL);
+ ASSERT_NE(b2ClientMask, b1ClientMask);
+}
+
TEST_F(BufferHubBufferTest, CreateBufferHubBufferFails) {
// Buffer Creation will fail: BLOB format requires height to be 1.
auto b1 = BufferHubBuffer::Create(kWidth, /*height=*/2, kLayerCount,
@@ -315,5 +353,180 @@
EXPECT_EQ(nullptr, client2.get());
}
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) {
+ ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+ // Successful gaining the buffer should change the buffer state bit of b1 to
+ // gained state, other client state bits to released state.
+ EXPECT_EQ(b1->Gain(), 0);
+ EXPECT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromGainedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ auto current_buffer_state = b1->buffer_state();
+ ASSERT_TRUE(IsClientGained(current_buffer_state, b1ClientMask));
+
+ // Gaining from gained state by the same client should not return error.
+ EXPECT_EQ(b1->Gain(), 0);
+
+ // Gaining from gained state by another client should return error.
+ EXPECT_EQ(b2->Gain(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromAcquiredState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_EQ(b2->Acquire(), 0);
+ ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+
+ // Gaining from acquired state should fail.
+ EXPECT_EQ(b1->Gain(), -EBUSY);
+ EXPECT_EQ(b2->Gain(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromOtherClientInPostedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+ // Gaining a buffer who has other posted client should succeed.
+ EXPECT_EQ(b1->Gain(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromSelfInPostedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+ // A posted client should be able to gain the buffer when there is no other clients in
+ // acquired state.
+ EXPECT_EQ(b2->Gain(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromOtherInGainedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+
+ EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromSelfInGainedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+
+ EXPECT_EQ(b1->Post(), 0);
+ auto current_buffer_state = b1->buffer_state();
+ EXPECT_TRUE(IsClientReleased(current_buffer_state, b1ClientMask));
+ EXPECT_TRUE(IsClientPosted(current_buffer_state, b2ClientMask));
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromPostedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+ // Post from posted state should fail.
+ EXPECT_EQ(b1->Post(), -EBUSY);
+ EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromAcquiredState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_EQ(b2->Acquire(), 0);
+ ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+
+ // Posting from acquired state should fail.
+ EXPECT_EQ(b1->Post(), -EBUSY);
+ EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromReleasedState) {
+ ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+ // Posting from released state should fail.
+ EXPECT_EQ(b1->Post(), -EBUSY);
+ EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInPostedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask));
+
+ // Acquire from posted state should pass.
+ EXPECT_EQ(b2->Acquire(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromOtherInPostedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask));
+
+ // Acquire from released state should fail, although there are other clients
+ // in posted state.
+ EXPECT_EQ(b1->Acquire(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInAcquiredState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_EQ(b2->Acquire(), 0);
+ auto current_buffer_state = b1->buffer_state();
+ ASSERT_TRUE(IsClientAcquired(current_buffer_state, b2ClientMask));
+
+ // Acquiring from acquired state by the same client should not error out.
+ EXPECT_EQ(b2->Acquire(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromReleasedState) {
+ ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+ // Acquiring form released state should fail.
+ EXPECT_EQ(b1->Acquire(), -EBUSY);
+ EXPECT_EQ(b2->Acquire(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromGainedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_TRUE(AnyClientGained(b1->buffer_state()));
+
+ // Acquiring from gained state should fail.
+ EXPECT_EQ(b1->Acquire(), -EBUSY);
+ EXPECT_EQ(b2->Acquire(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInReleasedState) {
+ ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+ EXPECT_EQ(b1->Release(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInGainedState) {
+ ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_TRUE(AnyClientGained(b1->buffer_state()));
+
+ EXPECT_EQ(b1->Release(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInPostedState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+ EXPECT_EQ(b2->Release(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInAcquiredState) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_EQ(b2->Acquire(), 0);
+ ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+
+ EXPECT_EQ(b2->Release(), 0);
+}
+
} // namespace
} // namespace android
diff --git a/libs/ui/tests/BufferHubEventFd_test.cpp b/libs/ui/tests/BufferHubEventFd_test.cpp
index 8e61c68..92fb33f 100644
--- a/libs/ui/tests/BufferHubEventFd_test.cpp
+++ b/libs/ui/tests/BufferHubEventFd_test.cpp
@@ -19,14 +19,14 @@
#include <sys/epoll.h>
#include <sys/eventfd.h>
-#include <hidl/ServiceManagement.h>
-#include <hwbinder/IPCThreadState.h>
+#include <array>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <log/log.h>
#include <ui/BufferHubEventFd.h>
namespace android {
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 43ac79e..fa92830 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -22,14 +22,12 @@
"buffer_hub_base.cpp",
"buffer_hub_rpc.cpp",
"consumer_buffer.cpp",
- "buffer_client_impl.cpp",
"ion_buffer.cpp",
"producer_buffer.cpp",
]
sharedLibraries = [
"libbase",
- "libbinder",
"libcutils",
"libhardware",
"liblog",
diff --git a/libs/vr/libbufferhub/buffer_client_impl.cpp b/libs/vr/libbufferhub/buffer_client_impl.cpp
deleted file mode 100644
index efa9c28..0000000
--- a/libs/vr/libbufferhub/buffer_client_impl.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include <log/log.h>
-#include <private/dvr/IBufferClient.h>
-
-namespace android {
-namespace dvr {
-
-class BpBufferClient : public BpInterface<IBufferClient> {
- public:
- explicit BpBufferClient(const sp<IBinder>& impl)
- : BpInterface<IBufferClient>(impl) {}
-
- bool isValid() override;
-
- status_t duplicate(uint64_t* outToken) override;
-};
-
-IMPLEMENT_META_INTERFACE(BufferClient, "android.dvr.IBufferClient");
-
-// Transaction code
-enum {
- IS_VALID = IBinder::FIRST_CALL_TRANSACTION,
- DUPLICATE,
-};
-
-bool BpBufferClient::isValid() {
- Parcel data, reply;
- status_t ret =
- data.writeInterfaceToken(IBufferClient::getInterfaceDescriptor());
- if (ret != OK) {
- ALOGE("BpBufferClient::isValid: failed to write into parcel; errno=%d",
- ret);
- return false;
- }
-
- ret = remote()->transact(IS_VALID, data, &reply);
- if (ret == OK) {
- return reply.readBool();
- } else {
- ALOGE("BpBufferClient::isValid: failed to transact; errno=%d", ret);
- return false;
- }
-}
-
-status_t BpBufferClient::duplicate(uint64_t* outToken) {
- Parcel data, reply;
- status_t ret =
- data.writeInterfaceToken(IBufferClient::getInterfaceDescriptor());
- if (ret != OK) {
- ALOGE("BpBufferClient::duplicate: failed to write into parcel; errno=%d",
- ret);
- return ret;
- }
-
- ret = remote()->transact(DUPLICATE, data, &reply);
- if (ret == OK) {
- *outToken = reply.readUint64();
- return OK;
- } else {
- ALOGE("BpBufferClient::duplicate: failed to transact; errno=%d", ret);
- return ret;
- }
-}
-
-status_t BnBufferClient::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags) {
- switch (code) {
- case IS_VALID: {
- CHECK_INTERFACE(IBufferClient, data, reply);
- return reply->writeBool(isValid());
- }
- case DUPLICATE: {
- CHECK_INTERFACE(IBufferClient, data, reply);
- uint64_t token = 0;
- status_t ret = duplicate(&token);
- if (ret != OK) {
- return ret;
- }
- return reply->writeUint64(token);
- }
- default:
- // Should not reach except binder defined transactions such as dumpsys
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file
diff --git a/libs/vr/libbufferhub/include/private/dvr/IBufferClient.h b/libs/vr/libbufferhub/include/private/dvr/IBufferClient.h
deleted file mode 100644
index 31bf79d..0000000
--- a/libs/vr/libbufferhub/include/private/dvr/IBufferClient.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef ANDROID_DVR_IBUFFERCLIENT_H
-#define ANDROID_DVR_IBUFFERCLIENT_H
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-namespace dvr {
-
-// Interface for acessing BufferHubBuffer remotely.
-class IBufferClient : public IInterface {
- public:
- DECLARE_META_INTERFACE(BufferClient);
-
- // Checks if the buffer node is valid.
- virtual bool isValid() = 0;
-
- // Duplicates the client. Token_out will be set to a new token when succeed,
- // and not changed when failed.
- virtual status_t duplicate(uint64_t* outToken) = 0;
-};
-
-// BnInterface for IBufferClient. Should only be created in bufferhub service.
-class BnBufferClient : public BnInterface<IBufferClient> {
- public:
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_IBUFFERCLIENT_H
\ No newline at end of file
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index de03fad..cd92b62 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -224,15 +224,17 @@
uint64_t current_fence_state = fence_state_->load(std::memory_order_acquire);
uint64_t current_active_clients_bit_mask =
active_clients_bit_mask_->load(std::memory_order_acquire);
- // If there is an release fence from consumer, we need to return it.
+ // If there are release fence(s) from consumer(s), we need to return it to the
+ // consumer(s).
// TODO(b/112007999) add an atomic variable in metadata header in shared
// memory to indicate which client is the last producer of the buffer.
// Currently, assume the first client is the only producer to the buffer.
if (current_fence_state & current_active_clients_bit_mask &
(~BufferHubDefs::kFirstClientBitMask)) {
*out_fence = shared_release_fence_.Duplicate();
- out_meta->release_fence_mask =
- current_fence_state & current_active_clients_bit_mask;
+ out_meta->release_fence_mask = current_fence_state &
+ current_active_clients_bit_mask &
+ (~BufferHubDefs::kFirstClientBitMask);
}
return 0;
diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp
index 9a1d2e5..c884cb3 100644
--- a/libs/vr/libvrflinger/tests/Android.bp
+++ b/libs/vr/libvrflinger/tests/Android.bp
@@ -32,7 +32,6 @@
"-Wall",
"-Werror",
],
- cppflags: ["-std=c++1z"],
name: "vrflinger_test",
// TODO(b/117568153): Temporarily opt out using libcrt.
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index ad4ffd7..501bf58 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -28,17 +28,17 @@
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/*
-** This header is generated from the Khronos OpenGL / OpenGL ES XML
-** API Registry. The current version of the Registry, generator scripts
+** This header is generated from the Khronos EGL XML API Registry.
+** The current version of the Registry, generator scripts
** used to make the header, and the header can be found at
** http://www.khronos.org/registry/egl
**
-** Khronos $Git commit SHA1: bae3518c48 $ on $Git commit date: 2018-05-17 10:56:57 -0700 $
+** Khronos $Git commit SHA1: 726475c203 $ on $Git commit date: 2018-10-03 23:51:49 -0700 $
*/
#include <EGL/eglplatform.h>
-#define EGL_EGLEXT_VERSION 20180517
+#define EGL_EGLEXT_VERSION 20181204
/* Generated C header for:
* API: egl
@@ -681,6 +681,7 @@
#ifndef EGL_EXT_device_drm
#define EGL_EXT_device_drm 1
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
+#define EGL_DRM_MASTER_FD_EXT 0x333C
#endif /* EGL_EXT_device_drm */
#ifndef EGL_EXT_device_enumeration
@@ -716,6 +717,11 @@
#define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
#endif /* EGL_EXT_gl_colorspace_display_p3_linear */
+#ifndef EGL_EXT_gl_colorspace_display_p3_passthrough
+#define EGL_EXT_gl_colorspace_display_p3_passthrough 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT 0x3490
+#endif /* EGL_EXT_gl_colorspace_display_p3_passthrough */
+
#ifndef EGL_EXT_gl_colorspace_scrgb
#define EGL_EXT_gl_colorspace_scrgb 1
#define EGL_GL_COLORSPACE_SCRGB_EXT 0x3351
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 6edadcd..50e30c2 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -41,6 +41,12 @@
extern "C" {
android_namespace_t* android_get_exported_namespace(const char*);
+ typedef enum ANGLEPreference {
+ ANGLE_PREFER_DEFAULT = 0,
+ ANGLE_PREFER_NATIVE = 1,
+ ANGLE_PREFER_ANGLE = 2,
+ } ANGLEPreference;
+
// TODO(ianelliott@): Get the following from an ANGLE header:
// Version-1 API:
typedef bool (*fpANGLEGetUtilityAPI)(unsigned int* versionToUse);
@@ -524,6 +530,17 @@
return nullptr;
}
+static ANGLEPreference getAngleDevOption(const char* devOption) {
+ if (devOption == nullptr)
+ return ANGLE_PREFER_DEFAULT;
+
+ if (strcmp(devOption, "angle") == 0) {
+ return ANGLE_PREFER_ANGLE;
+ } else if (strcmp(devOption, "native") == 0) {
+ return ANGLE_PREFER_NATIVE;
+ }
+ return ANGLE_PREFER_DEFAULT;
+}
static bool check_angle_rules(void* so, const char* app_name) {
bool use_angle = false;
@@ -646,15 +663,19 @@
char prop[PROPERTY_VALUE_MAX];
const char* app_name = android::GraphicsEnv::getInstance().getAngleAppName();
- bool developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn();
+ const char* developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn();
// Determine whether or not to use ANGLE:
- bool use_angle = developer_opt_in;
+ ANGLEPreference developer_option = getAngleDevOption(developer_opt_in);
+ bool use_angle = (developer_option == ANGLE_PREFER_ANGLE);
if (use_angle) {
ALOGV("User set \"Developer Options\" to force the use of ANGLE");
} else if (cnx->angleDecided) {
use_angle = cnx->useAngle;
+ } else if (developer_option == ANGLE_PREFER_NATIVE) {
+ ALOGV("User set \"Developer Options\" to force the use of Native");
+ use_angle = false;
} 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:
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 4433af0..c100db7 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -378,7 +378,8 @@
if (wideColorBoardConfig && hasColorSpaceSupport) {
mExtensionString.append(
"EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear "
- "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 ");
+ "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 "
+ "EGL_EXT_gl_colorspace_display_p3_passthrough ");
}
bool hasHdrBoardConfig =
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 547a669..4ebd8bd 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -466,6 +466,8 @@
return HAL_DATASPACE_DISPLAY_P3;
} else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
return HAL_DATASPACE_DISPLAY_P3_LINEAR;
+ } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT) {
+ return HAL_DATASPACE_DISPLAY_P3;
} else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) {
return HAL_DATASPACE_V0_SCRGB;
} else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
@@ -510,6 +512,9 @@
if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_linear")) {
colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
}
+ if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_passthrough")) {
+ colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT);
+ }
return colorSpaces;
}
@@ -527,6 +532,7 @@
case EGL_GL_COLORSPACE_LINEAR_KHR:
case EGL_GL_COLORSPACE_SRGB_KHR:
case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+ case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
case EGL_GL_COLORSPACE_SCRGB_EXT:
case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 459b135..cca91c3 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -217,6 +217,7 @@
// Test that display-p3 extensions exist
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
// Use 8-bit to keep forcus on Display-P3 aspect
EGLint attrs[] = {
@@ -289,6 +290,59 @@
EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
}
+TEST_F(EGLTest, EGLDisplayP3Passthrough) {
+ EGLConfig config;
+ EGLBoolean success;
+
+ if (!hasWideColorDisplay) {
+ // skip this test if device does not have wide-color display
+ std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
+ return;
+ }
+
+ // Test that display-p3 extensions exist
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
+
+ get8BitConfig(config);
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+ EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT,
+ EGL_NONE, EGL_NONE
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ android_dataspace dataspace =
+ static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
+ ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
+
+ EGLint value;
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT, value);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
TEST_F(EGLTest, EGLDisplayP31010102) {
EGLint numConfigs;
EGLConfig config;
@@ -303,6 +357,7 @@
// Test that display-p3 extensions exist
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
// Use 8-bit to keep forcus on Display-P3 aspect
EGLint attrs[] = {
diff --git a/opengl/tests/lib/include/EGLUtils.h b/opengl/tests/lib/include/EGLUtils.h
index eb9571d..cfa378f 100644
--- a/opengl/tests/lib/include/EGLUtils.h
+++ b/opengl/tests/lib/include/EGLUtils.h
@@ -280,6 +280,8 @@
return String8("EGL_GL_COLORSPACE_SRGB_KHR");
case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
return String8("EGL_GL_COLORSPACE_DISPLAY_P3_EXT");
+ case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
+ return String8("EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT");
case EGL_GL_COLORSPACE_LINEAR_KHR:
return String8("EGL_GL_COLORSPACE_LINEAR_KHR");
default:
diff --git a/opengl/tools/glgen2/registry/egl.xml b/opengl/tools/glgen2/registry/egl.xml
index 26771e1..8d661ae 100644
--- a/opengl/tools/glgen2/registry/egl.xml
+++ b/opengl/tools/glgen2/registry/egl.xml
@@ -894,6 +894,11 @@
<unused start="0x3481" end="0x348F"/>
</enums>
+ <enums namespace="EGL" start="0x3490" end="0x349F" vendor="EXT" comment="Reserved for Courtney Goeltzenleuchter - Android (gitlab EGL bug 69)">
+ <enum value="0x3490" name="EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"/>
+ <unused start="0x3491" end="0x349F"/>
+ </enums>
+
<!-- Please remember that new enumerant allocations must be obtained by
request to the Khronos API registrar (see comments at the top of this
file) File requests in the Khronos Bugzilla, EGL project, Registry
@@ -903,8 +908,8 @@
<!-- Reservable for future use. To generate a new range, allocate multiples
of 16 starting at the lowest available point in this block. -->
- <enums namespace="EGL" start="0x3490" end="0x3FFF" vendor="KHR" comment="Reserved for future use">
- <unused start="0x3490" end="0x3FFF"/>
+ <enums namespace="EGL" start="0x34A0" end="0x3FFF" vendor="KHR" comment="Reserved for future use">
+ <unused start="0x34A0" end="0x3FFF"/>
</enums>
<enums namespace="EGL" start="0x8F70" end="0x8F7F" vendor="HI" comment="For Mark Callow, Khronos bug 4055. Shared with GL.">
@@ -2250,6 +2255,11 @@
<enum name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
</require>
</extension>
+ <extension name="EGL_EXT_gl_colorspace_display_p3_passthrough" supported="egl">
+ <require>
+ <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"/>
+ </require>
+ </extension>
<extension name="EGL_EXT_image_dma_buf_import" supported="egl">
<require>
<enum name="EGL_LINUX_DMA_BUF_EXT"/>
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 4a8b613..1fbc6bf 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -15,8 +15,6 @@
cc_library_shared {
name: "libinputflinger",
- cpp_std: "c++17",
-
srcs: [
"InputDispatcher.cpp",
"InputManager.cpp",
@@ -60,8 +58,6 @@
cc_library_shared {
name: "libinputreader",
- cpp_std: "c++17",
-
srcs: [
"EventHub.cpp",
"InputReader.cpp",
@@ -100,8 +96,6 @@
cc_library_shared {
name: "libinputflinger_base",
- cpp_std: "c++17",
-
srcs: [
"InputListener.cpp",
"InputReaderBase.cpp",
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 885348e..ac17dca 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1663,11 +1663,17 @@
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
+ sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
+ if (inputChannel == nullptr) {
+ ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
+ return;
+ }
+
inputTargets.push();
const InputWindowInfo* windowInfo = windowHandle->getInfo();
InputTarget& target = inputTargets.editTop();
- target.inputChannel = getInputChannelLocked(windowHandle->getToken());
+ target.inputChannel = inputChannel;
target.flags = targetFlags;
target.xOffset = - windowInfo->frameLeft;
target.yOffset = - windowInfo->frameTop;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 9e748d8..9ba4140 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2638,6 +2638,7 @@
mOrientation = internalViewport->orientation;
}
}
+ getPolicy()->updatePointerDisplay();
bumpGeneration();
}
}
@@ -2783,7 +2784,7 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
- displayId = ADISPLAY_ID_DEFAULT;
+ displayId = mPointerController->getDisplayId();
} else {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
@@ -3601,6 +3602,9 @@
(mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
if (mPointerController == nullptr) {
mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+ getPolicy()->updatePointerDisplay();
+ } else if (viewportChanged) {
+ getPolicy()->updatePointerDisplay();
}
} else {
mPointerController.clear();
@@ -5387,7 +5391,8 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ int32_t displayId = mPointerController->getDisplayId();
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
@@ -6294,6 +6299,7 @@
void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
bool down, bool hovering) {
int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t displayId = mViewport.displayId;
if (mPointerController != nullptr) {
if (down || hovering) {
@@ -6304,13 +6310,14 @@
} else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
}
+ displayId = mPointerController->getDisplayId();
}
if (mPointerSimple.down && !down) {
mPointerSimple.down = false;
// Send up.
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0,
/* deviceTimestamp */ 0,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
@@ -6323,7 +6330,7 @@
mPointerSimple.hovering = false;
// Send hover exit.
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0,
/* deviceTimestamp */ 0,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
@@ -6338,7 +6345,7 @@
mPointerSimple.downTime = when;
// Send down.
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0,
/* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
@@ -6348,7 +6355,7 @@
}
// Send move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0,
/* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
@@ -6362,7 +6369,7 @@
mPointerSimple.hovering = true;
// Send hover enter.
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
mCurrentRawState.buttonState, 0,
/* deviceTimestamp */ 0,
@@ -6373,7 +6380,7 @@
}
// Send hover move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
mCurrentRawState.buttonState, 0,
/* deviceTimestamp */ 0,
@@ -6395,7 +6402,7 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0,
/* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &pointerCoords,
@@ -6457,8 +6464,9 @@
ALOG_ASSERT(false);
}
}
-
- NotifyMotionArgs args(when, getDeviceId(), source, mViewport.displayId, policyFlags,
+ int32_t displayId = mPointerController != nullptr ?
+ mPointerController->getDisplayId() : mViewport.displayId;
+ NotifyMotionArgs args(when, getDeviceId(), source, displayId, policyFlags,
action, actionButton, flags, metaState, buttonState, edgeFlags,
deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
xPrecision, yPrecision, downTime);
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index fe1c50b..5a78df7 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -342,6 +342,9 @@
/* Gets the affine calibration associated with the specified device. */
virtual TouchAffineTransformation getTouchAffineTransformation(
const std::string& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
+
+ /* Update the pointer controller associated with the specified display. */
+ virtual void updatePointerDisplay() = 0;
};
} // namespace android
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index e94dd94..e60b3f4 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -58,6 +58,9 @@
/* Gets the absolute location of the pointer. */
virtual void getPosition(float* outX, float* outY) const = 0;
+ /* Gets the id of the display where the pointer should be shown. */
+ virtual int32_t getDisplayId() const = 0;
+
enum Transition {
// Fade/unfade immediately.
TRANSITION_IMMEDIATE,
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 389a57c..5b275fb 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -2,7 +2,6 @@
cc_test {
name: "inputflinger_tests",
- cpp_std: "c++17",
srcs: [
"InputReader_test.cpp",
"InputDispatcher_test.cpp",
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 04b87d5..b18cae3 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -57,6 +57,7 @@
float mMinX, mMinY, mMaxX, mMaxY;
float mX, mY;
int32_t mButtonState;
+ int32_t mDisplayId;
protected:
virtual ~FakePointerController() { }
@@ -64,7 +65,7 @@
public:
FakePointerController() :
mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0), mX(0), mY(0),
- mButtonState(0) {
+ mButtonState(0), mDisplayId(ADISPLAY_ID_DEFAULT) {
}
void setBounds(float minX, float minY, float maxX, float maxY) {
@@ -75,6 +76,10 @@
mMaxY = maxY;
}
+ void setDisplayId(int32_t displayId) {
+ mDisplayId = displayId;
+ }
+
virtual void setPosition(float x, float y) {
mX = x;
mY = y;
@@ -93,6 +98,10 @@
*outY = mY;
}
+ virtual int32_t getDisplayId() const {
+ return mDisplayId;
+ }
+
private:
virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
*outMinX = mMinX;
@@ -262,6 +271,9 @@
virtual std::string getDeviceAlias(const InputDeviceIdentifier&) {
return "";
}
+
+ virtual void updatePointerDisplay() {
+ }
};
@@ -3127,6 +3139,30 @@
ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
}
+TEST_F(CursorInputMapperTest, Process_ShouldHandleDisplayId) {
+ CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+ addMapperAndConfigure(mapper);
+
+ // Setup PointerController for second display.
+ constexpr int32_t SECOND_DISPLAY_ID = 1;
+ mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+ mFakePointerController->setPosition(100, 200);
+ mFakePointerController->setButtonState(0);
+ mFakePointerController->setDisplayId(SECOND_DISPLAY_ID);
+
+ NotifyMotionArgs args;
+ process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
+ process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20);
+ process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
+ ASSERT_EQ(SECOND_DISPLAY_ID, args.displayId);
+}
+
// --- TouchInputMapperTest ---
@@ -4625,7 +4661,6 @@
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
}
-
// --- MultiTouchInputMapperTest ---
class MultiTouchInputMapperTest : public TouchInputMapperTest {
@@ -6246,4 +6281,30 @@
ASSERT_EQ(DISPLAY_ID, args.displayId);
}
+TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
+ // Setup PointerController for second display.
+ sp<FakePointerController> fakePointerController = new FakePointerController();
+ fakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+ fakePointerController->setPosition(100, 200);
+ fakePointerController->setButtonState(0);
+ fakePointerController->setDisplayId(SECONDARY_DISPLAY_ID);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ addMapperAndConfigure(mapper);
+
+ // Check source is mouse that would obtain the PointerController.
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
+
+ NotifyMotionArgs motionArgs;
+ processPosition(mapper, 100, 100);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
+ ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
+}
+
} // namespace android
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index f2336cb..9b2cd50 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -467,6 +467,10 @@
size_t eventsToRead = std::min({availableEvents, maxNumEventsToRead, mEventBuffer.size()});
if (eventsToRead > 0) {
if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) {
+ // Notify the Sensors HAL that sensor events have been read. This is required to support
+ // the use of writeBlocking by the Sensors HAL.
+ mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ));
+
for (size_t i = 0; i < eventsToRead; i++) {
convertToSensorEvent(mEventBuffer[i], &buffer[i]);
}
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 8dc80cc..776efab 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -32,8 +32,9 @@
const String16& opPackageName, bool hasSensorAccess)
: mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr),
- mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName),
- mDestroyed(false), mHasSensorAccess(hasSensorAccess) {
+ mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
+ mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false),
+ mHasSensorAccess(hasSensorAccess) {
mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -405,9 +406,6 @@
reAllocateCacheLocked(events, count);
} else {
// The events do not fit within the cache: drop the oldest events.
- ALOGW("Dropping events from cache (%d / %d) to save %d newer events", mCacheSize,
- mMaxCacheSize, count);
-
int freeSpace = mMaxCacheSize - mCacheSize;
// Drop up to the currently cached number of events to make room for new events
@@ -419,6 +417,18 @@
// Determine the number of new events to copy into the cache
int eventsToCopy = std::min(mMaxCacheSize, count);
+ constexpr nsecs_t kMinimumTimeBetweenDropLogNs = 2 * 1000 * 1000 * 1000; // 2 sec
+ if (events[0].timestamp - mTimeOfLastEventDrop > kMinimumTimeBetweenDropLogNs) {
+ ALOGW("Dropping %d cached events (%d/%d) to save %d/%d new events. %d events previously"
+ " dropped", cachedEventsToDrop, mCacheSize, mMaxCacheSize, eventsToCopy,
+ count, mEventsDropped);
+ mEventsDropped = 0;
+ mTimeOfLastEventDrop = events[0].timestamp;
+ } else {
+ // Record the number dropped
+ mEventsDropped += cachedEventsToDrop + newEventsToDrop;
+ }
+
// Check for any flush complete events in the events that will be dropped
countFlushCompleteEventsLocked(mEventCache, cachedEventsToDrop);
countFlushCompleteEventsLocked(events, newEventsToDrop);
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index eefd81a..061809f 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -165,6 +165,8 @@
sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize;
+ int64_t mTimeOfLastEventDrop;
+ int mEventsDropped;
String8 mPackageName;
const String16 mOpPackageName;
#if DEBUG_CONNECTIONS
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 1f71a44..efc2c9f 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -97,10 +97,9 @@
return stateUpdateAvailable;
}
-Rect BufferStateLayer::getCrop(const Layer::State& s) const {
- return (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
- ? GLConsumer::scaleDownCrop(s.crop, s.active.w, s.active.h)
- : s.crop;
+// Crop that applies to the window
+Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const {
+ return Rect::INVALID_RECT;
}
bool BufferStateLayer::setTransform(uint32_t transform) {
@@ -130,6 +129,30 @@
return true;
}
+bool BufferStateLayer::setFrame(const Rect& frame) {
+ int x = frame.left;
+ int y = frame.top;
+ int w = frame.getWidth();
+ int h = frame.getHeight();
+
+ if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y &&
+ mCurrentState.active.w == w && mCurrentState.active.h == h) {
+ return false;
+ }
+
+ if (!frame.isValid()) {
+ x = y = w = h = 0;
+ }
+ mCurrentState.active.transform.set(x, y);
+ mCurrentState.active.w = w;
+ mCurrentState.active.h = h;
+
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer) {
if (mCurrentState.buffer) {
mReleasePreviousBuffer = true;
@@ -239,27 +262,6 @@
return willPresent;
}
-bool BufferStateLayer::setSize(uint32_t w, uint32_t h) {
- if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false;
- mCurrentState.active.w = w;
- mCurrentState.active.h = h;
- mCurrentState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setPosition(float x, float y, bool /*immediate*/) {
- if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y)
- return false;
-
- mCurrentState.active.transform.set(x, y);
-
- mCurrentState.sequence++;
- mCurrentState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
mCurrentState.transparentRegionHint = transparent;
mCurrentState.modified = true;
@@ -267,21 +269,26 @@
return true;
}
-bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix,
- bool allowNonRectPreservingTransforms) {
- ui::Transform t;
- t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
-
- if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
- ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
- return false;
+Rect BufferStateLayer::getBufferSize(const State& s) const {
+ // for buffer state layers we use the display frame size as the buffer size.
+ if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) {
+ return Rect(getActiveWidth(s), getActiveHeight(s));
}
- mCurrentState.sequence++;
- mCurrentState.active.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
- mCurrentState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
+ // if the display frame is not defined, use the parent bounds as the buffer size.
+ const auto& p = mDrawingParent.promote();
+ if (p != nullptr) {
+ Rect parentBounds = Rect(p->computeBounds(Region()));
+ if (!parentBounds.isEmpty()) {
+ return parentBounds;
+ }
+ }
+
+ // if there is no parent layer, use the buffer's bounds as the buffer size
+ if (s.buffer) {
+ return s.buffer->getBounds();
+ }
+ return Rect::INVALID_RECT;
}
// -----------------------------------------------------------------------
@@ -317,8 +324,14 @@
return getDrawingState().dataspace;
}
+// Crop that applies to the buffer
Rect BufferStateLayer::getDrawingCrop() const {
- return Rect::INVALID_RECT;
+ const State& s(getDrawingState());
+
+ if (s.crop.isEmpty() && s.buffer) {
+ return s.buffer->getBounds();
+ }
+ return s.crop;
}
uint32_t BufferStateLayer::getDrawingScalingMode() const {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 315d5af..3f891d3 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -62,6 +62,7 @@
bool setTransform(uint32_t transform) override;
bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
bool setCrop(const Rect& crop) override;
+ bool setFrame(const Rect& frame) override;
bool setBuffer(const sp<GraphicBuffer>& buffer) override;
bool setAcquireFence(const sp<Fence>& fence) override;
bool setDataspace(ui::Dataspace dataspace) override;
@@ -71,18 +72,22 @@
bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
- bool setSize(uint32_t w, uint32_t h) override;
- bool setPosition(float x, float y, bool immediate) override;
- bool setTransparentRegionHint(const Region& transparent) override;
- bool setMatrix(const layer_state_t::matrix22_t& matrix,
- bool allowNonRectPreservingTransforms) override;
-
// Override to ignore legacy layer state properties that are not used by BufferStateLayer
- bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; };
+ bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
+ bool setPosition(float /*x*/, float /*y*/, bool /*immediate*/) override { return false; }
+ bool setTransparentRegionHint(const Region& transparent) override;
+ bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/,
+ bool /*allowNonRectPreservingTransforms*/) override {
+ return false;
+ }
+ bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }
+ bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; }
void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/,
uint64_t /*frameNumber*/) override {}
void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
uint64_t /*frameNumber*/) override {}
+
+ Rect getBufferSize(const State& s) const override;
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/Colorizer.h b/services/surfaceflinger/Colorizer.h
index d56b1c8..b7d61ce 100644
--- a/services/surfaceflinger/Colorizer.h
+++ b/services/surfaceflinger/Colorizer.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_SURFACE_FLINGER_COLORIZER_H
#define ANDROID_SURFACE_FLINGER_COLORIZER_H
-#include <utils/String8.h>
+#include <android-base/stringprintf.h>
namespace android {
@@ -40,19 +40,19 @@
: mEnabled(enabled) {
}
- void colorize(String8& out, color c) {
+ void colorize(std::string& out, color c) {
if (mEnabled) {
- out.appendFormat("\e[%dm", c);
+ base::StringAppendF(&out, "\e[%dm", c);
}
}
- void bold(String8& out) {
+ void bold(std::string& out) {
if (mEnabled) {
out.append("\e[1m");
}
}
- void reset(String8& out) {
+ void reset(std::string& out) {
if (mEnabled) {
out.append("\e[0m");
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 1215bd9..48fd47f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -54,6 +54,7 @@
// retrieve triple buffer setting from configstore
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+using android::base::StringAppendF;
using android::ui::ColorMode;
using android::ui::Dataspace;
using android::ui::Hdr;
@@ -412,10 +413,9 @@
if (mGraphicBuffer == nullptr) {
ALOGE("No buffer is ready for display [%s]", mDisplayName.c_str());
} else {
- int fd = mBufferReady.release();
-
status_t res = mNativeWindow->queueBuffer(mNativeWindow.get(),
- mGraphicBuffer->getNativeBuffer(), fd);
+ mGraphicBuffer->getNativeBuffer(),
+ dup(mBufferReady));
if (res != NO_ERROR) {
ALOGE("Error when queueing buffer for display [%s]: %d", mDisplayName.c_str(), res);
// We risk blocking on dequeueBuffer if the primary display failed
@@ -424,9 +424,12 @@
LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", res);
} else {
mNativeWindow->cancelBuffer(mNativeWindow.get(),
- mGraphicBuffer->getNativeBuffer(), fd);
+ mGraphicBuffer->getNativeBuffer(),
+ dup(mBufferReady));
}
}
+
+ mBufferReady.reset();
mGraphicBuffer = nullptr;
}
}
@@ -715,33 +718,33 @@
mDisplayName.c_str());
}
-void DisplayDevice::dump(String8& result) const {
+void DisplayDevice::dump(std::string& result) const {
const ui::Transform& tr(mGlobalTransform);
ANativeWindow* const window = mNativeWindow.get();
- result.appendFormat("+ %s\n", getDebugName().c_str());
- result.appendFormat(" layerStack=%u, (%4dx%4d), ANativeWindow=%p "
- "format=%d, orient=%2d (type=%08x), flips=%u, isSecure=%d, "
- "powerMode=%d, activeConfig=%d, numLayers=%zu\n",
- mLayerStack, mDisplayWidth, mDisplayHeight, window,
- ANativeWindow_getFormat(window), mOrientation, tr.getType(),
- getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
- mVisibleLayersSortedByZ.size());
- result.appendFormat(" v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
- "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
- mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
- mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left,
- mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0],
- tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
+ StringAppendF(&result, "+ %s\n", getDebugName().c_str());
+ StringAppendF(&result,
+ " layerStack=%u, (%4dx%4d), ANativeWindow=%p "
+ "format=%d, orient=%2d (type=%08x), flips=%u, isSecure=%d, "
+ "powerMode=%d, activeConfig=%d, numLayers=%zu\n",
+ mLayerStack, mDisplayWidth, mDisplayHeight, window,
+ ANativeWindow_getFormat(window), mOrientation, tr.getType(), getPageFlipCount(),
+ mIsSecure, mPowerMode, mActiveConfig, mVisibleLayersSortedByZ.size());
+ StringAppendF(&result,
+ " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
+ "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
+ mViewport.left, mViewport.top, mViewport.right, mViewport.bottom, mFrame.left,
+ mFrame.top, mFrame.right, mFrame.bottom, mScissor.left, mScissor.top,
+ mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0], tr[0][1], tr[1][1],
+ tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
auto const surface = static_cast<Surface*>(window);
ui::Dataspace dataspace = surface->getBuffersDataSpace();
- result.appendFormat(" wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
- mHasWideColorGamut, mHasHdr10, decodeColorMode(mActiveColorMode).c_str(),
- dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(),
- dataspace);
+ StringAppendF(&result, " wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
+ mHasWideColorGamut, mHasHdr10, decodeColorMode(mActiveColorMode).c_str(),
+ dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace);
String8 surfaceDump;
mDisplaySurface->dumpAsString(surfaceDump);
- result.append(surfaceDump);
+ result.append(surfaceDump.string(), surfaceDump.size());
}
// Map dataspace/intent to the best matched dataspace/colorMode/renderIntent
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index eb2c5c3..8357228 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -37,7 +37,6 @@
#include <ui/Transform.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>
-#include <utils/String8.h>
#include <utils/Timers.h>
#include "DisplayHardware/DisplayIdentification.h"
@@ -201,7 +200,7 @@
*/
uint32_t getPageFlipCount() const;
std::string getDebugName() const;
- void dump(String8& result) const;
+ void dump(std::string& result) const;
private:
const sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 3b7ed15..d6237cb 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -1079,6 +1079,31 @@
maxFrames);
}
+Error Composer::getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp,
+ DisplayedFrameStats* outStats) {
+ if (!outStats) {
+ return Error::BAD_PARAMETER;
+ }
+ if (!mClient_2_3) {
+ return Error::UNSUPPORTED;
+ }
+ Error error = kDefaultError;
+ mClient_2_3->getDisplayedContentSample(display, maxFrames, timestamp,
+ [&](const auto tmpError, auto tmpNumFrames,
+ const auto& tmpSamples0, const auto& tmpSamples1,
+ const auto& tmpSamples2, const auto& tmpSamples3) {
+ error = tmpError;
+ if (error == Error::NONE) {
+ outStats->numFrames = tmpNumFrames;
+ outStats->component_0_sample = tmpSamples0;
+ outStats->component_1_sample = tmpSamples1;
+ outStats->component_2_sample = tmpSamples2;
+ outStats->component_3_sample = tmpSamples3;
+ }
+ });
+ return error;
+}
+
CommandReader::~CommandReader()
{
resetData();
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 0db12a1..38ee7ad 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -30,6 +30,7 @@
#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
+#include <ui/DisplayedFrameStats.h>
#include <ui/GraphicBuffer.h>
#include <utils/StrongPointer.h>
@@ -194,6 +195,8 @@
uint8_t* outComponentMask) = 0;
virtual Error setDisplayContentSamplingEnabled(Display display, bool enabled,
uint8_t componentMask, uint64_t maxFrames) = 0;
+ virtual Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp,
+ DisplayedFrameStats* outStats) = 0;
virtual Error getDisplayCapabilities(Display display,
std::vector<DisplayCapability>* outCapabilities) = 0;
};
@@ -400,6 +403,8 @@
uint8_t* outComponentMask) override;
Error setDisplayContentSamplingEnabled(Display display, bool enabled, uint8_t componentMask,
uint64_t maxFrames) override;
+ Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp,
+ DisplayedFrameStats* outStats) override;
Error getDisplayCapabilities(Display display,
std::vector<DisplayCapability>* outCapabilities) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 733a5da..d2aa4ad 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -562,6 +562,12 @@
return static_cast<Error>(intError);
}
+Error Display::getDisplayedContentSample(uint64_t maxFrames, uint64_t timestamp,
+ android::DisplayedFrameStats* outStats) const {
+ auto intError = mComposer.getDisplayedContentSample(mId, maxFrames, timestamp, outStats);
+ return static_cast<Error>(intError);
+}
+
Error Display::getReleaseFences(
std::unordered_map<Layer*, sp<Fence>>* outFences) const
{
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 2d65051..f5cb97e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -40,6 +40,7 @@
#include "PowerAdvisor.h"
namespace android {
+ struct DisplayedFrameStats;
class Fence;
class FloatRect;
class GraphicBuffer;
@@ -243,6 +244,8 @@
[[clang::warn_unused_result]] Error setDisplayContentSamplingEnabled(bool enabled,
uint8_t componentMask,
uint64_t maxFrames) const;
+ [[clang::warn_unused_result]] Error getDisplayedContentSample(
+ uint64_t maxFrames, uint64_t timestamp, android::DisplayedFrameStats* outStats) const;
[[clang::warn_unused_result]] Error getReleaseFences(
std::unordered_map<Layer*,
android::sp<android::Fence>>* outFences) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index b27344d..0497571 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -770,15 +770,25 @@
return NO_ERROR;
}
+status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
+ uint64_t timestamp, DisplayedFrameStats* outStats) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error =
+ mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
+ outStats);
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
bool HWComposer::isUsingVrComposer() const {
return getComposer()->isUsingVrComposer();
}
-void HWComposer::dump(String8& result) const {
+void HWComposer::dump(std::string& result) const {
// TODO: In order to provide a dump equivalent to HWC1, we need to shadow
// all the state going into the layers. This is probably better done in
// Layer itself, but it's going to take a bit of work to get there.
- result.append(mHwcDevice->dump().c_str());
+ result.append(mHwcDevice->dump());
}
std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3f1328e..d9a0916 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -36,8 +36,8 @@
namespace android {
+struct DisplayedFrameStats;
class GraphicBuffer;
-class String8;
class TestableSurfaceFlinger;
struct CompositionInfo;
@@ -133,6 +133,8 @@
uint8_t* outComponentMask);
status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
uint8_t componentMask, uint64_t maxFrames);
+ status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, uint64_t timestamp,
+ DisplayedFrameStats* outStats);
// Events handling ---------------------------------------------------------
@@ -161,7 +163,7 @@
bool isUsingVrComposer() const;
// for debugging ----------------------------------------------------------
- void dump(String8& out) const;
+ void dump(std::string& out) const;
Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index 1539873..f4cc49b 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -19,6 +19,7 @@
#include <inttypes.h>
+#include <android-base/stringprintf.h>
#include <android/log.h>
#include <utils/String8.h>
@@ -230,17 +231,17 @@
mFrameRecords[idx].actualPresentTime < INT64_MAX;
}
-void FrameTracker::dumpStats(String8& result) const {
+void FrameTracker::dumpStats(std::string& result) const {
Mutex::Autolock lock(mMutex);
processFencesLocked();
const size_t o = mOffset;
for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
const size_t index = (o+i) % NUM_FRAME_RECORDS;
- result.appendFormat("%" PRId64 "\t%" PRId64 "\t%" PRId64 "\n",
- mFrameRecords[index].desiredPresentTime,
- mFrameRecords[index].actualPresentTime,
- mFrameRecords[index].frameReadyTime);
+ base::StringAppendF(&result, "%" PRId64 "\t%" PRId64 "\t%" PRId64 "\n",
+ mFrameRecords[index].desiredPresentTime,
+ mFrameRecords[index].actualPresentTime,
+ mFrameRecords[index].frameReadyTime);
}
result.append("\n");
}
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
index b4a9fd6..555dcc1 100644
--- a/services/surfaceflinger/FrameTracker.h
+++ b/services/surfaceflinger/FrameTracker.h
@@ -90,7 +90,7 @@
void logAndResetStats(const String8& name);
// dumpStats dump appends the current frame display time history to the result string.
- void dumpStats(String8& result) const;
+ void dumpStats(std::string& result) const;
private:
struct FrameRecord {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f53ffae..6d0fdad 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -25,6 +25,8 @@
#include <sys/types.h>
#include <algorithm>
+#include <android-base/stringprintf.h>
+
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
@@ -63,6 +65,8 @@
namespace android {
+using base::StringAppendF;
+
std::atomic<int32_t> Layer::sSequence{1};
Layer::Layer(const LayerCreationArgs& args)
@@ -92,8 +96,8 @@
mCurrentState.requested_legacy = mCurrentState.active_legacy;
mCurrentState.appId = 0;
mCurrentState.type = 0;
- mCurrentState.active.w = 0;
- mCurrentState.active.h = 0;
+ mCurrentState.active.w = UINT32_MAX;
+ mCurrentState.active.h = UINT32_MAX;
mCurrentState.active.transform.set(0, 0);
mCurrentState.transform = 0;
mCurrentState.transformToDisplayInverse = false;
@@ -289,8 +293,10 @@
return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
}
-Rect Layer::computeScreenBounds() const {
- FloatRect bounds = computeBounds();
+Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
+ const State& s(getDrawingState());
+ Region transparentRegion = reduceTransparentRegion ? getActiveTransparentRegion(s) : Region();
+ FloatRect bounds = computeBounds(transparentRegion);
ui::Transform t = getTransform();
// Transform to screen space.
bounds = t.transform(bounds);
@@ -500,8 +506,7 @@
// this gives us only the "orientation" component of the transform
const State& s(getDrawingState());
- const int bufferWidth = getBufferSize(s).getWidth();
- const int bufferHeight = getBufferSize(s).getHeight();
+ const Rect bufferSize = getBufferSize(s);
auto blendMode = HWC2::BlendMode::None;
if (!isOpaque(s) || getAlpha() != 1.0f) {
blendMode =
@@ -520,7 +525,7 @@
Region activeTransparentRegion(getActiveTransparentRegion(s));
ui::Transform t = getTransform();
Rect activeCrop = getCrop(s);
- if (!activeCrop.isEmpty()) {
+ if (!activeCrop.isEmpty() && bufferSize.isValid()) {
activeCrop = t.transform(activeCrop);
if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
activeCrop.clear();
@@ -532,15 +537,16 @@
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
- if (!activeCrop.intersect(Rect(bufferWidth, bufferHeight), &activeCrop)) {
+ if (!activeCrop.intersect(bufferSize, &activeCrop)) {
activeCrop.clear();
}
// mark regions outside the crop as transparent
- activeTransparentRegion.orSelf(Rect(0, 0, bufferWidth, activeCrop.top));
- activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, bufferWidth, bufferHeight));
+ activeTransparentRegion.orSelf(Rect(0, 0, bufferSize.getWidth(), activeCrop.top));
+ activeTransparentRegion.orSelf(
+ Rect(0, activeCrop.bottom, bufferSize.getWidth(), bufferSize.getHeight()));
activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
activeTransparentRegion.orSelf(
- Rect(activeCrop.right, activeCrop.top, bufferWidth, activeCrop.bottom));
+ Rect(activeCrop.right, activeCrop.top, bufferSize.getWidth(), activeCrop.bottom));
}
// computeBounds returns a FloatRect to provide more accuracy during the
@@ -1399,7 +1405,7 @@
info.mName = getName();
sp<Layer> parent = getParent();
info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string());
- info.mType = String8(getTypeId());
+ info.mType = std::string(getTypeId());
info.mTransparentRegion = ds.activeTransparentRegion_legacy;
info.mVisibleRegion = visibleRegion;
info.mSurfaceDamageRegion = surfaceDamageRegion;
@@ -1439,7 +1445,7 @@
return info;
}
-void Layer::miniDumpHeader(String8& result) {
+void Layer::miniDumpHeader(std::string& result) {
result.append("-------------------------------");
result.append("-------------------------------");
result.append("-----------------------------\n");
@@ -1454,50 +1460,51 @@
result.append("-----------------------------\n");
}
-void Layer::miniDump(String8& result, DisplayId displayId) const {
+void Layer::miniDump(std::string& result, DisplayId displayId) const {
if (!hasHwcLayer(displayId)) {
return;
}
- String8 name;
+ std::string name;
if (mName.length() > 77) {
std::string shortened;
shortened.append(mName.string(), 36);
shortened.append("[...]");
shortened.append(mName.string() + (mName.length() - 36), 36);
- name = shortened.c_str();
+ name = shortened;
} else {
- name = mName;
+ name = std::string(mName.string(), mName.size());
}
- result.appendFormat(" %s\n", name.string());
+ StringAppendF(&result, " %s\n", name.c_str());
const State& layerState(getDrawingState());
const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId);
if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
- result.appendFormat(" rel %6d | ", layerState.z);
+ StringAppendF(&result, " rel %6d | ", layerState.z);
} else {
- result.appendFormat(" %10d | ", layerState.z);
+ StringAppendF(&result, " %10d | ", layerState.z);
}
- result.appendFormat("%10s | ", to_string(getCompositionType(displayId)).c_str());
- result.appendFormat("%10s | ", to_string(hwcInfo.transform).c_str());
+ StringAppendF(&result, "%10s | ", to_string(getCompositionType(displayId)).c_str());
+ StringAppendF(&result, "%10s | ", to_string(hwcInfo.transform).c_str());
const Rect& frame = hwcInfo.displayFrame;
- result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
+ StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
const FloatRect& crop = hwcInfo.sourceCrop;
- result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom);
+ StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right,
+ crop.bottom);
result.append("- - - - - - - - - - - - - - - -\n");
std::string compositionInfoStr;
getBE().compositionInfo.dump(compositionInfoStr, "compositionInfo");
- result.append(compositionInfoStr.c_str());
+ result.append(compositionInfoStr);
result.append("- - - - - - - - - - - - - - - -");
result.append("- - - - - - - - - - - - - - - -");
result.append("- - - - - - - - - - - - - - -\n");
}
-void Layer::dumpFrameStats(String8& result) const {
+void Layer::dumpFrameStats(std::string& result) const {
mFrameTracker.dumpStats(result);
}
@@ -1513,8 +1520,8 @@
mFrameTracker.getStats(outStats);
}
-void Layer::dumpFrameEvents(String8& result) {
- result.appendFormat("- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this);
+void Layer::dumpFrameEvents(std::string& result) {
+ StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this);
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.checkFencesForCompletion();
mFrameEventHistory.dump(result);
@@ -2150,7 +2157,6 @@
// Position the touchable region relative to frame screen location and restrict it to frame
// bounds.
info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop);
- info.touchableRegion = info.touchableRegion.intersect(frame);
info.visible = isVisible();
return info;
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6ea80c7..7b6709e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -296,6 +296,7 @@
virtual bool setTransform(uint32_t /*transform*/) { return false; };
virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
virtual bool setCrop(const Rect& /*crop*/) { return false; };
+ virtual bool setFrame(const Rect& /*frame*/) { return false; };
virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/) { return false; };
virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; };
@@ -565,10 +566,10 @@
LayerDebugInfo getLayerDebugInfo() const;
/* always call base class first */
- static void miniDumpHeader(String8& result);
- void miniDump(String8& result, DisplayId displayId) const;
- void dumpFrameStats(String8& result) const;
- void dumpFrameEvents(String8& result);
+ static void miniDumpHeader(std::string& result);
+ void miniDump(std::string& result, DisplayId displayId) const;
+ void dumpFrameStats(std::string& result) const;
+ void dumpFrameEvents(std::string& result);
void clearFrameStats();
void logFrameStats();
void getFrameStats(FrameStats* outStats) const;
@@ -616,7 +617,7 @@
ssize_t removeChild(const sp<Layer>& layer);
sp<Layer> getParent() const { return mCurrentParent.promote(); }
bool hasParent() const { return getParent() != nullptr; }
- Rect computeScreenBounds() const;
+ Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
bool setChildRelativeLayer(const sp<Layer>& childLayer,
const sp<IBinder>& relativeToHandle, int32_t relativeZ);
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index 70b00dd..e39babe 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -101,15 +101,8 @@
result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left,
hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
- {
- //
- // Keep a conversion from std::string to String8 and back until Region can use std::string
- //
- String8 regionString;
- hwc.visibleRegion.dump(regionString, "visibleRegion");
- hwc.surfaceDamage.dump(regionString, "surfaceDamage");
- result += regionString.string();
- }
+ hwc.visibleRegion.dump(result, "visibleRegion");
+ hwc.surfaceDamage.dump(result, "surfaceDamage");
result += base::StringPrintf("\tcolor transform matrix:\n"
"\t\t[%f, %f, %f, %f,\n"
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index c0174ae..a2d1feb 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -23,11 +23,13 @@
#include <android-base/stringprintf.h>
#include <log/log.h>
-#include <utils/String8.h>
#include <utils/Trace.h>
namespace android {
+using base::StringAppendF;
+using base::StringPrintf;
+
void LayerStats::enable() {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
@@ -64,26 +66,24 @@
if (!layer) continue;
traverseLayerTreeStatsLocked(layer->children, layerGlobal, outLayerShapeVec);
std::string key = "";
- base::StringAppendF(&key, ",%s", layer->type.c_str());
- 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).c_str());
- base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
- base::StringAppendF(&key, ",%s",
- destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0],
- true));
- base::StringAppendF(&key, ",%s",
- destinationLocation(layer->hwcFrame.top, layerGlobal.resolution[1],
- false));
- base::StringAppendF(&key, ",%s",
- destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
- layerGlobal.resolution[0], true));
- base::StringAppendF(&key, ",%s",
- destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
- layerGlobal.resolution[1], false));
- base::StringAppendF(&key, ",%s", scaleRatioWH(layer).c_str());
- base::StringAppendF(&key, ",%s", alpha(static_cast<float>(layer->color.a)));
+ StringAppendF(&key, ",%s", layer->type.c_str());
+ StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
+ StringAppendF(&key, ",%d", layer->isProtected);
+ StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
+ StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
+ StringAppendF(&key, ",%s", layer->dataspace.c_str());
+ StringAppendF(&key, ",%s",
+ destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0], true));
+ StringAppendF(&key, ",%s",
+ destinationLocation(layer->hwcFrame.top, layerGlobal.resolution[1], false));
+ StringAppendF(&key, ",%s",
+ destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
+ layerGlobal.resolution[0], true));
+ StringAppendF(&key, ",%s",
+ destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
+ layerGlobal.resolution[1], false));
+ StringAppendF(&key, ",%s", scaleRatioWH(layer).c_str());
+ StringAppendF(&key, ",%s", alpha(static_cast<float>(layer->color.a)));
outLayerShapeVec->push_back(key);
ALOGV("%s", key.c_str());
@@ -101,9 +101,9 @@
traverseLayerTreeStatsLocked(layerTree.topLevelLayers, layerGlobal, &layerShapeVec);
std::string layerShapeKey =
- base::StringPrintf("%d,%s,%s,%s", static_cast<int32_t>(layerShapeVec.size()),
- layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(),
- layerTransform(layerGlobal.globalTransform));
+ StringPrintf("%d,%s,%s,%s", static_cast<int32_t>(layerShapeVec.size()),
+ layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(),
+ layerTransform(layerGlobal.globalTransform));
ALOGV("%s", layerShapeKey.c_str());
std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater<std::string>());
@@ -114,7 +114,7 @@
mLayerShapeStatsMap[layerShapeKey]++;
}
-void LayerStats::dump(String8& result) {
+void LayerStats::dump(std::string& result) {
ATRACE_CALL();
ALOGD("Dumping");
std::lock_guard<std::mutex> lock(mMutex);
@@ -122,7 +122,7 @@
result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,");
result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n");
for (auto& u : mLayerShapeStatsMap) {
- result.appendFormat("%u,%s\n", u.second, u.first.c_str());
+ StringAppendF(&result, "%u,%s\n", u.second, u.first.c_str());
}
}
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 9de9cce..62b2688 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -24,7 +24,6 @@
using namespace android::surfaceflinger;
namespace android {
-class String8;
class LayerStats {
public:
@@ -33,7 +32,7 @@
void clear();
bool isEnabled();
void logLayerStats(const LayersProto& layersProto);
- void dump(String8& result);
+ void dump(std::string& result);
private:
// Traverse layer tree to get all visible layers' stats
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 172c418..b74b901 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -24,9 +24,9 @@
#include <algorithm>
-#include <log/log.h>
+#include <android-base/stringprintf.h>
#include <cutils/properties.h>
-#include <utils/String8.h>
+#include <log/log.h>
#include <utils/Thread.h>
#include <utils/Trace.h>
@@ -36,6 +36,7 @@
#include "EventLog/EventLog.h"
#include "SurfaceFlinger.h"
+using android::base::StringAppendF;
using std::max;
using std::min;
@@ -667,54 +668,56 @@
}
}
-void DispSync::dump(String8& result) const {
+void DispSync::dump(std::string& result) const {
Mutex::Autolock lock(mMutex);
- result.appendFormat("present fences are %s\n", mIgnorePresentFences ? "ignored" : "used");
- result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n", mPeriod,
- 1000000000.0 / mPeriod, mRefreshSkipCount);
- result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase);
- result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError));
- result.appendFormat("mNumResyncSamplesSincePresent: %d (limit %d)\n",
- mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT);
- result.appendFormat("mNumResyncSamples: %zd (max %d)\n", mNumResyncSamples, MAX_RESYNC_SAMPLES);
+ StringAppendF(&result, "present fences are %s\n", mIgnorePresentFences ? "ignored" : "used");
+ StringAppendF(&result, "mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n", mPeriod,
+ 1000000000.0 / mPeriod, mRefreshSkipCount);
+ StringAppendF(&result, "mPhase: %" PRId64 " ns\n", mPhase);
+ StringAppendF(&result, "mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError));
+ StringAppendF(&result, "mNumResyncSamplesSincePresent: %d (limit %d)\n",
+ mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT);
+ StringAppendF(&result, "mNumResyncSamples: %zd (max %d)\n", mNumResyncSamples,
+ MAX_RESYNC_SAMPLES);
- result.appendFormat("mResyncSamples:\n");
+ result.append("mResyncSamples:\n");
nsecs_t previous = -1;
for (size_t i = 0; i < mNumResyncSamples; i++) {
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
nsecs_t sampleTime = mResyncSamples[idx];
if (i == 0) {
- result.appendFormat(" %" PRId64 "\n", sampleTime);
+ StringAppendF(&result, " %" PRId64 "\n", sampleTime);
} else {
- result.appendFormat(" %" PRId64 " (+%" PRId64 ")\n", sampleTime,
- sampleTime - previous);
+ StringAppendF(&result, " %" PRId64 " (+%" PRId64 ")\n", sampleTime,
+ sampleTime - previous);
}
previous = sampleTime;
}
- result.appendFormat("mPresentFences [%d]:\n", NUM_PRESENT_SAMPLES);
+ StringAppendF(&result, "mPresentFences [%d]:\n", NUM_PRESENT_SAMPLES);
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
previous = Fence::SIGNAL_TIME_INVALID;
for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES;
nsecs_t presentTime = mPresentFences[idx]->getSignalTime();
if (presentTime == Fence::SIGNAL_TIME_PENDING) {
- result.appendFormat(" [unsignaled fence]\n");
+ StringAppendF(&result, " [unsignaled fence]\n");
} else if (presentTime == Fence::SIGNAL_TIME_INVALID) {
- result.appendFormat(" [invalid fence]\n");
+ StringAppendF(&result, " [invalid fence]\n");
} else if (previous == Fence::SIGNAL_TIME_PENDING ||
previous == Fence::SIGNAL_TIME_INVALID) {
- result.appendFormat(" %" PRId64 " (%.3f ms ago)\n", presentTime,
- (now - presentTime) / 1000000.0);
+ StringAppendF(&result, " %" PRId64 " (%.3f ms ago)\n", presentTime,
+ (now - presentTime) / 1000000.0);
} else {
- result.appendFormat(" %" PRId64 " (+%" PRId64 " / %.3f) (%.3f ms ago)\n", presentTime,
- presentTime - previous, (presentTime - previous) / (double)mPeriod,
- (now - presentTime) / 1000000.0);
+ StringAppendF(&result, " %" PRId64 " (+%" PRId64 " / %.3f) (%.3f ms ago)\n",
+ presentTime, presentTime - previous,
+ (presentTime - previous) / (double)mPeriod,
+ (now - presentTime) / 1000000.0);
}
previous = presentTime;
}
- result.appendFormat("current monotonic time: %" PRId64 "\n", now);
+ StringAppendF(&result, "current monotonic time: %" PRId64 "\n", now);
}
// TODO(b/113612090): Figure out how much of this is still relevant.
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index 5d19093..4a90f10 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -29,7 +29,6 @@
namespace android {
-class String8;
class FenceTime;
class DispSync {
@@ -57,7 +56,7 @@
virtual void setIgnorePresentFences(bool ignore) = 0;
virtual nsecs_t expectedPresentTime() = 0;
- virtual void dump(String8& result) const = 0;
+ virtual void dump(std::string& result) const = 0;
};
namespace impl {
@@ -161,7 +160,7 @@
nsecs_t expectedPresentTime();
// dump appends human-readable debug info to the result string.
- void dump(String8& result) const override;
+ void dump(std::string& result) const override;
private:
void updateModelLocked();
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 9bee9a3..49e7ef6 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -22,18 +22,20 @@
#include <chrono>
#include <cstdint>
+#include <android-base/stringprintf.h>
+
#include <cutils/compiler.h>
#include <cutils/sched_policy.h>
#include <gui/DisplayEventReceiver.h>
#include <utils/Errors.h>
-#include <utils/String8.h>
#include <utils/Trace.h>
#include "EventThread.h"
using namespace std::chrono_literals;
+using android::base::StringAppendF;
// ---------------------------------------------------------------------------
@@ -384,18 +386,18 @@
}
}
-void EventThread::dump(String8& result) const {
+void EventThread::dump(std::string& result) const {
std::lock_guard<std::mutex> lock(mMutex);
- result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled");
- result.appendFormat(" soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled");
- result.appendFormat(" numListeners=%zu,\n events-delivered: %u\n",
- mDisplayEventConnections.size(), mVSyncEvent[0].vsync.count);
+ StringAppendF(&result, "VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled");
+ StringAppendF(&result, " soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled");
+ StringAppendF(&result, " numListeners=%zu,\n events-delivered: %u\n",
+ mDisplayEventConnections.size(), mVSyncEvent[0].vsync.count);
for (const wp<Connection>& weak : mDisplayEventConnections) {
sp<Connection> connection = weak.promote();
- result.appendFormat(" %p: count=%d\n", connection.get(),
- connection != nullptr ? connection->count : 0);
+ StringAppendF(&result, " %p: count=%d\n", connection.get(),
+ connection != nullptr ? connection->count : 0);
}
- result.appendFormat(" other-events-pending: %zu\n", mPendingEvents.size());
+ StringAppendF(&result, " other-events-pending: %zu\n", mPendingEvents.size());
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 5e7ed13..15b5bba 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -40,7 +40,6 @@
class EventThreadTest;
class SurfaceFlinger;
-class String8;
// ---------------------------------------------------------------------------
@@ -76,7 +75,7 @@
// called when receiving a hotplug event
virtual void onHotplugReceived(DisplayType displayType, bool connected) = 0;
- virtual void dump(String8& result) const = 0;
+ virtual void dump(std::string& result) const = 0;
virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
};
@@ -131,7 +130,7 @@
// called when receiving a hotplug event
void onHotplugReceived(DisplayType displayType, bool connected) override;
- void dump(String8& result) const override;
+ void dump(std::string& result) const override;
void setPhaseOffset(nsecs_t phaseOffset) override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 4457f72..5b8cc10 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -133,7 +133,7 @@
mConnections[handle->id]->thread->onScreenReleased();
}
-void Scheduler::dump(const sp<Scheduler::ConnectionHandle>& handle, String8& result) const {
+void Scheduler::dump(const sp<Scheduler::ConnectionHandle>& handle, std::string& result) const {
RETURN_IF_INVALID();
mConnections.at(handle->id)->thread->dump(result);
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 764ad00..ea90824 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -91,7 +91,7 @@
void onScreenReleased(const sp<ConnectionHandle>& handle);
// Should be called when dumpsys command is received.
- void dump(const sp<ConnectionHandle>& handle, String8& result) const;
+ void dump(const sp<ConnectionHandle>& handle, std::string& result) const;
// Offers ability to modify phase offset in the event thread.
void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0bda020..a142928 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -113,6 +113,7 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+using base::StringAppendF;
using ui::ColorMode;
using ui::Dataspace;
using ui::Hdr;
@@ -1145,6 +1146,19 @@
componentMask, maxFrames);
}
+status_t SurfaceFlinger::getDisplayedContentSample(const sp<IBinder>& displayToken,
+ uint64_t maxFrames, uint64_t timestamp,
+ DisplayedFrameStats* outStats) const {
+ const auto display = getDisplayDevice(displayToken);
+ if (!display || !display->getId()) {
+ ALOGE("getDisplayContentSample: Bad display token: %p", displayToken.get());
+ return BAD_VALUE;
+ }
+
+ return getHwComposer().getDisplayedContentSample(*display->getId(), maxFrames, timestamp,
+ outStats);
+}
+
status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
postMessageSync(new LambdaMessage([&] {
Mutex::Autolock _l(mStateLock);
@@ -2753,7 +2767,10 @@
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (layer->hasInput()) {
- inputHandles.add(layer->fillInputInfo(layer->computeScreenBounds()));
+ // When calculating the screen bounds we ignore the transparent region since it may
+ // result in an unwanted offset.
+ inputHandles.add(layer->fillInputInfo(
+ layer->computeScreenBounds(false /* reduceTransparentRegion */)));
}
});
mInputFlinger->setInputWindows(inputHandles);
@@ -3505,7 +3522,7 @@
uint32_t flags = 0;
- const uint32_t what = s.what;
+ const uint64_t what = s.what;
bool geometryAppliesWithResize =
what & layer_state_t::eGeometryAppliesWithResize;
@@ -3677,6 +3694,9 @@
if (what & layer_state_t::eCropChanged) {
if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eFrameChanged) {
+ if (layer->setFrame(s.frame)) flags |= eTraversalNeeded;
+ }
if (what & layer_state_t::eBufferChanged) {
if (layer->setBuffer(s.buffer)) flags |= eTraversalNeeded;
}
@@ -4094,7 +4114,7 @@
status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto)
NO_THREAD_SAFETY_ANALYSIS {
- String8 result;
+ std::string result;
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
@@ -4102,8 +4122,8 @@
if ((uid != AID_SHELL) &&
!PermissionCache::checkPermission(sDump, pid, uid)) {
- result.appendFormat("Permission Denial: "
- "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
+ StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n",
+ pid, uid);
} else {
// Try to get the main lock, but give up after one second
// (this would indicate SF is stuck, but we want to be able to
@@ -4111,9 +4131,10 @@
status_t err = mStateLock.timedLock(s2ns(1));
bool locked = (err == NO_ERROR);
if (!locked) {
- result.appendFormat(
- "SurfaceFlinger appears to be unresponsive (%s [%d]), "
- "dumping anyways (no locks held)\n", strerror(-err), err);
+ StringAppendF(&result,
+ "SurfaceFlinger appears to be unresponsive (%s [%d]), dumping anyways "
+ "(no locks held)\n",
+ strerror(-err), err);
}
bool dumpAll = true;
@@ -4231,21 +4252,18 @@
mStateLock.unlock();
}
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
-void SurfaceFlinger::listLayersLocked(const Vector<String16>& /* args */,
- size_t& /* index */, String8& result) const
-{
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- result.appendFormat("%s\n", layer->getName().string());
- });
+void SurfaceFlinger::listLayersLocked(const Vector<String16>& /* args */, size_t& /* index */,
+ std::string& result) const {
+ mCurrentState.traverseInZOrder(
+ [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getName().string()); });
}
void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
- String8& result) const
-{
+ std::string& result) const {
String8 name;
if (index < args.size()) {
name = String8(args[index]);
@@ -4256,7 +4274,7 @@
displayId && getHwComposer().isConnected(*displayId)) {
const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
const nsecs_t period = activeConfig->getVsyncPeriod();
- result.appendFormat("%" PRId64 "\n", period);
+ StringAppendF(&result, "%" PRId64 "\n", period);
}
if (name.isEmpty()) {
@@ -4271,8 +4289,7 @@
}
void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
- String8& /* result */)
-{
+ std::string& /* result */) {
String8 name;
if (index < args.size()) {
name = String8(args[index]);
@@ -4298,37 +4315,34 @@
mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
}
-void SurfaceFlinger::appendSfConfigString(String8& result) const
-{
+void SurfaceFlinger::appendSfConfigString(std::string& result) const {
result.append(" [sf");
if (isLayerTripleBufferingDisabled())
result.append(" DISABLE_TRIPLE_BUFFERING");
- result.appendFormat(" PRESENT_TIME_OFFSET=%" PRId64 , dispSyncPresentTimeOffset);
- result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
- result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
- result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
- result.appendFormat(" NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
- maxFrameBufferAcquiredBuffers);
+ StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset);
+ StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
+ StringAppendF(&result, " MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
+ StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
+ StringAppendF(&result, " NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
+ maxFrameBufferAcquiredBuffers);
result.append("]");
}
-void SurfaceFlinger::dumpStaticScreenStats(String8& result) const
-{
- result.appendFormat("Static screen stats:\n");
+void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const {
+ result.append("Static screen stats:\n");
for (size_t b = 0; b < SurfaceFlingerBE::NUM_BUCKETS - 1; ++b) {
float bucketTimeSec = getBE().mFrameBuckets[b] / 1e9;
float percent = 100.0f *
static_cast<float>(getBE().mFrameBuckets[b]) / getBE().mTotalTime;
- result.appendFormat(" < %zd frames: %.3f s (%.1f%%)\n",
- b + 1, bucketTimeSec, percent);
+ StringAppendF(&result, " < %zd frames: %.3f s (%.1f%%)\n", b + 1, bucketTimeSec, percent);
}
float bucketTimeSec = getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] / 1e9;
float percent = 100.0f *
static_cast<float>(getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1]) / getBE().mTotalTime;
- result.appendFormat(" %zd+ frames: %.3f s (%.1f%%)\n",
- SurfaceFlingerBE::NUM_BUCKETS - 1, bucketTimeSec, percent);
+ StringAppendF(&result, " %zd+ frames: %.3f s (%.1f%%)\n", SurfaceFlingerBE::NUM_BUCKETS - 1,
+ bucketTimeSec, percent);
}
void SurfaceFlinger::recordBufferingStats(const char* layerName,
@@ -4349,8 +4363,8 @@
}
}
-void SurfaceFlinger::dumpFrameEventsLocked(String8& result) {
- result.appendFormat("Layer frame timestamps:\n");
+void SurfaceFlinger::dumpFrameEventsLocked(std::string& result) {
+ result.append("Layer frame timestamps:\n");
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
const size_t count = currentLayers.size();
@@ -4359,7 +4373,7 @@
}
}
-void SurfaceFlinger::dumpBufferingStats(String8& result) const {
+void SurfaceFlinger::dumpBufferingStats(std::string& result) const {
result.append("Buffering stats:\n");
result.append(" [Layer name] <Active time> <Two buffer> "
"<Double buffered> <Triple buffered>\n");
@@ -4385,15 +4399,13 @@
for (const auto& sortedPair : sorted) {
float activeTime = sortedPair.first;
const BufferTuple& values = sortedPair.second;
- result.appendFormat(" [%s] %.2f %.3f %.3f %.3f\n",
- std::get<0>(values).c_str(), activeTime,
- std::get<1>(values), std::get<2>(values),
- std::get<3>(values));
+ StringAppendF(&result, " [%s] %.2f %.3f %.3f %.3f\n", std::get<0>(values).c_str(),
+ activeTime, std::get<1>(values), std::get<2>(values), std::get<3>(values));
}
result.append("\n");
}
-void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const {
+void SurfaceFlinger::dumpDisplayIdentificationData(std::string& result) const {
for (const auto& [token, display] : mDisplays) {
const auto displayId = display->getId();
if (!displayId) {
@@ -4404,8 +4416,9 @@
continue;
}
- result.appendFormat("Display %s (HWC display %" PRIu64 "): ", to_string(*displayId).c_str(),
- *hwcDisplayId);
+ StringAppendF(&result,
+ "Display %s (HWC display %" PRIu64 "): ", to_string(*displayId).c_str(),
+ *hwcDisplayId);
uint8_t port;
DisplayIdentificationData data;
if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) {
@@ -4416,7 +4429,7 @@
if (!isEdid(data)) {
result.append("unknown identification data: ");
for (uint8_t byte : data) {
- result.appendFormat("%x ", byte);
+ StringAppendF(&result, "%x ", byte);
}
result.append("\n");
continue;
@@ -4426,23 +4439,23 @@
if (!edid) {
result.append("invalid EDID: ");
for (uint8_t byte : data) {
- result.appendFormat("%x ", byte);
+ StringAppendF(&result, "%x ", byte);
}
result.append("\n");
continue;
}
- result.appendFormat("port=%u pnpId=%s displayName=\"", port, edid->pnpId.data());
+ StringAppendF(&result, "port=%u pnpId=%s displayName=\"", port, edid->pnpId.data());
result.append(edid->displayName.data(), edid->displayName.length());
result.append("\"\n");
}
}
-void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
- result.appendFormat("Device has wide color display: %d\n", hasWideColorDisplay);
- result.appendFormat("Device uses color management: %d\n", useColorManagement);
- result.appendFormat("DisplayColorSetting: %s\n",
- decodeDisplayColorSetting(mDisplayColorSetting).c_str());
+void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {
+ StringAppendF(&result, "Device has wide color display: %d\n", hasWideColorDisplay);
+ StringAppendF(&result, "Device uses color management: %d\n", useColorManagement);
+ StringAppendF(&result, "DisplayColorSetting: %s\n",
+ decodeDisplayColorSetting(mDisplayColorSetting).c_str());
// TODO: print out if wide-color mode is active or not
@@ -4452,22 +4465,20 @@
continue;
}
- result.appendFormat("Display %s color modes:\n", to_string(*displayId).c_str());
+ StringAppendF(&result, "Display %s color modes:\n", to_string(*displayId).c_str());
std::vector<ColorMode> modes = getHwComposer().getColorModes(*displayId);
for (auto&& mode : modes) {
- result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode);
+ StringAppendF(&result, " %s (%d)\n", decodeColorMode(mode).c_str(), mode);
}
ColorMode currentMode = display->getActiveColorMode();
- result.appendFormat(" Current color mode: %s (%d)\n",
- decodeColorMode(currentMode).c_str(), currentMode);
+ StringAppendF(&result, " Current color mode: %s (%d)\n",
+ decodeColorMode(currentMode).c_str(), currentMode);
}
result.append("\n");
}
-void SurfaceFlinger::dumpFrameCompositionInfo(String8& result) const {
- std::string stringResult;
-
+void SurfaceFlinger::dumpFrameCompositionInfo(std::string& result) const {
for (const auto& [token, display] : mDisplays) {
const auto it = getBE().mEndOfFrameCompositionInfo.find(token);
if (it == getBE().mEndOfFrameCompositionInfo.end()) {
@@ -4475,15 +4486,13 @@
}
const auto& compositionInfoList = it->second;
- stringResult += base::StringPrintf("%s\n", display->getDebugName().c_str());
- stringResult += base::StringPrintf("numComponents: %zu\n", compositionInfoList.size());
+ StringAppendF(&result, "%s\n", display->getDebugName().c_str());
+ StringAppendF(&result, "numComponents: %zu\n", compositionInfoList.size());
for (const auto& compositionInfo : compositionInfoList) {
- compositionInfo.dump(stringResult, nullptr);
- stringResult += base::StringPrintf("\n");
+ compositionInfo.dump(result, nullptr);
+ result.append("\n");
}
}
-
- result.append(stringResult.c_str());
}
LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const {
@@ -4522,8 +4531,7 @@
}
void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
- String8& result) const
-{
+ std::string& result) const {
bool colorize = false;
if (index < args.size()
&& (args[index] == String16("--color"))) {
@@ -4571,16 +4579,17 @@
if (const auto displayId = getInternalDisplayId();
displayId && getHwComposer().isConnected(*displayId)) {
const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
- result.appendFormat("Display %s: app phase %" PRId64 " ns, "
- "sf phase %" PRId64 " ns, "
- "early app phase %" PRId64 " ns, "
- "early sf phase %" PRId64 " ns, "
- "early app gl phase %" PRId64 " ns, "
- "early sf gl phase %" PRId64 " ns, "
- "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- to_string(*displayId).c_str(), vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
- appEarlyOffset, sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset,
- dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
+ StringAppendF(&result,
+ "Display %s: app phase %" PRId64 " ns, "
+ "sf phase %" PRId64 " ns, "
+ "early app phase %" PRId64 " ns, "
+ "early sf phase %" PRId64 " ns, "
+ "early app gl phase %" PRId64 " ns, "
+ "early sf gl phase %" PRId64 " ns, "
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+ to_string(*displayId).c_str(), vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
+ appEarlyOffset, sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset,
+ dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
}
result.append("\n");
@@ -4589,7 +4598,7 @@
dumpStaticScreenStats(result);
result.append("\n");
- result.appendFormat("Missed frame count: %u\n\n", mFrameMissedCount.load());
+ StringAppendF(&result, "Missed frame count: %u\n\n", mFrameMissedCount.load());
dumpBufferingStats(result);
@@ -4597,15 +4606,15 @@
* Dump the visible layer list
*/
colorizer.bold(result);
- result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
- result.appendFormat("GraphicBufferProducers: %zu, max %zu\n",
- mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize);
+ StringAppendF(&result, "Visible layers (count = %zu)\n", mNumLayers);
+ StringAppendF(&result, "GraphicBufferProducers: %zu, max %zu\n",
+ mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize);
colorizer.reset(result);
{
LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- result.append(LayerProtoParser::layerTreeToString(layerTree).c_str());
+ result.append(LayerProtoParser::layerTreeToString(layerTree));
result.append("\n");
}
@@ -4618,7 +4627,7 @@
*/
colorizer.bold(result);
- result.appendFormat("Displays (%zu entries)\n", mDisplays.size());
+ StringAppendF(&result, "Displays (%zu entries)\n", mDisplays.size());
colorizer.reset(result);
for (const auto& [token, display] : mDisplays) {
display->dump(result);
@@ -4637,27 +4646,28 @@
if (const auto display = getDefaultDisplayDeviceLocked()) {
display->undefinedRegion.dump(result, "undefinedRegion");
- result.appendFormat(" orientation=%d, isPoweredOn=%d\n", display->getOrientation(),
- display->isPoweredOn());
+ StringAppendF(&result, " orientation=%d, isPoweredOn=%d\n", display->getOrientation(),
+ display->isPoweredOn());
}
- result.appendFormat(" transaction-flags : %08x\n"
- " gpu_to_cpu_unsupported : %d\n",
- mTransactionFlags.load(), !mGpuToCpuSupported);
+ StringAppendF(&result,
+ " transaction-flags : %08x\n"
+ " gpu_to_cpu_unsupported : %d\n",
+ mTransactionFlags.load(), !mGpuToCpuSupported);
if (const auto displayId = getInternalDisplayId();
displayId && getHwComposer().isConnected(*displayId)) {
const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
- result.appendFormat(" refresh-rate : %f fps\n"
- " x-dpi : %f\n"
- " y-dpi : %f\n",
- 1e9 / activeConfig->getVsyncPeriod(), activeConfig->getDpiX(),
- activeConfig->getDpiY());
+ StringAppendF(&result,
+ " refresh-rate : %f fps\n"
+ " x-dpi : %f\n"
+ " y-dpi : %f\n",
+ 1e9 / activeConfig->getVsyncPeriod(), activeConfig->getDpiX(),
+ activeConfig->getDpiY());
}
- result.appendFormat(" transaction time: %f us\n",
- inTransactionDuration/1000.0);
+ StringAppendF(&result, " transaction time: %f us\n", inTransactionDuration / 1000.0);
- result.appendFormat(" use Scheduler: %s\n", mUseScheduler ? "true" : "false");
+ StringAppendF(&result, " use Scheduler: %s\n", mUseScheduler ? "true" : "false");
/*
* VSYNC state
*/
@@ -4683,7 +4693,7 @@
continue;
}
- result.appendFormat("Display %s HWC layers:\n", to_string(*displayId).c_str());
+ StringAppendF(&result, "Display %s HWC layers:\n", to_string(*displayId).c_str());
Layer::miniDumpHeader(result);
mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, *displayId); });
result.append("\n");
@@ -4696,8 +4706,7 @@
result.append("h/w composer state:\n");
colorizer.reset(result);
bool hwcDisabled = mDebugDisableHWC || mDebugRegion;
- result.appendFormat(" h/w composer %s\n",
- hwcDisabled ? "disabled" : "enabled");
+ StringAppendF(&result, " h/w composer %s\n", hwcDisabled ? "disabled" : "enabled");
getHwComposer().dump(result);
/*
@@ -4711,7 +4720,7 @@
*/
if (mVrFlingerRequestsDisplay && mVrFlinger) {
result.append("VrFlinger state:\n");
- result.append(mVrFlinger->Dump().c_str());
+ result.append(mVrFlinger->Dump());
result.append("\n");
}
}
@@ -4791,7 +4800,8 @@
case INJECT_VSYNC:
case SET_POWER_MODE:
case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
- case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: {
+ case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
+ case GET_DISPLAYED_CONTENT_SAMPLE: {
if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
IPCThreadState* ipc = IPCThreadState::self();
ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index fe2f1c26..9f52058 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -486,6 +486,9 @@
virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
uint8_t componentMask,
uint64_t maxFrames) const override;
+ virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ uint64_t timestamp,
+ DisplayedFrameStats* outStats) const override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
@@ -806,25 +809,25 @@
return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
}
- void listLayersLocked(const Vector<String16>& args, size_t& index, String8& result) const;
- void dumpStatsLocked(const Vector<String16>& args, size_t& index, String8& result) const;
- void clearStatsLocked(const Vector<String16>& args, size_t& index, String8& result);
- void dumpAllLocked(const Vector<String16>& args, size_t& index, String8& result) const;
+ void listLayersLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
+ void dumpStatsLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
+ void clearStatsLocked(const Vector<String16>& args, size_t& index, std::string& result);
+ void dumpAllLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
bool startDdmConnection();
- void appendSfConfigString(String8& result) const;
+ void appendSfConfigString(std::string& result) const;
void logFrameStats();
- void dumpStaticScreenStats(String8& result) const;
+ void dumpStaticScreenStats(std::string& result) const;
// Not const because each Layer needs to query Fences and cache timestamps.
- void dumpFrameEventsLocked(String8& result);
+ void dumpFrameEventsLocked(std::string& result);
void recordBufferingStats(const char* layerName,
std::vector<OccupancyTracker::Segment>&& history);
- void dumpBufferingStats(String8& result) const;
- void dumpDisplayIdentificationData(String8& result) const;
- void dumpWideColorInfo(String8& result) const;
- void dumpFrameCompositionInfo(String8& result) const;
+ void dumpBufferingStats(std::string& result) const;
+ void dumpDisplayIdentificationData(std::string& result) const;
+ void dumpWideColorInfo(std::string& result) const;
+ void dumpFrameCompositionInfo(std::string& result) const;
LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const;
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 1835929..b7e9a91 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -20,6 +20,7 @@
#include "SurfaceTracing.h"
#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <log/log.h>
#include <utils/SystemClock.h>
#include <utils/Trace.h>
@@ -120,12 +121,13 @@
return NO_ERROR;
}
-void SurfaceTracing::dump(String8& result) const {
+void SurfaceTracing::dump(std::string& result) const {
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- result.appendFormat("Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
- result.appendFormat(" number of entries: %zu (%.2fMB / %.2fMB)\n", mBuffer.frameCount(),
- float(mBuffer.used()) / float(1_MB), float(mBuffer.size()) / float(1_MB));
+ base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
+ base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
+ mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
+ float(mBuffer.size()) / float(1_MB));
}
} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index ec01be7..fd919af 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -18,7 +18,6 @@
#include <layerproto/LayerProtoHeader.h>
#include <utils/Errors.h>
-#include <utils/String8.h>
#include <memory>
#include <mutex>
@@ -43,7 +42,7 @@
void traceLayers(const char* where, LayersProto);
bool isEnabled() const;
- void dump(String8& result) const;
+ void dump(std::string& result) const;
private:
static constexpr auto kDefaultBufferCapInByte = 100_MB;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 2b9f5c8..6a5488a 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -33,7 +33,7 @@
namespace android {
void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, size_t& index,
- String8& result) {
+ std::string& result) {
ATRACE_CALL();
if (args.size() > index + 10) {
@@ -564,7 +564,7 @@
return mEnabled.load();
}
-void TimeStats::dump(bool asProto, std::optional<uint32_t> maxLayers, String8& result) {
+void TimeStats::dump(bool asProto, std::optional<uint32_t> maxLayers, std::string& result) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
@@ -582,7 +582,7 @@
result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize());
} else {
ALOGD("Dumping TimeStats as text");
- result.append(mTimeStats.toString(maxLayers).c_str());
+ result.append(mTimeStats.toString(maxLayers));
result.append("\n");
}
}
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 0b24c46..71c3ed7 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -24,7 +24,6 @@
#include <ui/FenceTime.h>
#include <utils/String16.h>
-#include <utils/String8.h>
#include <utils/Vector.h>
#include <deque>
@@ -35,7 +34,6 @@
using namespace android::surfaceflinger;
namespace android {
-class String8;
class TimeStats {
struct FrameTime {
@@ -79,7 +77,7 @@
TimeStats() = default;
~TimeStats() = default;
- void parseArgs(bool asProto, const Vector<String16>& args, size_t& index, String8& result);
+ void parseArgs(bool asProto, const Vector<String16>& args, size_t& index, std::string& result);
bool isEnabled();
void incrementTotalFrames();
@@ -117,7 +115,7 @@
void enable();
void disable();
void clear();
- void dump(bool asProto, std::optional<uint32_t> maxLayers, String8& result);
+ void dump(bool asProto, std::optional<uint32_t> maxLayers, std::string& result);
std::atomic<bool> mEnabled = false;
std::mutex mMutex;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index b0360a2..cef598c 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -396,7 +396,7 @@
BufferUsage::COMPOSER_OVERLAY,
"test");
fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color);
- Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply();
+ Transaction().setBuffer(layer, buffer).apply();
}
void fillLayerColor(uint32_t mLayerType, const sp<SurfaceControl>& layer, const Color& color,
@@ -484,13 +484,14 @@
uint32_t mDisplayWidth;
uint32_t mDisplayHeight;
uint32_t mDisplayLayerStack;
+ Rect mDisplayRect = Rect::INVALID_RECT;
// leave room for ~256 layers
const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256;
- void setPositionWithResizeHelper(uint32_t layerType);
- void setSizeBasicHelper(uint32_t layerType);
- void setMatrixWithResizeHelper(uint32_t layerType);
+ void setRelativeZBasicHelper(uint32_t layerType);
+ void setRelativeZGroupHelper(uint32_t layerType);
+ void setAlphaBasicHelper(uint32_t layerType);
sp<SurfaceControl> mBlackBgSurface;
bool mColorManagementUsed;
@@ -505,6 +506,8 @@
SurfaceComposerClient::getDisplayInfo(mDisplay, &info);
mDisplayWidth = info.w;
mDisplayHeight = info.h;
+ mDisplayRect =
+ Rect(static_cast<int32_t>(mDisplayWidth), static_cast<int32_t>(mDisplayHeight));
// After a new buffer is queued, SurfaceFlinger is notified and will
// latch the new buffer on next vsync. Let's heuristically wait for 3
@@ -575,31 +578,33 @@
::testing::Values(static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue),
static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)));
-TEST_P(LayerTypeTransactionTest, SetPositionBasic) {
+TEST_F(LayerTransactionTest, SetPositionBasic_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
{
SCOPED_TRACE("default position");
+ const Rect rect(0, 0, 32, 32);
auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
}
Transaction().setPosition(layer, 5, 10).apply();
{
SCOPED_TRACE("new position");
+ const Rect rect(5, 10, 37, 42);
auto shot = screenshot();
- shot->expectColor(Rect(5, 10, 37, 42), Color::RED);
- shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK);
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
}
}
-TEST_P(LayerTypeTransactionTest, SetPositionRounding) {
+TEST_F(LayerTransactionTest, SetPositionRounding_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// GLES requires only 4 bits of subpixel precision during rasterization
// XXX GLES composition does not match HWC composition due to precision
@@ -618,28 +623,28 @@
}
}
-TEST_P(LayerTypeTransactionTest, SetPositionOutOfBounds) {
+TEST_F(LayerTransactionTest, SetPositionOutOfBounds_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
Transaction().setPosition(layer, -32, -32).apply();
{
SCOPED_TRACE("negative coordinates");
- screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ screenshot()->expectColor(mDisplayRect, Color::BLACK);
}
Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply();
{
SCOPED_TRACE("positive coordinates");
- screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ screenshot()->expectColor(mDisplayRect, Color::BLACK);
}
}
-TEST_P(LayerTypeTransactionTest, SetPositionPartiallyOutOfBounds) {
+TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// partially out of bounds
Transaction().setPosition(layer, -30, -30).apply();
@@ -657,10 +662,10 @@
}
}
-void LayerTransactionTest::setPositionWithResizeHelper(uint32_t layerType) {
+TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// setPosition is applied immediately by default, with or without resize
// pending
@@ -668,39 +673,18 @@
{
SCOPED_TRACE("resize pending");
auto shot = screenshot();
- Rect rect;
- switch (layerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- rect = {5, 10, 37, 42};
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- rect = {5, 10, 69, 74};
- break;
- default:
- ASSERT_FALSE(true) << "Unsupported layer type";
- }
-
+ const Rect rect(5, 10, 37, 42);
shot->expectColor(rect, Color::RED);
shot->expectBorder(rect, Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
{
SCOPED_TRACE("resize applied");
screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED);
}
}
-TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) {
- ASSERT_NO_FATAL_FAILURE(
- setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
-}
-
-TEST_F(LayerTransactionTest, SetPositionWithResize_BufferState) {
- ASSERT_NO_FATAL_FAILURE(
- setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
-}
-
TEST_F(LayerTransactionTest, SetPositionWithNextResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
@@ -757,55 +741,38 @@
}
}
-void LayerTransactionTest::setSizeBasicHelper(uint32_t layerType) {
+TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
Transaction().setSize(layer, 64, 64).apply();
{
SCOPED_TRACE("resize pending");
auto shot = screenshot();
- Rect rect;
- switch (layerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- rect = {0, 0, 32, 32};
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- rect = {0, 0, 64, 64};
- break;
- default:
- ASSERT_FALSE(true) << "Unsupported layer type";
- }
+ const Rect rect(0, 0, 32, 32);
shot->expectColor(rect, Color::RED);
shot->expectBorder(rect, Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
{
SCOPED_TRACE("resize applied");
auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
- shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+ const Rect rect(0, 0, 64, 64);
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
}
}
-TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) {
- setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue);
-}
-
-TEST_F(LayerTransactionTest, SetSizeBasic_BufferState) {
- setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState);
-}
-
TEST_P(LayerTypeTransactionTest, SetSizeInvalid) {
// cannot test robustness against invalid sizes (zero or really huge)
}
-TEST_P(LayerTypeTransactionTest, SetSizeWithScaleToWindow) {
+TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// setSize is immediate with SCALE_TO_WINDOW, unlike setPosition
Transaction()
@@ -867,18 +834,31 @@
}
}
-TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) {
+void LayerTransactionTest::setRelativeZBasicHelper(uint32_t layerType) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32));
- Transaction()
- .setPosition(layerG, 16, 16)
- .setRelativeLayer(layerG, layerR->getHandle(), 1)
- .apply();
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ Transaction()
+ .setPosition(layerG, 16, 16)
+ .setRelativeLayer(layerG, layerR->getHandle(), 1)
+ .apply();
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ Transaction()
+ .setFrame(layerR, Rect(0, 0, 32, 32))
+ .setFrame(layerG, Rect(16, 16, 48, 48))
+ .setRelativeLayer(layerG, layerR->getHandle(), 1)
+ .apply();
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
{
SCOPED_TRACE("layerG above");
auto shot = screenshot();
@@ -895,6 +875,14 @@
}
}
+TEST_F(LayerTransactionTest, SetRelativeZBasic_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZBasic_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) {
sp<SurfaceControl> parent =
LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
@@ -920,28 +908,44 @@
std::unique_ptr<ScreenCapture> screenshot;
// only layerB is in this range
sp<IBinder> parentHandle = parent->getHandle();
- ScreenCapture::captureLayers(&screenshot, parentHandle);
+ ScreenCapture::captureLayers(&screenshot, parentHandle, Rect(0, 0, 32, 32));
screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
}
-TEST_P(LayerTypeTransactionTest, SetRelativeZGroup) {
+void LayerTransactionTest::setRelativeZGroupHelper(uint32_t layerType) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
sp<SurfaceControl> layerB;
- ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
- ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerB, Color::BLUE, 32, 32));
// layerR = 0, layerG = layerR + 3, layerB = 2
- Transaction()
- .setPosition(layerG, 8, 8)
- .setRelativeLayer(layerG, layerR->getHandle(), 3)
- .setPosition(layerB, 16, 16)
- .setLayer(layerB, mLayerZBase + 2)
- .apply();
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ Transaction()
+ .setPosition(layerG, 8, 8)
+ .setRelativeLayer(layerG, layerR->getHandle(), 3)
+ .setPosition(layerB, 16, 16)
+ .setLayer(layerB, mLayerZBase + 2)
+ .apply();
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ Transaction()
+ .setFrame(layerR, Rect(0, 0, 32, 32))
+ .setFrame(layerG, Rect(8, 8, 40, 40))
+ .setRelativeLayer(layerG, layerR->getHandle(), 3)
+ .setFrame(layerB, Rect(16, 16, 48, 48))
+ .setLayer(layerB, mLayerZBase + 2)
+ .apply();
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
+
{
SCOPED_TRACE("(layerR < layerG) < layerB");
auto shot = screenshot();
@@ -991,6 +995,14 @@
}
}
+TEST_F(LayerTransactionTest, SetRelativeZGroup_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZGroup_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
@@ -1018,7 +1030,7 @@
Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply();
{
SCOPED_TRACE("layer hidden");
- screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ screenshot()->expectColor(mDisplayRect, Color::BLACK);
}
Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply();
@@ -1130,7 +1142,7 @@
Transaction()
.setTransparentRegionHint(layer, Region(top))
.setBuffer(layer, buffer)
- .setSize(layer, 32, 32)
+ .setFrame(layer, Rect(0, 0, 32, 32))
.apply();
{
SCOPED_TRACE("top transparent");
@@ -1154,7 +1166,7 @@
ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::RED));
ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT));
- Transaction().setBuffer(layer, buffer).setSize(layer, 32, 32).apply();
+ Transaction().setBuffer(layer, buffer).apply();
{
SCOPED_TRACE("bottom transparent");
auto shot = screenshot();
@@ -1163,7 +1175,7 @@
}
}
-TEST_P(LayerTypeTransactionTest, SetTransparentRegionHintOutOfBounds) {
+TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds_BufferQueue) {
sp<SurfaceControl> layerTransparent;
sp<SurfaceControl> layerR;
ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
@@ -1171,30 +1183,64 @@
// check that transparent region hint is bound by the layer size
Transaction()
- .setTransparentRegionHint(layerTransparent,
- Region(Rect(0, 0, mDisplayWidth, mDisplayHeight)))
+ .setTransparentRegionHint(layerTransparent, Region(mDisplayRect))
.setPosition(layerR, 16, 16)
.setLayer(layerR, mLayerZBase + 1)
.apply();
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layerR, Color::RED, 32, 32));
screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED);
}
-TEST_P(LayerTypeTransactionTest, SetAlphaBasic) {
+TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds_BufferState) {
+ sp<SurfaceControl> layerTransparent;
+ sp<SurfaceControl> layerR;
+ ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ layerR = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ // check that transparent region hint is bound by the layer size
+ Transaction()
+ .setTransparentRegionHint(layerTransparent, Region(mDisplayRect))
+ .setFrame(layerR, Rect(16, 16, 48, 48))
+ .setLayer(layerR, mLayerZBase + 1)
+ .apply();
+ ASSERT_NO_FATAL_FAILURE(
+ fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layerR, Color::RED, 32, 32));
+ screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED);
+}
+
+void LayerTransactionTest::setAlphaBasicHelper(uint32_t layerType) {
sp<SurfaceControl> layer1;
sp<SurfaceControl> layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}, 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer1, {64, 0, 0, 255}, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer2, {0, 64, 0, 255}, 32, 32));
- Transaction()
- .setAlpha(layer1, 0.25f)
- .setAlpha(layer2, 0.75f)
- .setPosition(layer2, 16, 0)
- .setLayer(layer2, mLayerZBase + 1)
- .apply();
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ Transaction()
+ .setAlpha(layer1, 0.25f)
+ .setAlpha(layer2, 0.75f)
+ .setPosition(layer2, 16, 0)
+ .setLayer(layer2, mLayerZBase + 1)
+ .apply();
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ Transaction()
+ .setAlpha(layer1, 0.25f)
+ .setAlpha(layer2, 0.75f)
+ .setFrame(layer1, Rect(0, 0, 32, 32))
+ .setFrame(layer2, Rect(16, 0, 48, 32))
+ .setLayer(layer2, mLayerZBase + 1)
+ .apply();
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
{
auto shot = screenshot();
uint8_t r = 16; // 64 * 0.25f
@@ -1207,6 +1253,14 @@
}
}
+TEST_F(LayerTransactionTest, SetAlphaBasic_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_F(LayerTransactionTest, SetAlphaBasic_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
TEST_P(LayerTypeTransactionTest, SetAlphaClamped) {
const Color color = {64, 0, 0, 255};
sp<SurfaceControl> layer;
@@ -1230,7 +1284,7 @@
sp<SurfaceControl> layer;
const uint8_t size = 64;
const uint8_t testArea = 4;
- const float cornerRadius = 16.0f;
+ const float cornerRadius = 20.0f;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
@@ -1238,13 +1292,43 @@
.setCornerRadius(layer, cornerRadius)
.apply();
{
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
auto shot = screenshot();
// Transparent corners
shot->expectColor(Rect(0, 0, testArea, testArea), Color::BLACK);
- shot->expectColor(Rect(0, size - testArea, testArea, testArea), Color::BLACK);
- shot->expectColor(Rect(size - testArea, 0, testArea, testArea), Color::BLACK);
- shot->expectColor(Rect(size - testArea, size - testArea, testArea, testArea),
- Color::BLACK);
+ shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::BLACK);
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
+ shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::BLACK);
+ }
+}
+
+TEST_P(LayerTypeTransactionTest, SetCornerRadiusChildCrop) {
+ sp<SurfaceControl> parent;
+ sp<SurfaceControl> child;
+ const uint8_t size = 64;
+ const uint8_t testArea = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, size, size));
+ ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2));
+
+ Transaction()
+ .setCornerRadius(parent, cornerRadius)
+ .reparent(child, parent->getHandle())
+ .setPosition(child, 0, size / 2)
+ .apply();
+ {
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
+ auto shot = screenshot();
+ // Top edge of child should not have rounded corners because it's translated in the parent
+ shot->expectColor(Rect(0, size / 2, right, static_cast<int>(bottom - cornerRadius)),
+ Color::GREEN);
+ // But bottom edges should have been clipped according to parent bounds
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
+ shot->expectColor(Rect(right - testArea, bottom - testArea, right, bottom), Color::BLACK);
}
}
@@ -1362,7 +1446,7 @@
Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply();
{
SCOPED_TRACE("non-existing layer stack");
- screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ screenshot()->expectColor(mDisplayRect, Color::BLACK);
}
Transaction().setLayerStack(layer, mDisplayLayerStack).apply();
@@ -1372,11 +1456,11 @@
}
}
-TEST_P(LayerTypeTransactionTest, SetMatrixBasic) {
+TEST_F(LayerTransactionTest, SetMatrixBasic_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(
- fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply();
{
@@ -1414,11 +1498,57 @@
}
}
-TEST_P(LayerTypeTransactionTest, SetMatrixRot45) {
+TEST_F(LayerTransactionTest, SetMatrixBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction()
+ .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f)
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .apply();
+ {
+ SCOPED_TRACE("IDENTITY");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply();
+ {
+ SCOPED_TRACE("FLIP_H");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply();
+ {
+ SCOPED_TRACE("FLIP_V");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply();
+ {
+ SCOPED_TRACE("ROT_90");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply();
+ {
+ SCOPED_TRACE("SCALE");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetMatrixRot45_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(
- fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
const float rot = M_SQRT1_2; // 45 degrees
const float trans = M_SQRT2 * 16.0f;
@@ -1437,52 +1567,33 @@
shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE);
}
-void LayerTransactionTest::setMatrixWithResizeHelper(uint32_t layerType) {
+TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// setMatrix is applied after any pending resize, unlike setPosition
Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply();
{
SCOPED_TRACE("resize pending");
auto shot = screenshot();
- Rect rect;
- switch (layerType) {
- case ISurfaceComposerClient::eFXSurfaceBufferQueue:
- rect = {0, 0, 32, 32};
- break;
- case ISurfaceComposerClient::eFXSurfaceBufferState:
- rect = {0, 0, 128, 128};
- break;
- default:
- ASSERT_FALSE(true) << "Unsupported layer type";
- }
+ const Rect rect(0, 0, 32, 32);
shot->expectColor(rect, Color::RED);
shot->expectBorder(rect, Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
{
SCOPED_TRACE("resize applied");
- screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
+ const Rect rect(0, 0, 128, 128);
+ screenshot()->expectColor(rect, Color::RED);
}
}
-TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) {
- ASSERT_NO_FATAL_FAILURE(
- setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
-}
-
-TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferState) {
- ASSERT_NO_FATAL_FAILURE(
- setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
-}
-
-TEST_P(LayerTypeTransactionTest, SetMatrixWithScaleToWindow) {
+TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition
Transaction()
@@ -1493,11 +1604,11 @@
screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
}
-TEST_P(LayerTypeTransactionTest, SetOverrideScalingModeBasic) {
+TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(
- fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
// XXX SCALE_CROP is not respected; calling setSize and
// setOverrideScalingMode in separate transactions does not work
@@ -1547,8 +1658,8 @@
Transaction().setCrop(layer, crop).apply();
auto shot = screenshot();
- shot->expectColor(crop, Color::RED);
- shot->expectBorder(crop, Color::BLACK);
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
}
TEST_F(LayerTransactionTest, SetCropEmpty_BufferQueue) {
@@ -1599,18 +1710,22 @@
shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply();
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-}
-
+// TODO (marissaw): change Layer to make crop to be in bounds instead of passing a bad crop to hwc
+// TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) {
+// sp<SurfaceControl> layer;
+// ASSERT_NO_FATAL_FAILURE(
+// layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+// ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+//
+// Transaction()
+// .setCrop(layer, Rect(-128, -64, 128, 64))
+// .setFrame(layer, Rect(0, 0, 32, 32))
+// .apply();
+// auto shot = screenshot();
+// shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+// shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+//}
+//
TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
@@ -1630,12 +1745,12 @@
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
- const Point position(32, 32);
+ const Rect frame(32, 32, 64, 64);
const Rect crop(8, 8, 24, 24);
- Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply();
+ Transaction().setFrame(layer, frame).setCrop(layer, crop).apply();
auto shot = screenshot();
- shot->expectColor(crop + position, Color::RED);
- shot->expectBorder(crop + position, Color::BLACK);
+ shot->expectColor(frame, Color::RED);
+ shot->expectBorder(frame, Color::BLACK);
}
TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) {
@@ -1643,7 +1758,7 @@
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
- // crop is affected by matrix
+ // crop_legacy is affected by matrix
Transaction()
.setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
.setCrop_legacy(layer, Rect(8, 8, 24, 24))
@@ -1653,22 +1768,6 @@
shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetCropWithScale_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- // crop is affected by matrix
- Transaction()
- .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
- .setCrop(layer, Rect(8, 8, 24, 24))
- .apply();
- auto shot = screenshot();
- shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
- shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
-}
-
TEST_F(LayerTransactionTest, SetCropWithResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
@@ -1692,30 +1791,6 @@
}
}
-TEST_F(LayerTransactionTest, SetCropWithResize_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- // setCrop_legacy is applied immediately by default, with or without resize pending
- Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
- {
- SCOPED_TRACE("new buffer pending");
- auto shot = screenshot();
- shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
- shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
- }
-
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16));
- {
- SCOPED_TRACE("new buffer");
- auto shot = screenshot();
- shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
- shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
- }
-}
-
TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
@@ -1753,41 +1828,6 @@
}
}
-TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferState) {
- sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
- // request setCrop_legacy to be applied with the next resize
- Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply();
- {
- SCOPED_TRACE("set crop 1");
- screenshot()->expectColor(Rect(8, 8, 24, 24), Color::RED);
- }
-
- Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply();
- {
- SCOPED_TRACE("set crop 2");
- screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED);
- }
-
- Transaction().setSize(layer, 16, 16).apply();
- {
- SCOPED_TRACE("resize");
- screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED);
- }
-
- // finally resize
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16));
- {
- SCOPED_TRACE("new buffer");
- auto shot = screenshot();
- shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
- shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
- }
-}
-
TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
@@ -1819,37 +1859,122 @@
}
}
-TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) {
+TEST_F(LayerTransactionTest, SetFrameBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ const Rect frame(8, 8, 24, 24);
+
+ Transaction().setFrame(layer, frame).apply();
+ auto shot = screenshot();
+ shot->expectColor(frame, Color::RED);
+ shot->expectBorder(frame, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFrameEmpty_BufferState) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
- // all properties are applied immediate so setGeometryAppliesWithResize has no effect
- Transaction()
- .setCrop(layer, Rect(4, 4, 12, 12))
- .setSize(layer, 16, 16)
- .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
- .setGeometryAppliesWithResize(layer)
- .apply();
{
- SCOPED_TRACE("new crop pending");
- auto shot = screenshot();
- shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
- shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ SCOPED_TRACE("empty rect");
+ Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
}
- Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16));
- Transaction().setPosition(layer, 0, 0).apply();
{
- SCOPED_TRACE("new crop applied");
- auto shot = screenshot();
- shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
- shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ SCOPED_TRACE("negative rect");
+ Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
}
}
+TEST_F(LayerTransactionTest, SetFrameDefaultParentless_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10));
+
+ // A parentless layer will default to a frame with the same size as the buffer
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 10, 10), Color::RED);
+ shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFrameDefaultBSParent_BufferState) {
+ sp<SurfaceControl> parent, child;
+ ASSERT_NO_FATAL_FAILURE(
+ parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
+ Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
+
+ ASSERT_NO_FATAL_FAILURE(
+ child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+
+ Transaction().reparent(child, parent->getHandle()).apply();
+
+ // A layer will default to the frame of its parent
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFrameDefaultBQParent_BufferState) {
+ sp<SurfaceControl> parent, child;
+ ASSERT_NO_FATAL_FAILURE(parent = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32));
+
+ ASSERT_NO_FATAL_FAILURE(
+ child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+
+ Transaction().reparent(child, parent->getHandle()).apply();
+
+ // A layer will default to the frame of its parent
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFrameUpdate_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ std::this_thread::sleep_for(500ms);
+
+ Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply();
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
+ shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFrameOutsideBounds_BufferState) {
+ sp<SurfaceControl> parent, child;
+ ASSERT_NO_FATAL_FAILURE(
+ parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(
+ child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ Transaction().reparent(child, parent->getHandle()).apply();
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
+ Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+ Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply();
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 16), Color::RED);
+ shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
@@ -1906,6 +2031,7 @@
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64));
+ Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply();
{
SCOPED_TRACE("set layer 1 buffer red");
auto shot = screenshot();
@@ -1914,6 +2040,7 @@
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32));
+ Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply();
{
SCOPED_TRACE("set layer 2 buffer blue");
auto shot = screenshot();
@@ -1950,7 +2077,10 @@
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
Color::BLUE, Color::WHITE));
- Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90).apply();
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90)
+ .apply();
screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE,
Color::GREEN, true /* filtered */);
@@ -1964,7 +2094,10 @@
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
Color::BLUE, Color::WHITE));
- Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H).apply();
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H)
+ .apply();
screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE,
Color::BLUE, true /* filtered */);
@@ -1978,7 +2111,10 @@
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
Color::BLUE, Color::WHITE));
- Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V).apply();
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V)
+ .apply();
screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED,
Color::GREEN, true /* filtered */);
@@ -2013,7 +2149,6 @@
Transaction()
.setBuffer(layer, buffer)
.setAcquireFence(layer, fence)
- .setSize(layer, 32, 32)
.apply();
auto shot = screenshot();
@@ -2036,7 +2171,6 @@
Transaction()
.setBuffer(layer, buffer)
.setDataspace(layer, ui::Dataspace::UNKNOWN)
- .setSize(layer, 32, 32)
.apply();
auto shot = screenshot();
@@ -2061,7 +2195,6 @@
Transaction()
.setBuffer(layer, buffer)
.setHdrMetadata(layer, hdrMetadata)
- .setSize(layer, 32, 32)
.apply();
auto shot = screenshot();
@@ -2086,7 +2219,6 @@
Transaction()
.setBuffer(layer, buffer)
.setSurfaceDamageRegion(layer, region)
- .setSize(layer, 32, 32)
.apply();
auto shot = screenshot();
@@ -2109,7 +2241,6 @@
Transaction()
.setBuffer(layer, buffer)
.setApi(layer, NATIVE_WINDOW_API_CPU)
- .setSize(layer, 32, 32)
.apply();
auto shot = screenshot();
@@ -2465,36 +2596,33 @@
};
class LayerCallbackTest : public LayerTransactionTest {
-protected:
+public:
virtual sp<SurfaceControl> createBufferStateLayer() {
- return createLayer(mClient, "test", mWidth, mHeight,
- ISurfaceComposerClient::eFXSurfaceBufferState);
+ return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
}
- virtual void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
- const sp<SurfaceControl>& layer = nullptr) {
+ static void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
+ const sp<SurfaceControl>& layer = nullptr) {
if (layer) {
sp<GraphicBuffer> buffer =
- new GraphicBuffer(mWidth, mHeight, PIXEL_FORMAT_RGBA_8888, 1,
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
BufferUsage::COMPOSER_OVERLAY |
BufferUsage::GPU_TEXTURE,
"test");
- fillGraphicBufferColor(buffer, Rect(0, 0, mWidth, mHeight), Color::RED);
+ fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
sp<Fence> fence = new Fence(-1);
- transaction.setBuffer(layer, buffer)
- .setAcquireFence(layer, fence)
- .setSize(layer, mWidth, mHeight);
+ transaction.setBuffer(layer, buffer).setAcquireFence(layer, fence);
}
transaction.addTransactionCompletedCallback(callbackHelper->function,
callbackHelper->getContext());
}
- void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
- bool finalState = false) {
+ static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
+ bool finalState = false) {
TransactionStats transactionStats;
ASSERT_NO_FATAL_FAILURE(helper.getTransactionStats(&transactionStats));
EXPECT_NO_FATAL_FAILURE(expectedResult.verifyTransactionStats(transactionStats));
@@ -2504,9 +2632,9 @@
}
}
- void waitForCallbacks(CallbackHelper& helper,
- const std::vector<ExpectedResult>& expectedResults,
- bool finalState = false) {
+ static void waitForCallbacks(CallbackHelper& helper,
+ const std::vector<ExpectedResult>& expectedResults,
+ bool finalState = false) {
for (const auto& expectedResult : expectedResults) {
waitForCallback(helper, expectedResult);
}
@@ -2514,9 +2642,6 @@
ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
}
}
-
- uint32_t mWidth = 32;
- uint32_t mHeight = 32;
};
TEST_F(LayerCallbackTest, Basic) {
@@ -2542,7 +2667,7 @@
CallbackHelper callback;
fillTransaction(transaction, &callback);
- transaction.setPosition(layer, mWidth, mHeight).apply();
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer);
@@ -2568,7 +2693,7 @@
CallbackHelper callback;
fillTransaction(transaction, &callback, layer);
- transaction.setPosition(layer, -100, -100).apply();
+ transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply();
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
@@ -2585,7 +2710,8 @@
fillTransaction(transaction1, &callback1, layer1);
fillTransaction(transaction2, &callback2, layer2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -2638,7 +2764,8 @@
fillTransaction(transaction1, &callback1, layer1);
fillTransaction(transaction2, &callback2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -2654,9 +2781,9 @@
ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
Transaction transaction1, transaction2;
@@ -2664,7 +2791,8 @@
fillTransaction(transaction1, &callback1, layer1);
fillTransaction(transaction2, &callback2, layer2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -2729,7 +2857,7 @@
fillTransaction(transaction, &callback);
}
- transaction.setPosition(layer, mWidth, mHeight).apply();
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
ExpectedResult expected;
expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED
@@ -2751,7 +2879,8 @@
fillTransaction(transaction1, &callback1, layer1);
fillTransaction(transaction2, &callback2, layer2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
@@ -2772,9 +2901,9 @@
ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
Transaction transaction1, transaction2;
@@ -2783,7 +2912,8 @@
fillTransaction(transaction1, &callback1, layer1);
fillTransaction(transaction2, &callback2, layer2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
@@ -2804,9 +2934,9 @@
ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
Transaction transaction1, transaction2;
@@ -2816,7 +2946,8 @@
fillTransaction(transaction1, &callback1, layer1);
fillTransaction(transaction2, &callback2, layer2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -2842,9 +2973,9 @@
ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient";
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", mWidth, mHeight,
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0,
ISurfaceComposerClient::eFXSurfaceBufferState));
Transaction transaction1, transaction2;
@@ -2854,7 +2985,8 @@
fillTransaction(transaction1, &callback1, layer1);
fillTransaction(transaction2, &callback2, layer2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -2866,7 +2998,7 @@
fillTransaction(transaction1, &callback1);
fillTransaction(transaction2, &callback2);
- transaction2.setPosition(layer2, mWidth, mHeight).merge(std::move(transaction1)).apply();
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2);
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
@@ -2930,7 +3062,7 @@
CallbackHelper callback;
fillTransaction(transaction, &callback, layer);
- transaction.setPosition(layer, mWidth, mHeight).apply();
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
ExpectedResult expectedResult;
expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
@@ -2944,7 +3076,7 @@
fillTransaction(transaction, &callback);
- transaction.setPosition(layer, mWidth, mHeight).apply();
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
std::this_thread::sleep_for(200ms);
}
@@ -4245,7 +4377,7 @@
// red area to the right of the blue area
mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
- Rect crop = Rect(0, 0, 30, 30);
+ const Rect crop = Rect(0, 0, 30, 30);
ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
// Capturing the cropped screen, cropping out the shown red area, should leave only the blue
// area visible.
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index d0cf1b7..35f30d7 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -117,7 +117,7 @@
mScheduler->hotplugReceived(nullptr, EventThread::DisplayType::Primary, false));
ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(nullptr));
ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(nullptr));
- String8 testString;
+ std::string testString;
ASSERT_NO_FATAL_FAILURE(mScheduler->dump(nullptr, testString));
EXPECT_TRUE(testString == "");
ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(nullptr, 10));
@@ -146,7 +146,7 @@
EXPECT_CALL(*mEventThread, onScreenReleased()).Times(0);
ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(connectionHandle));
- String8 testString;
+ std::string testString;
EXPECT_CALL(*mEventThread, dump(_)).Times(0);
ASSERT_NO_FATAL_FAILURE(mScheduler->dump(connectionHandle, testString));
EXPECT_TRUE(testString == "");
@@ -176,7 +176,7 @@
EXPECT_CALL(*mEventThread, onScreenReleased()).Times(1);
ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(mConnectionHandle));
- String8 testString("dump");
+ std::string testString("dump");
EXPECT_CALL(*mEventThread, dump(testString)).Times(1);
ASSERT_NO_FATAL_FAILURE(mScheduler->dump(mConnectionHandle, testString));
EXPECT_TRUE(testString != "");
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index 186ed79..bfd34cd 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -21,7 +21,6 @@
#include <log/log.h>
#include <utils/String16.h>
-#include <utils/String8.h>
#include <utils/Vector.h>
#include <random>
@@ -131,7 +130,7 @@
std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
size_t index = 0;
- String8 result;
+ std::string result;
Vector<String16> args;
switch (cmd) {
@@ -162,7 +161,7 @@
}
EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, index, result));
- return std::string(result.string(), result.size());
+ return result;
}
static std::string genLayerName(int32_t layerID) {
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 68fd8b4..dfdda09 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -116,6 +116,8 @@
MOCK_METHOD4(getDisplayedContentSamplingAttributes,
Error(Display, PixelFormat*, Dataspace*, uint8_t*));
MOCK_METHOD4(setDisplayContentSamplingEnabled, Error(Display, bool, uint8_t, uint64_t));
+ MOCK_METHOD4(getDisplayedContentSample,
+ Error(Display, uint64_t, uint64_t, DisplayedFrameStats*));
MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*));
};
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index 34e71cb..9213ae5 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -18,7 +18,6 @@
#include <gmock/gmock.h>
-#include <utils/String8.h>
#include "Scheduler/DispSync.h"
namespace android {
@@ -44,7 +43,7 @@
MOCK_METHOD1(setIgnorePresentFences, void(bool));
MOCK_METHOD0(expectedPresentTime, nsecs_t());
- MOCK_CONST_METHOD1(dump, void(String8&));
+ MOCK_CONST_METHOD1(dump, void(std::string&));
};
} // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index ad2463d..0a1c827 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -32,7 +32,7 @@
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(DisplayType, bool));
- MOCK_CONST_METHOD1(dump, void(String8&));
+ MOCK_CONST_METHOD1(dump, void(std::string&));
MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset));
};
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index a416808..11e5631 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -38,7 +38,7 @@
MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
MOCK_CONST_METHOD0(primeCache, void());
- MOCK_METHOD1(dump, void(String8&));
+ MOCK_METHOD1(dump, void(std::string&));
MOCK_CONST_METHOD0(useNativeFenceSync, bool());
MOCK_CONST_METHOD0(useWaitSync, bool());
MOCK_CONST_METHOD0(isCurrent, bool());
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 0a59f29..7a7e437 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -14,7 +14,6 @@
sharedLibraries = [
"libbase",
- "libbinder",
"libbufferhubservice",
"libcutils",
"libgtest_prod",
@@ -30,12 +29,9 @@
name: "libbufferhubd",
srcs: [
"buffer_channel.cpp",
- "buffer_client.cpp",
"buffer_hub.cpp",
- "buffer_hub_binder.cpp",
"consumer_channel.cpp",
"consumer_queue_channel.cpp",
- "IBufferHub.cpp",
"producer_channel.cpp",
"producer_queue_channel.cpp",
],
@@ -45,10 +41,7 @@
"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
export_include_dirs: ["include"],
- header_libs: [
- "libdvr_headers",
- "libnativewindow_headers",
- ],
+ header_libs: ["libdvr_headers"],
shared_libs: sharedLibraries,
static_libs: [
"libbufferhub",
diff --git a/services/vr/bufferhubd/IBufferHub.cpp b/services/vr/bufferhubd/IBufferHub.cpp
deleted file mode 100644
index 5980873..0000000
--- a/services/vr/bufferhubd/IBufferHub.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <log/log.h>
-#include <private/dvr/IBufferHub.h>
-
-namespace android {
-namespace dvr {
-
-class BpBufferHub : public BpInterface<IBufferHub> {
- public:
- explicit BpBufferHub(const sp<IBinder>& impl)
- : BpInterface<IBufferHub>(impl) {}
-
- sp<IBufferClient> createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage,
- uint64_t user_metadata_size) override;
-
- status_t importBuffer(uint64_t token, sp<IBufferClient>* outClient) override;
-};
-
-IMPLEMENT_META_INTERFACE(BufferHub, "android.dvr.IBufferHub");
-
-// Transaction code
-enum {
- CREATE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- IMPORT_BUFFER,
-};
-
-sp<IBufferClient> BpBufferHub::createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count,
- uint32_t format, uint64_t usage,
- uint64_t user_metadata_size) {
- Parcel data, reply;
- status_t ret = OK;
- ret |= data.writeInterfaceToken(IBufferHub::getInterfaceDescriptor());
- ret |= data.writeUint32(width);
- ret |= data.writeUint32(height);
- ret |= data.writeUint32(layer_count);
- ret |= data.writeUint32(format);
- ret |= data.writeUint64(usage);
- ret |= data.writeUint64(user_metadata_size);
-
- if (ret != OK) {
- ALOGE("BpBufferHub::createBuffer: failed to write into parcel");
- return nullptr;
- }
-
- ret = remote()->transact(CREATE_BUFFER, data, &reply);
- if (ret == OK) {
- return interface_cast<IBufferClient>(reply.readStrongBinder());
- } else {
- ALOGE("BpBufferHub::createBuffer: failed to transact; errno=%d", ret);
- return nullptr;
- }
-}
-
-status_t BpBufferHub::importBuffer(uint64_t token,
- sp<IBufferClient>* outClient) {
- Parcel data, reply;
- status_t ret = OK;
- ret |= data.writeInterfaceToken(IBufferHub::getInterfaceDescriptor());
- ret |= data.writeUint64(token);
- if (ret != OK) {
- ALOGE("BpBufferHub::importBuffer: failed to write into parcel");
- return ret;
- }
-
- ret = remote()->transact(IMPORT_BUFFER, data, &reply);
- if (ret == OK) {
- *outClient = interface_cast<IBufferClient>(reply.readStrongBinder());
- return OK;
- } else {
- ALOGE("BpBufferHub::importBuffer: failed to transact; errno=%d", ret);
- return ret;
- }
-}
-
-status_t BnBufferHub::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags) {
- switch (code) {
- case CREATE_BUFFER: {
- CHECK_INTERFACE(IBufferHub, data, reply);
- uint32_t width = data.readUint32();
- uint32_t height = data.readUint32();
- uint32_t layer_count = data.readUint32();
- uint32_t format = data.readUint32();
- uint64_t usage = data.readUint64();
- uint64_t user_metadata_size = data.readUint64();
- sp<IBufferClient> ret = createBuffer(width, height, layer_count, format,
- usage, user_metadata_size);
- return reply->writeStrongBinder(IInterface::asBinder(ret));
- }
- case IMPORT_BUFFER: {
- CHECK_INTERFACE(IBufferHub, data, reply);
- uint64_t token = data.readUint64();
- sp<IBufferClient> client;
- status_t ret = importBuffer(token, &client);
- if (ret == OK) {
- return reply->writeStrongBinder(IInterface::asBinder(client));
- } else {
- return ret;
- }
- }
- default:
- // Should not reach except binder defined transactions such as dumpsys
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file
diff --git a/services/vr/bufferhubd/buffer_client.cpp b/services/vr/bufferhubd/buffer_client.cpp
deleted file mode 100644
index f14faf7..0000000
--- a/services/vr/bufferhubd/buffer_client.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <private/dvr/buffer_client.h>
-#include <private/dvr/buffer_hub_binder.h>
-
-namespace android {
-namespace dvr {
-
-status_t BufferClient::duplicate(uint64_t* outToken) {
- if (!buffer_node_) {
- // Should never happen
- ALOGE("BufferClient::duplicate: node is missing.");
- return UNEXPECTED_NULL;
- }
- return service_->registerToken(std::weak_ptr<BufferNode>(buffer_node_),
- outToken);
-}
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file
diff --git a/services/vr/bufferhubd/buffer_hub_binder.cpp b/services/vr/bufferhubd/buffer_hub_binder.cpp
deleted file mode 100644
index 580433e..0000000
--- a/services/vr/bufferhubd/buffer_hub_binder.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-#include <stdio.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <log/log.h>
-#include <private/dvr/buffer_hub_binder.h>
-#include <private/dvr/buffer_node.h>
-
-namespace android {
-namespace dvr {
-
-status_t BufferHubBinderService::start(
- const std::shared_ptr<BufferHubService>& pdx_service) {
- IPCThreadState::self()->disableBackgroundScheduling(true);
-
- sp<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 != OK) {
- ALOGE("Publishing bufferhubd failed with error %d", result);
- return result;
- }
-
- sp<ProcessState> process_self(ProcessState::self());
- process_self->startThreadPool();
-
- return result;
-}
-
-status_t BufferHubBinderService::dump(int fd, const Vector<String16>& args) {
- FILE* out = fdopen(dup(fd), "w");
-
- // 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");
- }
-
- fprintf(out, "Binder service:\n");
- // Active buffers
- fprintf(out, "Active BufferClients: %zu\n", client_list_.size());
- // TODO(b/117790952): print buffer information after BufferNode has it
- // TODO(b/116526156): print more information once we have them
-
- if (pdx_service_) {
- fprintf(out, "\nPDX service:\n");
- // 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 OK;
-}
-
-status_t BufferHubBinderService::registerToken(
- const std::weak_ptr<BufferNode> node, uint64_t* outToken) {
- do {
- *outToken = token_engine_();
- } while (token_map_.find(*outToken) != token_map_.end());
-
- token_map_.emplace(*outToken, node);
- return OK;
-}
-
-sp<IBufferClient> BufferHubBinderService::createBuffer(
- uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
- uint64_t usage, uint64_t user_metadata_size) {
- std::shared_ptr<BufferNode> node = std::make_shared<BufferNode>(
- width, height, layer_count, format, usage, user_metadata_size);
-
- sp<BufferClient> client = new BufferClient(node, this);
- // Add it to list for bookkeeping and dumpsys.
- client_list_.push_back(client);
-
- return client;
-}
-
-status_t BufferHubBinderService::importBuffer(uint64_t token,
- sp<IBufferClient>* outClient) {
- auto iter = token_map_.find(token);
-
- if (iter == token_map_.end()) { // Not found
- ALOGE("BufferHubBinderService::importBuffer: token %" PRIu64
- "does not exist.",
- token);
- return PERMISSION_DENIED;
- }
-
- if (iter->second.expired()) { // Gone
- ALOGW(
- "BufferHubBinderService::importBuffer: the original node of token "
- "%" PRIu64 "has gone.",
- token);
- token_map_.erase(iter);
- return DEAD_OBJECT;
- }
-
- // Promote the weak_ptr
- std::shared_ptr<BufferNode> node(iter->second);
- if (!node) {
- ALOGE("BufferHubBinderService::importBuffer: promote weak_ptr failed.");
- token_map_.erase(iter);
- return DEAD_OBJECT;
- }
-
- sp<BufferClient> client = new BufferClient(node, this);
- *outClient = client;
-
- token_map_.erase(iter);
- client_list_.push_back(client);
-
- return OK;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index e44cc2a..50cb3b7 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -6,7 +6,6 @@
#include <log/log.h>
#include <pdx/service_dispatcher.h>
#include <private/dvr/buffer_hub.h>
-#include <private/dvr/buffer_hub_binder.h>
int main(int, char**) {
int ret = -1;
@@ -40,10 +39,6 @@
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::OK, 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/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index f936e95..158ef9c 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -153,6 +153,17 @@
}
}
+void ConsumerChannel::OnProducerGained() {
+ // Clear the signal if exist. There is a possiblity that the signal still
+ // exist in consumer client when producer gains the buffer, e.g. newly added
+ // consumer fail to acquire the previous posted buffer in time. Then, when
+ // producer gains back the buffer, posts the buffer again and signal the
+ // consumer later, there won't be an signal change in eventfd, and thus,
+ // consumer will miss the posted buffer later. Thus, we need to clear the
+ // signal in consumer clients if the signal exist.
+ ClearAvailable();
+}
+
void ConsumerChannel::OnProducerPosted() {
acquired_ = false;
released_ = false;
diff --git a/services/vr/bufferhubd/include/private/dvr/IBufferHub.h b/services/vr/bufferhubd/include/private/dvr/IBufferHub.h
deleted file mode 100644
index 502c6d6..0000000
--- a/services/vr/bufferhubd/include/private/dvr/IBufferHub.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef ANDROID_DVR_IBUFFERHUB_H
-#define ANDROID_DVR_IBUFFERHUB_H
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <private/dvr/IBufferClient.h>
-
-namespace android {
-namespace dvr {
-
-class IBufferHub : public IInterface {
- public:
- DECLARE_META_INTERFACE(BufferHub);
-
- static const char* getServiceName() { return "bufferhubd"; }
- virtual sp<IBufferClient> createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage,
- uint64_t user_metadata_size) = 0;
-
- virtual status_t importBuffer(uint64_t token,
- sp<IBufferClient>* outClient) = 0;
-};
-
-class BnBufferHub : public BnInterface<IBufferHub> {
- public:
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_IBUFFERHUB_H
\ No newline at end of file
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_client.h b/services/vr/bufferhubd/include/private/dvr/buffer_client.h
deleted file mode 100644
index d79ec0a..0000000
--- a/services/vr/bufferhubd/include/private/dvr/buffer_client.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef ANDROID_DVR_BUFFERCLIENT_H
-#define ANDROID_DVR_BUFFERCLIENT_H
-
-#include <private/dvr/IBufferClient.h>
-#include <private/dvr/buffer_node.h>
-
-namespace android {
-namespace dvr {
-
-// Forward declaration to avoid circular dependency
-class BufferHubBinderService;
-
-class BufferClient : public BnBufferClient {
- public:
- // Creates a server-side buffer client from an existing BufferNode. Note that
- // this funciton takes ownership of the shared_ptr.
- explicit BufferClient(std::shared_ptr<BufferNode> node,
- BufferHubBinderService* service)
- : service_(service), buffer_node_(std::move(node)){};
-
- // Binder IPC functions
- bool isValid() override {
- return buffer_node_ ? buffer_node_->IsValid() : false;
- };
-
- status_t duplicate(uint64_t* outToken) override;
-
- private:
- // Hold a pointer to the service to bypass binder interface, as BufferClient
- // and the service will be in the same process. Also, since service owns
- // Client, if service dead the clients will be destroyed, so this pointer is
- // guaranteed to be valid.
- BufferHubBinderService* service_;
-
- std::shared_ptr<BufferNode> buffer_node_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_IBUFFERCLIENT_H
\ No newline at end of file
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
deleted file mode 100644
index cf6124b..0000000
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef ANDROID_DVR_BUFFER_HUB_BINDER_H
-#define ANDROID_DVR_BUFFER_HUB_BINDER_H
-
-#include <random>
-#include <unordered_map>
-#include <vector>
-
-#include <binder/BinderService.h>
-#include <private/dvr/IBufferHub.h>
-#include <private/dvr/buffer_client.h>
-#include <private/dvr/buffer_hub.h>
-#include <private/dvr/buffer_node.h>
-
-namespace android {
-namespace dvr {
-
-class BufferHubBinderService : public BinderService<BufferHubBinderService>,
- public BnBufferHub {
- public:
- static status_t start(const std::shared_ptr<BufferHubService>& pdx_service);
- // Dumps bufferhub related information to given fd (usually stdout)
- // usage: adb shell dumpsys bufferhubd
- virtual status_t dump(int fd, const Vector<String16>& args) override;
-
- // Marks a BufferNode to be duplicated.
- // TODO(b/116681016): add importToken(int64_t)
- status_t registerToken(const std::weak_ptr<BufferNode> node,
- uint64_t* outToken);
-
- // Binder IPC functions
- sp<IBufferClient> createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage,
- uint64_t user_metadata_size) override;
-
- status_t importBuffer(uint64_t token, sp<IBufferClient>* outClient) override;
-
- private:
- std::shared_ptr<BufferHubService> pdx_service_;
-
- std::vector<sp<BufferClient>> client_list_;
-
- // TODO(b/118180214): use a more secure implementation
- std::mt19937_64 token_engine_;
- // The mapping from token to a specific node. This is a many-to-one mapping.
- // One node could be refered by 0 to multiple tokens.
- std::unordered_map<uint64_t, std::weak_ptr<BufferNode>> token_map_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
diff --git a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
index de0f23c..5fb4ec1 100644
--- a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
@@ -26,6 +26,7 @@
uint64_t client_state_mask() const { return client_state_mask_; }
BufferInfo GetBufferInfo() const override;
+ void OnProducerGained();
void OnProducerPosted();
void OnProducerClosed();
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index ab1d94c..b541fb3 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -424,7 +424,7 @@
// Signal any interested consumers. If there are none, the buffer will stay
// in posted state until a consumer comes online. This behavior guarantees
// that no frame is silently dropped.
- for (auto consumer : consumer_channels_) {
+ for (auto& consumer : consumer_channels_) {
consumer->OnProducerPosted();
}
@@ -437,6 +437,9 @@
ClearAvailable();
post_fence_.close();
+ for (auto& consumer : consumer_channels_) {
+ consumer->OnProducerGained();
+ }
return {std::move(returned_fence_)};
}
@@ -533,7 +536,7 @@
uint64_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
- if (BufferHubDefs::IsClientReleased(current_buffer_state,
+ if (BufferHubDefs::IsBufferReleased(current_buffer_state &
~orphaned_consumer_bit_mask_)) {
SignalAvailable();
if (orphaned_consumer_bit_mask_) {
@@ -560,7 +563,7 @@
uint64_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
- if (BufferHubDefs::IsClientReleased(current_buffer_state,
+ if (BufferHubDefs::IsBufferReleased(current_buffer_state &
~orphaned_consumer_bit_mask_)) {
SignalAvailable();
}
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
deleted file mode 100644
index a611268..0000000
--- a/services/vr/bufferhubd/tests/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-cc_test {
- name: "buffer_hub_binder_service-test",
- srcs: ["buffer_hub_binder_service-test.cpp"],
- cflags: [
- "-DLOG_TAG=\"buffer_hub_binder_service-test\"",
- "-DTRACE=0",
- "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
- ],
- header_libs: ["libdvr_headers"],
- static_libs: [
- "libbufferhub",
- "libbufferhubd",
- "libgmock",
- ],
- shared_libs: [
- "libbase",
- "libbinder",
- "liblog",
- "libpdx_default_transport",
- "libui",
- "libutils",
- ],
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
-}
diff --git a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
deleted file mode 100644
index 94b422a..0000000
--- a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <binder/IServiceManager.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <private/dvr/IBufferClient.h>
-#include <private/dvr/IBufferHub.h>
-#include <ui/PixelFormat.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-using testing::IsNull;
-using testing::NotNull;
-
-const int kWidth = 640;
-const int kHeight = 480;
-const int kLayerCount = 1;
-const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
-
-class BufferHubBinderServiceTest : public ::testing::Test {
- protected:
- void SetUp() override {
- status_t ret = getService<IBufferHub>(
- String16(IBufferHub::getServiceName()), &service);
- ASSERT_EQ(ret, OK);
- ASSERT_THAT(service, NotNull());
- }
-
- sp<IBufferHub> service;
-};
-
-TEST_F(BufferHubBinderServiceTest, TestCreateBuffer) {
- sp<IBufferClient> bufferClient = service->createBuffer(
- kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
- ASSERT_THAT(bufferClient, NotNull());
- EXPECT_TRUE(bufferClient->isValid());
-}
-
-TEST_F(BufferHubBinderServiceTest, TestDuplicateAndImportBuffer) {
- sp<IBufferClient> bufferClient = service->createBuffer(
- kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
- ASSERT_THAT(bufferClient, NotNull());
- EXPECT_TRUE(bufferClient->isValid());
-
- uint64_t token1 = 0ULL;
- status_t ret = bufferClient->duplicate(&token1);
- EXPECT_EQ(ret, OK);
-
- // Tokens should be unique even corresponding to the same buffer
- uint64_t token2 = 0ULL;
- ret = bufferClient->duplicate(&token2);
- EXPECT_EQ(ret, OK);
- EXPECT_NE(token2, token1);
-
- sp<IBufferClient> bufferClient1;
- ret = service->importBuffer(token1, &bufferClient1);
- EXPECT_EQ(ret, OK);
- ASSERT_THAT(bufferClient1, NotNull());
- EXPECT_TRUE(bufferClient1->isValid());
-
- // Consumes the token to keep the service clean
- sp<IBufferClient> bufferClient2;
- ret = service->importBuffer(token2, &bufferClient2);
- EXPECT_EQ(ret, OK);
- ASSERT_THAT(bufferClient2, NotNull());
- EXPECT_TRUE(bufferClient2->isValid());
-}
-
-TEST_F(BufferHubBinderServiceTest, TestImportUnexistingToken) {
- // There is very little chance that this test fails if there is a token = 0
- // in the service.
- uint64_t unexistingToken = 0ULL;
- sp<IBufferClient> bufferClient;
- status_t ret = service->importBuffer(unexistingToken, &bufferClient);
- EXPECT_EQ(ret, PERMISSION_DENIED);
- EXPECT_THAT(bufferClient, IsNull());
-}
-
-} // namespace
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index e4c50d5..09db37a 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -524,8 +524,8 @@
@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
// 166
-@extension("VK_NV_raytracing") define VK_NV_RAYTRACING_SPEC_VERSION 2
-@extension("VK_NV_raytracing") define VK_NV_RAYTRACING_EXTENSION_NAME "VK_NV_raytracing"
+@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_SPEC_VERSION 3
+@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing"
// 167
@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
@@ -703,7 +703,7 @@
@extension("VK_EXT_validation_cache") @nonDispatchHandle type u64 VkValidationCacheEXT
// 166
-@extension("VK_NV_raytracing") @nonDispatchHandle type u64 VkAccelerationStructureNV
+@extension("VK_NV_ray_tracing") @nonDispatchHandle type u64 VkAccelerationStructureNV
/////////////
// Enums //
@@ -804,7 +804,7 @@
//@extension("VK_EXT_inline_uniform_block") // 139
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
}
@@ -816,7 +816,7 @@
//@extension("VK_EXT_transform_feedback") // 29
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000,
}
@@ -833,7 +833,7 @@
VK_PIPELINE_BIND_POINT_GRAPHICS = 0x00000000,
VK_PIPELINE_BIND_POINT_COMPUTE = 0x00000001,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000,
}
@@ -860,7 +860,7 @@
VK_INDEX_TYPE_UINT16 = 0x00000000,
VK_INDEX_TYPE_UINT32 = 0x00000001,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_INDEX_TYPE_NONE_NV = 1000165000,
}
@@ -1796,7 +1796,7 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000,
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001,
VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003,
@@ -2030,7 +2030,7 @@
//@extension("VK_EXT_validation_cache") // 161
VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
}
@@ -2154,7 +2154,7 @@
//@extension("VK_KHR_sampler_ycbcr_conversion") // 157
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000,
}
@@ -2330,32 +2330,32 @@
VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
enum VkRayTracingShaderGroupTypeNV {
VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0,
VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1,
VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
enum VkGeometryTypeNV {
VK_GEOMETRY_TYPE_TRIANGLES_NV = 0,
VK_GEOMETRY_TYPE_AABBS_NV = 1,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
enum VkAccelerationStructureTypeNV {
VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0,
VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
enum VkCopyAccelerationStructureModeNV {
VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0,
VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
enum VkAccelerationStructureMemoryRequirementsTypeNV {
VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0,
VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1,
@@ -2474,7 +2474,7 @@
//@extension("VK_NV_shading_rate_image") // 165
VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000,
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000,
@@ -2500,7 +2500,7 @@
//@extension("VK_EXT_conditional_rendering") // 82
VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400,
//@extension("VK_EXT_transform_feedback") // 29
@@ -2532,7 +2532,7 @@
VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_SHADER_STAGE_RAYGEN_BIT_NV = 0x00000100,
VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200,
VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400,
@@ -2636,7 +2636,7 @@
VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008,
VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = 0x00000010,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020,
}
@@ -2832,7 +2832,7 @@
//@extension("VK_NV_shading_rate_image") // 165
VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
- //@extension("VK_NV_raytracing") // 166
+ //@extension("VK_NV_ray_tracing") // 166
VK_PIPELINE_STAGE_RAY_TRACING_BIT_NV = 0x00200000,
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000,
@@ -2842,6 +2842,9 @@
//@extension("VK_EXT_transform_feedback") // 29
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000,
+
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000,
}
/// Render pass attachment description flags
@@ -3520,17 +3523,17 @@
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = 0x00000008,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
type VkFlags VkGeometryFlagsNV
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
bitfield VkGeometryFlagBitsNV {
VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001,
VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 0x00000002,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
type VkFlags VkGeometryInstanceFlagsNV
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
bitfield VkGeometryInstanceFlagBitsNV {
VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001,
VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
@@ -3538,9 +3541,9 @@
VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 0x00000008,
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
type VkFlags VkBuildAccelerationStructureFlagsNV
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
bitfield VkBuildAccelerationStructureFlagBitsNV {
VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001,
VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002,
@@ -7276,7 +7279,7 @@
const VkCoarseSampleOrderCustomNV* pCustomSampleOrders
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkRayTracingShaderGroupCreateInfoNV {
VkStructureType sType
const void* pNext
@@ -7287,7 +7290,7 @@
u32 intersectionShader
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkRayTracingPipelineCreateInfoNV {
VkStructureType sType
const void* pNext
@@ -7302,7 +7305,7 @@
s32 basePipelineIndex
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkGeometryTrianglesNV {
VkStructureType sType
const void* pNext
@@ -7319,7 +7322,7 @@
VkDeviceSize transformOffset
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkGeometryAABBNV {
VkStructureType sType
const void* pNext
@@ -7329,13 +7332,13 @@
VkDeviceSize offset
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkGeometryDataNV {
VkGeometryTrianglesNV triangles
VkGeometryAABBNV aabbs
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkGeometryNV {
VkStructureType sType
const void* pNext
@@ -7344,7 +7347,7 @@
VkGeometryFlagsNV flags
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkAccelerationStructureInfoNV {
VkStructureType sType
const void* pNext
@@ -7355,7 +7358,7 @@
const VkGeometryNV* pGeometries
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkAccelerationStructureCreateInfoNV {
VkStructureType sType
const void* pNext
@@ -7363,7 +7366,7 @@
VkAccelerationStructureInfoNV info
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkBindAccelerationStructureMemoryInfoNV {
VkStructureType sType
const void* pNext
@@ -7374,7 +7377,7 @@
const u32* pDeviceIndices
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkDescriptorAccelerationStructureInfoNV {
VkStructureType sType
const void* pNext
@@ -7382,7 +7385,7 @@
const VkAccelerationStructureNV* pAccelerationStructures
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkAccelerationStructureMemoryRequirementsInfoNV {
VkStructureType sType
const void* pNext
@@ -7390,7 +7393,7 @@
VkAccelerationStructureNV accelerationStructure
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
class VkPhysicalDeviceRaytracingPropertiesNV {
VkStructureType sType
void* pNext
@@ -11502,7 +11505,7 @@
const VkCoarseSampleOrderCustomNV* pCustomSampleOrders) {
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd VkResult vkCreateAccelerationStructureNV(
VkDevice device,
const VkAccelerationStructureCreateInfoNV* pCreateInfo,
@@ -11511,21 +11514,21 @@
return ?
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd void vkDestroyAccelerationStructureNV(
VkDevice device,
VkAccelerationStructureNV accelerationStructure,
const VkAllocationCallbacks* pAllocator) {
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd void vkGetAccelerationStructureMemoryRequirementsNV(
VkDevice device,
const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo,
VkMemoryRequirements2KHR* pMemoryRequirements) {
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd VkResult vkBindAccelerationStructureMemoryNV(
VkDevice device,
u32 bindInfoCount,
@@ -11533,7 +11536,7 @@
return ?
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd void vkCmdBuildAccelerationStructureNV(
VkCommandBuffer commandBuffer,
const VkAccelerationStructureInfoNV* pInfo,
@@ -11546,7 +11549,7 @@
VkDeviceSize scratchOffset) {
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd void vkCmdCopyAccelerationStructureNV(
VkCommandBuffer commandBuffer,
VkAccelerationStructureNV dst,
@@ -11554,7 +11557,7 @@
VkCopyAccelerationStructureModeNV mode) {
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd void vkCmdTraceRaysNV(
VkCommandBuffer commandBuffer,
VkBuffer raygenShaderBindingTableBuffer,
@@ -11573,7 +11576,7 @@
u32 depth) {
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd VkResult vkCreateRaytracingPipelinesNV(
VkDevice device,
VkPipelineCache pipelineCache,
@@ -11584,7 +11587,7 @@
return ?
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd VkResult vkGetRaytracingShaderHandlesNV(
VkDevice device,
VkPipeline pipeline,
@@ -11595,7 +11598,7 @@
return ?
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd VkResult vkGetAccelerationStructureHandleNV(
VkDevice device,
VkAccelerationStructureNV accelerationStructure,
@@ -11604,7 +11607,7 @@
return ?
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd void vkCmdWriteAccelerationStructurePropertiesNV(
VkCommandBuffer commandBuffer,
u32 accelerationStructureCount,
@@ -11614,7 +11617,7 @@
u32 firstQuery) {
}
-@extension("VK_NV_raytracing") // 166
+@extension("VK_NV_ray_tracing") // 166
cmd VkResult vkCompileDeferredNV(
VkDevice device,
VkPipeline pipeline,
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 7eaf7b2..fed8481 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -39,6 +39,9 @@
"-Wno-switch-enum",
"-Wno-undef",
+ // Have clang emit complete debug_info.
+ "-fstandalone-debug",
+
//"-DLOG_NDEBUG=0",
],