Merge "atrace: Set saved_cmdline_size to 8192"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index eff7c92..94c6821 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -183,6 +183,7 @@
{ "binder_driver", "Binder Kernel driver", 0, {
{ REQ, "events/binder/binder_transaction/enable" },
{ REQ, "events/binder/binder_transaction_received/enable" },
+ { OPT, "events/binder/binder_set_priority/enable" },
} },
{ "binder_lock", "Binder global lock trace", 0, {
{ OPT, "events/binder/binder_lock/enable" },
diff --git a/cmds/dumpstate/DumpstateInternal.h b/cmds/dumpstate/DumpstateInternal.h
index 2f7704d..10db5d6 100644
--- a/cmds/dumpstate/DumpstateInternal.h
+++ b/cmds/dumpstate/DumpstateInternal.h
@@ -32,6 +32,12 @@
ALOGI(__VA_ARGS__);
#endif
+#ifndef MYLOGW
+#define MYLOGW(...) \
+ fprintf(stderr, __VA_ARGS__); \
+ ALOGW(__VA_ARGS__);
+#endif
+
#ifndef MYLOGE
#define MYLOGE(...) \
fprintf(stderr, __VA_ARGS__); \
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f84d86d..745361c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -21,13 +21,9 @@
#include <fcntl.h>
#include <libgen.h>
#include <limits.h>
-#include <memory>
-#include <regex>
-#include <set>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string>
#include <string.h>
#include <sys/prctl.h>
#include <sys/resource.h>
@@ -35,6 +31,11 @@
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <memory>
+#include <regex>
+#include <set>
+#include <string>
+#include <vector>
#include <android-base/file.h>
#include <android-base/properties.h>
@@ -78,19 +79,29 @@
#define LOGPERSIST_DATA_DIR "/data/misc/logd"
#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
-#define TOMBSTONE_DIR "/data/tombstones"
-#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
-/* Can accomodate a tombstone number up to 9999. */
-#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
-#define NUM_TOMBSTONES 10
#define WLUTIL "/vendor/xbin/wlutil"
-typedef struct {
- char name[TOMBSTONE_MAX_LEN];
- int fd;
-} tombstone_data_t;
+// TODO(narayan): Since this information has to be kept in sync
+// with tombstoned, we should just put it in a common header.
+//
+// File: system/core/debuggerd/tombstoned/tombstoned.cpp
+static const std::string TOMBSTONE_DIR = "/data/tombstones/";
+static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
+static const std::string ANR_DIR = "/data/anr/";
+static const std::string ANR_FILE_PREFIX = "anr_";
-static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
+struct DumpData {
+ std::string name;
+ int fd;
+ time_t mtime;
+};
+
+static bool operator<(const DumpData& d1, const DumpData& d2) {
+ return d1.mtime > d2.mtime;
+}
+
+static std::unique_ptr<std::vector<DumpData>> tombstone_data;
+static std::unique_ptr<std::vector<DumpData>> anr_data;
// TODO: temporary variables and functions used during C++ refactoring
static Dumpstate& ds = Dumpstate::GetInstance();
@@ -122,23 +133,79 @@
static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
-/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
- * otherwise, gets just those modified in the last half an hour. */
-static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
- time_t thirty_minutes_ago = ds.now_ - 60 * 30;
- for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
- snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
- int fd = TEMP_FAILURE_RETRY(open(data[i].name,
- O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
- struct stat st;
- if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
- (ds.IsZipping() || st.st_mtime >= thirty_minutes_ago)) {
- data[i].fd = fd;
- } else {
- close(fd);
- data[i].fd = -1;
+/*
+ * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
+ * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
+ * is set, the vector only contains files that were written in the last 30 minutes.
+ */
+static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
+ const std::string& file_prefix,
+ bool limit_by_mtime) {
+ const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
+
+ std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
+ std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
+
+ struct dirent* entry = nullptr;
+ while ((entry = readdir(dump_dir.get()))) {
+ if (entry->d_type != DT_REG) {
+ continue;
}
+
+ const std::string base_name(entry->d_name);
+ if (base_name.find(file_prefix) != 0) {
+ continue;
+ }
+
+ const std::string abs_path = dir_path + base_name;
+ android::base::unique_fd fd(
+ TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
+ if (fd == -1) {
+ MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
+ break;
+ }
+
+ struct stat st = {};
+ if (fstat(fd, &st) == -1) {
+ MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
+ continue;
+ }
+
+ if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
+ MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
+ continue;
+ }
+
+ DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
+
+ dump_data->push_back(data);
}
+
+ std::sort(dump_data->begin(), dump_data->end());
+
+ return dump_data.release();
+}
+
+static bool AddDumps(const std::vector<DumpData>::const_iterator start,
+ const std::vector<DumpData>::const_iterator end,
+ const char* type_name, const bool add_to_zip) {
+ bool dumped = false;
+ for (auto it = start; it != end; ++it) {
+ const std::string& name = it->name;
+ const int fd = it->fd;
+ dumped = true;
+ if (ds.IsZipping() && add_to_zip) {
+ if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
+ MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
+ }
+ } else {
+ dump_file_from_fd(type_name, name.c_str(), fd);
+ }
+
+ close(fd);
+ }
+
+ return dumped;
}
// for_each_pid() callback to get mount info about a process.
@@ -860,11 +927,10 @@
RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
}
-static void AddAnrTraceFiles() {
- bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
+ const std::string& anr_traces_dir) {
std::string dump_traces_dir;
- /* show the traces we collected in main(), if that was done */
if (dump_traces_path != nullptr) {
if (add_to_zip) {
dump_traces_dir = dirname(dump_traces_path);
@@ -877,8 +943,6 @@
}
}
- std::string anr_traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
- std::string anr_traces_dir = dirname(anr_traces_path.c_str());
// Make sure directory is not added twice.
// TODO: this is an overzealous check because it's relying on dump_traces_path - which is
@@ -888,54 +952,110 @@
// be revisited.
bool already_dumped = anr_traces_dir == dump_traces_dir;
- MYLOGD("AddAnrTraceFiles(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
+ MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
- if (anr_traces_path.empty()) {
- printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
+ int fd = TEMP_FAILURE_RETRY(
+ open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
+ if (fd < 0) {
+ printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
} else {
- int fd = TEMP_FAILURE_RETRY(
- open(anr_traces_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
- if (fd < 0) {
- printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path.c_str(),
- strerror(errno));
- } else {
- if (add_to_zip) {
- if (!already_dumped) {
- MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
- anr_traces_dir.c_str());
- ds.AddDir(anr_traces_dir, true);
- already_dumped = true;
- }
- } else {
- MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
- anr_traces_path.c_str());
- dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path.c_str(), fd);
+ if (add_to_zip) {
+ if (!already_dumped) {
+ MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
+ anr_traces_dir.c_str());
+ ds.AddDir(anr_traces_dir, true);
}
+ } else {
+ MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
+ anr_traces_file.c_str());
+ dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
+ }
+ }
+}
+
+static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
+ MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
+ anr_traces_dir.c_str());
+
+ // If we're here, dump_traces_path will always be a temporary file
+ // (created with mkostemp or similar) that contains dumps taken earlier
+ // on in the process.
+ if (dump_traces_path != nullptr) {
+ if (add_to_zip) {
+ ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
+ } else {
+ MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
+ dump_traces_path);
+ ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
+ }
+
+ const int ret = unlink(dump_traces_path);
+ if (ret == -1) {
+ MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
+ strerror(errno));
}
}
- if (add_to_zip && already_dumped) {
- MYLOGD("Already dumped directory %s to the zip file\n", anr_traces_dir.c_str());
+ // Add a specific message for the first ANR Dump.
+ if (anr_data->size() > 0) {
+ AddDumps(anr_data->begin(), anr_data->begin() + 1,
+ "VM TRACES AT LAST ANR", add_to_zip);
+
+ if (anr_data->size() > 1) {
+ AddDumps(anr_data->begin() + 1, anr_data->end(),
+ "HISTORICAL ANR", add_to_zip);
+ }
+ } else {
+ printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
+ }
+}
+
+static void AddAnrTraceFiles() {
+ const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+
+ std::string anr_traces_file;
+ std::string anr_traces_dir;
+ bool is_global_trace_file = true;
+
+ // First check whether the stack-trace-dir property is set. When it's set,
+ // each ANR trace will be written to a separate file and not to a global
+ // stack trace file.
+ anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
+ if (anr_traces_dir.empty()) {
+ anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+ if (!anr_traces_file.empty()) {
+ anr_traces_dir = dirname(anr_traces_file.c_str());
+ }
+ } else {
+ is_global_trace_file = false;
+ }
+
+ // We have neither configured a global trace file nor a trace directory,
+ // there will be nothing to dump.
+ if (anr_traces_file.empty() && anr_traces_dir.empty()) {
+ printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
return;
}
+ if (is_global_trace_file) {
+ AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
+ } else {
+ AddAnrTraceDir(add_to_zip, anr_traces_dir);
+ }
+
/* slow traces for slow operations */
struct stat st;
- if (!anr_traces_path.empty()) {
- int tail = anr_traces_path.size() - 1;
- while (tail > 0 && anr_traces_path.at(tail) != '/') {
- tail--;
- }
+ if (!anr_traces_dir.empty()) {
int i = 0;
- while (1) {
- anr_traces_path = anr_traces_path.substr(0, tail + 1) +
- android::base::StringPrintf("slow%02d.txt", i);
- if (stat(anr_traces_path.c_str(), &st)) {
+ while (true) {
+ const std::string slow_trace_path =
+ anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
+ if (stat(slow_trace_path.c_str(), &st)) {
// No traces file at this index, done with the files.
break;
}
- ds.DumpFile("VM TRACES WHEN SLOW", anr_traces_path.c_str());
+ ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
i++;
}
}
@@ -1010,25 +1130,12 @@
AddAnrTraceFiles();
- int dumped = 0;
- for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
- if (tombstone_data[i].fd != -1) {
- const char *name = tombstone_data[i].name;
- int fd = tombstone_data[i].fd;
- dumped = 1;
- if (ds.IsZipping()) {
- if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
- MYLOGE("Unable to add tombstone %s to zip file\n", name);
- }
- } else {
- dump_file_from_fd("TOMBSTONE", name, fd);
- }
- close(fd);
- tombstone_data[i].fd = -1;
- }
- }
- if (!dumped) {
- printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
+ // NOTE: tombstones are always added as separate entries in the zip archive
+ // and are not interspersed with the main report.
+ const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
+ "TOMBSTONE", true /* add_to_zip */);
+ if (!tombstones_dumped) {
+ printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
}
DumpFile("NETWORK DEV INFO", "/proc/net/dev");
@@ -1707,7 +1814,9 @@
dump_traces_path = dump_traces();
/* Run some operations that require root. */
- get_tombstone_fds(tombstone_data);
+ tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
+ anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
+
ds.AddDir(RECOVERY_DIR, true);
ds.AddDir(RECOVERY_DATA_DIR, true);
ds.AddDir(LOGPERSIST_DATA_DIR, false);
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index f649a5e..5698d1b 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -38,6 +38,7 @@
#include <time.h>
#include <unistd.h>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -46,6 +47,7 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <cutils/properties.h>
#include <cutils/sockets.h>
@@ -852,15 +854,143 @@
return pids; // whether it was okay or not
}
+const char* DumpTraces(const std::string& traces_path);
+const char* DumpTracesTombstoned(const std::string& traces_dir);
+
/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
const char *dump_traces() {
DurationReporter duration_reporter("DUMP TRACES");
- const char* result = nullptr;
+ const std::string traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
+ if (!traces_dir.empty()) {
+ return DumpTracesTombstoned(traces_dir);
+ }
- std::string traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
- if (traces_path.empty()) return nullptr;
+ const std::string traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+ if (!traces_file.empty()) {
+ return DumpTraces(traces_file);
+ }
+ return nullptr;
+}
+
+static bool IsZygote(int pid) {
+ static const std::string kZygotePrefix = "zygote";
+
+ std::string cmdline;
+ if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
+ &cmdline)) {
+ return true;
+ }
+
+ return (cmdline.find(kZygotePrefix) == 0);
+}
+
+const char* DumpTracesTombstoned(const std::string& traces_dir) {
+ const std::string temp_file_pattern = traces_dir + "/dumptrace_XXXXXX";
+
+ const size_t buf_size = temp_file_pattern.length() + 1;
+ std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
+ memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
+
+ // Create a new, empty file to receive all trace dumps.
+ //
+ // TODO: This can be simplified once we remove support for the old style
+ // dumps. We can have a file descriptor passed in to dump_traces instead
+ // of creating a file, closing it and then reopening it again.
+ android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
+ if (fd < 0) {
+ MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
+ return nullptr;
+ }
+
+ // Nobody should have access to this temporary file except dumpstate, but we
+ // temporarily grant 'read' to 'others' here because this file is created
+ // when tombstoned is still running as root, but dumped after dropping. This
+ // can go away once support for old style dumping has.
+ const int chmod_ret = fchmod(fd, 0666);
+ if (chmod_ret < 0) {
+ MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
+ return nullptr;
+ }
+
+ std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
+ if (proc.get() == nullptr) {
+ MYLOGE("opendir /proc failed: %s\n", strerror(errno));
+ return nullptr;
+ }
+
+ // Number of times process dumping has timed out. If we encounter too many
+ // failures, we'll give up.
+ int timeout_failures = 0;
+ bool dalvik_found = false;
+
+ const std::set<int> hal_pids = get_interesting_hal_pids();
+
+ struct dirent* d;
+ while ((d = readdir(proc.get()))) {
+ int pid = atoi(d->d_name);
+ if (pid <= 0) {
+ continue;
+ }
+
+ const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
+ std::string exe;
+ if (!android::base::Readlink(link_name, &exe)) {
+ continue;
+ }
+
+ bool is_java_process;
+ if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
+ // Don't bother dumping backtraces for the zygote.
+ if (IsZygote(pid)) {
+ continue;
+ }
+
+ dalvik_found = true;
+ is_java_process = true;
+ } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
+ is_java_process = false;
+ } else {
+ // Probably a native process we don't care about, continue.
+ continue;
+ }
+
+ // If 3 backtrace dumps fail in a row, consider debuggerd dead.
+ if (timeout_failures == 3) {
+ dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
+ break;
+ }
+
+ const uint64_t start = Nanotime();
+ const int ret = dump_backtrace_to_file_timeout(
+ pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
+ is_java_process ? 5 : 20, fd);
+
+ if (ret == -1) {
+ dprintf(fd, "dumping failed, likely due to a timeout\n");
+ timeout_failures++;
+ continue;
+ }
+
+ // We've successfully dumped stack traces, reset the failure count
+ // and write a summary of the elapsed time to the file and continue with the
+ // next process.
+ timeout_failures = 0;
+
+ dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
+ pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
+ }
+
+ if (!dalvik_found) {
+ MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
+ }
+
+ return file_name_buf.release();
+}
+
+const char* DumpTraces(const std::string& traces_path) {
+ const char* result = NULL;
/* move the old traces.txt (if any) out of the way temporarily */
std::string anrtraces_path = traces_path + ".anr";
if (rename(traces_path.c_str(), anrtraces_path.c_str()) && errno != ENOENT) {
@@ -973,7 +1103,8 @@
/* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
if (timeout_failures == 3) {
dprintf(fd, "too many stack dump failures, skipping...\n");
- } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) {
+ } else if (dump_backtrace_to_file_timeout(
+ pid, kDebuggerdNativeBacktrace, 20, fd) == -1) {
dprintf(fd, "dumping failed, likely due to a timeout\n");
timeout_failures++;
} else {
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index a1fea8d..22ad718 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -915,15 +915,8 @@
return res;
}
-/* Try to ensure free_size bytes of storage are available.
- * Returns 0 on success.
- * This is rather simple-minded because doing a full LRU would
- * be potentially memory-intensive, and without atime it would
- * also require that apps constantly modify file metadata even
- * when just reading from the cache, which is pretty awful.
- */
binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid,
- int64_t freeStorageSize, int32_t flags) {
+ int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
std::lock_guard<std::recursive_mutex> lock(mLock);
@@ -938,11 +931,12 @@
return error("Failed to determine free space for " + data_path);
}
- int64_t needed = freeStorageSize - free;
+ int64_t cleared = 0;
+ int64_t needed = targetFreeBytes - free;
LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
- << freeStorageSize << "; needed " << needed;
+ << targetFreeBytes << "; needed " << needed;
- if (free >= freeStorageSize) {
+ if (free >= targetFreeBytes) {
return ok();
}
@@ -999,6 +993,7 @@
// 2. Populate tracker stats and insert into priority queue
ATRACE_BEGIN("populate");
+ int64_t cacheTotal = 0;
auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
return (left->getCacheRatio() < right->getCacheRatio());
};
@@ -1007,6 +1002,7 @@
for (const auto& it : trackers) {
it.second->loadStats();
queue.push(it.second);
+ cacheTotal += it.second->cacheUsed;
}
ATRACE_END();
@@ -1023,6 +1019,12 @@
break;
}
+ // Only keep clearing when we haven't pushed into reserved area
+ if (cacheReservedBytes > 0 && cleared >= (cacheTotal - cacheReservedBytes)) {
+ LOG(DEBUG) << "Refusing to clear cached data in reserved space";
+ break;
+ }
+
// Find the best tracker to work with; this might involve swapping
// if the active tracker is no longer the most over quota
bool nextBetter = active && !queue.empty()
@@ -1052,13 +1054,14 @@
}
active->cacheUsed -= item->size;
needed -= item->size;
+ cleared += item->size;
}
// Verify that we're actually done before bailing, since sneaky
// apps might be using hardlinks
if (needed <= 0) {
free = data_disk_free(data_path);
- needed = freeStorageSize - free;
+ needed = targetFreeBytes - free;
if (needed <= 0) {
break;
} else {
@@ -1073,11 +1076,11 @@
}
free = data_disk_free(data_path);
- if (free >= freeStorageSize) {
+ if (free >= targetFreeBytes) {
return ok();
} else {
return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64,
- freeStorageSize, data_path.c_str(), free));
+ targetFreeBytes, data_path.c_str(), free));
}
}
@@ -2256,13 +2259,13 @@
}
binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
- const std::string& instructionSet, const std::string& outputPath) {
+ const std::string& instructionSet, const std::unique_ptr<std::string>& outputPath) {
ENFORCE_UID(AID_SYSTEM);
std::lock_guard<std::recursive_mutex> lock(mLock);
const char* apk_path = apkPath.c_str();
const char* instruction_set = instructionSet.c_str();
- const char* oat_dir = outputPath.c_str();
+ const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
bool res = delete_odex(apk_path, instruction_set, oat_dir);
return res ? ok() : error();
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index a94223c..5756b82 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -101,8 +101,8 @@
binder::Status removeIdmap(const std::string& overlayApkPath);
binder::Status rmPackageDir(const std::string& packageDir);
binder::Status markBootComplete(const std::string& instructionSet);
- binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize,
- int32_t flags);
+ binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes,
+ int64_t cacheReservedBytes, int32_t flags);
binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid,
const std::string& packageName, const std::string& nativeLibPath32, int32_t userId);
binder::Status createOatDir(const std::string& oatDir, const std::string& instructionSet);
@@ -111,7 +111,7 @@
binder::Status moveAb(const std::string& apkPath, const std::string& instructionSet,
const std::string& outputPath);
binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
- const std::string& outputPath);
+ const std::unique_ptr<std::string>& outputPath);
binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index efcae4f..c8e76b0 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -66,7 +66,8 @@
void removeIdmap(@utf8InCpp String overlayApkPath);
void rmPackageDir(@utf8InCpp String packageDir);
void markBootComplete(@utf8InCpp String instructionSet);
- void freeCache(@nullable @utf8InCpp String uuid, long freeStorageSize, int flags);
+ void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes,
+ long cacheReservedBytes, int flags);
void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid,
@utf8InCpp String packageName, @utf8InCpp String nativeLibPath32, int userId);
void createOatDir(@utf8InCpp String oatDir, @utf8InCpp String instructionSet);
@@ -75,7 +76,7 @@
void moveAb(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
@utf8InCpp String outputPath);
void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
- @utf8InCpp String outputPath);
+ @nullable @utf8InCpp String outputPath);
boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 7419eb4..af78bfb 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1242,13 +1242,7 @@
ALOGE("installd cannot compute input vdex location for '%s'\n", path);
return false;
}
- if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
- // When we dex2oat because of boot image change, we are going to update
- // in-place the vdex file.
- in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
- } else {
- in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
- }
+ in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
}
// Infer the name of the output VDEX and create it.
@@ -1257,27 +1251,12 @@
return false;
}
- // If we are compiling because the boot image is out of date, we do not
- // need to recreate a vdex, and can use the same existing one.
- if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
- in_vdex_wrapper_fd->get() != -1 &&
- in_vdex_path_str == out_vdex_path_str) {
- // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
- // have bogus stale vdex files.
- out_vdex_wrapper_fd->reset(
- in_vdex_wrapper_fd->get(),
- [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
- // Disable auto close for the in wrapper fd (it will be done when destructing the out
- // wrapper).
- in_vdex_wrapper_fd->DisableAutoClose();
- } else {
- out_vdex_wrapper_fd->reset(
- open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
- [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
- if (out_vdex_wrapper_fd->get() < 0) {
- ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
- return false;
- }
+ out_vdex_wrapper_fd->reset(
+ open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+ [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+ if (out_vdex_wrapper_fd->get() < 0) {
+ ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
+ return false;
}
if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
out_vdex_path_str.c_str(), is_secondary_dex)) {
@@ -1940,8 +1919,11 @@
// Derive and delete the app image.
bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
+ // Derive and delete the vdex file.
+ bool return_value_vdex = unlink_and_check(create_vdex_filename(out_path).c_str());
+
// Report success.
- return return_value_oat && return_value_art;
+ return return_value_oat && return_value_art && return_value_vdex;
}
} // namespace installd
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 174ce77..aed068c 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -146,7 +146,7 @@
EXPECT_EQ(0, exists("com.example/cache/foo/one"));
EXPECT_EQ(0, exists("com.example/cache/foo/two"));
- service->freeCache(testUuid, kTbInBytes,
+ service->freeCache(testUuid, kTbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(0, exists("com.example/normal"));
@@ -163,13 +163,13 @@
touch("com.example/cache/foo/one", kMbInBytes, 60);
touch("com.example/cache/foo/two", kMbInBytes, 120);
- service->freeCache(testUuid, free() + kKbInBytes,
+ service->freeCache(testUuid, free() + kKbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
EXPECT_EQ(0, exists("com.example/cache/foo/two"));
- service->freeCache(testUuid, free() + kKbInBytes,
+ service->freeCache(testUuid, free() + kKbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
@@ -197,7 +197,7 @@
EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar1"));
EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar2"));
- service->freeCache(testUuid, kTbInBytes,
+ service->freeCache(testUuid, kTbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
@@ -219,7 +219,7 @@
setxattr("com.example/cache/foo", "user.cache_group");
- service->freeCache(testUuid, free() + kKbInBytes,
+ service->freeCache(testUuid, free() + kKbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
@@ -264,7 +264,7 @@
setxattr("com.example/cache/tomb", "user.cache_tombstone");
setxattr("com.example/cache/tomb/group", "user.cache_group");
- service->freeCache(testUuid, free() + kKbInBytes,
+ service->freeCache(testUuid, free() + kKbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(kMbInBytes, size("com.example/cache/group/file1"));
@@ -285,7 +285,7 @@
EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
- service->freeCache(testUuid, free() + kKbInBytes,
+ service->freeCache(testUuid, free() + kKbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(-1, size("com.example/cache/group/file1"));
@@ -306,7 +306,7 @@
EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
- service->freeCache(testUuid, kTbInBytes,
+ service->freeCache(testUuid, kTbInBytes, 0,
FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
EXPECT_EQ(-1, size("com.example/cache/group/file1"));
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 2eb58ae..87b9104 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -467,7 +467,8 @@
using namespace ::android::hardware;
using namespace ::android::hidl::manager::V1_0;
using namespace ::android::hidl::base::V1_0;
- auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+ using std::literals::chrono_literals::operator""s;
+ auto ret = timeoutIPC(2s, manager, &IServiceManager::debugDump, [&] (const auto &infos) {
std::map<std::string, TableEntry> entries;
for (const auto &info : infos) {
std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
@@ -477,7 +478,7 @@
.transport = "passthrough",
.serverPid = NO_PID,
.serverObjectAddress = NO_PTR,
- .clientPids = {},
+ .clientPids = info.clientPids,
.arch = ARCH_UNKNOWN
}).first->second.arch |= fromBaseArchitecture(info.arch);
}
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index ca477bf..c940404 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -77,14 +77,15 @@
return success;
}
-template<class Function, class I, class... Args>
+template<class R, class P, class Function, class I, class... Args>
typename std::result_of<Function(I *, Args...)>::type
-timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
+timeoutIPC(std::chrono::duration<R, P> wait, const sp<I> &interfaceObject, Function &&func,
+ Args &&... args) {
using ::android::hardware::Status;
typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()};
auto boundFunc = std::bind(std::forward<Function>(func),
interfaceObject.get(), std::forward<Args>(args)...);
- bool success = timeout(IPC_CALL_WAIT, [&ret, &boundFunc] {
+ bool success = timeout(wait, [&ret, &boundFunc] {
ret = std::move(boundFunc());
});
if (!success) {
@@ -93,5 +94,12 @@
return ret;
}
+template<class Function, class I, class... Args>
+typename std::result_of<Function(I *, Args...)>::type
+timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
+ return timeoutIPC(IPC_CALL_WAIT, interfaceObject, func, args...);
+}
+
+
} // namespace lshal
} // namespace android
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index 834dcbd..009dc52 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -26,6 +26,9 @@
typedef enum {
PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE = 11,
PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD = 12,
+ PLAYER_TYPE_AAUDIO = 13,
+ PLAYER_TYPE_HW_SOURCE = 14,
+ PLAYER_TYPE_EXTERNAL_PROXY = 15,
} player_type_t;
typedef enum {
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index f194bdf..d108120 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -121,13 +121,12 @@
// GraphicBuffers of a defaultDataSpace if no data space is specified
// in queueBuffer.
// The initial default is HAL_DATASPACE_UNKNOWN
- virtual status_t setDefaultBufferDataSpace(
- android_dataspace defaultDataSpace);
+ virtual status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
// setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
// These are merged with the bits passed to dequeueBuffer. The values are
// enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
- virtual status_t setConsumerUsageBits(uint32_t usage);
+ virtual status_t setConsumerUsageBits(uint64_t usage) override;
// setConsumerIsProtected will turn on an internal bit that indicates whether
// the consumer can handle protected gralloc buffers (i.e. with
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index dd8b992..537c957 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -170,7 +170,7 @@
// mConsumerUsageBits contains flags that the consumer wants for
// GraphicBuffers.
- uint32_t mConsumerUsageBits;
+ uint64_t mConsumerUsageBits;
// mConsumerIsProtected indicates the consumer is ready to handle protected
// buffer.
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 87bc800..0f8917a 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -80,9 +80,9 @@
//
// In both cases, the producer will need to call requestBuffer to get a
// GraphicBuffer handle for the returned slot.
- status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
+ virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
uint32_t width, uint32_t height, PixelFormat format,
- uint32_t usage, FrameEventHistoryDelta* outTimestamps) override;
+ uint64_t usage, FrameEventHistoryDelta* outTimestamps) override;
// See IGraphicBufferProducer::detachBuffer
virtual status_t detachBuffer(int slot);
@@ -152,7 +152,7 @@
// See IGraphicBufferProducer::allocateBuffers
virtual void allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage);
+ PixelFormat format, uint64_t usage) override;
// See IGraphicBufferProducer::allowAllocation
virtual status_t allowAllocation(bool allow);
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 57cce16..90de114 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -241,7 +241,7 @@
// e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
//
// Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t setConsumerUsageBits(uint32_t usage) = 0;
+ virtual status_t setConsumerUsageBits(uint64_t usage) = 0;
// setConsumerIsProtected will turn on an internal bit that indicates whether
// the consumer can handle protected gralloc buffers (i.e. with
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 9250806..6d16e74 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -195,7 +195,7 @@
// All other negative values are an unknown error returned downstream
// from the graphics allocator (typically errno).
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
- uint32_t h, PixelFormat format, uint32_t usage,
+ uint32_t h, PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) = 0;
// detachBuffer attempts to remove all ownership of the buffer in the given
@@ -517,7 +517,7 @@
// dequeueBuffer. If there are already the maximum number of buffers
// allocated, this function has no effect.
virtual void allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage) = 0;
+ PixelFormat format, uint64_t usage) = 0;
// Sets whether dequeueBuffer is allowed to allocate new buffers.
//
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index c8c6e99..0f7e12a 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -160,6 +160,9 @@
status_t getUniqueId(uint64_t* outId) const;
+ // Returns the CLOCK_MONOTONIC start time of the last dequeueBuffer call
+ nsecs_t getLastDequeueStartTime() const;
+
protected:
virtual ~Surface();
@@ -204,8 +207,8 @@
int dispatchSetBuffersStickyTransform(va_list args);
int dispatchSetBuffersTimestamp(va_list args);
int dispatchSetCrop(va_list args);
- int dispatchSetPostTransformCrop(va_list args);
int dispatchSetUsage(va_list args);
+ int dispatchSetUsage64(va_list args);
int dispatchLock(va_list args);
int dispatchUnlockAndPost(va_list args);
int dispatchSetSidebandStream(va_list args);
@@ -239,7 +242,7 @@
virtual int setBuffersTimestamp(int64_t timestamp);
virtual int setBuffersDataSpace(android_dataspace dataSpace);
virtual int setCrop(Rect const* rect);
- virtual int setUsage(uint32_t reqUsage);
+ virtual int setUsage(uint64_t reqUsage);
virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
public:
@@ -318,7 +321,7 @@
// mReqUsage is the set of buffer usage flags that will be requested
// at the next deuque operation. It is initialized to 0.
- uint32_t mReqUsage;
+ uint64_t mReqUsage;
// mTimestamp is the timestamp that will be used for the next buffer queue
// operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that
@@ -421,6 +424,9 @@
nsecs_t mLastDequeueDuration = 0;
nsecs_t mLastQueueDuration = 0;
+ // Stores the time right before we call IGBP::dequeueBuffer
+ nsecs_t mLastDequeueStartTime = 0;
+
Condition mQueueBufferCondition;
uint64_t mNextFrameNumber = 1;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index ec310cf..145c059 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -271,6 +271,7 @@
uint32_t getStride() const;
// size of allocated memory in bytes
size_t getSize() const;
+ android_dataspace getDataSpace() const;
};
// ---------------------------------------------------------------------------
diff --git a/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index 93c452a..c3a9d44 100644
--- a/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -65,7 +65,7 @@
status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
status_t setAsyncMode(bool async) override;
status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
- uint32_t h, ::android::PixelFormat format, uint32_t usage,
+ uint32_t h, ::android::PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) override;
status_t detachBuffer(int slot) override;
status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence)
@@ -83,7 +83,7 @@
override;
status_t setSidebandStream(const sp<NativeHandle>& stream) override;
void allocateBuffers(uint32_t width, uint32_t height,
- ::android::PixelFormat format, uint32_t usage) override;
+ ::android::PixelFormat format, uint64_t usage) override;
status_t allowAllocation(bool allow) override;
status_t setGenerationNumber(uint32_t generationNumber) override;
String8 getConsumerName() const override;
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index be754c2..168d355 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -703,9 +703,9 @@
return NO_ERROR;
}
-status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
+status_t BufferQueueConsumer::setConsumerUsageBits(uint64_t usage) {
ATRACE_CALL();
- BQ_LOGV("setConsumerUsageBits: %#x", usage);
+ BQ_LOGV("setConsumerUsageBits: %#" PRIx64, usage);
Mutex::Autolock lock(mCore->mMutex);
mCore->mConsumerUsageBits = usage;
return NO_ERROR;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 7510069..b39ecc5 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -349,7 +349,7 @@
status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
sp<android::Fence> *outFence, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage,
+ PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) {
ATRACE_CALL();
{ // Autolock scope
@@ -367,8 +367,7 @@
}
} // Autolock scope
- BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
- format, usage);
+ BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#" PRIx64, width, height, format, usage);
if ((width && !height) || (!width && height)) {
BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
@@ -418,11 +417,9 @@
// buffer. If this buffer would require reallocation to meet the
// requested attributes, we free it and attempt to get another one.
if (!mCore->mAllowAllocation) {
- if (buffer->needsReallocation(width, height, format,
- BQ_LAYER_COUNT, usage)) {
+ if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
if (mCore->mSharedBufferSlot == found) {
- BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
- "buffer");
+ BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
return BAD_VALUE;
}
mCore->mFreeSlots.insert(found);
@@ -435,8 +432,7 @@
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if (mCore->mSharedBufferSlot == found &&
- buffer->needsReallocation(width, height, format,
- BQ_LAYER_COUNT, usage)) {
+ buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
"buffer");
@@ -470,8 +466,7 @@
} else {
// We add 1 because that will be the frame number when this buffer
// is queued
- mCore->mBufferAge =
- mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
+ mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
}
BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
@@ -1313,14 +1308,14 @@
}
void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage) {
+ PixelFormat format, uint64_t usage) {
ATRACE_CALL();
while (true) {
size_t newBufferCount = 0;
uint32_t allocWidth = 0;
uint32_t allocHeight = 0;
PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
- uint32_t allocUsage = 0;
+ uint64_t allocUsage = 0;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
@@ -1354,7 +1349,7 @@
if (result != NO_ERROR) {
BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
- " %u, usage %u)", width, height, format, usage);
+ " %u, usage %#" PRIx64 ")", width, height, format, usage);
Mutex::Autolock lock(mCore->mMutex);
mCore->mIsAllocating = false;
mCore->mIsAllocatingCondition.broadcast();
@@ -1369,7 +1364,7 @@
uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
PixelFormat checkFormat = format != 0 ?
format : mCore->mDefaultBufferFormat;
- uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
+ uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
if (checkWidth != allocWidth || checkHeight != allocHeight ||
checkFormat != allocFormat || checkUsage != allocUsage) {
// Something changed while we released the lock. Retry.
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index c654f08..34c9d78 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -21,6 +21,8 @@
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
+#include <inttypes.h>
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
@@ -1219,7 +1221,7 @@
mEglDisplay = EGL_NO_DISPLAY;
mCropRect.makeInvalid();
const sp<GraphicBuffer>& buffer = mGraphicBuffer;
- ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d",
+ ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
buffer->getUsage(), buffer->getPixelFormat());
return UNKNOWN_ERROR;
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index a573bee..c705d39 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -132,7 +132,7 @@
return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_DATA_SPACE, defaultDataSpace);
}
- status_t setConsumerUsageBits(uint32_t usage) override {
+ status_t setConsumerUsageBits(uint64_t usage) override {
using Signature = decltype(&IGraphicBufferConsumer::setConsumerUsageBits);
return callRemote<Signature>(Tag::SET_CONSUMER_USAGE_BITS, usage);
}
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 8481b50..1b0fe06 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -125,7 +125,7 @@
}
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
- uint32_t height, PixelFormat format, uint32_t usage,
+ uint32_t height, PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) {
Parcel data, reply;
bool getFrameTimestamps = (outTimestamps != nullptr);
@@ -134,7 +134,7 @@
data.writeUint32(width);
data.writeUint32(height);
data.writeInt32(static_cast<int32_t>(format));
- data.writeUint32(usage);
+ data.writeUint64(usage);
data.writeBool(getFrameTimestamps);
status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
@@ -333,13 +333,13 @@
}
virtual void allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage) {
+ PixelFormat format, uint64_t usage) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeUint32(width);
data.writeUint32(height);
data.writeInt32(static_cast<int32_t>(format));
- data.writeUint32(usage);
+ data.writeUint64(usage);
status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
if (result != NO_ERROR) {
ALOGE("allocateBuffers failed to transact: %d", result);
@@ -517,7 +517,7 @@
}
status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage,
+ PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) override {
return mBase->dequeueBuffer(
slot, fence, w, h, format, usage, outTimestamps);
@@ -569,7 +569,7 @@
}
void allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage) override {
+ PixelFormat format, uint64_t usage) override {
return mBase->allocateBuffers(width, height, format, usage);
}
@@ -654,7 +654,7 @@
uint32_t width = data.readUint32();
uint32_t height = data.readUint32();
PixelFormat format = static_cast<PixelFormat>(data.readInt32());
- uint32_t usage = data.readUint32();
+ uint64_t usage = data.readUint64();
bool getTimestamps = data.readBool();
int buf = 0;
@@ -777,7 +777,7 @@
uint32_t width = data.readUint32();
uint32_t height = data.readUint32();
PixelFormat format = static_cast<PixelFormat>(data.readInt32());
- uint32_t usage = data.readUint32();
+ uint64_t usage = data.readUint64();
allocateBuffers(width, height, format, usage);
return NO_ERROR;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 83ebbe8..409a3cb 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -20,6 +20,8 @@
#include <gui/Surface.h>
+#include <inttypes.h>
+
#include <android/native_window.h>
#include <utils/Log.h>
@@ -471,7 +473,7 @@
uint32_t reqWidth;
uint32_t reqHeight;
PixelFormat reqFormat;
- uint32_t reqUsage;
+ uint64_t reqUsage;
bool enableFrameTimestamps;
{
@@ -501,18 +503,18 @@
int buf = -1;
sp<Fence> fence;
- nsecs_t now = systemTime();
+ nsecs_t startTime = systemTime();
FrameEventHistoryDelta frameTimestamps;
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
reqWidth, reqHeight, reqFormat, reqUsage,
enableFrameTimestamps ? &frameTimestamps : nullptr);
- mLastDequeueDuration = systemTime() - now;
+ mLastDequeueDuration = systemTime() - startTime;
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
- "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
- reqUsage, result);
+ "(%d, %d, %d, %#" PRIx64 ") failed: %d",
+ reqWidth, reqHeight, reqFormat, reqUsage, result);
return result;
}
@@ -524,6 +526,9 @@
Mutex::Autolock lock(mMutex);
+ // Write this while holding the mutex
+ mLastDequeueStartTime = startTime;
+
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen
@@ -959,6 +964,9 @@
case NATIVE_WINDOW_GET_HDR_SUPPORT:
res = dispatchGetHdrSupport(args);
break;
+ case NATIVE_WINDOW_SET_USAGE64:
+ res = dispatchSetUsage64(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -977,8 +985,13 @@
}
int Surface::dispatchSetUsage(va_list args) {
- int usage = va_arg(args, int);
- return setUsage(static_cast<uint32_t>(usage));
+ uint64_t usage = va_arg(args, uint32_t);
+ return setUsage(usage);
+}
+
+int Surface::dispatchSetUsage64(va_list args) {
+ uint64_t usage = va_arg(args, uint64_t);
+ return setUsage(usage);
}
int Surface::dispatchSetCrop(va_list args) {
@@ -1256,8 +1269,7 @@
uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
graphicBuffer->mGenerationNumber = mGenerationNumber;
int32_t attachedSlot = -1;
- status_t result = mGraphicBufferProducer->attachBuffer(
- &attachedSlot, graphicBuffer);
+ status_t result = mGraphicBufferProducer->attachBuffer(&attachedSlot, graphicBuffer);
if (result != NO_ERROR) {
ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
graphicBuffer->mGenerationNumber = priorGeneration;
@@ -1271,7 +1283,7 @@
return NO_ERROR;
}
-int Surface::setUsage(uint32_t reqUsage)
+int Surface::setUsage(uint64_t reqUsage)
{
ALOGV("Surface::setUsage");
Mutex::Autolock lock(mMutex);
@@ -1702,6 +1714,11 @@
return mGraphicBufferProducer->getUniqueId(outId);
}
+nsecs_t Surface::getLastDequeueStartTime() const {
+ Mutex::Autolock lock(mMutex);
+ return mLastDequeueStartTime;
+}
+
status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out) {
if (out == nullptr) {
ALOGE("%s: out must not be null!", __FUNCTION__);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8c83843..7ae2672 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1080,5 +1080,9 @@
return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
}
+android_dataspace ScreenshotClient::getDataSpace() const {
+ return mBuffer.dataSpace;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index fda5b94..7c0552e 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -125,7 +125,7 @@
t->attr.stride = l.getStride();
t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
t->attr.layerCount = l.getLayerCount();
- t->attr.usage = l.getUsage();
+ t->attr.usage = uint32_t(l.getUsage()); // FIXME: need 64-bits usage version
t->attr.id = l.getId();
t->attr.generationNumber = l.getGenerationNumber();
t->nativeHandle = hidl_handle(l.handle);
@@ -988,14 +988,15 @@
return toStatusT(mBase->setAsyncMode(async));
}
+// FIXME: usage bits truncated -- needs a 64-bits usage version
status_t H2BGraphicBufferProducer::dequeueBuffer(
int* slot, sp<Fence>* fence,
uint32_t w, uint32_t h, ::android::PixelFormat format,
- uint32_t usage, FrameEventHistoryDelta* outTimestamps) {
+ uint64_t usage, FrameEventHistoryDelta* outTimestamps) {
*fence = new Fence();
status_t fnStatus;
status_t transStatus = toStatusT(mBase->dequeueBuffer(
- w, h, static_cast<PixelFormat>(format), usage,
+ w, h, static_cast<PixelFormat>(format), uint32_t(usage),
outTimestamps != nullptr,
[&fnStatus, slot, fence, outTimestamps] (
Status status,
@@ -1144,10 +1145,11 @@
return toStatusT(mBase->setSidebandStream(stream == nullptr ? nullptr : stream->handle()));
}
+// FIXME: usage bits truncated -- needs a 64-bits usage version
void H2BGraphicBufferProducer::allocateBuffers(uint32_t width, uint32_t height,
- ::android::PixelFormat format, uint32_t usage) {
+ ::android::PixelFormat format, uint64_t usage) {
mBase->allocateBuffers(
- width, height, static_cast<PixelFormat>(format), usage);
+ width, height, static_cast<PixelFormat>(format), uint32_t(usage));
}
status_t H2BGraphicBufferProducer::allowAllocation(bool allow) {
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index 7ecf08c..6bc3ccf 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -38,7 +38,7 @@
}
status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t usage, FrameEventHistoryDelta* outTimestamps) override {
+ uint64_t usage, FrameEventHistoryDelta* outTimestamps) override {
return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
}
status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
@@ -67,7 +67,7 @@
return mProducer->setSidebandStream(stream);
}
void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
- uint32_t usage) override {
+ uint64_t usage) override {
mProducer->allocateBuffers(width, height, format, usage);
}
status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
@@ -105,7 +105,7 @@
// Override dequeueBuffer, optionally corrupting the returned slot number
status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage,
+ PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) override {
EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index fcaa23a..81820de 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -393,6 +393,22 @@
ASSERT_LE(removedBuffers.size(), 1u);
}
+TEST_F(SurfaceTest, TestGetLastDequeueStartTime) {
+ sp<ANativeWindow> anw(mSurface);
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU));
+
+ ANativeWindowBuffer* buffer = nullptr;
+ int32_t fenceFd = -1;
+
+ nsecs_t before = systemTime(CLOCK_MONOTONIC);
+ anw->dequeueBuffer(anw.get(), &buffer, &fenceFd);
+ nsecs_t after = systemTime(CLOCK_MONOTONIC);
+
+ nsecs_t lastDequeueTime = mSurface->getLastDequeueStartTime();
+ ASSERT_LE(before, lastDequeueTime);
+ ASSERT_GE(after, lastDequeueTime);
+}
+
class FakeConsumer : public BnConsumerListener {
public:
void onFrameAvailable(const BufferItem& /*item*/) override {}
@@ -1568,4 +1584,4 @@
EXPECT_EQ(-1, outDisplayPresentTime);
}
-}
+} // namespace android
diff --git a/libs/math/include/math/TMatHelpers.h b/libs/math/include/math/TMatHelpers.h
index 5cb725d..1423ade 100644
--- a/libs/math/include/math/TMatHelpers.h
+++ b/libs/math/include/math/TMatHelpers.h
@@ -342,9 +342,9 @@
template <typename MATRIX>
String8 asString(const MATRIX& m) {
String8 s;
- for (size_t c = 0; c < MATRIX::col_size(); c++) {
+ for (size_t c = 0; c < MATRIX::COL_SIZE; c++) {
s.append("| ");
- for (size_t r = 0; r < MATRIX::row_size(); r++) {
+ for (size_t r = 0; r < MATRIX::ROW_SIZE; r++) {
s.appendFormat("%7.2f ", m[r][c]);
}
s.append("|\n");
diff --git a/libs/nativebase/include/nativebase/nativebase.h b/libs/nativebase/include/nativebase/nativebase.h
index 90afb3f..7ecdfbd 100644
--- a/libs/nativebase/include/nativebase/nativebase.h
+++ b/libs/nativebase/include/nativebase/nativebase.h
@@ -88,14 +88,18 @@
int height;
int stride;
int format;
- int usage;
+ int usage_deprecated;
uintptr_t layerCount;
void* reserved[1];
const native_handle_t* handle;
+ uint64_t usage;
- void* reserved_proc[8];
+ // we needed extra space for storing the 64-bits usage flags
+ // the number of slots to use from reserved_proc depends on the
+ // architecture.
+ void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
} ANativeWindowBuffer_t;
typedef struct ANativeWindowBuffer ANativeWindowBuffer;
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 9224df6..c6994c3 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -190,8 +190,7 @@
}
int ANativeWindow_setUsage(ANativeWindow* window, uint64_t usage) {
- usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
- return native_window_set_usage(window, (uint32_t)usage); // FIXME: we need a 64-bits version
+ return native_window_set_usage(window, usage);
}
int ANativeWindow_setBufferCount(ANativeWindow* window, size_t bufferCount) {
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 6429c52..3df97a1 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -193,36 +193,37 @@
*/
enum {
// clang-format off
- NATIVE_WINDOW_SET_USAGE = 0,
- NATIVE_WINDOW_CONNECT = 1, /* deprecated */
- NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */
- NATIVE_WINDOW_SET_CROP = 3, /* private */
- NATIVE_WINDOW_SET_BUFFER_COUNT = 4,
- NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = 5, /* deprecated */
- NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6,
- NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7,
- NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8,
- NATIVE_WINDOW_SET_BUFFERS_FORMAT = 9,
- NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */
- NATIVE_WINDOW_LOCK = 11, /* private */
- NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */
- NATIVE_WINDOW_API_CONNECT = 13, /* private */
- NATIVE_WINDOW_API_DISCONNECT = 14, /* private */
- NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
- NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* private */
- NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17,/* private */
- NATIVE_WINDOW_SET_SIDEBAND_STREAM = 18,
- NATIVE_WINDOW_SET_BUFFERS_DATASPACE = 19,
- NATIVE_WINDOW_SET_SURFACE_DAMAGE = 20, /* private */
- NATIVE_WINDOW_SET_SHARED_BUFFER_MODE = 21,
- NATIVE_WINDOW_SET_AUTO_REFRESH = 22,
- NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION= 23,
- NATIVE_WINDOW_GET_NEXT_FRAME_ID = 24,
- NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS = 25,
- NATIVE_WINDOW_GET_COMPOSITOR_TIMING = 26,
- NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27,
- NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28,
- NATIVE_WINDOW_GET_HDR_SUPPORT = 29,
+ NATIVE_WINDOW_SET_USAGE = 0, /* deprecated */
+ NATIVE_WINDOW_CONNECT = 1, /* deprecated */
+ NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */
+ NATIVE_WINDOW_SET_CROP = 3, /* private */
+ NATIVE_WINDOW_SET_BUFFER_COUNT = 4,
+ NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = 5, /* deprecated */
+ NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6,
+ NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7,
+ NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8,
+ NATIVE_WINDOW_SET_BUFFERS_FORMAT = 9,
+ NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */
+ NATIVE_WINDOW_LOCK = 11, /* private */
+ NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */
+ NATIVE_WINDOW_API_CONNECT = 13, /* private */
+ NATIVE_WINDOW_API_DISCONNECT = 14, /* private */
+ NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
+ NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* deprecated, unimplemented */
+ NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17, /* private */
+ NATIVE_WINDOW_SET_SIDEBAND_STREAM = 18,
+ NATIVE_WINDOW_SET_BUFFERS_DATASPACE = 19,
+ NATIVE_WINDOW_SET_SURFACE_DAMAGE = 20, /* private */
+ NATIVE_WINDOW_SET_SHARED_BUFFER_MODE = 21,
+ NATIVE_WINDOW_SET_AUTO_REFRESH = 22,
+ NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION = 23,
+ NATIVE_WINDOW_GET_NEXT_FRAME_ID = 24,
+ NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS = 25,
+ NATIVE_WINDOW_GET_COMPOSITOR_TIMING = 26,
+ NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27,
+ NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28,
+ NATIVE_WINDOW_GET_HDR_SUPPORT = 29,
+ NATIVE_WINDOW_SET_USAGE64 = 30,
// clang-format on
};
@@ -533,20 +534,18 @@
typedef struct ANativeWindow android_native_window_t __deprecated;
/*
- * native_window_set_usage(..., usage)
+ * native_window_set_usage64(..., usage)
* Sets the intended usage flags for the next buffers
* acquired with (*lockBuffer)() and on.
- * By default (if this function is never called), a usage of
- * GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
- * is assumed.
+ *
+ * Valid usage flags are defined in android/hardware_buffer.h
+ * All AHARDWAREBUFFER_USAGE_* flags can be specified as needed.
+ *
* Calling this function will usually cause following buffers to be
* reallocated.
*/
-
-static inline int native_window_set_usage(
- struct ANativeWindow* window, int usage)
-{
- return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+static inline int native_window_set_usage(struct ANativeWindow* window, uint64_t usage) {
+ return window->perform(window, NATIVE_WINDOW_SET_USAGE64, usage);
}
/* deprecated. Always returns 0. Don't call. */
@@ -589,45 +588,6 @@
}
/*
- * native_window_set_post_transform_crop(..., crop)
- * Sets which region of the next queued buffers needs to be considered.
- * Depending on the scaling mode, a buffer's crop region is scaled and/or
- * cropped to match the surface's size. This function sets the crop in
- * post-transformed pixel coordinates.
- *
- * The specified crop region applies to all buffers queued after it is called.
- *
- * If 'crop' is NULL, subsequently queued buffers won't be cropped.
- *
- * An error is returned if for instance the crop region is invalid, out of the
- * buffer's bound or if the window is invalid.
- */
-static inline int native_window_set_post_transform_crop(
- struct ANativeWindow* window,
- android_native_rect_t const * crop)
-{
- return window->perform(window, NATIVE_WINDOW_SET_POST_TRANSFORM_CROP, crop);
-}
-
-/*
- * native_window_set_active_rect(..., active_rect)
- *
- * This function is deprecated and will be removed soon. For now it simply
- * sets the post-transform crop for compatibility while multi-project commits
- * get checked.
- */
-static inline int native_window_set_active_rect(
- struct ANativeWindow* window,
- android_native_rect_t const * active_rect) __deprecated;
-
-static inline int native_window_set_active_rect(
- struct ANativeWindow* window,
- android_native_rect_t const * active_rect)
-{
- return native_window_set_post_transform_crop(window, active_rect);
-}
-
-/*
* native_window_set_buffer_count(..., count)
* Sets the number of buffers associated with this native window.
*/
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index ee85c9b..c880500 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -51,6 +51,7 @@
height =
stride =
format =
+ usage_deprecated = 0;
usage = 0;
layerCount = 0;
handle = NULL;
@@ -59,14 +60,12 @@
// deprecated
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
- : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage),
- requestorName)
+ : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage), requestorName)
{
}
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
- PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage,
- std::string requestorName)
+ PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, std::string requestorName)
: GraphicBuffer()
{
mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
@@ -139,7 +138,7 @@
static_cast<int>(inHeight) == height &&
inFormat == format &&
inLayerCount == layerCount &&
- static_cast<int>(inUsage) == usage)
+ inUsage == usage)
return NO_ERROR;
if (handle) {
@@ -147,8 +146,7 @@
allocator.free(handle);
handle = 0;
}
- return initWithSize(inWidth, inHeight, inFormat, inLayerCount,
- inUsage, "[Reallocation]");
+ return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
}
bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
@@ -158,7 +156,7 @@
if (static_cast<int>(inHeight) != height) return true;
if (inFormat != format) return true;
if (inLayerCount != layerCount) return true;
- if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
+ if ((usage & inUsage) != inUsage) return true;
return false;
}
@@ -176,7 +174,8 @@
height = static_cast<int>(inHeight);
format = inFormat;
layerCount = inLayerCount;
- usage = static_cast<int>(inUsage);
+ usage = inUsage;
+ usage_deprecated = int(usage);
stride = static_cast<int>(outStride);
}
return err;
@@ -191,7 +190,8 @@
ANativeWindowBuffer::height = static_cast<int>(height);
ANativeWindowBuffer::stride = static_cast<int>(stride);
ANativeWindowBuffer::format = format;
- ANativeWindowBuffer::usage = static_cast<int>(usage);
+ ANativeWindowBuffer::usage = usage;
+ ANativeWindowBuffer::usage_deprecated = int(usage);
ANativeWindowBuffer::layerCount = layerCount;
@@ -312,8 +312,7 @@
width, height);
return BAD_VALUE;
}
- status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect,
- ycbcr, fenceFd);
+ status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, ycbcr, fenceFd);
return res;
}
@@ -324,7 +323,7 @@
}
size_t GraphicBuffer::getFlattenedSize() const {
- return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int);
+ return static_cast<size_t>(13 + (handle ? handle->numInts : 0)) * sizeof(int);
}
size_t GraphicBuffer::getFdCount() const {
@@ -339,25 +338,25 @@
if (count < fdCountNeeded) return NO_MEMORY;
int32_t* buf = static_cast<int32_t*>(buffer);
- buf[0] = 'GBFR';
+ buf[0] = 'GB01';
buf[1] = width;
buf[2] = height;
buf[3] = stride;
buf[4] = format;
buf[5] = static_cast<int32_t>(layerCount);
- buf[6] = usage;
+ buf[6] = int(usage); // low 32-bits
buf[7] = static_cast<int32_t>(mId >> 32);
buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
buf[9] = static_cast<int32_t>(mGenerationNumber);
buf[10] = 0;
buf[11] = 0;
+ buf[12] = int(usage >> 32); // high 32-bits
if (handle) {
buf[10] = handle->numFds;
buf[11] = handle->numInts;
- memcpy(fds, handle->data,
- static_cast<size_t>(handle->numFds) * sizeof(int));
- memcpy(&buf[12], handle->data + handle->numFds,
+ memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int));
+ memcpy(buf + 13, handle->data + handle->numFds,
static_cast<size_t>(handle->numInts) * sizeof(int));
}
@@ -373,10 +372,21 @@
status_t GraphicBuffer::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
- if (size < 12 * sizeof(int)) return NO_MEMORY;
int const* buf = static_cast<int const*>(buffer);
- if (buf[0] != 'GBFR') return BAD_TYPE;
+
+ // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
+ // see H2BGraphicBufferProducer.cpp
+ uint32_t flattenWordCount = 0;
+ if (buf[0] == 'GB01') {
+ // new version with 64-bits usage bits
+ flattenWordCount = 13;
+ } else if (buf[0] == 'GBFR') {
+ // old version, when usage bits were 32-bits
+ flattenWordCount = 12;
+ } else {
+ return BAD_TYPE;
+ }
const size_t numFds = static_cast<size_t>(buf[10]);
const size_t numInts = static_cast<size_t>(buf[11]);
@@ -386,15 +396,16 @@
// chosen to be high enough to not cause issues and low enough to prevent
// overflow problems.
const size_t maxNumber = 4096;
- if (numFds >= maxNumber || numInts >= (maxNumber - 12)) {
- width = height = stride = format = layerCount = usage = 0;
+ if (numFds >= maxNumber || numInts >= (maxNumber - flattenWordCount)) {
+ width = height = stride = format = usage_deprecated = 0;
+ layerCount = 0;
+ usage = 0;
handle = NULL;
- ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
- numFds, numInts);
+ ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
return BAD_VALUE;
}
- const size_t sizeNeeded = (12 + numInts) * sizeof(int);
+ const size_t sizeNeeded = (flattenWordCount + numInts) * sizeof(int);
if (size < sizeNeeded) return NO_MEMORY;
size_t fdCountNeeded = numFds;
@@ -411,20 +422,29 @@
stride = buf[3];
format = buf[4];
layerCount = static_cast<uintptr_t>(buf[5]);
- usage = buf[6];
+ usage_deprecated = buf[6];
+ if (flattenWordCount == 13) {
+ usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6]);
+ } else {
+ usage = uint64_t(usage_deprecated);
+ }
native_handle* h = native_handle_create(
static_cast<int>(numFds), static_cast<int>(numInts));
if (!h) {
- width = height = stride = format = layerCount = usage = 0;
+ width = height = stride = format = usage_deprecated = 0;
+ layerCount = 0;
+ usage = 0;
handle = NULL;
ALOGE("unflatten: native_handle_create failed");
return NO_MEMORY;
}
memcpy(h->data, fds, numFds * sizeof(int));
- memcpy(h->data + numFds, &buf[12], numInts * sizeof(int));
+ memcpy(h->data + numFds, buf + flattenWordCount, numInts * sizeof(int));
handle = h;
} else {
- width = height = stride = format = layerCount = usage = 0;
+ width = height = stride = format = usage_deprecated = 0;
+ layerCount = 0;
+ usage = 0;
handle = NULL;
}
@@ -439,10 +459,11 @@
buffer_handle_t importedHandle;
status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
if (err != NO_ERROR) {
- width = height = stride = format = layerCount = usage = 0;
+ width = height = stride = format = usage_deprecated = 0;
+ layerCount = 0;
+ usage = 0;
handle = NULL;
- ALOGE("unflatten: registerBuffer failed: %s (%d)",
- strerror(-err), err);
+ ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
return err;
}
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 9a5aa69..95c2d22 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -141,7 +141,7 @@
uint32_t getWidth() const { return static_cast<uint32_t>(width); }
uint32_t getHeight() const { return static_cast<uint32_t>(height); }
uint32_t getStride() const { return static_cast<uint32_t>(stride); }
- uint32_t getUsage() const { return static_cast<uint32_t>(usage); }
+ uint64_t getUsage() const { return usage; }
PixelFormat getPixelFormat() const { return format; }
uint32_t getLayerCount() const { return static_cast<uint32_t>(layerCount); }
Rect getBounds() const { return Rect(width, height); }
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 7dd076a..fca5eca 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -131,9 +131,9 @@
status_t BufferHubQueueProducer::dequeueBuffer(
int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage,
+ PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* /* out_timestamps */) {
- ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%u", width,
+ ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%llu", width,
height, format, usage);
status_t ret;
@@ -532,7 +532,7 @@
void BufferHubQueueProducer::allocateBuffers(uint32_t /* width */,
uint32_t /* height */,
PixelFormat /* format */,
- uint32_t /* usage */) {
+ uint64_t /* usage */) {
// TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
// of buffers permitted by the current BufferQueue configuration (aka
// |max_buffer_count_|).
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index 7890176..638a56c 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -42,7 +42,7 @@
// See |IGraphicBufferProducer::dequeueBuffer|
status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
- uint32_t height, PixelFormat format, uint32_t usage,
+ uint32_t height, PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) override;
// See |IGraphicBufferProducer::detachBuffer|
@@ -80,7 +80,7 @@
// See |IGraphicBufferProducer::allocateBuffers|
void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
- uint32_t usage) override;
+ uint64_t usage) override;
// See |IGraphicBufferProducer::allowAllocation|
status_t allowAllocation(bool allow) override;
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 82469b8..4d9b215 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -1,6 +1,7 @@
#include "include/dvr/dvr_buffer.h"
#include <android/hardware_buffer.h>
+#include <dvr/dvr_shared_buffers.h>
#include <private/dvr/buffer_hub_client.h>
#include <ui/GraphicBuffer.h>
@@ -176,6 +177,11 @@
hardware_buffer);
}
+// Retrieve the shared buffer layout version defined in dvr_shared_buffers.h.
+int dvrBufferGlobalLayoutVersionGet() {
+ return android::dvr::kSharedBufferLayoutVersion;
+}
+
const struct native_handle* dvrWriteBufferGetNativeHandle(
DvrWriteBuffer* write_buffer) {
if (!write_buffer || !write_buffer->write_buffer)
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index 2affacd..0f4749d 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -171,8 +171,6 @@
auto status = client->GetGlobalBuffer(key);
if (!status) {
- ALOGE("dvrGetGlobalBuffer: Failed to find named buffer key=%d: %s", key,
- status.GetErrorMessage().c_str());
return -status.error();
}
*out_buffer = CreateDvrBufferFromIonBuffer(status.take());
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 47a2a60..17b29d4 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -145,6 +145,7 @@
typedef void (*DvrBufferDestroyPtr)(DvrBuffer* buffer);
typedef int (*DvrBufferGetAHardwareBufferPtr)(
DvrBuffer* buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrBufferGlobalLayoutVersionGetPtr)();
typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)(
DvrBuffer* buffer);
@@ -211,7 +212,7 @@
uint32_t* next_vsync_count);
// libs/vr/libvrsensor/include/dvr/pose_client.h
-typedef DvrPoseClient* (*DvrPoseClientCreatePtr)(void);
+typedef DvrPoseClient* (*DvrPoseClientCreatePtr)();
typedef void (*DvrPoseClientDestroyPtr)(DvrPoseClient* client);
typedef int (*DvrPoseClientGetPtr)(DvrPoseClient* client, uint32_t vsync_count,
DvrPoseAsync* out_pose);
@@ -222,7 +223,13 @@
DvrPoseAsync* out_pose);
// services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
-typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(void);
+
+// Touchpad IDs for *Touch*() and *ButtonState*() calls.
+enum {
+ DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
+ DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
+};
+typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)();
typedef void (*DvrVirtualTouchpadDestroyPtr)(DvrVirtualTouchpad* client);
typedef int (*DvrVirtualTouchpadAttachPtr)(DvrVirtualTouchpad* client);
typedef int (*DvrVirtualTouchpadDetachPtr)(DvrVirtualTouchpad* client);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 8cdad7d..802a0f7 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -60,6 +60,7 @@
DVR_V1_API_ENTRY(BufferDestroy);
DVR_V1_API_ENTRY(BufferGetAHardwareBuffer);
DVR_V1_API_ENTRY(BufferGetNativeHandle);
+DVR_V1_API_ENTRY(BufferGlobalLayoutVersionGet);
// Write buffer queue
DVR_V1_API_ENTRY(WriteBufferQueueDestroy);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index af55698..935a7b2 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -95,6 +95,9 @@
int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
AHardwareBuffer** hardware_buffer);
+// Retrieve the shared buffer layout version defined in dvr_shared_buffers.h.
+int dvrBufferGlobalLayoutVersionGet();
+
// TODO(eieio): Switch to return int and take an out parameter for the native
// handle.
const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
diff --git a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h b/libs/vr/libdvr/include/dvr/dvr_config.h
similarity index 74%
rename from libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
rename to libs/vr/libdvr/include/dvr/dvr_config.h
index cfe9d62..3d2c066 100644
--- a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
+++ b/libs/vr/libdvr/include/dvr/dvr_config.h
@@ -1,17 +1,18 @@
-#ifndef ANDROID_DVR_VRFLINGER_CONFIG_H
-#define ANDROID_DVR_VRFLINGER_CONFIG_H
+#ifndef ANDROID_DVR_CONFIG_H
+#define ANDROID_DVR_CONFIG_H
// This header is shared by VrCore and Android and must be kept in sync.
+#include <stdint.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
// This is a shared memory buffer for passing config data from VrCore to
// libvrflinger in SurfaceFlinger.
-struct DvrVrFlingerConfig {
+struct __attribute__((packed, aligned(16))) DvrConfig {
// Offset before vsync to submit frames to hardware composer.
- int frame_post_offset_ns{4000000};
+ int32_t frame_post_offset_ns{4000000};
// If the number of pending fences goes over this count at the point when we
// are about to submit a new frame to HWC, we will drop the frame. This
@@ -20,11 +21,14 @@
// the next vsync, at the point when the DMA to the display completes.
// Currently we use a smart display and the EDS timing coincides with zero
// pending fences, so this is 0.
- size_t allowed_pending_fence_count{0};
+ int32_t allowed_pending_fence_count{0};
// New fields should always be added to the end for backwards compat.
+
+ // Reserved padding to 16 bytes.
+ uint8_t pad[8];
};
__END_DECLS
-#endif // ANDROID_DVR_VRFLINGER_CONFIG_H
+#endif // ANDROID_DVR_CONFIG_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
index 4bb0a2f..26f85a0 100644
--- a/libs/vr/libdvr/include/dvr/dvr_display_manager.h
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -84,7 +84,7 @@
size_t* count_out);
// Returns the update flags for the surface at |surface_index| in the state
-// object. The flags may be used to determine what changes, if any, occured to
+// object. The flags may be used to determine what changes, if any, occurred to
// the surface since the last state update.
// @return 0 on success. Otherwise returns a negative error value.
int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
index 60e22de..0ba76e2 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
@@ -24,37 +24,73 @@
DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback,
void* client_state);
+// Called to free the DvrHwcClient pointer.
void dvrHwcClientDestroy(DvrHwcClient* client);
// Called to free the frame information.
+// @param frame Pointer for the valid frame used for the query.
void dvrHwcFrameDestroy(DvrHwcFrame* frame);
+// @param frame Pointer for the valid frame used for the query.
+// @return Identifier for the display associated by the frame.
DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
+// @param frame Pointer for the valid frame used for the query.
+// @return width of the physical display associated with |frame|. This does not
+// take into account any orientation changes.
int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame);
+// @param frame Pointer for the valid frame used for the query.
+// @return height of the physical display associated with |frame|. This does not
+// take into account any orientation changes.
int32_t dvrHwcFrameGetDisplayHeight(DvrHwcFrame* frame);
+// @param frame Pointer for the valid frame used for the query.
// @return True if the display has been removed. In this case the current frame
// does not contain any valid layers to display. It is a signal to clean up any
// display related state.
bool dvrHwcFrameGetDisplayRemoved(DvrHwcFrame* frame);
+// @param frame Pointer for the valid frame used for the query.
// @return Number of layers in the frame.
size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame);
+// @param frame Pointer for the valid frame used for the query.
+// @return The ID of the currently active display configuration.
uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The ID of the current color mode. See HAL_COLOR_MODE_* for valid
+// values.
uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @param out_matrix Output parameter for a float[16] array which will be filled
+// with the color transform matrix.
+// @param out_hint Output parameter which will contain the color transform hint.
+// See HAL_COLOR_TRANSFORM_* for valid values.
void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
int32_t* out_hint);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The current power mode for the display. See HWC2_POWER_MODE_* for
+// valid values.
uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The current state of vsync. See HWC2_VSYNC_* for valid values.
uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return A unique ID for the layer.
DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
// Return the graphic buffer associated with the layer at |layer_index| in
// |frame|.
//
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
// @return Graphic buffer. Caller owns the buffer and is responsible for freeing
// it. (see AHardwareBuffer_release())
AHardwareBuffer* dvrHwcFrameGetLayerBuffer(DvrHwcFrame* frame,
@@ -62,42 +98,98 @@
// Returns the fence FD for the layer at index |layer_index| in |frame|.
//
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
// @return Fence FD. Caller owns the FD and is responsible for closing it.
int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return describing the portion of the display covered by the layer. Will
+// not exceed the display dimensions.
DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return describing the portion of the layer that will fill the display
+// frame. Will not exceed the layer dimensions.
DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The blend mode of the layer.
DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The alpha value to be applied to the whole layer. Will be in the
+// [0.0, 1.0] range.
float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The type of the layer assigned by the window manager.
uint32_t dvrHwcFrameGetLayerType(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The application id the layer belongs to.
uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame,
size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The z-order for the layer.
uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param out_x Output parameter for the x coordinate of the cursor location.
+// @param out_y Output parameter for the y coordinate of the cursor location.
void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
int32_t* out_x, int32_t* out_y);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The transformation that needs to be applied to the layer before
+// presenting it. See DVR_HWC_TRANSFORM_* for valid values.
uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The dataspace which represents how the pixel values should be
+// interpreted. See HAL_DATASPACE_* for valid values.
uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The color of the layer if layer composition is SOLID_COLOR.
uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The number of visible regions.
uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param index The index of the visible region for the layer.
+// @return The rectangle describing the visible region.
DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
size_t layer_index, size_t index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The number of damanged regions.
uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
size_t layer_index);
+
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param index The index of the damanged region for the layer.
+// @return The rectangle describing the damaged region.
DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
size_t layer_index, size_t index);
#ifdef __cplusplus
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
index 36c30f9..1d5eda6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
@@ -26,6 +26,15 @@
DVR_HWC_COMPOSITION_SIDEBAND = 5,
};
+enum DvrHwcTransform {
+ DVR_HWC_TRANSFORM_NONE = 0,
+ DVR_HWC_TRANSFORM_FLIP_H = 1,
+ DVR_HWC_TRANSFORM_FLIP_V = 2,
+ DVR_HWC_TRANSFORM_ROT_90 = 4,
+ DVR_HWC_TRANSFORM_ROT_180 = 3,
+ DVR_HWC_TRANSFORM_ROT_270 = 7,
+};
+
typedef uint64_t DvrHwcDisplay;
typedef uint64_t DvrHwcLayer;
diff --git a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
index ce17f0c..096f800 100644
--- a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
+++ b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
@@ -1,8 +1,8 @@
#ifndef ANDROID_DVR_SHARED_BUFFERS_H_
#define ANDROID_DVR_SHARED_BUFFERS_H_
+#include <dvr/dvr_config.h>
#include <dvr/dvr_pose.h>
-#include <dvr/dvr_vrflinger_config.h>
#include <dvr/dvr_vsync.h>
#include <libbroadcastring/broadcast_ring.h>
@@ -11,7 +11,7 @@
namespace dvr {
// Increment when the layout for the buffers change.
-constexpr uint32_t kSharedBufferLayoutVersion = 1;
+enum : uint32_t { kSharedBufferLayoutVersion = 1 };
// Note: These buffers will be mapped from various system processes as well
// as VrCore and the application processes in a r/w manner.
@@ -26,6 +26,7 @@
static_assert(sizeof(DvrPoseAsync) == 128, "Unexpected size for DvrPoseAsync");
static_assert(sizeof(DvrPose) == 96, "Unexpected size for DvrPose");
static_assert(sizeof(DvrVsync) == 32, "Unexpected size for DvrVsync");
+static_assert(sizeof(DvrConfig) == 16, "Unexpected size for DvrConfig");
// A helper class that provides compile time sized traits for the BroadcastRing.
template <class DvrType, size_t StaticCount>
@@ -41,13 +42,12 @@
// Traits classes.
using DvrPoseTraits = DvrRingBufferTraits<DvrPose, 0>;
using DvrVsyncTraits = DvrRingBufferTraits<DvrVsync, 2>;
-using DvrVrFlingerConfigTraits = DvrRingBufferTraits<DvrVrFlingerConfig, 2>;
+using DvrConfigTraits = DvrRingBufferTraits<DvrConfig, 2>;
// The broadcast ring classes that will expose the data.
using DvrPoseRing = BroadcastRing<DvrPose, DvrPoseTraits>;
using DvrVsyncRing = BroadcastRing<DvrVsync, DvrVsyncTraits>;
-using DvrVrFlingerConfigRing =
- BroadcastRing<DvrVrFlingerConfig, DvrVrFlingerConfigTraits>;
+using DvrConfigRing = BroadcastRing<DvrConfig, DvrConfigTraits>;
// This is a shared memory buffer for passing pose data estimated at vsyncs.
//
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index 419083f..566f9de 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,9 +1,9 @@
#include <android/hardware_buffer.h>
#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_config.h>
#include <dvr/dvr_display_manager.h>
#include <dvr/dvr_shared_buffers.h>
#include <dvr/dvr_surface.h>
-#include <dvr/dvr_vrflinger_config.h>
#include <system/graphics.h>
#include <base/logging.h>
@@ -285,8 +285,8 @@
const uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
- size_t correct_size = DvrVrFlingerConfigRing::MemorySize();
- size_t wrong_size = DvrVrFlingerConfigRing::MemorySize(0);
+ size_t correct_size = DvrConfigRing::MemorySize();
+ size_t wrong_size = DvrConfigRing::MemorySize(0);
// Setup an invalid config buffer (too small) and assert that it fails.
DvrBuffer* setup_buffer = nullptr;
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 69300d6..f55e994 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -37,6 +37,7 @@
"libpdx",
"liblog",
"libutils",
+ "libvndksupport",
],
}
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 7a78d1f..c18ae82 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -481,9 +481,9 @@
int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
std::lock_guard<std::mutex> lock(shared_config_mutex_);
- shared_config_ring_ = DvrVrFlingerConfigRing();
+ shared_config_ring_ = DvrConfigRing();
- if (ion_buffer.width() < DvrVrFlingerConfigRing::MemorySize()) {
+ if (ion_buffer.width() < DvrConfigRing::MemorySize()) {
ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
return -EINVAL;
}
@@ -497,8 +497,7 @@
return -EPERM;
}
- shared_config_ring_ =
- DvrVrFlingerConfigRing::Create(buffer_base, ion_buffer.width());
+ shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width());
ion_buffer.Unlock();
return 0;
@@ -506,7 +505,7 @@
void HardwareComposer::ConfigBufferDeleted() {
std::lock_guard<std::mutex> lock(shared_config_mutex_);
- shared_config_ring_ = DvrVrFlingerConfigRing();
+ shared_config_ring_ = DvrConfigRing();
}
void HardwareComposer::UpdateConfigBuffer() {
@@ -514,7 +513,7 @@
if (!shared_config_ring_.is_valid())
return;
// Copy from latest record in shared_config_ring_ to local copy.
- DvrVrFlingerConfig record;
+ DvrConfig record;
if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
post_thread_config_ = record;
}
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index de6f9ff..98e8905 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -17,7 +17,7 @@
#include <tuple>
#include <vector>
-#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_config.h>
#include <dvr/dvr_vsync.h>
#include <pdx/file_handle.h>
#include <pdx/rpc/variant.h>
@@ -452,10 +452,10 @@
std::unique_ptr<CPUMappedBroadcastRing<DvrVsyncRing>> vsync_ring_;
// Broadcast ring for receiving config data from the DisplayManager.
- DvrVrFlingerConfigRing shared_config_ring_;
+ DvrConfigRing shared_config_ring_;
uint32_t shared_config_ring_sequence_{0};
// Config buffer for reading from the post thread.
- DvrVrFlingerConfig post_thread_config_;
+ DvrConfig post_thread_config_;
std::mutex shared_config_mutex_;
static constexpr int kPostThreadInterrupted = 1;
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index bff80cd..4e275db 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -111,6 +111,7 @@
"EGL/Loader.cpp",
"EGL/BlobCache.cpp",
],
+ shared_libs: ["libvndksupport"],
static_libs: ["libEGL_getProcAddress"],
ldflags: ["-Wl,--exclude-libs=ALL"],
export_include_dirs: ["EGL/include"],
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 1116400..6e5c510 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -29,6 +29,7 @@
#include <log/log.h>
#include <graphicsenv/GraphicsEnv.h>
+#include <vndksupport/linker.h>
#include "egl_trace.h"
#include "egldefs.h"
@@ -115,6 +116,11 @@
return android_dlopen_ext(path, mode, info);
}
+static void* do_android_load_sphal_library(const char* path, int mode) {
+ ATRACE_CALL();
+ return android_load_sphal_library(path, mode);
+}
+
// ----------------------------------------------------------------------------
Loader::driver_t::driver_t(void* gles)
@@ -424,27 +430,11 @@
const char* const driver_absolute_path = absolutePath.c_str();
// Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
- // the original routine when the namespace does not exist or the load from
- // the namespace fails.
+ // the original routine when the namespace does not exist.
// See /system/core/rootdir/etc/ld.config.txt for the configuration of the
// sphal namespace.
- android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
- if (sphal_namespace != NULL) {
- const android_dlextinfo dlextinfo = {
- .flags = ANDROID_DLEXT_USE_NAMESPACE,
- .library_namespace = sphal_namespace,
- };
- void* dso = do_android_dlopen_ext(driver_absolute_path, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
- if (dso) {
- ALOGD("loaded %s from sphal namespace", driver_absolute_path);
- return dso;
- }
- else {
- ALOGW("failed to load %s from sphal namespace: %s", driver_absolute_path, dlerror());
- }
- }
-
- void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
+ void* dso = do_android_load_sphal_library(driver_absolute_path,
+ RTLD_NOW | RTLD_LOCAL);
if (dso == 0) {
const char* err = dlerror();
ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 6bff38a..835e72b 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -897,19 +897,15 @@
egl_tls_t::setContext(EGL_NO_CONTEXT);
}
} else {
- // Force return to current context for drivers that cannot handle errors
- EGLBoolean restore_result = EGL_FALSE;
- // get a reference to the old current objects
- ContextRef _c2(dp.get(), cur_c);
- SurfaceRef _d2(dp.get(), cur_c->draw);
- SurfaceRef _r2(dp.get(), cur_c->read);
+ if (cur_c != NULL) {
+ // Force return to current context for drivers that cannot handle errors
+ EGLBoolean restore_result = EGL_FALSE;
+ // get a reference to the old current objects
+ ContextRef _c2(dp.get(), cur_c);
+ SurfaceRef _d2(dp.get(), cur_c->draw);
+ SurfaceRef _r2(dp.get(), cur_c->read);
- if (cur_c == NULL) {
- restore_result = dp->makeCurrent(c, cur_c,
- EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT,
- EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- } else {
c = cur_c;
impl_ctx = c->context;
impl_draw = EGL_NO_SURFACE;
@@ -925,13 +921,13 @@
restore_result = dp->makeCurrent(c, cur_c,
cur_c->draw, cur_c->read, cur_c->context,
impl_draw, impl_read, impl_ctx);
- }
- if (restore_result == EGL_TRUE) {
- _c2.acquire();
- _r2.acquire();
- _d2.acquire();
- } else {
- ALOGE("Could not restore original EGL context");
+ if (restore_result == EGL_TRUE) {
+ _c2.acquire();
+ _r2.acquire();
+ _d2.acquire();
+ } else {
+ ALOGE("Could not restore original EGL context");
+ }
}
// this will ALOGE the error
egl_connection_t* const cnx = &gEGLImpl;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 0366630..263ff00 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -856,6 +856,10 @@
Error Layer::setDataspace(android_dataspace_t dataspace)
{
+ if (dataspace == mDataSpace) {
+ return Error::None;
+ }
+ mDataSpace = dataspace;
auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
mId, intDataspace);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 97582a7..15a43df 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -326,6 +326,7 @@
hwc2_display_t mDisplayId;
Device& mDevice;
hwc2_layer_t mId;
+ android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
};
} // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 6e843d9..c129ae5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -16,6 +16,9 @@
// #define LOG_NDEBUG 0
#include "VirtualDisplaySurface.h"
+
+#include <inttypes.h>
+
#include "HWComposer.h"
#include "SurfaceFlinger.h"
@@ -339,7 +342,7 @@
}
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
- PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) {
+ PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
status_t result = mSource[source]->dequeueBuffer(sslot, fence,
@@ -372,7 +375,7 @@
mSource[source]->cancelBuffer(*sslot, *fence);
return result;
}
- VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#x",
+ VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64,
dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
mProducerBuffers[pslot]->getPixelFormat(),
mProducerBuffers[pslot]->getUsage());
@@ -382,7 +385,7 @@
}
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+ uint32_t w, uint32_t h, PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) {
if (mDisplayId < 0) {
return mSource[SOURCE_SINK]->dequeueBuffer(
@@ -393,7 +396,7 @@
"Unexpected dequeueBuffer() in %s state", dbgStateStr());
mDbgState = DBG_STATE_GLES;
- VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
+ VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#" PRIx64, w, h, format, usage);
status_t result = NO_ERROR;
Source source = fbSourceForCompositionType(mCompositionType);
@@ -423,8 +426,8 @@
(w != 0 && w != mSinkBufferWidth) ||
(h != 0 && h != mSinkBufferHeight)) {
VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
- "want %dx%d fmt=%d use=%#x, "
- "have %dx%d fmt=%d use=%#x",
+ "want %dx%d fmt=%d use=%#" PRIx64 ", "
+ "have %dx%d fmt=%d use=%#" PRIx64,
w, h, format, usage,
mSinkBufferWidth, mSinkBufferHeight,
buf->getPixelFormat(), buf->getUsage());
@@ -575,7 +578,7 @@
}
void VirtualDisplaySurface::allocateBuffers(uint32_t /* width */,
- uint32_t /* height */, PixelFormat /* format */, uint32_t /* usage */) {
+ uint32_t /* height */, PixelFormat /* format */, uint64_t /* usage */) {
// TODO: Should we actually allocate buffers for a virtual display?
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 5c0e084..7f8b39b 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -105,7 +105,7 @@
virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
virtual status_t setAsyncMode(bool async);
virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w,
- uint32_t h, PixelFormat format, uint32_t usage,
+ uint32_t h, PixelFormat format, uint64_t usage,
FrameEventHistoryDelta *outTimestamps);
virtual status_t detachBuffer(int slot);
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
@@ -120,7 +120,7 @@
virtual status_t disconnect(int api, DisconnectMode mode);
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
virtual void allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage);
+ PixelFormat format, uint64_t usage);
virtual status_t allowAllocation(bool allow);
virtual status_t setGenerationNumber(uint32_t generationNumber);
virtual String8 getConsumerName() const override;
@@ -135,7 +135,7 @@
// Utility methods
//
static Source fbSourceForCompositionType(CompositionType type);
- status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage,
+ status_t dequeueBuffer(Source source, PixelFormat format, uint64_t usage,
int* sslot, sp<Fence>* fence);
void updateQueueBufferOutput(QueueBufferOutput&& qbo);
void resetPerFrameState();
@@ -168,7 +168,7 @@
// the composition type changes or the GLES driver starts requesting
// different usage/format, we'll get a new buffer.
uint32_t mOutputFormat;
- uint32_t mOutputUsage;
+ uint64_t mOutputUsage;
// Since we present a single producer interface to the GLES driver, but
// are internally muxing between the sink and scratch producers, we have
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d19f964..9e139f2 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2531,6 +2531,14 @@
return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
}
+size_t Layer::getChildrenCount() const {
+ size_t count = 0;
+ for (const sp<Layer>& child : mCurrentChildren) {
+ count += 1 + child->getChildrenCount();
+ }
+ return count;
+}
+
void Layer::addChild(const sp<Layer>& layer) {
mCurrentChildren.add(layer);
layer->setParent(this);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c9ebf99..6955d73 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -518,6 +518,7 @@
const LayerVector::Visitor& visitor);
void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor);
+ size_t getChildrenCount() const;
void addChild(const sp<Layer>& layer);
// Returns index if removed, or negative value otherwise
// for symmetry with Vector::remove
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 2ba1b33..e717632 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -69,7 +69,7 @@
}
status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+ uint32_t w, uint32_t h, PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps) {
return mProducer->dequeueBuffer(
slot, fence, w, h, format, usage, outTimestamps);
@@ -116,7 +116,7 @@
}
void MonitoredProducer::allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage) {
+ PixelFormat format, uint64_t usage) {
mProducer->allocateBuffers(width, height, format, usage);
}
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index a3ec29d..58b9bc4 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -40,7 +40,7 @@
virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
virtual status_t setAsyncMode(bool async);
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
- uint32_t h, PixelFormat format, uint32_t usage,
+ uint32_t h, PixelFormat format, uint64_t usage,
FrameEventHistoryDelta* outTimestamps);
virtual status_t detachBuffer(int slot);
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
@@ -56,7 +56,7 @@
virtual status_t disconnect(int api, DisconnectMode mode);
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
virtual void allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage);
+ PixelFormat format, uint64_t usage);
virtual status_t allowAllocation(bool allow);
virtual status_t setGenerationNumber(uint32_t generationNumber);
virtual String8 getConsumerName() const override;
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 0dab872..effd319 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -26,8 +26,7 @@
namespace android {
-Description::Description() :
- mUniformsDirty(true) {
+Description::Description() {
mPlaneAlpha = 1.0f;
mPremultipliedAlpha = false;
mOpaque = true;
@@ -41,28 +40,20 @@
}
void Description::setPlaneAlpha(GLclampf planeAlpha) {
- if (planeAlpha != mPlaneAlpha) {
- mUniformsDirty = true;
- mPlaneAlpha = planeAlpha;
- }
+ mPlaneAlpha = planeAlpha;
}
void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
- if (premultipliedAlpha != mPremultipliedAlpha) {
- mPremultipliedAlpha = premultipliedAlpha;
- }
+ mPremultipliedAlpha = premultipliedAlpha;
}
void Description::setOpaque(bool opaque) {
- if (opaque != mOpaque) {
- mOpaque = opaque;
- }
+ mOpaque = opaque;
}
void Description::setTexture(const Texture& texture) {
mTexture = texture;
mTextureEnabled = true;
- mUniformsDirty = true;
}
void Description::disableTexture() {
@@ -74,12 +65,10 @@
mColor[1] = green;
mColor[2] = blue;
mColor[3] = alpha;
- mUniformsDirty = true;
}
void Description::setProjectionMatrix(const mat4& mtx) {
mProjectionMatrix = mtx;
- mUniformsDirty = true;
}
void Description::setColorMatrix(const mat4& mtx) {
@@ -92,5 +81,8 @@
return mColorMatrix;
}
+void Description::setWideGamut(bool wideGamut) {
+ mIsWideGamut = wideGamut;
+}
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 8a3447c..3beffdf 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -54,6 +54,8 @@
bool mColorMatrixEnabled;
mat4 mColorMatrix;
+ bool mIsWideGamut;
+
public:
Description();
~Description();
@@ -67,9 +69,7 @@
void setProjectionMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
const mat4& getColorMatrix() const;
-
-private:
- bool mUniformsDirty;
+ void setWideGamut(bool wideGamut);
};
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 18b2e1b..37a530b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -40,9 +40,7 @@
#include "Mesh.h"
#include "Texture.h"
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <configstore/Utils.h>
-
+#include <sstream>
#include <fstream>
// ---------------------------------------------------------------------------
@@ -111,8 +109,10 @@
namespace android {
// ---------------------------------------------------------------------------
-GLES20RenderEngine::GLES20RenderEngine() :
- mVpWidth(0), mVpHeight(0) {
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) :
+ mVpWidth(0),
+ mVpHeight(0),
+ mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
@@ -133,23 +133,16 @@
//mColorBlindnessCorrection = M;
#ifdef USE_HWC2
- // retrieve wide-color and hdr settings from configstore
- using namespace android::hardware::configstore;
- using namespace android::hardware::configstore::V1_0;
-
- mPlatformHasWideColor =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
if (mPlatformHasWideColor) {
// Compute sRGB to DisplayP3 color transform
// NOTE: For now, we are limiting wide-color support to
// Display-P3 only.
mat3 srgbToP3 = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
- // color transform needs to be transposed and expanded to 4x4
- // to be what the shader wants
+ // color transform needs to be expanded to 4x4 to be what the shader wants
// mat has an initializer that expands mat3 to mat4, but
// not an assignment operator
- mat4 gamutTransform(transpose(srgbToP3));
+ mat4 gamutTransform(srgbToP3);
mSrgbToDisplayP3 = gamutTransform;
}
#endif
@@ -392,6 +385,7 @@
Description wideColorState = mState;
if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+ wideColorState.setWideGamut(true);
ALOGV("drawMesh: gamut transform applied");
}
ProgramCache::getInstance().useProgram(wideColorState);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 19cbb60..eaf94af 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -59,7 +59,7 @@
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
public:
- GLES20RenderEngine();
+ GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
protected:
virtual ~GLES20RenderEngine();
@@ -86,7 +86,6 @@
android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB;
// Indicate if wide-color mode is needed or not
- bool mPlatformHasWideColor = false;
bool mDisplayHasWideColor = false;
bool mUseWideColor = false;
uint64_t mWideColorFrameCount = 0;
@@ -98,6 +97,8 @@
int alpha);
virtual void setupDimLayerBlending(int alpha);
#endif
+ bool mPlatformHasWideColor = false;
+
virtual void setupLayerTexturing(const Texture& texture);
virtual void setupLayerBlackedOut();
virtual void setupFillWithColor(float r, float g, float b, float a);
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index ba11259..06b2252 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -129,7 +129,9 @@
.set(Key::OPACITY_MASK,
description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
.set(Key::COLOR_MATRIX_MASK,
- description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF);
+ description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF)
+ .set(Key::WIDE_GAMUT_MASK,
+ description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
return needs;
}
@@ -175,6 +177,50 @@
if (needs.hasColorMatrix()) {
fs << "uniform mat4 colorMatrix;";
}
+ if (needs.hasColorMatrix()) {
+ // When in wide gamut mode, the color matrix will contain a color space
+ // conversion matrix that needs to be applied in linear space
+ // When not in wide gamut, we can simply no-op the transfer functions
+ // and let the shader compiler get rid of them
+ if (needs.isWideGamut()) {
+ fs << R"__SHADER__(
+ float OETF_sRGB(const float linear) {
+ return linear <= 0.0031308 ?
+ linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+ }
+
+ vec3 OETF_sRGB(const vec3 linear) {
+ return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
+ }
+
+ vec3 OETF_scRGB(const vec3 linear) {
+ return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
+ }
+
+ float EOTF_sRGB(float srgb) {
+ return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+ }
+
+ vec3 EOTF_sRGB(const vec3 srgb) {
+ return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
+ }
+
+ vec3 EOTF_scRGB(const vec3 srgb) {
+ return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+ }
+ )__SHADER__";
+ } else {
+ fs << R"__SHADER__(
+ vec3 OETF_scRGB(const vec3 linear) {
+ return linear;
+ }
+
+ vec3 EOTF_scRGB(const vec3 srgb) {
+ return srgb;
+ }
+ )__SHADER__";
+ }
+ }
fs << "void main(void) {" << indent;
if (needs.isTexturing()) {
fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
@@ -197,13 +243,15 @@
if (needs.hasColorMatrix()) {
if (!needs.isOpaque() && needs.isPremultiplied()) {
// un-premultiply if needed before linearization
- fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
+ // avoid divide by 0 by adding 0.5/256 to the alpha channel
+ fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
}
- fs << "vec4 transformed = colorMatrix * vec4(gl_FragColor.rgb, 1);";
- fs << "gl_FragColor.rgb = transformed.rgb/transformed.a;";
+ fs << "vec4 transformed = colorMatrix * vec4(EOTF_scRGB(gl_FragColor.rgb), 1);";
+ // We assume the last row is always {0,0,0,1} and we skip the division by w
+ fs << "gl_FragColor.rgb = OETF_scRGB(transformed.rgb);";
if (!needs.isOpaque() && needs.isPremultiplied()) {
// and re-premultiply if needed after gamma correction
- fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
+ fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);";
}
}
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 1fa53d3..5b0fbcd 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -69,6 +69,10 @@
COLOR_MATRIX_OFF = 0x00000000,
COLOR_MATRIX_ON = 0x00000020,
COLOR_MATRIX_MASK = 0x00000020,
+
+ WIDE_GAMUT_OFF = 0x00000000,
+ WIDE_GAMUT_ON = 0x00000040,
+ WIDE_GAMUT_MASK = 0x00000040,
};
inline Key() : mKey(0) { }
@@ -97,10 +101,13 @@
inline bool hasColorMatrix() const {
return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
}
+ inline bool isWideGamut() const {
+ return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON;
+ }
// this is the definition of a friend function -- not a method of class Needs
friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
- return (lhs.mKey < rhs.mKey) ? 1 : 0;
+ return (lhs.mKey < rhs.mKey) ? 1 : 0;
}
};
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index f8785db..ac2d8b2 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -47,7 +47,7 @@
return false;
}
-RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
+RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t featureFlags) {
// EGL_ANDROIDX_no_config_context is an experimental extension with no
// written specification. It will be replaced by something more formal.
// SurfaceFlinger is using it to allow a single EGLContext to render to
@@ -135,7 +135,7 @@
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- engine = new GLES20RenderEngine();
+ engine = new GLES20RenderEngine(featureFlags);
break;
}
engine->setEGLHandles(config, ctxt);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 8b031bc..56f5827 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -59,7 +59,10 @@
virtual ~RenderEngine() = 0;
public:
- static RenderEngine* create(EGLDisplay display, int hwcFormat);
+ enum FeatureFlag {
+ WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
+ };
+ static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
static EGLConfig chooseEglConfig(EGLDisplay display, int format);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 12afdf7..edc0140 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <algorithm>
#include <errno.h>
#include <math.h>
#include <mutex>
@@ -560,7 +561,8 @@
// Get a RenderEngine for the given display / config (can't fail)
mRenderEngine = RenderEngine::create(mEGLDisplay,
- HAL_PIXEL_FORMAT_RGBA_8888);
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
}
// Drop the state lock while we initialize the hardware composer. We drop
@@ -1674,9 +1676,25 @@
}
}
+mat4 SurfaceFlinger::computeSaturationMatrix() const {
+ if (mSaturation == 1.0f) {
+ return mat4();
+ }
+
+ // Rec.709 luma coefficients
+ float3 luminance{0.213f, 0.715f, 0.072f};
+ luminance *= 1.0f - mSaturation;
+ return mat4(
+ vec4{luminance.r + mSaturation, luminance.r, luminance.r, 0.0f},
+ vec4{luminance.g, luminance.g + mSaturation, luminance.g, 0.0f},
+ vec4{luminance.b, luminance.b, luminance.b + mSaturation, 0.0f},
+ vec4{0.0f, 0.0f, 0.0f, 1.0f}
+ );
+}
+
// pickColorMode translates a given dataspace into the best available color mode.
// Currently only support sRGB and Display-P3.
-android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) {
+android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const {
switch (dataSpace) {
// treat Unknown as regular SRGB buffer, since that's what the rest of the
// system expects.
@@ -1699,11 +1717,19 @@
}
}
-android_dataspace SurfaceFlinger::bestTargetDataSpace(android_dataspace a, android_dataspace b) {
+android_dataspace SurfaceFlinger::bestTargetDataSpace(
+ android_dataspace a, android_dataspace b) const {
// Only support sRGB and Display-P3 right now.
if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
return HAL_DATASPACE_DISPLAY_P3;
}
+ if (a == HAL_DATASPACE_V0_SCRGB_LINEAR || b == HAL_DATASPACE_V0_SCRGB_LINEAR) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
+ if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
+
return HAL_DATASPACE_V0_SRGB;
}
@@ -1771,7 +1797,7 @@
}
- mat4 colorMatrix = mColorMatrix * mDaltonizer();
+ mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
// Set the per-frame data
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
@@ -2507,8 +2533,8 @@
ALOGV("hasClientComposition");
#ifdef USE_HWC2
- mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+ mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
#endif
if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -2658,8 +2684,13 @@
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
+ if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
+ ALOGE("addClientLayer called with a removed parent");
+ return NAME_NOT_FOUND;
+ }
parent->addChild(lbc);
}
+
mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
mLayersAdded = true;
mNumLayers++;
@@ -2678,6 +2709,17 @@
const ssize_t index = (p != nullptr) ? p->removeChild(layer) :
mCurrentState.layersSortedByZ.remove(layer);
+ if (p != nullptr) {
+ sp<Layer> ancestor = p;
+ while (ancestor->getParent() != nullptr) {
+ ancestor = ancestor->getParent();
+ }
+ if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
+ ALOGE("removeLayer called with a layer whose parent has been removed");
+ return NAME_NOT_FOUND;
+ }
+ }
+
// As a matter of normal operation, the LayerCleaner will produce a second
// attempt to remove the surface. The Layer will be kept alive in mDrawingState
// so we will succeed in promoting it, but it's already been removed
@@ -2694,7 +2736,7 @@
mLayersPendingRemoval.add(layer);
mLayersRemoved = true;
- mNumLayers--;
+ mNumLayers -= 1 + layer->getChildrenCount();
setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}
@@ -3892,9 +3934,7 @@
// apply a color matrix
n = data.readInt32();
if (n) {
- // color matrix is sent as mat3 matrix followed by vec3
- // offset, then packed into a mat4 where the last row is
- // the offset and extra values are 0
+ // color matrix is sent as a column-major mat4 matrix
for (size_t i = 0 ; i < 4; i++) {
for (size_t j = 0; j < 4; j++) {
mColorMatrix[i][j] = data.readFloat();
@@ -3903,6 +3943,14 @@
} else {
mColorMatrix = mat4();
}
+
+ // Check that supplied matrix's last row is {0,0,0,1} so we can avoid
+ // the division by w in the fragment shader
+ float4 lastRow(transpose(mColorMatrix)[3]);
+ if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) {
+ ALOGE("The color transform's last row must be (0, 0, 0, 1)");
+ }
+
invalidateHwcGeometry();
repaintEverything();
return NO_ERROR;
@@ -3946,6 +3994,13 @@
mUseHwcVirtualDisplays = !n;
return NO_ERROR;
}
+ case 1022: { // Set saturation boost
+ mSaturation = std::max(0.0f, std::min(data.readFloat(), 2.0f));
+
+ invalidateHwcGeometry();
+ repaintEverything();
+ return NO_ERROR;
+ }
}
}
return err;
@@ -4209,6 +4264,11 @@
ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
}
+#ifdef USE_HWC2
+ engine.setWideColor(hw->getWideColorSupport());
+ engine.setColorMode(hw->getActiveColorMode());
+#endif
+
// make sure to clear all GL error flags
engine.checkErrors();
@@ -4338,6 +4398,14 @@
hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
useIdentityTransform, rotation);
+#ifdef USE_HWC2
+ if (hasWideColorDisplay) {
+ native_window_set_buffers_data_space(window,
+ getRenderEngine().usesWideColor() ?
+ HAL_DATASPACE_DISPLAY_P3 : HAL_DATASPACE_V0_SRGB);
+ }
+#endif
+
// Attempt to create a sync khr object that can produce a sync point. If that
// isn't available, create a non-dupable sync object in the fallback path and
// wait on it directly.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1bc689d..68a088a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -511,8 +511,10 @@
// Given a dataSpace, returns the appropriate color_mode to use
// to display that dataSpace.
- android_color_mode pickColorMode(android_dataspace dataSpace);
- android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b);
+ android_color_mode pickColorMode(android_dataspace dataSpace) const;
+ android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b) const;
+
+ mat4 computeSaturationMatrix() const;
void setUpHWComposer();
void doComposition();
@@ -747,7 +749,9 @@
std::atomic<bool> mVrFlingerRequestsDisplay;
static bool useVrFlinger;
#endif
- };
+
+ float mSaturation = 1.0f;
+};
}; // namespace android
#endif // ANDROID_SURFACE_FLINGER_H
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index f6ee660..0b3a0d0 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -536,7 +536,8 @@
*static_cast<HWComposer::EventHandler *>(this));
// get a RenderEngine for the given display / config (can't fail)
- mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
+ mRenderEngine = RenderEngine::create(mEGLDisplay,
+ mHwc->getVisualID(), 0);
// retrieve the EGL context that was selected/created
mEGLContext = mRenderEngine->getEGLContext();
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 3d5dfb2..b9aa8fe 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -13,10 +13,15 @@
"libutils",
]
+header_libraries = [
+ "libdvr_headers"
+]
+
cc_library {
srcs: src,
export_include_dirs: ["include"],
shared_libs: shared_libs,
+ header_libs: header_libraries,
cppflags: ["-std=c++11"],
cflags: ["-DLOG_TAG=\"VrVirtualTouchpad\""],
name: "libvirtualtouchpad",
@@ -42,6 +47,7 @@
srcs: test_src_files,
static_libs: test_static_libs,
shared_libs: test_shared_libs,
+ header_libs: header_libraries,
cppflags = [
"-std=c++11",
],
@@ -77,6 +83,7 @@
srcs: service_src,
static_libs: service_static_libs,
shared_libs: service_shared_libs,
+ header_libs: header_libraries,
cppflags: ["-std=c++11"],
cflags: [
"-DLOG_TAG=\"VrVirtualTouchpad\"",
@@ -107,6 +114,7 @@
cc_library {
srcs: client_src,
shared_libs: client_shared_libs,
+ header_libs: header_libraries,
cppflags: ["-std=c++11"],
cflags: ["-DLOG_TAG=\"VirtualTouchpadClient\""],
host_ldlibs: ["-llog"],
diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
new file mode 100644
index 0000000..3728ef0
--- /dev/null
+++ b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
@@ -0,0 +1,24 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Virtual touchpad for the VR virtual display
+device.internal = 1
+
+touch.deviceType = touchScreen
+
+# This displayID matches the unique ID of the virtual display created for VR.
+# This will indicate to input flinger than it should link this input device
+# with the virtual display.
+touch.displayId = virtual:android:277f1a09-b88d-4d1e-8716-796f114d080b
diff --git a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
index 08cca1b..15e6687 100644
--- a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
+++ b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
@@ -1,17 +1,14 @@
#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
#define ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
+#include <dvr/dvr_api.h>
+
#ifdef __cplusplus
extern "C" {
#endif
typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
-enum {
- DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
- DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
-};
-
// Creates a new virtual touchpad client.
//
// @return Pointer to the created virtual touchpad client; nullptr on failure.
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index cb893aa..ded9549 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1015,7 +1015,7 @@
return VK_ERROR_SURFACE_LOST_KHR;
}
}
- err = native_window_set_usage(surface.window.get(), gralloc_usage);
+ err = native_window_set_usage(surface.window.get(), uint64_t(gralloc_usage));
if (err != 0) {
// TODO(jessehall): Improve error reporting. Can we enumerate possible
// errors and translate them to valid Vulkan result codes?
@@ -1092,7 +1092,7 @@
image_native_buffer.handle = img.buffer->handle;
image_native_buffer.stride = img.buffer->stride;
image_native_buffer.format = img.buffer->format;
- image_native_buffer.usage = img.buffer->usage;
+ image_native_buffer.usage = int(img.buffer->usage);
// TODO: Adjust once ANativeWindowBuffer supports gralloc1-style usage.
// For now, this is the same translation Gralloc1On0Adapter does.
image_native_buffer.usage2.consumer =