Merge "Remove window obscurement information from ACTION_OUTSIDE events."
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index b1338f8..0fc03e6 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -562,7 +562,8 @@
}
});
if (!listRet.isOk()) {
- fprintf(stderr, "failed to list services: %s\n", listRet.description().c_str());
+ // TODO(b/34242478) fix this when we determine the correct ACL
+ //fprintf(stderr, "failed to list services: %s\n", listRet.description().c_str());
}
}
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 983700f..99024c3 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -21,12 +21,11 @@
libbinder \
libcutils \
libdumpstateaidl \
+ libdumpstateutil \
liblog \
libselinux \
libutils \
$(COMMON_ZIP_LIBRARIES)
-COMMON_STATIC_LIBRARIES := \
- libdumpstateutil
# ====================#
# libdumpstateutil #
@@ -42,9 +41,10 @@
DumpstateInternal.cpp \
DumpstateUtil.cpp
LOCAL_SHARED_LIBRARIES := \
- libbase
+ libbase \
+ liblog \
-include $(BUILD_STATIC_LIBRARY)
+include $(BUILD_SHARED_LIBRARY)
# ====================#
# libdumpstateheaders #
@@ -107,8 +107,6 @@
LOCAL_STATIC_LIBRARIES := $(COMMON_STATIC_LIBRARIES)
-LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
-
LOCAL_CFLAGS += $(COMMON_LOCAL_CFLAGS)
LOCAL_INIT_RC := dumpstate.rc
@@ -181,14 +179,3 @@
LOCAL_PICKUP_FILES := $(dumpstate_tests_intermediates)
include $(BUILD_NATIVE_TEST)
-
-# =======================#
-# libdumpstate.default #
-# =======================#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := libdumpstate_default.cpp
-LOCAL_MODULE := libdumpstate.default
-
-LOCAL_STATIC_LIBRARIES := libdumpstateheaders
-include $(BUILD_STATIC_LIBRARY)
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 9faa63e..26702c4 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -18,6 +18,7 @@
#include "DumpstateUtil.h"
+#include <dirent.h>
#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
@@ -25,15 +26,22 @@
#include <vector>
+#include <android-base/file.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <cutils/log.h>
#include "DumpstateInternal.h"
-// TODO: move to unnamed namespace
+namespace android {
+namespace os {
+namespace dumpstate {
+
+namespace {
+
static constexpr const char* kSuPath = "/system/xbin/su";
-// TODO: move to unnamed namespace
static bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
sigset_t child_mask, old_mask;
sigemptyset(&child_mask);
@@ -77,10 +85,10 @@
}
return true;
}
+} // unnamed namespace
CommandOptions CommandOptions::DEFAULT = CommandOptions::WithTimeout(10).Build();
CommandOptions CommandOptions::AS_ROOT = CommandOptions::WithTimeout(10).AsRoot().Build();
-CommandOptions CommandOptions::AS_ROOT_5 = CommandOptions::WithTimeout(5).AsRoot().Build();
CommandOptions::CommandOptionsBuilder::CommandOptionsBuilder(int64_t timeout) : values(timeout) {
}
@@ -342,3 +350,35 @@
return status;
}
+
+int GetPidByName(const std::string& ps_name) {
+ DIR* proc_dir;
+ struct dirent* ps;
+ unsigned int pid;
+ std::string cmdline;
+
+ if (!(proc_dir = opendir("/proc"))) {
+ MYLOGE("Can't open /proc\n");
+ return -1;
+ }
+
+ while ((ps = readdir(proc_dir))) {
+ if (!(pid = atoi(ps->d_name))) {
+ continue;
+ }
+ android::base::ReadFileToString("/proc/" + std::string(ps->d_name) + "/cmdline", &cmdline);
+ if (cmdline.find(ps_name) == std::string::npos) {
+ continue;
+ } else {
+ closedir(proc_dir);
+ return pid;
+ }
+ }
+ MYLOGE("can't find the pid\n");
+ closedir(proc_dir);
+ return -1;
+}
+
+} // namespace dumpstate
+} // namespace os
+} // namespace android
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index 8bda6f2..5a8ce5b 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef FRAMEWORK_NATIVE_CMD_DUMPSTATE_UTIL_H_
-#define FRAMEWORK_NATIVE_CMD_DUMPSTATE_UTIL_H_
+#ifndef ANDROID_OS_DUMPSTATE_UTIL_H_
+#define ANDROID_OS_DUMPSTATE_UTIL_H_
#include <cstdint>
#include <string>
-// TODO: use android::os::dumpstate (must wait until device code is refactored)
+namespace android {
+namespace os {
+namespace dumpstate {
/*
* Defines the Linux account that should be executing a command.
@@ -120,9 +122,6 @@
// Common options.
static CommandOptions DEFAULT;
static CommandOptions AS_ROOT;
-
- // TODO: temporary, until device implementations use AS_ROOT
- static CommandOptions AS_ROOT_5;
};
/*
@@ -174,4 +173,14 @@
*/
int DumpFileToFd(int fd, const std::string& title, const std::string& path);
-#endif // FRAMEWORK_NATIVE_CMD_DUMPSTATE_UTIL_H_
+/*
+ * Finds the process id by process name.
+ * |ps_name| the process name we want to search for
+ */
+int GetPidByName(const std::string& ps_name);
+
+} // namespace dumpstate
+} // namespace os
+} // namespace android
+
+#endif // ANDROID_OS_DUMPSTATE_UTIL_H_
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
new file mode 100644
index 0000000..0302ea5
--- /dev/null
+++ b/cmds/dumpstate/README.md
@@ -0,0 +1,103 @@
+# `dumpstate` development tips
+
+## To build `dumpstate`
+
+Do a full build first:
+
+```
+m -j dumpstate
+```
+
+Then incremental ones:
+
+```
+mmm -j frameworks/native/cmds/dumpstate
+```
+
+If you're working on device-specific code, you might need to build them as well. Example:
+
+```
+mmm -j frameworks/native/cmds/dumpstate device/acme/secret_device/dumpstate/ hardware/interfaces/dumpstate
+```
+
+## To build, deploy, and take a bugreport
+
+```
+mmm -j frameworks/native/cmds/dumpstate && adb push ${OUT}/system/bin/dumpstate system/bin && adb shell am bug-report
+```
+
+## To build, deploy, and run unit tests
+
+First create `/data/nativetest`:
+
+```
+adb shell mkdir /data/nativetest
+```
+
+Then run:
+
+```
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test
+```
+
+And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`):
+
+```
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test --gtest_filter=DumpstateTest.RunCommandNoArgs
+```
+
+## To take quick bugreports
+
+```
+adb shell setprop dumpstate.dry_run true
+```
+
+## To change the `dumpstate` version
+
+```
+adb shell setprop dumpstate.version VERSION_NAME
+```
+
+Example:
+
+```
+adb shell setprop dumpstate.version split-dumpsys && adb shell dumpstate -v
+```
+
+
+Then to restore the default version:
+
+```
+adb shell setprop dumpstate.version default
+```
+
+## Code style and formatting
+
+Use the style defined at the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
+and make sure to run the following command prior to `repo upload`:
+
+```
+git clang-format --style=file HEAD~
+```
+
+## Useful Bash tricks
+
+```
+export BR_DIR=/bugreports
+
+alias br='adb shell cmd activity bug-report'
+alias ls_bugs='adb shell ls -l ${BR_DIR}/'
+
+unzip_bug() {
+ adb pull ${BR_DIR}/$1 && emacs $1 && mv $1 /tmp
+}
+
+less_bug() {
+ adb pull ${BR_DIR}/$1 && less $1 && mv $1 /tmp
+}
+
+rm_bugs() {
+ if [ -z "${BR_DIR}" ] ; then echo "Variable BR_DIR not set"; else adb shell rm -rf ${BR_DIR}/*; fi
+}
+
+```
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 3065d29..7d45f86 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -57,6 +57,12 @@
using ::android::hardware::vibrator::V1_0::IVibrator;
using VibratorStatus = ::android::hardware::vibrator::V1_0::Status;
+// TODO: remove once moved to namespace
+using android::os::dumpstate::CommandOptions;
+using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::PropertiesHelper;
+using android::os::dumpstate::GetPidByName;
+
/* read before root is shed */
static char cmdline_buf[16384] = "(unknown)";
static const char *dump_traces_path = NULL;
@@ -107,6 +113,9 @@
// Relative directory (inside the zip) for all files copied as-is into the bugreport.
static const std::string ZIP_ROOT_DIR = "FS";
+// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
+static const std::string kDumpstateBoardPath = "/bugreports/dumpstate_board.txt";
+
static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
@@ -189,34 +198,7 @@
closedir(d);
}
-// return pid of a userspace process. If not found or error, return 0.
-static unsigned int pid_of_process(const char* ps_name) {
- DIR *proc_dir;
- struct dirent *ps;
- unsigned int pid;
- std::string cmdline;
- if (!(proc_dir = opendir("/proc"))) {
- MYLOGE("Can't open /proc\n");
- return 0;
- }
-
- while ((ps = readdir(proc_dir))) {
- if (!(pid = atoi(ps->d_name))) {
- continue;
- }
- android::base::ReadFileToString("/proc/"
- + std::string(ps->d_name) + "/cmdline", &cmdline);
- if (cmdline.find(ps_name) == std::string::npos) {
- continue;
- } else {
- closedir(proc_dir);
- return pid;
- }
- }
- closedir(proc_dir);
- return 0;
-}
// dump anrd's trace and add to the zip file.
// 1. check if anrd is running on this device.
@@ -239,7 +221,7 @@
}
// find anrd's pid if it is running.
- pid = pid_of_process("/system/xbin/anrd");
+ pid = GetPidByName("/system/xbin/anrd");
if (pid > 0) {
if (stat(trace_path, &st) == 0) {
@@ -813,7 +795,52 @@
return true;
}
-static void dump_iptables() {
+static void DoKmsg() {
+ struct stat st;
+ if (!stat(PSTORE_LAST_KMSG, &st)) {
+ /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
+ DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
+ } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
+ DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
+ } else {
+ /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
+ DumpFile("LAST KMSG", "/proc/last_kmsg");
+ }
+}
+
+static void DoLogcat() {
+ unsigned long timeout;
+ // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
+ // calculate timeout
+ timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ RunCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
+ CommandOptions::WithTimeout(timeout / 1000).Build());
+ timeout = logcat_timeout("events");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ RunCommand("EVENT LOG",
+ {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
+ CommandOptions::WithTimeout(timeout / 1000).Build());
+ timeout = logcat_timeout("radio");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ RunCommand("RADIO LOG",
+ {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
+ CommandOptions::WithTimeout(timeout / 1000).Build());
+
+ RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
+
+ /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
+ RunCommand("LAST LOGCAT",
+ {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-d", "*:v"});
+}
+
+static void DumpIpTables() {
RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
@@ -907,7 +934,6 @@
static void dumpstate() {
DurationReporter duration_reporter("DUMPSTATE");
- unsigned long timeout;
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
RunCommand("UPTIME", {"uptime"});
@@ -957,30 +983,7 @@
ds.TakeScreenshot();
}
- // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
- // calculate timeout
- timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
- if (timeout < 20000) {
- timeout = 20000;
- }
- RunCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
- CommandOptions::WithTimeout(timeout / 1000).Build());
- timeout = logcat_timeout("events");
- if (timeout < 20000) {
- timeout = 20000;
- }
- RunCommand("EVENT LOG",
- {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
- CommandOptions::WithTimeout(timeout / 1000).Build());
- timeout = logcat_timeout("radio");
- if (timeout < 20000) {
- timeout = 20000;
- }
- RunCommand("RADIO LOG",
- {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
- CommandOptions::WithTimeout(timeout / 1000).Build());
-
- RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
+ DoLogcat();
AddAnrTraceFiles();
@@ -1011,20 +1014,7 @@
DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
- struct stat st;
- if (!stat(PSTORE_LAST_KMSG, &st)) {
- /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
- DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
- } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
- DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
- } else {
- /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
- DumpFile("LAST KMSG", "/proc/last_kmsg");
- }
-
- /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
- RunCommand("LAST LOGCAT",
- {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-d", "*:v"});
+ DoKmsg();
/* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
@@ -1045,11 +1035,11 @@
CommandOptions::WithTimeout(20).Build());
#ifdef FWDUMP_bcmdhd
- RunCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT_5);
+ RunCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT);
RunCommand("DUMP WIFI INTERNAL COUNTERS (1)", {WLUTIL, "counters"}, AS_ROOT_20);
- RunCommand("ND OFFLOAD STATUS (1)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
+ RunCommand("ND OFFLOAD STATUS (1)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT);
#endif
DumpFile("INTERRUPTS (1)", "/proc/interrupts");
@@ -1062,7 +1052,7 @@
RunCommand("DUMP WIFI INTERNAL COUNTERS (2)", {WLUTIL, "counters"}, AS_ROOT_20);
- RunCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
+ RunCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT);
#endif
DumpFile("INTERRUPTS (2)", "/proc/interrupts");
@@ -1099,7 +1089,7 @@
ds.DumpstateBoard();
- /* Migrate the ril_dumpstate to a dumpstate_board()? */
+ /* Migrate the ril_dumpstate to a device specific dumpstate? */
int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
if (rilDumpstateTimeout > 0) {
// su does not exist on user builds, so try running without it.
@@ -1168,21 +1158,18 @@
printf("== Board\n");
printf("========================================================\n");
- ::android::sp<IDumpstateDevice> dumpstate_device(
- IDumpstateDevice::getService("DumpstateDevice"));
+ ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService("dumpstate"));
if (dumpstate_device == nullptr) {
- // TODO: temporary workaround until devices on master implement it
- MYLOGE("no IDumpstateDevice implementation; using legacy dumpstate_board()\n");
- dumpstate_board();
+ MYLOGE("No IDumpstateDevice implementation\n");
return;
}
if (!IsZipping()) {
- MYLOGE("Not dumping board info because it's not a zipped bugreport\n");
+ MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
return;
}
- std::string path = ds.GetPath("-dumpstate-board.txt");
+ std::string path = kDumpstateBoardPath;
MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path.c_str());
int fd =
@@ -1201,7 +1188,13 @@
handle->data[0] = fd;
// TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
- dumpstate_device->dumpstateBoard(handle);
+ android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
+ if (!status.isOk()) {
+ MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ return;
+ }
AddZipEntry("dumpstate-board.txt", path);
printf("*** See dumpstate-board.txt entry ***\n");
@@ -1352,6 +1345,7 @@
int is_remote_mode = 0;
bool show_header_only = false;
bool do_start_service = false;
+ bool telephony_only = false;
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
@@ -1419,6 +1413,8 @@
do_fb = 0;
} else if (ds.extra_options_ == "bugreportwear") {
ds.update_progress_ = true;
+ } else if (ds.extra_options_ == "bugreporttelephony") {
+ telephony_only = true;
} else {
MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
}
@@ -1518,6 +1514,11 @@
ds.name_ = "undated";
}
std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
+
+ if (telephony_only) {
+ ds.base_name_ += "-telephony";
+ }
+
ds.base_name_ += "-" + buildId;
if (do_fb) {
ds.screenshot_path_ = ds.GetPath(".png");
@@ -1634,51 +1635,64 @@
// duration is logged into MYLOG instead.
ds.PrintHeader();
- // Dumps systrace right away, otherwise it will be filled with unnecessary events.
- // First try to dump anrd trace if the daemon is running. Otherwise, dump
- // the raw trace.
- if (!dump_anrd_trace()) {
- dump_systrace();
+ if (telephony_only) {
+ DumpIpTables();
+ if (!DropRootUser()) {
+ return -1;
+ }
+ do_dmesg();
+ DoLogcat();
+ DoKmsg();
+ ds.DumpstateBoard();
+ DumpModemLogs();
+ } else {
+ // Dumps systrace right away, otherwise it will be filled with unnecessary events.
+ // First try to dump anrd trace if the daemon is running. Otherwise, dump
+ // the raw trace.
+ if (!dump_anrd_trace()) {
+ dump_systrace();
+ }
+
+ // Invoking the following dumpsys calls before dump_traces() to try and
+ // keep the system stats as close to its initial state as possible.
+ RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
+ CommandOptions::WithTimeout(90).DropRoot().Build());
+ RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
+ CommandOptions::WithTimeout(10).DropRoot().Build());
+
+ // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
+ dump_raft();
+
+ /* collect stack traces from Dalvik and native processes (needs root) */
+ dump_traces_path = dump_traces();
+
+ /* Run some operations that require root. */
+ get_tombstone_fds(tombstone_data);
+ ds.AddDir(RECOVERY_DIR, true);
+ ds.AddDir(RECOVERY_DATA_DIR, true);
+ ds.AddDir(LOGPERSIST_DATA_DIR, false);
+ if (!PropertiesHelper::IsUserBuild()) {
+ ds.AddDir(PROFILE_DATA_DIR_CUR, true);
+ ds.AddDir(PROFILE_DATA_DIR_REF, true);
+ }
+ add_mountinfo();
+ DumpIpTables();
+
+ // Capture any IPSec policies in play. No keys are exposed here.
+ RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
+ CommandOptions::WithTimeout(10).Build());
+
+ // Run ss as root so we can see socket marks.
+ RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
+ CommandOptions::WithTimeout(10).Build());
+
+ if (!DropRootUser()) {
+ return -1;
+ }
+
+ dumpstate();
}
- // Invoking the following dumpsys calls before dump_traces() to try and
- // keep the system stats as close to its initial state as possible.
- RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
- CommandOptions::WithTimeout(90).DropRoot().Build());
- RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
- CommandOptions::WithTimeout(10).DropRoot().Build());
-
- // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
- dump_raft();
-
- /* collect stack traces from Dalvik and native processes (needs root) */
- dump_traces_path = dump_traces();
-
- /* Run some operations that require root. */
- get_tombstone_fds(tombstone_data);
- ds.AddDir(RECOVERY_DIR, true);
- ds.AddDir(RECOVERY_DATA_DIR, true);
- ds.AddDir(LOGPERSIST_DATA_DIR, false);
- if (!PropertiesHelper::IsUserBuild()) {
- ds.AddDir(PROFILE_DATA_DIR_CUR, true);
- ds.AddDir(PROFILE_DATA_DIR_REF, true);
- }
- add_mountinfo();
- dump_iptables();
-
- // Capture any IPSec policies in play. No keys are exposed here.
- RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
- CommandOptions::WithTimeout(10).Build());
-
- // Run ss as root so we can see socket marks.
- RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
-
- if (!DropRootUser()) {
- return -1;
- }
-
- dumpstate();
-
/* close output if needed */
if (is_redirecting) {
fclose(stdout);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 2c11c0c..b2cd241 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -36,6 +36,19 @@
// TODO: remove once not used
#define MAX_ARGS_ARRAY_SIZE 1000
+// TODO: move everything under this namespace
+// TODO: and then remove explicitly android::os::dumpstate:: prefixes
+namespace android {
+namespace os {
+namespace dumpstate {
+
+class DumpstateTest;
+class ProgressTest;
+
+} // namespace dumpstate
+} // namespace os
+} // namespace android
+
// TODO: remove once moved to HAL
#ifdef __cplusplus
extern "C" {
@@ -74,8 +87,8 @@
*
*/
class Progress {
- friend class ProgressTest;
- friend class DumpstateTest;
+ friend class android::os::dumpstate::ProgressTest;
+ friend class android::os::dumpstate::DumpstateTest;
public:
/*
@@ -152,13 +165,10 @@
friend class DumpstateTest;
public:
- static CommandOptions DEFAULT_DUMPSYS;
+ static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS;
static Dumpstate& GetInstance();
- // TODO: temporary function until device code uses PropertiesHelper::IsUserBuild()
- bool IsUserBuild();
-
/* Checkes whether dumpstate is generating a zipped bugreport. */
bool IsZipping() const;
@@ -172,7 +182,8 @@
* |options| optional argument defining the command's behavior.
*/
int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
- const CommandOptions& options = CommandOptions::DEFAULT);
+ const android::os::dumpstate::CommandOptions& options =
+ android::os::dumpstate::CommandOptions::DEFAULT);
/*
* Runs `dumpsys` with the given arguments, automatically setting its timeout
@@ -187,7 +198,8 @@
* timeout from `options`)
*/
void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
- const CommandOptions& options = DEFAULT_DUMPSYS, long dumpsys_timeout = 0);
+ const android::os::dumpstate::CommandOptions& options = DEFAULT_DUMPSYS,
+ long dumpsys_timeout = 0);
/*
* Prints the contents of a file.
@@ -399,9 +411,6 @@
/* Play a sound via Stagefright */
void play_sound(const char *path);
-/* Implemented by libdumpstate_board to dump board-specific info */
-void dumpstate_board();
-
/* Checks if a given path is a directory. */
bool is_dir(const char* pathname);
diff --git a/cmds/dumpstate/libdumpstate_default.cpp b/cmds/dumpstate/libdumpstate_default.cpp
deleted file mode 100644
index f3997ab..0000000
--- a/cmds/dumpstate/libdumpstate_default.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "dumpstate.h"
-
-void dumpstate_board(void)
-{
-}
-
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2e35112..1c19268 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -37,7 +37,9 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-using namespace android;
+namespace android {
+namespace os {
+namespace dumpstate {
using ::testing::EndsWith;
using ::testing::HasSubstr;
@@ -52,14 +54,6 @@
using ::testing::internal::GetCapturedStderr;
using ::testing::internal::GetCapturedStdout;
-using os::DumpstateService;
-using os::IDumpstateListener;
-using os::IDumpstateToken;
-
-// Not used on test cases yet...
-void dumpstate_board(void) {
-}
-
class DumpstateListenerMock : public IDumpstateListener {
public:
MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
@@ -845,6 +839,14 @@
return status;
}
+ // Find out the pid of the process_name
+ int FindPidOfProcess(const std::string& process_name) {
+ CaptureStderr();
+ int status = GetPidByName(process_name);
+ err = GetCapturedStderr();
+ return status;
+ }
+
int fd;
// 'fd` output and `stderr` from the last command ran.
@@ -1137,3 +1139,19 @@
out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
}
+
+TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
+ // init process always has pid 1.
+ EXPECT_EQ(1, FindPidOfProcess("init"));
+ EXPECT_THAT(err, IsEmpty());
+}
+
+TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
+ // find the process with abnormal name.
+ EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
+ EXPECT_THAT(err, StrEq("can't find the pid\n"));
+}
+
+} // namespace dumpstate
+} // namespace os
+} // namespace android
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 0f50fc9..6cc430d 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -41,7 +41,6 @@
#include <string>
#include <vector>
-#include <android/log.h>
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -49,10 +48,16 @@
#include <cutils/debugger.h>
#include <cutils/properties.h>
#include <cutils/sockets.h>
+#include <log/log.h>
#include <private/android_filesystem_config.h>
#include "DumpstateInternal.h"
+// TODO: remove once moved to namespace
+using android::os::dumpstate::CommandOptions;
+using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::PropertiesHelper;
+
static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
/* Most simple commands have 10 as timeout, so 5 is a good estimate */
@@ -64,9 +69,6 @@
const CommandOptions& options = CommandOptions::DEFAULT) {
return ds.RunCommand(title, full_command, options);
}
-bool Dumpstate::IsUserBuild() {
- return PropertiesHelper::IsUserBuild();
-}
/* list of native processes to include in the native dumps */
// This matches the /proc/pid/exe link instead of /proc/pid/cmdline.
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index ee4d541..987e8da 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -16,6 +16,8 @@
#include "InstalldNativeService.h"
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
#include <errno.h>
#include <inttypes.h>
#include <fstream>
@@ -39,13 +41,14 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/fs.h>
-#include <cutils/log.h> // TODO: Move everything to base/logging.
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
+#include <log/log.h> // TODO: Move everything to base/logging.
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
#include <system/thread_defs.h>
+#include <utils/Trace.h>
#include "dexopt.h"
#include "globals.h"
@@ -60,6 +63,7 @@
#endif
using android::base::StringPrintf;
+using std::endl;
namespace android {
namespace installd {
@@ -189,15 +193,22 @@
}
status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) {
+ auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd));
const binder::Status dump_permission = checkPermission(kDump);
if (!dump_permission.isOk()) {
- const String8 msg(dump_permission.toString8());
- write(fd, msg.string(), msg.size());
+ out << dump_permission.toString8() << endl;
return PERMISSION_DENIED;
}
+ std::lock_guard<std::recursive_mutex> lock(mLock);
- std::string msg = "installd is happy\n";
- write(fd, msg.c_str(), strlen(msg.c_str()));
+ out << "installd is happy!" << endl << endl;
+ out << "Devices with quota support:" << endl;
+ for (const auto& n : mQuotaDevices) {
+ out << " " << n.first << " = " << n.second << endl;
+ }
+ out << endl;
+ out.flush();
+
return NO_ERROR;
}
@@ -288,12 +299,13 @@
}
}
+ mode_t actual_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
if (st.st_uid != uid) {
// Mismatched UID is real trouble; we can't recover
LOG(ERROR) << "Mismatched UID at " << path << ": found " << st.st_uid
<< " but expected " << uid;
return -1;
- } else if (st.st_gid == gid && st.st_mode == target_mode) {
+ } else if (st.st_gid == gid && actual_mode == target_mode) {
// Everything looks good!
return 0;
}
@@ -337,6 +349,7 @@
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
const char* pkgname = packageName.c_str();
@@ -344,10 +357,15 @@
// Assume invalid inode unless filled in below
if (_aidl_return != nullptr) *_aidl_return = -1;
- uid_t uid = multiuser_get_uid(userId, appId);
- gid_t cacheGid = multiuser_get_cache_gid(userId, appId);
+ int32_t uid = multiuser_get_uid(userId, appId);
+ int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
+ // If UID doesn't have a specific cache GID, use UID value
+ if (cacheGid == -1) {
+ cacheGid = uid;
+ }
+
if (flags & FLAG_STORAGE_CE) {
auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
bool existing = (access(path.c_str(), F_OK) == 0);
@@ -423,6 +441,7 @@
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
const char* pkgname = packageName.c_str();
@@ -465,6 +484,7 @@
binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* pkgname = packageName.c_str();
binder::Status res = ok();
@@ -482,6 +502,7 @@
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
const char* pkgname = packageName.c_str();
@@ -541,6 +562,7 @@
binder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* pkgname = packageName.c_str();
binder::Status res = ok();
@@ -561,6 +583,7 @@
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
const char* pkgname = packageName.c_str();
@@ -594,6 +617,7 @@
CHECK_ARGUMENT_UUID(fromUuid);
CHECK_ARGUMENT_UUID(toUuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr;
const char* to_uuid = toUuid ? toUuid->c_str() : nullptr;
@@ -728,6 +752,7 @@
int32_t userId, int32_t userSerial ATTRIBUTE_UNUSED, int32_t flags) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
if (flags & FLAG_STORAGE_DE) {
@@ -744,6 +769,7 @@
int32_t userId, int32_t flags) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
binder::Status res = ok();
@@ -787,6 +813,7 @@
int64_t freeStorageSize) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
cache_t* cache;
@@ -829,6 +856,8 @@
binder::Status InstalldNativeService::rmdex(const std::string& codePath,
const std::string& instructionSet) {
ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
char dex_path[PKG_PATH_MAX];
const char* path = codePath.c_str();
@@ -871,28 +900,6 @@
}
#endif
-static std::string findDeviceForUuid(const std::unique_ptr<std::string>& uuid) {
- auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
- std::ifstream in("/proc/mounts");
- if (!in.is_open()) {
- PLOG(ERROR) << "Failed to read mounts";
- return "";
- }
- std::string source;
- std::string target;
- while (!in.eof()) {
- std::getline(in, source, ' ');
- std::getline(in, target, ' ');
- if (target == path) {
- return source;
- }
- // Skip to next line
- std::getline(in, source);
- }
- PLOG(ERROR) << "Failed to resolve block device for " << path;
- return "";
-}
-
static void collectQuotaStats(const std::string& device, int32_t userId,
int32_t appId, struct stats* stats, struct stats* extStats ATTRIBUTE_UNUSED) {
if (device.empty()) return;
@@ -947,11 +954,6 @@
#endif
}
-static void collectQuotaStats(const std::unique_ptr<std::string>& uuid, int32_t userId,
- int32_t appId, struct stats* stats, struct stats* extStats) {
- collectQuotaStats(findDeviceForUuid(uuid), userId, appId, stats, extStats);
-}
-
static void collectManualStats(const std::string& path, struct stats* stats) {
DIR *d;
int dfd;
@@ -1044,6 +1046,7 @@
for (auto packageName : packageNames) {
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
}
+ std::lock_guard<std::recursive_mutex> lock(mLock);
// When modifying this logic, always verify using tests:
// runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize
@@ -1072,56 +1075,73 @@
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+ auto device = findQuotaDeviceForUuid(uuid);
+ if (device.empty()) {
+ flags &= ~FLAG_USE_QUOTA;
+ }
+
+ ATRACE_BEGIN("obb");
for (auto packageName : packageNames) {
auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str());
calculate_tree_size(obbCodePath, &extStats.codeSize);
}
+ ATRACE_END();
if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START) {
+ ATRACE_BEGIN("code");
for (auto codePath : codePaths) {
calculate_tree_size(codePath, &stats.codeSize, -1,
multiuser_get_shared_gid(userId, appId));
}
+ ATRACE_END();
- collectQuotaStats(uuid, userId, appId, &stats, &extStats);
+ ATRACE_BEGIN("quota");
+ collectQuotaStats(device, userId, appId, &stats, &extStats);
+ ATRACE_END();
} else {
+ ATRACE_BEGIN("code");
for (auto codePath : codePaths) {
calculate_tree_size(codePath, &stats.codeSize);
}
+ ATRACE_END();
for (size_t i = 0; i < packageNames.size(); i++) {
const char* pkgname = packageNames[i].c_str();
+ ATRACE_BEGIN("data");
auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]);
collectManualStats(cePath, &stats);
-
auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
collectManualStats(dePath, &stats);
+ ATRACE_END();
+ ATRACE_BEGIN("profiles");
auto userProfilePath = create_data_user_profile_package_path(userId, pkgname);
calculate_tree_size(userProfilePath, &stats.dataSize);
-
auto refProfilePath = create_data_ref_profile_package_path(pkgname);
calculate_tree_size(refProfilePath, &stats.codeSize);
+ ATRACE_END();
#if MEASURE_EXTERNAL
+ ATRACE_BEGIN("external");
auto extPath = create_data_media_package_path(uuid_, userId, pkgname, "data");
collectManualStats(extPath, &extStats);
-
auto mediaPath = create_data_media_package_path(uuid_, userId, pkgname, "media");
calculate_tree_size(mediaPath, &extStats.dataSize);
+ ATRACE_END();
#endif
}
+ ATRACE_BEGIN("dalvik");
int32_t sharedGid = multiuser_get_shared_gid(userId, appId);
if (sharedGid != -1) {
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
sharedGid, -1);
}
-
calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
multiuser_get_uid(userId, appId), -1);
+ ATRACE_END();
}
std::vector<int64_t> ret;
@@ -1143,6 +1163,7 @@
std::vector<int64_t>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
// When modifying this logic, always verify using tests:
// runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize
@@ -1158,35 +1179,49 @@
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+ ATRACE_BEGIN("obb");
auto obbPath = create_data_path(uuid_) + "/media/obb";
calculate_tree_size(obbPath, &extStats.codeSize);
+ ATRACE_END();
+
+ auto device = findQuotaDeviceForUuid(uuid);
+ if (device.empty()) {
+ flags &= ~FLAG_USE_QUOTA;
+ }
if (flags & FLAG_USE_QUOTA) {
+ ATRACE_BEGIN("code");
calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
+ ATRACE_END();
+ ATRACE_BEGIN("data");
auto cePath = create_data_user_ce_path(uuid_, userId);
collectManualStatsForUser(cePath, &stats, true);
-
auto dePath = create_data_user_de_path(uuid_, userId);
collectManualStatsForUser(dePath, &stats, true);
+ ATRACE_END();
+ ATRACE_BEGIN("profile");
auto userProfilePath = create_data_user_profile_path(userId);
calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
-
auto refProfilePath = create_data_ref_profile_path();
calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
+ ATRACE_END();
#if MEASURE_EXTERNAL
+ ATRACE_BEGIN("external");
// TODO: measure external storage paths
+ ATRACE_END();
#endif
+ ATRACE_BEGIN("dalvik");
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
-1, -1, true);
-
calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
-1, -1, true);
+ ATRACE_END();
- auto device = findDeviceForUuid(uuid);
+ ATRACE_BEGIN("quota");
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
collectQuotaStats(device, userId, appId, &stats, &extStats);
@@ -1196,28 +1231,36 @@
#endif
}
}
+ ATRACE_END();
} else {
+ ATRACE_BEGIN("code");
calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize);
+ ATRACE_END();
+ ATRACE_BEGIN("data");
auto cePath = create_data_user_ce_path(uuid_, userId);
collectManualStatsForUser(cePath, &stats);
-
auto dePath = create_data_user_de_path(uuid_, userId);
collectManualStatsForUser(dePath, &stats);
+ ATRACE_END();
+ ATRACE_BEGIN("profile");
auto userProfilePath = create_data_user_profile_path(userId);
calculate_tree_size(userProfilePath, &stats.dataSize);
-
auto refProfilePath = create_data_ref_profile_path();
calculate_tree_size(refProfilePath, &stats.codeSize);
+ ATRACE_END();
#if MEASURE_EXTERNAL
+ ATRACE_BEGIN("external");
// TODO: measure external storage paths
+ ATRACE_END();
#endif
+ ATRACE_BEGIN("dalvik");
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
-
calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize);
+ ATRACE_END();
}
std::vector<int64_t> ret;
@@ -1238,6 +1281,7 @@
int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
// When modifying this logic, always verify using tests:
// runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize
@@ -1253,11 +1297,14 @@
int64_t videoSize = 0;
int64_t imageSize = 0;
+ auto device = findQuotaDeviceForUuid(uuid);
+ if (device.empty()) {
+ flags &= ~FLAG_USE_QUOTA;
+ }
+
if (flags & FLAG_USE_QUOTA) {
struct dqblk dq;
- auto device = findDeviceForUuid(uuid);
-
uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
reinterpret_cast<char*>(&dq)) != 0) {
@@ -1349,6 +1396,7 @@
const std::string& codePaths, bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* pkgname = packageName.c_str();
const char* code_paths = codePaths.c_str();
@@ -1362,6 +1410,7 @@
bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* pkgname = packageName.c_str();
*_aidl_return = analyse_profiles(uid, pkgname);
@@ -1378,6 +1427,7 @@
if (packageName && *packageName != "*") {
CHECK_ARGUMENT_PACKAGE_NAME(*packageName);
}
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* apk_path = apkPath.c_str();
const char* pkgname = packageName ? packageName->c_str() : "*";
@@ -1394,6 +1444,8 @@
binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
const char* instruction_set = instructionSet.c_str();
char boot_marker_path[PKG_PATH_MAX];
@@ -1437,6 +1489,7 @@
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
const char* pkgname = packageName.c_str();
@@ -1559,6 +1612,8 @@
binder::Status InstalldNativeService::idmap(const std::string& targetApkPath,
const std::string& overlayApkPath, int32_t uid) {
ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
const char* target_apk = targetApkPath.c_str();
const char* overlay_apk = overlayApkPath.c_str();
ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
@@ -1630,6 +1685,7 @@
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
binder::Status res = ok();
@@ -1658,6 +1714,8 @@
binder::Status InstalldNativeService::createOatDir(const std::string& oatDir,
const std::string& instructionSet) {
ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
const char* oat_dir = oatDir.c_str();
const char* instruction_set = instructionSet.c_str();
char oat_instr_dir[PKG_PATH_MAX];
@@ -1680,6 +1738,8 @@
binder::Status InstalldNativeService::rmPackageDir(const std::string& packageDir) {
ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
if (validate_apk_path(packageDir.c_str())) {
return error("Invalid path " + packageDir);
}
@@ -1692,6 +1752,8 @@
binder::Status InstalldNativeService::linkFile(const std::string& relativePath,
const std::string& fromBase, const std::string& toBase) {
ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
const char* relative_path = relativePath.c_str();
const char* from_base = fromBase.c_str();
const char* to_base = toBase.c_str();
@@ -1718,6 +1780,7 @@
binder::Status InstalldNativeService::moveAb(const std::string& apkPath,
const std::string& instructionSet, const 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();
@@ -1730,6 +1793,7 @@
binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
const std::string& instructionSet, const 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();
@@ -1739,5 +1803,42 @@
return res ? ok() : error();
}
+binder::Status InstalldNativeService::invalidateMounts() {
+ ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ mQuotaDevices.clear();
+
+ std::ifstream in("/proc/mounts");
+ if (!in.is_open()) {
+ return error("Failed to read mounts");
+ }
+
+ std::string source;
+ std::string target;
+ std::string ignored;
+ struct dqblk dq;
+ while (!in.eof()) {
+ std::getline(in, source, ' ');
+ std::getline(in, target, ' ');
+ std::getline(in, ignored);
+
+ if (source.compare(0, 11, "/dev/block/") == 0) {
+ if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
+ reinterpret_cast<char*>(&dq)) == 0) {
+ LOG(DEBUG) << "Found " << source << " with quota";
+ mQuotaDevices[target] = source;
+ }
+ }
+ }
+ return ok();
+}
+
+std::string InstalldNativeService::findQuotaDeviceForUuid(
+ const std::unique_ptr<std::string>& uuid) {
+ auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
+ return mQuotaDevices[path];
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 5397a74..0208fb1 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <vector>
+#include <unordered_map>
#include <binder/BinderService.h>
#include <cutils/multiuser.h>
@@ -99,6 +100,16 @@
const std::string& outputPath);
binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
const std::string& outputPath);
+
+ binder::Status invalidateMounts();
+
+private:
+ std::recursive_mutex mLock;
+
+ /* Map from mount point to underlying device node */
+ std::unordered_map<std::string, std::string> mQuotaDevices;
+
+ std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};
} // namespace installd
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 6e4d7fa..2f12ea9 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -68,4 +68,6 @@
@utf8InCpp String outputPath);
void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
@utf8InCpp String outputPath);
+
+ void invalidateMounts();
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 5025fde..76d5695 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -27,13 +27,13 @@
#include <sys/wait.h>
#include <unistd.h>
-#include <android/log.h> // TODO: Move everything to base/logging.
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
+#include <log/log.h> // TODO: Move everything to base/logging.
#include <private/android_filesystem_config.h>
#include <system/thread_defs.h>
@@ -153,57 +153,6 @@
return count;
}
-static void run_patchoat(int input_oat_fd, int input_vdex_fd, int out_oat_fd, int out_vdex_fd,
- const char* input_oat_file_name, const char* input_vdex_file_name,
- const char* output_oat_file_name, const char* output_vdex_file_name,
- const char *pkgname ATTRIBUTE_UNUSED, const char *instruction_set)
-{
- static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
- static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
-
- static const char* PATCHOAT_BIN = "/system/bin/patchoat";
- if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
- ALOGE("Instruction set %s longer than max length of %d",
- instruction_set, MAX_INSTRUCTION_SET_LEN);
- return;
- }
-
- /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
- char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
- char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
- char input_vdex_fd_arg[strlen("--input-vdex-fd=") + MAX_INT_LEN];
- char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
- char output_vdex_fd_arg[strlen("--output-vdex-fd=") + MAX_INT_LEN];
- const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
- // The caller has already gotten all the locks we need.
- const char* no_lock_arg = "--no-lock-output";
- sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
- sprintf(output_oat_fd_arg, "--output-oat-fd=%d", out_oat_fd);
- sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_oat_fd);
- ALOGV("Running %s isa=%s in-oat-fd=%d (%s) in-vdex-fd=%d (%s) "
- "out-oat-fd=%d (%s) out-vdex-fd=%d (%s)\n",
- PATCHOAT_BIN, instruction_set,
- input_oat_fd, input_oat_file_name,
- input_vdex_fd, input_vdex_file_name,
- out_oat_fd, output_oat_file_name,
- out_vdex_fd, output_vdex_file_name);
-
- /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
- char* argv[9];
- argv[0] = (char*) PATCHOAT_BIN;
- argv[1] = (char*) patched_image_location_arg;
- argv[2] = (char*) no_lock_arg;
- argv[3] = instruction_set_arg;
- argv[4] = input_oat_fd_arg;
- argv[5] = input_vdex_fd_arg;
- argv[6] = output_oat_fd_arg;
- argv[7] = output_vdex_fd_arg;
- argv[8] = NULL;
-
- execv(PATCHOAT_BIN, (char* const *)argv);
- ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
-}
-
static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
const char* input_file_name, const char* output_file_name, int swap_fd,
const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
@@ -502,7 +451,7 @@
return kDefaultProvideSwapFile;
}
-static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
+static void SetDex2OatScheduling(bool set_to_bg) {
if (set_to_bg) {
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
ALOGE("set_sched_policy failed: %s\n", strerror(errno));
@@ -1062,40 +1011,12 @@
return false;
}
- const char *input_file;
- char in_odex_path[PKG_PATH_MAX];
- int dexopt_action = abs(dexopt_needed);
- bool is_odex_location = dexopt_needed < 0;
- switch (dexopt_action) {
- case DEX2OAT_FROM_SCRATCH:
- case DEX2OAT_FOR_BOOT_IMAGE:
- case DEX2OAT_FOR_FILTER:
- case DEX2OAT_FOR_RELOCATION:
- input_file = apk_path;
- break;
-
- case PATCHOAT_FOR_RELOCATION:
- if (is_odex_location) {
- if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
- return -1;
- }
- input_file = in_odex_path;
- } else {
- input_file = out_oat_path;
- }
- break;
-
- default:
- ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
- return 72;
- }
-
+ const char *input_file = apk_path;
struct stat input_stat;
memset(&input_stat, 0, sizeof(input_stat));
stat(input_file, &input_stat);
- // Open the input file. If running dex2oat, `input_file` is the APK. If running
- // patchoat, it is the OAT file to be relocated.
+ // Open the input file.
base::unique_fd input_fd(open(input_file, O_RDONLY, 0));
if (input_fd.get() < 0) {
ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
@@ -1117,22 +1038,12 @@
// Open the existing VDEX. We do this before creating the new output VDEX, which will
// unlink the old one.
+ char in_odex_path[PKG_PATH_MAX];
+ int dexopt_action = abs(dexopt_needed);
+ bool is_odex_location = dexopt_needed < 0;
base::unique_fd in_vdex_fd;
std::string in_vdex_path_str;
- if (dexopt_action == PATCHOAT_FOR_RELOCATION) {
- // `input_file` is the OAT file to be relocated. The VDEX has to be there as well.
- in_vdex_path_str = create_vdex_filename(input_file);
- if (in_vdex_path_str.empty()) {
- ALOGE("installd cannot compute input vdex location for '%s'\n", input_file);
- return -1;
- }
- in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
- if (in_vdex_fd.get() < 0) {
- ALOGE("installd cannot open '%s' for input during dexopt: %s\n",
- in_vdex_path_str.c_str(), strerror(errno));
- return -1;
- }
- } else if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
+ if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
// Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
const char* path = nullptr;
if (is_odex_location) {
@@ -1212,7 +1123,7 @@
// Avoid generating an app image for extract only since it will not contain any classes.
Dex2oatFileWrapper<std::function<void ()>> image_fd;
const std::string image_path = create_image_filename(out_oat_path);
- if (dexopt_action != PATCHOAT_FOR_RELOCATION && !image_path.empty()) {
+ if (!image_path.empty()) {
char app_image_format[kPropertyValueMax];
bool have_app_image_format =
get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
@@ -1256,42 +1167,29 @@
/* child -- drop privileges before continuing */
drop_capabilities(uid);
- SetDex2OatAndPatchOatScheduling(boot_complete);
+ SetDex2OatScheduling(boot_complete);
if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
_exit(67);
}
- if (dexopt_action == PATCHOAT_FOR_RELOCATION) {
- run_patchoat(input_fd.get(),
- in_vdex_fd.get(),
- out_oat_fd.get(),
- out_vdex_fd,
- input_file,
- in_vdex_path_str.c_str(),
- out_oat_path,
- out_vdex_path_str.c_str(),
- pkgname,
- instruction_set);
- } else {
- // Pass dex2oat the relative path to the input file.
- const char *input_file_name = get_location_from_path(input_file);
- run_dex2oat(input_fd.get(),
- out_oat_fd.get(),
- in_vdex_fd.get(),
- out_vdex_fd,
- image_fd.get(),
- input_file_name,
- out_oat_path,
- swap_fd.get(),
- instruction_set,
- compiler_filter,
- vm_safe_mode,
- debuggable,
- boot_complete,
- reference_profile_fd.get(),
- shared_libraries);
- }
+ // Pass dex2oat the relative path to the input file.
+ const char *input_file_name = get_location_from_path(input_file);
+ run_dex2oat(input_fd.get(),
+ out_oat_fd.get(),
+ in_vdex_fd.get(),
+ out_vdex_fd,
+ image_fd.get(),
+ input_file_name,
+ out_oat_path,
+ swap_fd.get(),
+ instruction_set,
+ compiler_filter,
+ vm_safe_mode,
+ debuggable,
+ boot_complete,
+ reference_profile_fd.get(),
+ shared_libraries);
_exit(68); /* only get here on exec failure */
} else {
int res = wait_child(pid);
diff --git a/cmds/installd/globals.cpp b/cmds/installd/globals.cpp
index c0ea79c..edcdb6a 100644
--- a/cmds/installd/globals.cpp
+++ b/cmds/installd/globals.cpp
@@ -19,7 +19,7 @@
#include <stdlib.h>
#include <string.h>
-#include <android/log.h> // TODO: Move everything to base::logging.
+#include <log/log.h> // TODO: Move everything to base::logging.
#include <globals.h>
#include <installd_constants.h>
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 7aba5d0..c74c65b 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -27,13 +27,13 @@
#include <sys/stat.h>
#include <sys/wait.h>
-#include <android/log.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/fs.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <private/android_filesystem_config.h>
#include "InstalldNativeService.h"
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 9849a0f..0b1cd7e 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -30,10 +30,10 @@
#include <sys/statfs.h>
#endif
-#include <android/log.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <cutils/fs.h>
+#include <log/log.h>
#include <private/android_filesystem_config.h>
#include "globals.h" // extern variables.
diff --git a/cmds/ip-up-vpn/ip-up-vpn.c b/cmds/ip-up-vpn/ip-up-vpn.c
index 5c566fc..3b8955b 100644
--- a/cmds/ip-up-vpn/ip-up-vpn.c
+++ b/cmds/ip-up-vpn/ip-up-vpn.c
@@ -29,7 +29,7 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <android/log.h>
+#include <log/log.h>
#define DIR "/data/misc/vpn/"
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index cb557aa..753aeb5 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -12,7 +12,7 @@
#include <sys/mman.h>
#include <unistd.h>
-#include <android/log.h>
+#include <log/log.h>
#include "binder.h"
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 8f4e01b..43c4c8b 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -22,7 +22,7 @@
#define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
#else
#define LOG_TAG "ServiceManager"
-#include <android/log.h>
+#include <log/log.h>
#endif
struct audit_data {
@@ -363,6 +363,7 @@
int main()
{
struct binder_state *bs;
+ union selinux_callback cb;
bs = binder_open(128*1024);
if (!bs) {
@@ -375,6 +376,11 @@
return -1;
}
+ cb.func_audit = audit_callback;
+ selinux_set_callback(SELINUX_CB_AUDIT, cb);
+ cb.func_log = selinux_log_callback;
+ selinux_set_callback(SELINUX_CB_LOG, cb);
+
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
@@ -388,11 +394,6 @@
abort();
}
- union selinux_callback cb;
- cb.func_audit = audit_callback;
- selinux_set_callback(SELINUX_CB_AUDIT, cb);
- cb.func_log = selinux_log_callback;
- selinux_set_callback(SELINUX_CB_LOG, cb);
binder_loop(bs, svcmgr_handler);
diff --git a/include/android/configuration.h b/include/android/configuration.h
index 8e10f67..b469e7e 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -300,6 +300,11 @@
* <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a> resource qualifier specified.
*/
ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06,
+ /**
+ * UI mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">vr</a> resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_TYPE_VR_HEADSET = 0x07,
/** UI night mode: not specified.*/
ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00,
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index d561594..834dcbd 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -23,19 +23,19 @@
#define PLAYER_PIID_INVALID -1
-enum {
+typedef enum {
PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE = 11,
PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD = 12,
-};
+} player_type_t;
-enum {
+typedef enum {
PLAYER_STATE_UNKNOWN = -1,
PLAYER_STATE_RELEASED = 0,
PLAYER_STATE_IDLE = 1,
PLAYER_STATE_STARTED = 2,
PLAYER_STATE_PAUSED = 3,
PLAYER_STATE_STOPPED = 4,
-};
+} player_state_t;
}; // namespace android
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index f5ea259..909318a 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -114,10 +114,12 @@
// The parcels created by these methods must be kept in sync with the
// corresponding methods from IAudioService.aidl and objects it imports.
- virtual audio_unique_id_t trackPlayer(int playerType, int usage, int content) = 0;
- /*oneway*/ virtual status_t playerAttributes(audio_unique_id_t piid, int usage, int content)= 0;
- /*oneway*/ virtual status_t playerEvent(int piid, int event) = 0;
- /*oneway*/ virtual status_t releasePlayer(int piid) = 0;
+ virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
+ audio_content_type_t content, const sp<IBinder>& player) = 0;
+ /*oneway*/ virtual status_t playerAttributes(audio_unique_id_t piid, audio_usage_t usage,
+ audio_content_type_t content)= 0;
+ /*oneway*/ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event) = 0;
+ /*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/audiomanager/IPlayer.h b/include/audiomanager/IPlayer.h
new file mode 100644
index 0000000..efcac74
--- /dev/null
+++ b/include/audiomanager/IPlayer.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IPLAYER_H
+#define ANDROID_IPLAYER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IPlayer : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(Player);
+
+ virtual void start() = 0;
+
+ virtual void pause() = 0;
+
+ virtual void stop() = 0;
+
+ virtual void setVolume(float vol) = 0;
+
+};
+
+// ----------------------------------------------------------------------------
+
+class BnPlayer : public BnInterface<IPlayer>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IPLAYER_H
diff --git a/include/gfx/SafeLog.h b/include/gfx/SafeLog.h
new file mode 100644
index 0000000..e45e541
--- /dev/null
+++ b/include/gfx/SafeLog.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Weverything"
+#include <fmt/format.h>
+#include <log/log.h>
+#pragma clang diagnostic pop
+
+#include <type_traits>
+
+namespace android {
+namespace gfx {
+
+/* SafeLog is a mix-in that can be used to easily add typesafe logging using fmtlib to any class.
+ * To use it, inherit from it using CRTP and implement the getLogTag method.
+ *
+ * For example:
+ *
+ * class Frobnicator : private SafeLog<Frobnicator> {
+ * friend class SafeLog<Frobnicator>; // Allows getLogTag to be private
+ *
+ * public:
+ * void frobnicate(int32_t i);
+ *
+ * private:
+ * // SafeLog does member access on the object calling alog*, so this tag can theoretically vary
+ * // by instance unless getLogTag is made static
+ * const char* getLogTag() { return "Frobnicator"; }
+ * };
+ *
+ * void Frobnicator::frobnicate(int32_t i) {
+ * // Logs something like "04-16 21:35:46.811 3513 3513 I Frobnicator: frobnicating 42"
+ * alogi("frobnicating {}", i);
+ * }
+ *
+ * See http://fmtlib.net for more information on the formatting API.
+ */
+
+template <typename T>
+class SafeLog {
+ protected:
+ template <typename... Args>
+#if LOG_NDEBUG
+ void alogv(Args&&... /*unused*/) const {
+ }
+#else
+ void alogv(Args&&... args) const {
+ alog<ANDROID_LOG_VERBOSE>(std::forward<Args>(args)...);
+ }
+#endif
+
+ template <typename... Args>
+ void alogd(Args&&... args) const {
+ alog<ANDROID_LOG_DEBUG>(std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ void alogi(Args&&... args) const {
+ alog<ANDROID_LOG_INFO>(std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ void alogw(Args&&... args) const {
+ alog<ANDROID_LOG_WARN>(std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ void aloge(Args&&... args) const {
+ alog<ANDROID_LOG_ERROR>(std::forward<Args>(args)...);
+ }
+
+ private:
+ // Suppresses clang-tidy check cppcoreguidelines-pro-bounds-array-to-pointer-decay
+ template <size_t strlen, typename... Args>
+ void write(fmt::MemoryWriter* writer, const char (&str)[strlen], Args&&... args) const {
+ writer->write(static_cast<const char*>(str), std::forward<Args>(args)...);
+ }
+
+ template <int priority, typename... Args>
+ void alog(Args&&... args) const {
+ static_assert(std::is_base_of<SafeLog<T>, T>::value, "Can't convert to SafeLog pointer");
+ fmt::MemoryWriter writer;
+ write(&writer, std::forward<Args>(args)...);
+ auto derivedThis = static_cast<const T*>(this);
+ android_writeLog(priority, derivedThis->getLogTag(), writer.c_str());
+ }
+};
+
+} // namespace gfx
+} // namespace android
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index e2bafec..da574ec 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -22,6 +22,7 @@
#include <gui/BufferQueueDefs.h>
#include <gui/IGraphicBufferConsumer.h>
+#include <utils/String8.h>
namespace android {
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 8a3fa39..46ca2c2 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -44,6 +44,7 @@
GL_COMPOSITION_DONE,
DISPLAY_PRESENT,
DISPLAY_RETIRE,
+ DEQUEUE_READY,
RELEASE,
EVENT_COUNT, // Not an actual event.
};
@@ -61,6 +62,7 @@
bool hasDisplayPresentInfo() const;
bool hasDisplayRetireInfo() const;
bool hasReleaseInfo() const;
+ bool hasDequeueReadyInfo() const;
void checkFencesForCompletion();
void dump(String8& outString) const;
@@ -84,6 +86,7 @@
nsecs_t latchTime{-1};
nsecs_t firstRefreshStartTime{-1};
nsecs_t lastRefreshStartTime{-1};
+ nsecs_t dequeueReadyTime{-1};
std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
@@ -116,13 +119,22 @@
public:
~ProducerFrameEventHistory() override;
- void updateAcquireFence(
+ // virtual for testing.
+ virtual void updateAcquireFence(
uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire);
void applyDelta(const FrameEventHistoryDelta& delta);
void updateSignalTimes();
-private:
+protected:
+ void applyFenceDelta(FenceTimeline* timeline,
+ std::shared_ptr<FenceTime>* dst,
+ const FenceTime::Snapshot& src) const;
+
+ // virtual for testing.
+ virtual std::shared_ptr<FenceTime> createFenceTime(
+ const sp<Fence>& fence) const;
+
size_t mAcquireOffset{0};
// The consumer updates it's timelines in Layer and SurfaceFlinger since
@@ -185,7 +197,7 @@
const std::shared_ptr<FenceTime>& displayPresent);
void addRetire(uint64_t frameNumber,
const std::shared_ptr<FenceTime>& displayRetire);
- void addRelease(uint64_t frameNumber,
+ void addRelease(uint64_t frameNumber, nsecs_t dequeueReadyTime,
std::shared_ptr<FenceTime>&& release);
void getAndResetDelta(FrameEventHistoryDelta* delta);
@@ -246,6 +258,7 @@
nsecs_t mLatchTime{0};
nsecs_t mFirstRefreshStartTime{0};
nsecs_t mLastRefreshStartTime{0};
+ nsecs_t mDequeueReadyTime{0};
FenceTime::Snapshot mGpuCompositionDoneFence;
FenceTime::Snapshot mDisplayPresentFence;
diff --git a/include/gui/GraphicsEnv.h b/include/gui/GraphicsEnv.h
new file mode 100644
index 0000000..4c7366f
--- /dev/null
+++ b/include/gui/GraphicsEnv.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef ANDROID_GUI_GRAPHICS_ENV_H
+#define ANDROID_GUI_GRAPHICS_ENV_H 1
+
+#include <string>
+
+struct android_namespace_t;
+
+namespace android {
+
+class GraphicsEnv {
+public:
+ static GraphicsEnv& getInstance();
+
+ // Set a search path for loading graphics drivers. The path is a list of
+ // directories separated by ':'. A directory can be contained in a zip file
+ // (drivers must be stored uncompressed and page aligned); such elements
+ // in the search path must have a '!' after the zip filename, e.g.
+ // /data/app/com.example.driver/base.apk!/lib/arm64-v8a
+ void setDriverPath(const std::string path);
+ android_namespace_t* getDriverNamespace();
+
+private:
+ GraphicsEnv() = default;
+ std::string mDriverPath;
+ android_namespace_t* mDriverNamespace = nullptr;
+};
+
+} // namespace android
+
+/* FIXME
+ * Export an un-mangled function that just does
+ * return android::GraphicsEnv::getInstance().getDriverNamespace();
+ * This allows libEGL to get the function pointer via dlsym, since it can't
+ * directly link against libgui. In a future release, we'll fix this so that
+ * libgui does not depend on graphics API libraries, and libEGL can link
+ * against it. The current dependencies from libgui -> libEGL are:
+ * - the GLConsumer class, which should be moved to its own library
+ * - the EGLsyncKHR synchronization in BufferQueue, which is deprecated and
+ * will be removed soon.
+ */
+extern "C" android_namespace_t* android_getDriverNamespace();
+
+#endif // ANDROID_GUI_GRAPHICS_ENV_H
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index a10dad1..0b6a8f7 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -33,6 +33,8 @@
namespace android {
+class ISurfaceComposer;
+
/*
* An implementation of ANativeWindow that feeds graphics buffers into a
* BufferQueue.
@@ -66,7 +68,8 @@
* the controlledByApp flag indicates that this Surface (producer) is
* controlled by the application. This flag is used at connect time.
*/
- explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false);
+ explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer,
+ bool controlledByApp = false);
/* getIGraphicBufferProducer() returns the IGraphicBufferProducer this
* Surface was created with. Usually it's an error to use the
@@ -143,15 +146,19 @@
// See IGraphicBufferProducer::getFrameTimestamps
status_t getFrameTimestamps(uint64_t frameNumber,
nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
- nsecs_t* outRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
+ nsecs_t* outLatchTime, nsecs_t* outFirstRefreshStartTime,
+ nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
nsecs_t* outDisplayPresentTime, nsecs_t* outDisplayRetireTime,
- nsecs_t* outReleaseTime);
+ nsecs_t* outDequeueReadyTime, nsecs_t* outReleaseTime);
status_t getUniqueId(uint64_t* outId) const;
protected:
virtual ~Surface();
+ // Virtual for testing.
+ virtual sp<ISurfaceComposer> composerService() const;
+
private:
// can't be copied
Surface& operator = (const Surface& rhs);
@@ -245,7 +252,6 @@
enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
-private:
void querySupportedTimestampsLocked() const;
void freeAllBuffers();
@@ -389,7 +395,8 @@
Condition mQueueBufferCondition;
- uint64_t mNextFrameNumber;
+ uint64_t mNextFrameNumber = 1;
+ uint64_t mLastFrameNumber = 0;
// Mutable because ANativeWindow::query needs this class const.
mutable bool mQueriedSupportedTimestamps;
@@ -398,7 +405,7 @@
// A cached copy of the FrameEventHistory maintained by the consumer.
bool mEnableFrameTimestamps = false;
- ProducerFrameEventHistory mFrameEventHistory;
+ std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
};
namespace view {
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 9352c57..b86c72c 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -214,7 +214,13 @@
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ,
bool useIdentityTransform);
-
+ static status_t captureToBuffer(
+ const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ,
+ bool useIdentityTransform,
+ uint32_t rotation,
+ sp<GraphicBuffer>* outbuffer);
private:
mutable sp<CpuConsumer> mCpuConsumer;
mutable sp<IGraphicBufferProducer> mProducer;
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index 99b39d8..58df24c 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -18,21 +18,17 @@
#define ANDROID_FENCE_H
#include <stdint.h>
-#include <sys/types.h>
-#include <ui/ANativeObjectBase.h>
-#include <ui/PixelFormat.h>
-#include <ui/Rect.h>
#include <utils/Flattenable.h>
-#include <utils/String8.h>
+#include <utils/RefBase.h>
#include <utils/Timers.h>
#include <experimental/optional>
-struct ANativeWindowBuffer;
-
namespace android {
+class String8;
+
// ===========================================================================
// Fence
// ===========================================================================
@@ -62,6 +58,12 @@
// closed.
explicit Fence(int fenceFd);
+ // Not copyable or movable.
+ Fence(const Fence& rhs) = delete;
+ Fence& operator=(const Fence& rhs) = delete;
+ Fence(Fence&& rhs) = delete;
+ Fence& operator=(Fence&& rhs) = delete;
+
// Check whether the Fence has an open fence file descriptor. Most Fence
// methods treat an invalid file descriptor just like a valid fence that
// is already signalled, so using this is usually not necessary.
@@ -135,11 +137,6 @@
friend class LightRefBase<Fence>;
~Fence();
- // Disallow copying
- Fence(const Fence& rhs);
- Fence& operator = (const Fence& rhs);
- const Fence& operator = (const Fence& rhs) const;
-
int mFenceFd;
};
diff --git a/include/ui/FenceTime.h b/include/ui/FenceTime.h
index 27cc720..871fcf2 100644
--- a/include/ui/FenceTime.h
+++ b/include/ui/FenceTime.h
@@ -24,13 +24,17 @@
#include <atomic>
#include <mutex>
#include <queue>
+#include <unordered_map>
namespace android {
+class FenceToFenceTimeMap;
+
// A wrapper around fence that only implements isValid and getSignalTime.
// It automatically closes the fence in a thread-safe manner once the signal
// time is known.
class FenceTime {
+friend class FenceToFenceTimeMap;
public:
// An atomic snapshot of the FenceTime that is flattenable.
//
@@ -107,15 +111,22 @@
// Returns a snapshot of the FenceTime in its current state.
Snapshot getSnapshot() const;
+ void signalForTest(nsecs_t signalTime);
+
// Override new and delete since this needs 8-byte alignment, which
// is not guaranteed on x86.
static void* operator new(size_t nbytes) noexcept;
static void operator delete(void *p);
private:
+ // For tests only. If forceValidForTest is true, then getSignalTime will
+ // never return SIGNAL_TIME_INVALID and isValid will always return true.
+ FenceTime(const sp<Fence>& fence, bool forceValidForTest);
+
enum class State {
VALID,
INVALID,
+ FORCED_VALID_FOR_TEST,
};
const State mState{State::INVALID};
@@ -156,6 +167,42 @@
std::queue<std::weak_ptr<FenceTime>> mQueue;
};
+// Used by test code to create or get FenceTimes for a given Fence.
+//
+// By design, Fences cannot be signaled from user space. However, this class
+// allows test code to set the apparent signalTime of a Fence and
+// have it be visible to all FenceTimes. Release code should not use
+// FenceToFenceTimeMap.
+//
+// FenceToFenceTimeMap keeps a weak reference to the FenceTime and automatically
+// garbage collects entries every time a new FenceTime is created to avoid
+// leaks. This prevents us from having to make the Fence destructor
+// automatically notify that the underlying fence has been destroyed, which
+// would affect release code paths. Garbage collecting so often is inefficient,
+// but acceptable for testing.
+//
+// Since FenceTimes maintain a strong reference to underlying Fences, there
+// should not be any aliasing issues where a new Fence happens to have the same
+// address as a previous Fence; the previous entry will be garbage collected
+// before the new one is added.
+class FenceToFenceTimeMap {
+public:
+ // Create a new FenceTime with that wraps the provided Fence.
+ std::shared_ptr<FenceTime> createFenceTimeForTest(const sp<Fence>& fence);
+
+ // Signals all FenceTimes created through this class that are wrappers
+ // around |fence|.
+ void signalAllForTest(const sp<Fence>& fence, nsecs_t signalTime);
+
+private:
+ // Cleans up the entries that no longer have a strong reference.
+ void garbageCollectLocked();
+
+ mutable std::mutex mMutex;
+ std::unordered_map<Fence*, std::vector<std::weak_ptr<FenceTime>>> mMap;
+};
+
+
}; // namespace android
#endif // ANDROID_FENCE_TIME_H
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index 8aadd58..ce33d4e 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -21,9 +21,10 @@
#include <utils/Flattenable.h>
#include <utils/Log.h>
#include <utils/TypeHelpers.h>
+#include <log/log.h>
+
#include <ui/Point.h>
-#include <android/log.h>
#include <android/rect.h>
namespace android {
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 45633f3..f4e0a60 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -25,9 +25,9 @@
#include <sys/mman.h>
#include <unistd.h>
-#include <android/log.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
+#include <log/log.h>
#include <utils/CallStack.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 415c252..03f00be 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -25,11 +25,10 @@
#include <sys/types.h>
#include <unistd.h>
-#include <android/log.h>
+#include <binder/MemoryHeapBase.h>
#include <cutils/ashmem.h>
#include <cutils/atomic.h>
-
-#include <binder/MemoryHeapBase.h>
+#include <log/log.h>
namespace android {
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 70d425e..e7078ba 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -20,9 +20,9 @@
#include <limits>
-#include <android/log.h>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
+#include <log/log.h>
#include <utils/Errors.h>
using android::BAD_TYPE;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index cb17da4..3815bdc 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -77,6 +77,7 @@
"FrameTimestamps.cpp",
"GLConsumer.cpp",
"GraphicBufferAlloc.cpp",
+ "GraphicsEnv.cpp",
"GuiConfig.cpp",
"IDisplayEventConnection.cpp",
"IGraphicBufferAlloc.cpp",
@@ -99,6 +100,7 @@
],
shared_libs: [
+ "libnativeloader",
"libsync",
"libbinder",
"libcutils",
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index c9b8948..73537bf 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -18,6 +18,7 @@
#include <cutils/compiler.h> // For CC_[UN]LIKELY
#include <inttypes.h>
+#include <utils/Log.h>
#include <utils/String8.h>
#include <algorithm>
@@ -54,6 +55,10 @@
return addRetireCalled || addReleaseCalled;
}
+bool FrameEvents::hasDequeueReadyInfo() const {
+ return Fence::isValidTimestamp(dequeueReadyTime);
+}
+
bool FrameEvents::hasAcquireInfo() const {
return acquireFence->isValid();
}
@@ -140,6 +145,14 @@
!addPostCompositeCalled, *displayPresentFence);
dumpFenceTime(outString, "Display Retire \t",
!addRetireCalled, *displayRetireFence);
+
+ outString.appendFormat("--- DequeueReady \t");
+ if (Fence::isValidTimestamp(dequeueReadyTime)) {
+ outString.appendFormat("%" PRId64 "\n", dequeueReadyTime);
+ } else {
+ outString.appendFormat("Pending\n");
+ }
+
dumpFenceTime(outString, "Release \t",
true, *releaseFence);
}
@@ -241,33 +254,6 @@
}
}
-static void applyFenceDelta(FenceTimeline* timeline,
- std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) {
- if (CC_UNLIKELY(dst == nullptr)) {
- ALOGE("applyFenceDelta: dst is null.");
- return;
- }
-
- switch (src.state) {
- case FenceTime::Snapshot::State::EMPTY:
- return;
- case FenceTime::Snapshot::State::FENCE:
- if (CC_UNLIKELY((*dst)->isValid())) {
- ALOGE("applyFenceDelta: Unexpected fence.");
- }
- *dst = std::make_shared<FenceTime>(src.fence);
- timeline->push(*dst);
- return;
- case FenceTime::Snapshot::State::SIGNAL_TIME:
- if ((*dst)->isValid()) {
- (*dst)->applyTrustedSnapshot(src);
- } else {
- *dst = std::make_shared<FenceTime>(src.signalTime);
- }
- return;
- }
-}
-
void ProducerFrameEventHistory::applyDelta(
const FrameEventHistoryDelta& delta) {
for (auto& d : delta.mDeltas) {
@@ -288,6 +274,7 @@
frame.latchTime = d.mLatchTime;
frame.firstRefreshStartTime = d.mFirstRefreshStartTime;
frame.lastRefreshStartTime = d.mLastRefreshStartTime;
+ frame.dequeueReadyTime = d.mDequeueReadyTime;
if (frame.frameNumber != d.mFrameNumber) {
// We got a new frame. Initialize some of the fields.
@@ -320,6 +307,38 @@
mReleaseTimeline.updateSignalTimes();
}
+void ProducerFrameEventHistory::applyFenceDelta(FenceTimeline* timeline,
+ std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) const {
+ if (CC_UNLIKELY(dst == nullptr)) {
+ ALOGE("applyFenceDelta: dst is null.");
+ return;
+ }
+
+ switch (src.state) {
+ case FenceTime::Snapshot::State::EMPTY:
+ return;
+ case FenceTime::Snapshot::State::FENCE:
+ if (CC_UNLIKELY((*dst)->isValid())) {
+ ALOGE("applyFenceDelta: Unexpected fence.");
+ }
+ *dst = createFenceTime(src.fence);
+ timeline->push(*dst);
+ return;
+ case FenceTime::Snapshot::State::SIGNAL_TIME:
+ if ((*dst)->isValid()) {
+ (*dst)->applyTrustedSnapshot(src);
+ } else {
+ *dst = std::make_shared<FenceTime>(src.signalTime);
+ }
+ return;
+ }
+}
+
+std::shared_ptr<FenceTime> ProducerFrameEventHistory::createFenceTime(
+ const sp<Fence>& fence) const {
+ return std::make_shared<FenceTime>(fence);
+}
+
// ============================================================================
// ConsumerFrameEventHistory
@@ -405,14 +424,15 @@
mFramesDirty[mRetireOffset].setDirty<FrameEvent::DISPLAY_RETIRE>();
}
-void ConsumerFrameEventHistory::addRelease(
- uint64_t frameNumber, std::shared_ptr<FenceTime>&& release) {
+void ConsumerFrameEventHistory::addRelease(uint64_t frameNumber,
+ nsecs_t dequeueReadyTime, std::shared_ptr<FenceTime>&& release) {
FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
if (frame == nullptr) {
ALOGE("ConsumerFrameEventHistory::addRelease: Did not find frame.");
return;
}
frame->addReleaseCalled = true;
+ frame->dequeueReadyTime = dequeueReadyTime;
frame->releaseFence = std::move(release);
mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>();
}
@@ -461,7 +481,8 @@
mRequestedPresentTime(frameTimestamps.requestedPresentTime),
mLatchTime(frameTimestamps.latchTime),
mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime),
- mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime) {
+ mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime),
+ mDequeueReadyTime(frameTimestamps.dequeueReadyTime) {
if (dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>()) {
mGpuCompositionDoneFence =
frameTimestamps.gpuCompositionDoneFence->getSnapshot();
@@ -489,7 +510,8 @@
sizeof(FrameEventsDelta::mRequestedPresentTime) +
sizeof(FrameEventsDelta::mLatchTime) +
sizeof(FrameEventsDelta::mFirstRefreshStartTime) +
- sizeof(FrameEventsDelta::mLastRefreshStartTime);
+ sizeof(FrameEventsDelta::mLastRefreshStartTime) +
+ sizeof(FrameEventsDelta::mDequeueReadyTime);
return min;
}
@@ -538,6 +560,7 @@
FlattenableUtils::write(buffer, size, mLatchTime);
FlattenableUtils::write(buffer, size, mFirstRefreshStartTime);
FlattenableUtils::write(buffer, size, mLastRefreshStartTime);
+ FlattenableUtils::write(buffer, size, mDequeueReadyTime);
// Fences
for (auto fence : allFences(this)) {
@@ -576,6 +599,7 @@
FlattenableUtils::read(buffer, size, mLatchTime);
FlattenableUtils::read(buffer, size, mFirstRefreshStartTime);
FlattenableUtils::read(buffer, size, mLastRefreshStartTime);
+ FlattenableUtils::read(buffer, size, mDequeueReadyTime);
// Fences
for (auto fence : allFences(this)) {
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
index 7d91d33..30f5e53 100644
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -15,7 +15,7 @@
** limitations under the License.
*/
-#include <android/log.h>
+#include <log/log.h>
#include <ui/GraphicBuffer.h>
diff --git a/libs/gui/GraphicsEnv.cpp b/libs/gui/GraphicsEnv.cpp
new file mode 100644
index 0000000..68f0f98
--- /dev/null
+++ b/libs/gui/GraphicsEnv.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 1
+#define LOG_TAG "GraphicsEnv"
+#include <gui/GraphicsEnv.h>
+
+#include <mutex>
+
+#include <log/log.h>
+#include <nativeloader/dlext_namespaces.h>
+
+namespace android {
+
+/*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
+ static GraphicsEnv env;
+ return env;
+}
+
+void GraphicsEnv::setDriverPath(const std::string path) {
+ if (!mDriverPath.empty()) {
+ ALOGV("ignoring attempt to change driver path from '%s' to '%s'",
+ mDriverPath.c_str(), path.c_str());
+ return;
+ }
+ ALOGV("setting driver path to '%s'", path.c_str());
+ mDriverPath = path;
+}
+
+android_namespace_t* GraphicsEnv::getDriverNamespace() {
+ static std::once_flag once;
+ std::call_once(once, [this]() {
+ // TODO; In the next version of Android, all graphics drivers will be
+ // loaded into a custom namespace. To minimize risk for this release,
+ // only updated drivers use a custom namespace.
+ //
+ // Additionally, the custom namespace will be
+ // ANDROID_NAMESPACE_TYPE_ISOLATED, and will only have access to a
+ // subset of the system.
+ if (mDriverPath.empty())
+ return;
+
+ char defaultPath[PATH_MAX];
+ android_get_LD_LIBRARY_PATH(defaultPath, sizeof(defaultPath));
+ size_t defaultPathLen = strlen(defaultPath);
+
+ std::string path;
+ path.reserve(mDriverPath.size() + 1 + defaultPathLen);
+ path.append(mDriverPath);
+ path.push_back(':');
+ path.append(defaultPath, defaultPathLen);
+
+ mDriverNamespace = android_create_namespace(
+ "gfx driver",
+ nullptr, // ld_library_path
+ path.c_str(), // default_library_path
+ ANDROID_NAMESPACE_TYPE_SHARED,
+ nullptr, // permitted_when_isolated_path
+ nullptr); // parent
+ });
+ return mDriverNamespace;
+}
+
+} // namespace android
+
+extern "C" android_namespace_t* android_getDriverNamespace() {
+ return android::GraphicsEnv::getInstance().getDriverNamespace();
+}
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 2401464..ef770e8 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -19,6 +19,7 @@
#include <utils/Errors.h>
#include <utils/NativeHandle.h>
+#include <utils/String8.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h>
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index e37b65b..18a80e8 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -20,6 +20,7 @@
#include <utils/Errors.h>
#include <utils/NativeHandle.h>
#include <utils/RefBase.h>
+#include <utils/String8.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index dbf03a5..a69de5e 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -19,11 +19,11 @@
#include <sys/limits.h>
#include <sys/types.h>
-#include <android/log.h>
#include <binder/AppOpsManager.h>
#include <binder/IServiceManager.h>
#include <gui/Sensor.h>
#include <hardware/sensors.h>
+#include <log/log.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <utils/Flattenable.h>
@@ -243,6 +243,14 @@
mStringType = SENSOR_STRING_TYPE_HEART_BEAT;
mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
break;
+
+ // TODO: Placeholder for LLOB sensor type
+
+
+ case SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED:
+ mStringType = SENSOR_STRING_TYPE_ACCELEROMETER_UNCALIBRATED;
+ mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+ break;
default:
// Only pipe the stringType, requiredPermission and flags for custom sensors.
if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.stringType) {
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 1e79e06..c859828 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -49,11 +49,11 @@
mAutoRefresh(false),
mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
mSharedBufferHasBeenQueued(false),
- mNextFrameNumber(1),
mQueriedSupportedTimestamps(false),
mFrameTimestampsSupportsPresent(false),
mFrameTimestampsSupportsRetire(false),
- mEnableFrameTimestamps(false)
+ mEnableFrameTimestamps(false),
+ mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
{
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = hook_setSwapInterval;
@@ -97,6 +97,10 @@
}
}
+sp<ISurfaceComposer> Surface::composerService() const {
+ return ComposerService::getComposerService();
+}
+
sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
return mGraphicBufferProducer;
}
@@ -144,6 +148,43 @@
mEnableFrameTimestamps = enable;
}
+static bool checkConsumerForUpdates(
+ const FrameEvents* e, const uint64_t lastFrameNumber,
+ const nsecs_t* outLatchTime,
+ const nsecs_t* outFirstRefreshStartTime,
+ const nsecs_t* outLastRefreshStartTime,
+ const nsecs_t* outGlCompositionDoneTime,
+ const nsecs_t* outDisplayPresentTime,
+ const nsecs_t* outDisplayRetireTime,
+ const nsecs_t* outDequeueReadyTime,
+ const nsecs_t* outReleaseTime) {
+ bool checkForLatch = (outLatchTime != nullptr) && !e->hasLatchInfo();
+ bool checkForFirstRefreshStart = (outFirstRefreshStartTime != nullptr) &&
+ !e->hasFirstRefreshStartInfo();
+ bool checkForGlCompositionDone = (outGlCompositionDoneTime != nullptr) &&
+ !e->hasGpuCompositionDoneInfo();
+ bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) &&
+ !e->hasDisplayPresentInfo();
+
+ // LastRefreshStart, DisplayRetire, DequeueReady, and Release are never
+ // available for the last frame.
+ bool checkForLastRefreshStart = (outLastRefreshStartTime != nullptr) &&
+ !e->hasLastRefreshStartInfo() &&
+ (e->frameNumber != lastFrameNumber);
+ bool checkForDisplayRetire = (outDisplayRetireTime != nullptr) &&
+ !e->hasDisplayRetireInfo() && (e->frameNumber != lastFrameNumber);
+ bool checkForDequeueReady = (outDequeueReadyTime != nullptr) &&
+ !e->hasDequeueReadyInfo() && (e->frameNumber != lastFrameNumber);
+ bool checkForRelease = (outReleaseTime != nullptr) &&
+ !e->hasReleaseInfo() && (e->frameNumber != lastFrameNumber);
+
+ // RequestedPresent and Acquire info are always available producer-side.
+ return checkForLatch || checkForFirstRefreshStart ||
+ checkForLastRefreshStart || checkForGlCompositionDone ||
+ checkForDisplayPresent || checkForDisplayRetire ||
+ checkForDequeueReady || checkForRelease;
+}
+
static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
if (dst != nullptr) {
*dst = Fence::isValidTimestamp(src) ? src : 0;
@@ -159,9 +200,10 @@
status_t Surface::getFrameTimestamps(uint64_t frameNumber,
nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
- nsecs_t* outRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
+ nsecs_t* outLatchTime, nsecs_t* outFirstRefreshStartTime,
+ nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
nsecs_t* outDisplayPresentTime, nsecs_t* outDisplayRetireTime,
- nsecs_t* outReleaseTime) {
+ nsecs_t* outDequeueReadyTime, nsecs_t* outReleaseTime) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
@@ -179,30 +221,35 @@
return BAD_VALUE;
}
- FrameEvents* events = mFrameEventHistory.getFrame(frameNumber);
-
- // Update our cache of events if the requested events are not available.
- if (events == nullptr ||
- (outRequestedPresentTime && !events->hasRequestedPresentInfo()) ||
- (outAcquireTime && !events->hasAcquireInfo()) ||
- (outRefreshStartTime && !events->hasFirstRefreshStartInfo()) ||
- (outGlCompositionDoneTime && !events->hasGpuCompositionDoneInfo()) ||
- (outDisplayPresentTime && !events->hasDisplayPresentInfo()) ||
- (outDisplayRetireTime && !events->hasDisplayRetireInfo()) ||
- (outReleaseTime && !events->hasReleaseInfo())) {
- FrameEventHistoryDelta delta;
- mGraphicBufferProducer->getFrameTimestamps(&delta);
- mFrameEventHistory.applyDelta(delta);
- events = mFrameEventHistory.getFrame(frameNumber);
+ FrameEvents* events = mFrameEventHistory->getFrame(frameNumber);
+ if (events == nullptr) {
+ // If the entry isn't available in the producer, it's definitely not
+ // available in the consumer.
+ return NAME_NOT_FOUND;
}
- // A record for the requested frame does not exist.
+ // Update our cache of events if the requested events are not available.
+ if (checkConsumerForUpdates(events, mLastFrameNumber,
+ outLatchTime, outFirstRefreshStartTime, outLastRefreshStartTime,
+ outGlCompositionDoneTime, outDisplayPresentTime,
+ outDisplayRetireTime, outDequeueReadyTime, outReleaseTime)) {
+ FrameEventHistoryDelta delta;
+ mGraphicBufferProducer->getFrameTimestamps(&delta);
+ mFrameEventHistory->applyDelta(delta);
+ events = mFrameEventHistory->getFrame(frameNumber);
+ }
+
if (events == nullptr) {
+ // The entry was available before the update, but was overwritten
+ // after the update. Make sure not to send the wrong frame's data.
return NAME_NOT_FOUND;
}
getFrameTimestamp(outRequestedPresentTime, events->requestedPresentTime);
- getFrameTimestamp(outRefreshStartTime, events->firstRefreshStartTime);
+ getFrameTimestamp(outLatchTime, events->latchTime);
+ getFrameTimestamp(outFirstRefreshStartTime, events->firstRefreshStartTime);
+ getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
+ getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
getFrameTimestampFence(outAcquireTime, events->acquireFence);
getFrameTimestampFence(
@@ -347,11 +394,9 @@
nsecs_t now = systemTime();
FrameEventHistoryDelta frameTimestamps;
- FrameEventHistoryDelta* frameTimestampsOrNull =
- enableFrameTimestamps ? &frameTimestamps : nullptr;
-
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
- reqWidth, reqHeight, reqFormat, reqUsage, frameTimestampsOrNull);
+ reqWidth, reqHeight, reqFormat, reqUsage,
+ enableFrameTimestamps ? &frameTimestamps : nullptr);
mLastDequeueDuration = systemTime() - now;
if (result < 0) {
@@ -373,7 +418,7 @@
}
if (enableFrameTimestamps) {
- mFrameEventHistory.applyDelta(frameTimestamps);
+ mFrameEventHistory->applyDelta(frameTimestamps);
}
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
@@ -567,18 +612,20 @@
}
if (mEnableFrameTimestamps) {
- mFrameEventHistory.applyDelta(output.frameTimestamps);
+ mFrameEventHistory->applyDelta(output.frameTimestamps);
// Update timestamps with the local acquire fence.
// The consumer doesn't send it back to prevent us from having two
// file descriptors of the same fence.
- mFrameEventHistory.updateAcquireFence(mNextFrameNumber,
+ mFrameEventHistory->updateAcquireFence(mNextFrameNumber,
std::make_shared<FenceTime>(std::move(fence)));
// Cache timestamps of signaled fences so we can close their file
// descriptors.
- mFrameEventHistory.updateSignalTimes();
+ mFrameEventHistory->updateSignalTimes();
}
+ mLastFrameNumber = mNextFrameNumber;
+
mDefaultWidth = output.width;
mDefaultHeight = output.height;
mNextFrameNumber = output.nextFrameNumber;
@@ -613,8 +660,7 @@
mQueriedSupportedTimestamps = true;
std::vector<FrameEvent> supportedFrameTimestamps;
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- status_t err = composer->getSupportedFrameTimestamps(
+ status_t err = composerService()->getSupportedFrameTimestamps(
&supportedFrameTimestamps);
if (err != NO_ERROR) {
@@ -643,9 +689,8 @@
}
break;
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
- sp<ISurfaceComposer> composer(
- ComposerService::getComposerService());
- if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
+ if (composerService()->authenticateSurfaceTexture(
+ mGraphicBufferProducer)) {
*value = 1;
} else {
*value = 0;
@@ -913,15 +958,19 @@
uint32_t framesAgo = va_arg(args, uint32_t);
nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*);
nsecs_t* outAcquireTime = va_arg(args, int64_t*);
- nsecs_t* outRefreshStartTime = va_arg(args, int64_t*);
+ nsecs_t* outLatchTime = va_arg(args, int64_t*);
+ nsecs_t* outFirstRefreshStartTime = va_arg(args, int64_t*);
+ nsecs_t* outLastRefreshStartTime = va_arg(args, int64_t*);
nsecs_t* outGlCompositionDoneTime = va_arg(args, int64_t*);
nsecs_t* outDisplayPresentTime = va_arg(args, int64_t*);
nsecs_t* outDisplayRetireTime = va_arg(args, int64_t*);
+ nsecs_t* outDequeueReadyTime = va_arg(args, int64_t*);
nsecs_t* outReleaseTime = va_arg(args, int64_t*);
return getFrameTimestamps(getNextFrameNumber() - 1 - framesAgo,
- outRequestedPresentTime, outAcquireTime, outRefreshStartTime,
+ outRequestedPresentTime, outAcquireTime, outLatchTime,
+ outFirstRefreshStartTime, outLastRefreshStartTime,
outGlCompositionDoneTime, outDisplayPresentTime,
- outDisplayRetireTime, outReleaseTime);
+ outDisplayRetireTime, outDequeueReadyTime, outReleaseTime);
}
int Surface::connect(int api) {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 78afc76..58b2a87 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -33,6 +33,7 @@
#include <ui/DisplayInfo.h>
+#include <gui/BufferItemConsumer.h>
#include <gui/CpuConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
@@ -859,6 +860,33 @@
reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
}
+status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform,
+ uint32_t rotation,
+ sp<GraphicBuffer>* outBuffer) {
+ sp<ISurfaceComposer> s(ComposerService::getComposerService());
+ if (s == NULL) return NO_INIT;
+
+ sp<IGraphicBufferConsumer> gbpConsumer;
+ sp<IGraphicBufferProducer> producer;
+ BufferQueue::createBufferQueue(&producer, &gbpConsumer);
+ sp<BufferItemConsumer> consumer(new BufferItemConsumer(gbpConsumer,
+ GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER,
+ 1, true));
+
+ status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight,
+ minLayerZ, maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ BufferItem b;
+ consumer->acquireBuffer(&b, 0, true);
+ *outBuffer = b.mGraphicBuffer;
+ return ret;
+}
+
ScreenshotClient::ScreenshotClient()
: mHaveBuffer(false) {
memset(&mBuffer, 0, sizeof(mBuffer));
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 66e1bb6..e40b4eb 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -19,22 +19,28 @@
#include <gtest/gtest.h>
#include <binder/IMemory.h>
+#include <binder/ProcessState.h>
+#include <gui/IDisplayEventConnection.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/BufferItemConsumer.h>
+#include <private/gui/ComposerService.h>
#include <ui/Rect.h>
#include <utils/String8.h>
-#include <private/gui/ComposerService.h>
-#include <binder/ProcessState.h>
-
+#include <limits>
#include <thread>
namespace android {
using namespace std::chrono_literals;
+class FakeSurfaceComposer;
+class FakeProducerFrameEventHistory;
+
+static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits<uint64_t>::max();
+
class SurfaceTest : public ::testing::Test {
protected:
@@ -102,7 +108,8 @@
BufferQueue::createBufferQueue(&producer, &consumer);
sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ sp<IBinder> display(sf->getBuiltInDisplay(
+ ISurfaceComposer::eDisplayIdMain));
ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
64, 64, 0, 0x7fffffff, false));
@@ -272,4 +279,947 @@
ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
}
+
+class FakeConsumer : public BnConsumerListener {
+public:
+ void onFrameAvailable(const BufferItem& /*item*/) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+
+ void addAndGetFrameTimestamps(
+ const NewFrameEventsEntry* newTimestamps,
+ FrameEventHistoryDelta* outDelta) override {
+ if (newTimestamps) {
+ if (mGetFrameTimestampsEnabled) {
+ EXPECT_GT(mNewFrameEntryOverride.frameNumber, 0u) <<
+ "Test should set mNewFrameEntryOverride before queuing "
+ "a frame.";
+ EXPECT_EQ(newTimestamps->frameNumber,
+ mNewFrameEntryOverride.frameNumber) <<
+ "Test attempting to add NewFrameEntryOverride with "
+ "incorrect frame number.";
+ mFrameEventHistory.addQueue(mNewFrameEntryOverride);
+ mNewFrameEntryOverride.frameNumber = 0;
+ }
+ mAddFrameTimestampsCount++;
+ mLastAddedFrameNumber = newTimestamps->frameNumber;
+ }
+ if (outDelta) {
+ mFrameEventHistory.getAndResetDelta(outDelta);
+ mGetFrameTimestampsCount++;
+ }
+ mAddAndGetFrameTimestampsCallCount++;
+ }
+
+ bool mGetFrameTimestampsEnabled = false;
+
+ ConsumerFrameEventHistory mFrameEventHistory;
+ int mAddAndGetFrameTimestampsCallCount = 0;
+ int mAddFrameTimestampsCount = 0;
+ int mGetFrameTimestampsCount = 0;
+ uint64_t mLastAddedFrameNumber = NO_FRAME_INDEX;
+
+ NewFrameEventsEntry mNewFrameEntryOverride = { 0, 0, 0, nullptr };
+};
+
+
+class FakeSurfaceComposer : public ISurfaceComposer{
+public:
+ ~FakeSurfaceComposer() override {}
+
+ void setSupportedTimestamps(bool supportsPresent, bool supportsRetire) {
+ mSupportsPresent = supportsPresent;
+ mSupportsRetire = supportsRetire;
+ }
+
+ sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
+ sp<IGraphicBufferAlloc> createGraphicBufferAlloc() override {
+ return nullptr;
+ }
+ sp<IDisplayEventConnection> createDisplayEventConnection() override {
+ return nullptr;
+ }
+ sp<IBinder> createDisplay(const String8& /*displayName*/,
+ bool /*secure*/) override { return nullptr; }
+ void destroyDisplay(const sp<IBinder>& /*display */) override {}
+ sp<IBinder> getBuiltInDisplay(int32_t /*id*/) override { return nullptr; }
+ void setTransactionState(const Vector<ComposerState>& /*state*/,
+ const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/)
+ override {}
+ void bootFinished() override {}
+ bool authenticateSurfaceTexture(
+ const sp<IGraphicBufferProducer>& /*surface*/) const override {
+ return false;
+ }
+
+ status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported)
+ const override {
+ *outSupported = {
+ FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GL_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE
+ };
+ if (mSupportsPresent) {
+ outSupported->push_back(
+ FrameEvent::DISPLAY_PRESENT);
+ }
+ if (mSupportsRetire) {
+ outSupported->push_back(
+ FrameEvent::DISPLAY_RETIRE);
+ }
+ return NO_ERROR;
+ }
+
+ void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {}
+ status_t getDisplayConfigs(const sp<IBinder>& /*display*/,
+ Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
+ status_t getDisplayStats(const sp<IBinder>& /*display*/,
+ DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
+ int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; }
+ status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/)
+ override {
+ return NO_ERROR;
+ }
+ status_t getDisplayColorModes(const sp<IBinder>& /*display*/,
+ Vector<android_color_mode_t>* /*outColorModes*/) override {
+ return NO_ERROR;
+ }
+ android_color_mode_t getActiveColorMode(const sp<IBinder>& /*display*/)
+ override {
+ return HAL_COLOR_MODE_NATIVE;
+ }
+ status_t setActiveColorMode(const sp<IBinder>& /*display*/,
+ android_color_mode_t /*colorMode*/) override { return NO_ERROR; }
+ status_t captureScreen(const sp<IBinder>& /*display*/,
+ const sp<IGraphicBufferProducer>& /*producer*/,
+ Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
+ uint32_t /*minLayerZ*/, uint32_t /*maxLayerZ*/,
+ bool /*useIdentityTransform*/,
+ Rotation /*rotation*/) override { return NO_ERROR; }
+ status_t clearAnimationFrameStats() override { return NO_ERROR; }
+ status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
+ return NO_ERROR;
+ }
+ status_t getHdrCapabilities(const sp<IBinder>& /*display*/,
+ HdrCapabilities* /*outCapabilities*/) const override {
+ return NO_ERROR;
+ }
+ status_t enableVSyncInjections(bool /*enable*/) override {
+ return NO_ERROR;
+ }
+ status_t injectVSync(nsecs_t /*when*/) override { return NO_ERROR; }
+
+protected:
+ IBinder* onAsBinder() override { return nullptr; }
+
+private:
+ bool mSupportsPresent{true};
+ bool mSupportsRetire{true};
+};
+
+class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
+public:
+ FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap)
+ : mFenceMap(fenceMap) {}
+
+ ~FakeProducerFrameEventHistory() {}
+
+ void updateAcquireFence(uint64_t frameNumber,
+ std::shared_ptr<FenceTime>&& acquire) override {
+ // Verify the acquire fence being added isn't the one from the consumer.
+ EXPECT_NE(mConsumerAcquireFence, acquire);
+ // Override the fence, so we can verify this was called by the
+ // producer after the frame is queued.
+ ProducerFrameEventHistory::updateAcquireFence(frameNumber,
+ std::shared_ptr<FenceTime>(mAcquireFenceOverride));
+ }
+
+ void setAcquireFenceOverride(
+ const std::shared_ptr<FenceTime>& acquireFenceOverride,
+ const std::shared_ptr<FenceTime>& consumerAcquireFence) {
+ mAcquireFenceOverride = acquireFenceOverride;
+ mConsumerAcquireFence = consumerAcquireFence;
+ }
+
+protected:
+ std::shared_ptr<FenceTime> createFenceTime(const sp<Fence>& fence)
+ const override {
+ return mFenceMap->createFenceTimeForTest(fence);
+ }
+
+ FenceToFenceTimeMap* mFenceMap{nullptr};
+
+ std::shared_ptr<FenceTime> mAcquireFenceOverride{FenceTime::NO_FENCE};
+ std::shared_ptr<FenceTime> mConsumerAcquireFence{FenceTime::NO_FENCE};
+};
+
+
+class TestSurface : public Surface {
+public:
+ TestSurface(const sp<IGraphicBufferProducer>& bufferProducer,
+ FenceToFenceTimeMap* fenceMap)
+ : Surface(bufferProducer),
+ mFakeSurfaceComposer(new FakeSurfaceComposer) {
+ mFakeFrameEventHistory = new FakeProducerFrameEventHistory(fenceMap);
+ mFrameEventHistory.reset(mFakeFrameEventHistory);
+ }
+
+ ~TestSurface() override {}
+
+ sp<ISurfaceComposer> composerService() const override {
+ return mFakeSurfaceComposer;
+ }
+
+public:
+ sp<FakeSurfaceComposer> mFakeSurfaceComposer;
+
+ // mFrameEventHistory owns the instance of FakeProducerFrameEventHistory,
+ // but this raw pointer gives access to test functionality.
+ FakeProducerFrameEventHistory* mFakeFrameEventHistory;
+};
+
+
+class GetFrameTimestampsTest : public SurfaceTest {
+protected:
+ struct FenceAndFenceTime {
+ explicit FenceAndFenceTime(FenceToFenceTimeMap& fenceMap)
+ : mFence(new Fence),
+ mFenceTime(fenceMap.createFenceTimeForTest(mFence)) {}
+ sp<Fence> mFence { nullptr };
+ std::shared_ptr<FenceTime> mFenceTime { nullptr };
+ };
+
+ struct RefreshEvents {
+ RefreshEvents(FenceToFenceTimeMap& fenceMap, nsecs_t refreshStart)
+ : mFenceMap(fenceMap),
+ kStartTime(refreshStart + 1),
+ kGpuCompositionDoneTime(refreshStart + 2),
+ kPresentTime(refreshStart + 3) {}
+
+ void signalPostCompositeFences() {
+ mFenceMap.signalAllForTest(
+ mGpuCompositionDone.mFence, kGpuCompositionDoneTime);
+ mFenceMap.signalAllForTest(mPresent.mFence, kPresentTime);
+ }
+
+ FenceToFenceTimeMap& mFenceMap;
+
+ FenceAndFenceTime mGpuCompositionDone { mFenceMap };
+ FenceAndFenceTime mPresent { mFenceMap };
+
+ const nsecs_t kStartTime;
+ const nsecs_t kGpuCompositionDoneTime;
+ const nsecs_t kPresentTime;
+ };
+
+ struct FrameEvents {
+ FrameEvents(FenceToFenceTimeMap& fenceMap, nsecs_t frameStartTime)
+ : mFenceMap(fenceMap),
+ kPostedTime(frameStartTime + 100),
+ kRequestedPresentTime(frameStartTime + 200),
+ kProducerAcquireTime(frameStartTime + 300),
+ kConsumerAcquireTime(frameStartTime + 301),
+ kLatchTime(frameStartTime + 500),
+ kDequeueReadyTime(frameStartTime + 600),
+ kRetireTime(frameStartTime + 700),
+ kReleaseTime(frameStartTime + 800),
+ mRefreshes {
+ { mFenceMap, frameStartTime + 410 },
+ { mFenceMap, frameStartTime + 420 },
+ { mFenceMap, frameStartTime + 430 } } {}
+
+ void signalQueueFences() {
+ mFenceMap.signalAllForTest(
+ mAcquireConsumer.mFence, kConsumerAcquireTime);
+ mFenceMap.signalAllForTest(
+ mAcquireProducer.mFence, kProducerAcquireTime);
+ }
+
+ void signalRefreshFences() {
+ for (auto& re : mRefreshes) {
+ re.signalPostCompositeFences();
+ }
+ }
+
+ void signalReleaseFences() {
+ mFenceMap.signalAllForTest(mRetire.mFence, kRetireTime);
+ mFenceMap.signalAllForTest(mRelease.mFence, kReleaseTime);
+ }
+
+ FenceToFenceTimeMap& mFenceMap;
+
+ FenceAndFenceTime mAcquireConsumer { mFenceMap };
+ FenceAndFenceTime mAcquireProducer { mFenceMap };
+ FenceAndFenceTime mRetire { mFenceMap };
+ FenceAndFenceTime mRelease { mFenceMap };
+
+ const nsecs_t kPostedTime;
+ const nsecs_t kRequestedPresentTime;
+ const nsecs_t kProducerAcquireTime;
+ const nsecs_t kConsumerAcquireTime;
+ const nsecs_t kLatchTime;
+ const nsecs_t kDequeueReadyTime;
+ const nsecs_t kRetireTime;
+ const nsecs_t kReleaseTime;
+
+ RefreshEvents mRefreshes[3];
+ };
+
+ GetFrameTimestampsTest() : SurfaceTest() {}
+
+ virtual void SetUp() {
+ SurfaceTest::SetUp();
+
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ mFakeConsumer = new FakeConsumer;
+ mCfeh = &mFakeConsumer->mFrameEventHistory;
+ mConsumer->consumerConnect(mFakeConsumer, false);
+ mConsumer->setConsumerName(String8("TestConsumer"));
+ mSurface = new TestSurface(mProducer, &mFenceMap);
+ mWindow = mSurface;
+
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mWindow.get(),
+ NATIVE_WINDOW_API_CPU));
+ native_window_set_buffer_count(mWindow.get(), 4);
+ }
+
+ void enableFrameTimestamps() {
+ mFakeConsumer->mGetFrameTimestampsEnabled = true;
+ native_window_enable_frame_timestamps(mWindow.get(), 1);
+ mFrameTimestampsEnabled = true;
+ }
+
+ int getAllFrameTimestamps(uint32_t framesAgo) {
+ return native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ &outRequestedPresentTime, &outAcquireTime, &outLatchTime,
+ &outFirstRefreshStartTime, &outLastRefreshStartTime,
+ &outGpuCompositionDoneTime, &outDisplayPresentTime,
+ &outDisplayRetireTime, &outDequeueReadyTime, &outReleaseTime);
+ }
+
+ void resetTimestamps() {
+ outRequestedPresentTime = -1;
+ outAcquireTime = -1;
+ outLatchTime = -1;
+ outFirstRefreshStartTime = -1;
+ outLastRefreshStartTime = -1;
+ outGpuCompositionDoneTime = -1;
+ outDisplayPresentTime = -1;
+ outDisplayRetireTime = -1;
+ outDequeueReadyTime = -1;
+ outReleaseTime = -1;
+ }
+
+ void dequeueAndQueue(uint64_t frameIndex) {
+ int fence = -1;
+ ANativeWindowBuffer* buffer = nullptr;
+ ASSERT_EQ(NO_ERROR,
+ mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence));
+
+ int oldAddFrameTimestampsCount =
+ mFakeConsumer->mAddFrameTimestampsCount;
+
+ FrameEvents* frame = &mFrames[frameIndex];
+ uint64_t frameNumber = frameIndex + 1;
+
+ NewFrameEventsEntry fe;
+ fe.frameNumber = frameNumber;
+ fe.postedTime = frame->kPostedTime;
+ fe.requestedPresentTime = frame->kRequestedPresentTime;
+ fe.acquireFence = frame->mAcquireConsumer.mFenceTime;
+ mFakeConsumer->mNewFrameEntryOverride = fe;
+
+ mSurface->mFakeFrameEventHistory->setAcquireFenceOverride(
+ frame->mAcquireProducer.mFenceTime,
+ frame->mAcquireConsumer.mFenceTime);
+
+ ASSERT_EQ(NO_ERROR, mWindow->queueBuffer(mWindow.get(), buffer, fence));
+
+ EXPECT_EQ(frameNumber, mFakeConsumer->mLastAddedFrameNumber);
+
+ EXPECT_EQ(
+ oldAddFrameTimestampsCount + (mFrameTimestampsEnabled ? 1 : 0),
+ mFakeConsumer->mAddFrameTimestampsCount);
+ }
+
+ void addFrameEvents(
+ bool gpuComposited, uint64_t iOldFrame, int64_t iNewFrame) {
+ FrameEvents* oldFrame =
+ (iOldFrame == NO_FRAME_INDEX) ? nullptr : &mFrames[iOldFrame];
+ FrameEvents* newFrame = &mFrames[iNewFrame];
+
+ uint64_t nOldFrame = iOldFrame + 1;
+ uint64_t nNewFrame = iNewFrame + 1;
+
+ // Latch, Composite, Retire, and Release the frames in a plausible
+ // order. Note: The timestamps won't necessarily match the order, but
+ // that's okay for the purposes of this test.
+ std::shared_ptr<FenceTime> gpuDoneFenceTime = FenceTime::NO_FENCE;
+
+ // Composite the previous frame one more time, which helps verify
+ // LastRefresh is updated properly.
+ if (oldFrame != nullptr) {
+ mCfeh->addPreComposition(nOldFrame,
+ oldFrame->mRefreshes[2].kStartTime);
+ gpuDoneFenceTime = gpuComposited ?
+ oldFrame->mRefreshes[2].mGpuCompositionDone.mFenceTime :
+ FenceTime::NO_FENCE;
+ mCfeh->addPostComposition(nOldFrame, gpuDoneFenceTime,
+ oldFrame->mRefreshes[2].mPresent.mFenceTime);
+ }
+
+ // Latch the new frame.
+ mCfeh->addLatch(nNewFrame, newFrame->kLatchTime);
+
+ mCfeh->addPreComposition(nNewFrame, newFrame->mRefreshes[0].kStartTime);
+ gpuDoneFenceTime = gpuComposited ?
+ newFrame->mRefreshes[0].mGpuCompositionDone.mFenceTime :
+ FenceTime::NO_FENCE;
+ // HWC2 releases the previous buffer after a new latch just before
+ // calling postComposition.
+ if (oldFrame != nullptr) {
+ mCfeh->addRelease(nOldFrame, oldFrame->kDequeueReadyTime,
+ std::shared_ptr<FenceTime>(oldFrame->mRelease.mFenceTime));
+ }
+ mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
+ newFrame->mRefreshes[0].mPresent.mFenceTime);
+
+ // Retire the previous buffer just after compositing the new buffer.
+ if (oldFrame != nullptr) {
+ mCfeh->addRetire(nOldFrame, oldFrame->mRetire.mFenceTime);
+ }
+
+ mCfeh->addPreComposition(nNewFrame, newFrame->mRefreshes[1].kStartTime);
+ gpuDoneFenceTime = gpuComposited ?
+ newFrame->mRefreshes[1].mGpuCompositionDone.mFenceTime :
+ FenceTime::NO_FENCE;
+ mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
+ newFrame->mRefreshes[1].mPresent.mFenceTime);
+ }
+
+ void QueryPresentRetireSupported(
+ bool displayPresentSupported, bool displayRetireSupported);
+ void PresentOrRetireUnsupportedNoSyncTest(
+ bool displayPresentSupported, bool displayRetireSupported);
+
+ sp<IGraphicBufferProducer> mProducer;
+ sp<IGraphicBufferConsumer> mConsumer;
+ sp<FakeConsumer> mFakeConsumer;
+ ConsumerFrameEventHistory* mCfeh;
+ sp<TestSurface> mSurface;
+ sp<ANativeWindow> mWindow;
+
+ FenceToFenceTimeMap mFenceMap;
+
+ bool mFrameTimestampsEnabled = false;
+
+ int64_t outRequestedPresentTime = -1;
+ int64_t outAcquireTime = -1;
+ int64_t outLatchTime = -1;
+ int64_t outFirstRefreshStartTime = -1;
+ int64_t outLastRefreshStartTime = -1;
+ int64_t outGpuCompositionDoneTime = -1;
+ int64_t outDisplayPresentTime = -1;
+ int64_t outDisplayRetireTime = -1;
+ int64_t outDequeueReadyTime = -1;
+ int64_t outReleaseTime = -1;
+
+ FrameEvents mFrames[2] { { mFenceMap, 1000 }, { mFenceMap, 2000 } };
+};
+
+
+// This test verifies that the frame timestamps are not retrieved when not
+// explicitly enabled via native_window_enable_frame_timestamps.
+// We want to check this to make sure there's no overhead for users
+// that don't need the timestamp information.
+TEST_F(GetFrameTimestampsTest, DefaultDisabled) {
+ int fence;
+ ANativeWindowBuffer* buffer;
+
+ EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
+ EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+
+ // Verify the producer doesn't get frame timestamps piggybacked on dequeue.
+ ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence));
+ EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
+ EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+
+ // Verify the producer doesn't get frame timestamps piggybacked on queue.
+ // It is okay that frame timestamps are added in the consumer since it is
+ // still needed for SurfaceFlinger dumps.
+ ASSERT_EQ(NO_ERROR, mWindow->queueBuffer(mWindow.get(), buffer, fence));
+ EXPECT_EQ(1, mFakeConsumer->mAddFrameTimestampsCount);
+ EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+
+ // Verify attempts to get frame timestamps fail.
+ const uint32_t framesAgo = 0;
+ int result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(INVALID_OPERATION, result);
+ EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+}
+
+// This test verifies that the frame timestamps are retrieved if explicitly
+// enabled via native_window_enable_frame_timestamps.
+TEST_F(GetFrameTimestampsTest, EnabledSimple) {
+ enableFrameTimestamps();
+
+ int fence;
+ ANativeWindowBuffer* buffer;
+
+ EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
+ EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+
+ // Verify getFrameTimestamps is piggybacked on dequeue.
+ ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence));
+ EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
+ EXPECT_EQ(1, mFakeConsumer->mGetFrameTimestampsCount);
+
+ NewFrameEventsEntry f1;
+ f1.frameNumber = 1;
+ f1.postedTime = mFrames[0].kPostedTime;
+ f1.requestedPresentTime = mFrames[0].kRequestedPresentTime;
+ f1.acquireFence = mFrames[0].mAcquireConsumer.mFenceTime;
+ mSurface->mFakeFrameEventHistory->setAcquireFenceOverride(
+ mFrames[0].mAcquireProducer.mFenceTime,
+ mFrames[0].mAcquireConsumer.mFenceTime);
+ mFakeConsumer->mNewFrameEntryOverride = f1;
+ mFrames[0].signalQueueFences();
+
+ // Verify getFrameTimestamps is piggybacked on queue.
+ ASSERT_EQ(NO_ERROR, mWindow->queueBuffer(mWindow.get(), buffer, fence));
+ EXPECT_EQ(1, mFakeConsumer->mAddFrameTimestampsCount);
+ EXPECT_EQ(1u, mFakeConsumer->mLastAddedFrameNumber);
+ EXPECT_EQ(2, mFakeConsumer->mGetFrameTimestampsCount);
+
+ // Verify queries for timestamps that the producer doesn't know about
+ // triggers a call to see if the consumer has any new timestamps.
+ const uint32_t framesAgo = 0;
+ int result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount);
+}
+
+void GetFrameTimestampsTest::QueryPresentRetireSupported(
+ bool displayPresentSupported, bool displayRetireSupported) {
+ mSurface->mFakeSurfaceComposer->setSupportedTimestamps(
+ displayPresentSupported, displayRetireSupported);
+
+ // Verify supported bits are forwarded.
+ int supportsPresent = -1;
+ mWindow.get()->query(mWindow.get(),
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+ EXPECT_EQ(displayPresentSupported, supportsPresent);
+
+ int supportsRetire = -1;
+ mWindow.get()->query(mWindow.get(),
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE, &supportsRetire);
+ EXPECT_EQ(displayRetireSupported, supportsRetire);
+}
+
+TEST_F(GetFrameTimestampsTest, QueryPresentSupported) {
+ QueryPresentRetireSupported(true, false);
+}
+
+TEST_F(GetFrameTimestampsTest, QueryRetireSupported) {
+ QueryPresentRetireSupported(false, true);
+}
+
+// This test verifies that:
+// 1) The timestamps recorded in the consumer's FrameTimestampsHistory are
+// properly retrieved by the producer for the correct frames.
+// 2) When framesAgo is 0, it is querying for the most recently queued frame.
+TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) {
+ enableFrameTimestamps();
+
+ dequeueAndQueue(0);
+ mFrames[0].signalQueueFences();
+
+ dequeueAndQueue(1);
+ mFrames[1].signalQueueFences();
+
+ addFrameEvents(true, NO_FRAME_INDEX, 0);
+ mFrames[0].signalRefreshFences();
+ addFrameEvents(true, 0, 1);
+ mFrames[0].signalReleaseFences();
+ mFrames[1].signalRefreshFences();
+
+ // Verify timestamps are correct for frame 1.
+ uint32_t framesAgo = 1;
+ resetTimestamps();
+ int result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kGpuCompositionDoneTime,
+ outGpuCompositionDoneTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
+ EXPECT_EQ(mFrames[0].kRetireTime, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
+ EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
+
+ // Verify timestamps are correct for frame 2.
+ framesAgo = 0;
+ resetTimestamps();
+ result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
+ outGpuCompositionDoneTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
+ EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(0, outDequeueReadyTime);
+ EXPECT_EQ(0, outReleaseTime);
+}
+
+// This test verifies the acquire fence recorded by the consumer is not sent
+// back to the producer and the producer saves its own fence.
+TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) {
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
+
+ const uint32_t framesAgo = 0;
+
+ // Dequeue and queue frame 1.
+ dequeueAndQueue(0);
+
+ // Verify queue-related timestamps for f1 are available immediately in the
+ // producer without asking the consumer again, even before signaling the
+ // acquire fence.
+ resetTimestamps();
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(0, outAcquireTime);
+
+ // Signal acquire fences. Verify a sync call still isn't necessary.
+ mFrames[0].signalQueueFences();
+
+ oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+
+ // Dequeue and queue frame 2.
+ dequeueAndQueue(1);
+
+ // Verify queue-related timestamps for f2 are available immediately in the
+ // producer without asking the consumer again, even before signaling the
+ // acquire fence.
+ resetTimestamps();
+ oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(0, outAcquireTime);
+
+ // Signal acquire fences. Verify a sync call still isn't necessary.
+ mFrames[1].signalQueueFences();
+
+ oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime);
+}
+
+TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) {
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
+
+ // Dequeue and queue frame 1.
+ dequeueAndQueue(0);
+ mFrames[0].signalQueueFences();
+
+ // Dequeue and queue frame 2.
+ dequeueAndQueue(1);
+ mFrames[1].signalQueueFences();
+
+ addFrameEvents(true, NO_FRAME_INDEX, 0);
+ mFrames[0].signalRefreshFences();
+ addFrameEvents(true, 0, 1);
+ mFrames[0].signalReleaseFences();
+ mFrames[1].signalRefreshFences();
+
+ // Verify a request for no timestamps doesn't result in a sync call.
+ const uint32_t framesAgo = 0;
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+}
+
+// This test verifies that fences can signal and update timestamps producer
+// side without an additional sync call to the consumer.
+TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) {
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
+
+ // Dequeue and queue frame 1.
+ dequeueAndQueue(0);
+ mFrames[0].signalQueueFences();
+
+ // Dequeue and queue frame 2.
+ dequeueAndQueue(1);
+ mFrames[1].signalQueueFences();
+
+ addFrameEvents(true, NO_FRAME_INDEX, 0);
+ addFrameEvents(true, 0, 1);
+
+ // Verify available timestamps are correct for frame 1, before any
+ // fence has been signaled.
+ // Note: A sync call is necessary here since the events triggered by
+ // addFrameEvents didn't get to piggyback on the earlier queues/dequeues.
+ uint32_t framesAgo = 1;
+ resetTimestamps();
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
+ EXPECT_EQ(0, outReleaseTime);
+
+ // Verify available timestamps are correct for frame 1 again, before any
+ // fence has been signaled.
+ // This time a sync call should not be necessary.
+ framesAgo = 1;
+ resetTimestamps();
+ oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
+ EXPECT_EQ(0, outReleaseTime);
+
+ // Signal the fences for frame 1.
+ mFrames[0].signalRefreshFences();
+ mFrames[0].signalReleaseFences();
+
+ // Verify all timestamps are available without a sync call.
+ framesAgo = 1;
+ resetTimestamps();
+ oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kGpuCompositionDoneTime,
+ outGpuCompositionDoneTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
+ EXPECT_EQ(mFrames[0].kRetireTime, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
+ EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
+}
+
+// This test verifies that if the frame wasn't GPU composited but has a refresh
+// event a sync call isn't made to get the GPU composite done time since it will
+// never exist.
+TEST_F(GetFrameTimestampsTest, NoGpuNoSync) {
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
+
+ const uint32_t framesAgo = 1;
+
+ // Dequeue and queue frame 1.
+ dequeueAndQueue(0);
+ mFrames[0].signalQueueFences();
+
+ // Dequeue and queue frame 2.
+ dequeueAndQueue(1);
+ mFrames[1].signalQueueFences();
+
+ addFrameEvents(false, NO_FRAME_INDEX, 0);
+ addFrameEvents(false, 0, 1);
+
+ // Verify available timestamps are correct for frame 1, before any
+ // fence has been signaled.
+ // Note: A sync call is necessary here since the events triggered by
+ // addFrameEvents didn't get to piggyback on the earlier queues/dequeues.
+ resetTimestamps();
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
+ EXPECT_EQ(0, outReleaseTime);
+
+ // Signal the fences for frame 1.
+ mFrames[0].signalRefreshFences();
+ mFrames[0].signalReleaseFences();
+
+ // Verify all timestamps, except GPU composition, are available without a
+ // sync call.
+ resetTimestamps();
+ oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
+ EXPECT_EQ(mFrames[0].kRetireTime, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
+ EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
+}
+
+// This test verifies that if the certain timestamps can't possibly exist for
+// the most recent frame, then a sync call is not done.
+TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) {
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
+
+ // Dequeue and queue frame 1.
+ dequeueAndQueue(0);
+ mFrames[0].signalQueueFences();
+
+ // Dequeue and queue frame 2.
+ dequeueAndQueue(1);
+ mFrames[1].signalQueueFences();
+
+ addFrameEvents(false, NO_FRAME_INDEX, 0);
+ addFrameEvents(false, 0, 1);
+
+ // Verify available timestamps are correct for frame 1, before any
+ // fence has been signaled.
+ // Note: A sync call is necessary here since the events triggered by
+ // addFrameEvents didn't get to piggyback on the earlier queues/dequeues.
+ uint32_t framesAgo = 1;
+ resetTimestamps();
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
+ EXPECT_EQ(0, outReleaseTime);
+
+ mFrames[0].signalRefreshFences();
+ mFrames[0].signalReleaseFences();
+ mFrames[1].signalRefreshFences();
+
+ // Verify querying for all timestmaps of f2 does not do a sync call.
+ // Even though the lastRefresh, retire, dequeueReady, and release times aren't
+ // available, a sync call should not occur because it's not possible for f2
+ // to encounter the final value for those events until another frame is
+ // queued.
+ framesAgo = 0;
+ resetTimestamps();
+ oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ result = getAllFrameTimestamps(framesAgo);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
+ EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime);
+ EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
+ EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
+ EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(0, outDequeueReadyTime);
+ EXPECT_EQ(0, outReleaseTime);
+}
+
+// This test verifies there are no sync calls for present or retire times
+// when they aren't supported and that an error is returned.
+void GetFrameTimestampsTest::PresentOrRetireUnsupportedNoSyncTest(
+ bool displayPresentSupported, bool displayRetireSupported) {
+
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportedTimestamps(
+ displayPresentSupported, displayRetireSupported);
+
+ // Dequeue and queue frame 1.
+ dequeueAndQueue(0);
+
+ // Verify a query for the Present and Retire times do not trigger
+ // a sync call if they are not supported.
+ const uint32_t framesAgo = 0;
+ resetTimestamps();
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ displayPresentSupported ? nullptr : &outDisplayPresentTime,
+ displayRetireSupported ? nullptr : &outDisplayRetireTime,
+ nullptr, nullptr);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(BAD_VALUE, result);
+ EXPECT_EQ(-1, outDisplayRetireTime);
+ EXPECT_EQ(-1, outDisplayPresentTime);
+}
+
+TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) {
+ PresentOrRetireUnsupportedNoSyncTest(false, true);
+}
+
+TEST_F(GetFrameTimestampsTest, RetireUnsupportedNoSync) {
+ PresentOrRetireUnsupportedNoSyncTest(true, false);
+}
+
}
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 136dd7f..af1c0af 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -27,8 +27,9 @@
#include <sys/types.h>
#include <unistd.h>
-#include <android/log.h>
#include <cutils/properties.h>
+#include <log/log.h>
+
#include <input/InputTransport.h>
namespace android {
diff --git a/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp
index 1a60f0f..6296abe 100644
--- a/libs/ui/ColorSpace.cpp
+++ b/libs/ui/ColorSpace.cpp
@@ -137,7 +137,7 @@
{0.3127f, 0.3290f},
std::bind(absRcpResponse, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f),
std::bind(absResponse, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f),
- std::bind(clamp<float>, _1, -0.5f, 7.5f)
+ std::bind(clamp<float>, _1, -0.799f, 2.399f)
};
}
@@ -148,7 +148,7 @@
{0.3127f, 0.3290f},
linearReponse,
linearReponse,
- std::bind(clamp<float>, _1, -0.5f, 7.5f)
+ std::bind(clamp<float>, _1, -0.5f, 7.499f)
};
}
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index a1dda3a..02d4137 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <ui/Fence.h>
+
#define LOG_TAG "Fence"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
@@ -25,9 +27,10 @@
#include <sync/sync.h>
#pragma clang diagnostic pop
-#include <ui/Fence.h>
+#include <sys/types.h>
#include <unistd.h>
#include <utils/Log.h>
+#include <utils/String8.h>
#include <utils/Trace.h>
namespace android {
diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp
index c0245eb..8106b16 100644
--- a/libs/ui/FenceTime.cpp
+++ b/libs/ui/FenceTime.cpp
@@ -17,6 +17,7 @@
#include <ui/FenceTime.h>
#include <cutils/compiler.h> // For CC_[UN]LIKELY
+#include <utils/Log.h>
#include <inttypes.h>
#include <stdlib.h>
@@ -130,6 +131,14 @@
// Make the system call without the lock held.
signalTime = fence->getSignalTime();
+ // Allow tests to override SIGNAL_TIME_INVALID behavior, since tests
+ // use invalid underlying Fences without real file descriptors.
+ if (CC_UNLIKELY(mState == State::FORCED_VALID_FOR_TEST)) {
+ if (signalTime == Fence::SIGNAL_TIME_INVALID) {
+ signalTime = Fence::SIGNAL_TIME_PENDING;
+ }
+ }
+
// Make the signal time visible to everyone if it is no longer pending
// and remove the class' reference to the fence.
if (signalTime != Fence::SIGNAL_TIME_PENDING) {
@@ -163,10 +172,28 @@
return Snapshot(mFence);
}
+// For tests only. If forceValidForTest is true, then getSignalTime will
+// never return SIGNAL_TIME_INVALID and isValid will always return true.
+FenceTime::FenceTime(const sp<Fence>& fence, bool forceValidForTest)
+ : mState(forceValidForTest ?
+ State::FORCED_VALID_FOR_TEST : State::INVALID),
+ mFence(fence),
+ mSignalTime(mState == State::INVALID ?
+ Fence::SIGNAL_TIME_INVALID : Fence::SIGNAL_TIME_PENDING) {
+}
+
+void FenceTime::signalForTest(nsecs_t signalTime) {
+ // To be realistic, this should really set a hidden value that
+ // gets picked up in the next call to getSignalTime, but this should
+ // be good enough.
+ std::lock_guard<std::mutex> lock(mMutex);
+ mFence.clear();
+ mSignalTime.store(signalTime, std::memory_order_relaxed);
+}
+
// ============================================================================
// FenceTime::Snapshot
// ============================================================================
-
FenceTime::Snapshot::Snapshot(const sp<Fence>& srcFence)
: state(State::FENCE), fence(srcFence) {
}
@@ -279,4 +306,60 @@
}
}
+// ============================================================================
+// FenceToFenceTimeMap
+// ============================================================================
+std::shared_ptr<FenceTime> FenceToFenceTimeMap::createFenceTimeForTest(
+ const sp<Fence>& fence) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ // Always garbage collecting isn't efficient, but this is only for testing.
+ garbageCollectLocked();
+ std::shared_ptr<FenceTime> fenceTime(new FenceTime(fence, true));
+ mMap[fence.get()].push_back(fenceTime);
+ return fenceTime;
+}
+
+void FenceToFenceTimeMap::signalAllForTest(
+ const sp<Fence>& fence, nsecs_t signalTime) {
+ bool signaled = false;
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ auto it = mMap.find(fence.get());
+ if (it != mMap.end()) {
+ for (auto& weakFenceTime : it->second) {
+ std::shared_ptr<FenceTime> fenceTime = weakFenceTime.lock();
+ if (!fenceTime) {
+ continue;
+ }
+ ALOGE_IF(!fenceTime->isValid(),
+ "FenceToFenceTimeMap::signalAllForTest: "
+ "Signaling invalid fence.");
+ fenceTime->signalForTest(signalTime);
+ signaled = true;
+ }
+ }
+
+ if (!signaled) {
+ ALOGE("FenceToFenceTimeMap::signalAllForTest: Nothing to signal.");
+ }
+}
+
+void FenceToFenceTimeMap::garbageCollectLocked() {
+ for (auto& it : mMap) {
+ // Erase all expired weak pointers from the vector.
+ auto& vect = it.second;
+ vect.erase(
+ std::remove_if(vect.begin(), vect.end(),
+ [](const std::weak_ptr<FenceTime>& ft) {
+ return ft.expired();
+ }),
+ vect.end());
+
+ // Also erase the map entry if the vector is now empty.
+ if (vect.empty()) {
+ mMap.erase(it.first);
+ }
+ }
+}
+
} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
index b444871..7ee01ad 100644
--- a/libs/ui/GrallocMapper.cpp
+++ b/libs/ui/GrallocMapper.cpp
@@ -140,7 +140,7 @@
int Mapper::unlock(buffer_handle_t handle) const
{
- int releaseFence;
+ int releaseFence = -1;
Error error = kDefaultError;
mMapper->unlock(handle,
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 6f57d37..5ae4faa 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -18,8 +18,7 @@
#define LOG_TAG "GraphicBufferAllocator"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <android/log.h>
-
+#include <log/log.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
#include <utils/Trace.h>
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 874e712..8b754d5 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -634,11 +634,14 @@
#define EGL_TIMESTAMPS_ANDROID 0x314D
#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
-#define EGL_COMPOSITION_START_TIME_ANDROID 0x3430
-#define EGL_COMPOSITION_FINISHED_TIME_ANDROID 0x3431
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3432
-#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3433
-#define EGL_READS_DONE_TIME_ANDROID 0x3434
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
+#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
+#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
+#define EGL_READS_DONE_TIME_ANDROID 0x3157
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 4e9cb5b..493c0b8 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -27,7 +27,7 @@
#include <sys/mman.h>
#include <unistd.h>
-#include <android/log.h>
+#include <log/log.h>
#include <utils/threads.h>
#include <ui/ANativeObjectBase.h>
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 27d81fe..27697ab 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -14,6 +14,9 @@
** limitations under the License.
*/
+//#define LOG_NDEBUG 0
+
+#include <array>
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
@@ -23,8 +26,9 @@
#include <stdlib.h>
#include <string.h>
-#include <android/log.h>
+#include <android/dlext.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <EGL/egl.h>
@@ -136,10 +140,26 @@
// ----------------------------------------------------------------------------
Loader::Loader()
- : getProcAddress(NULL) {
+ : getProcAddress(NULL),
+ mLibGui(nullptr),
+ mGetDriverNamespace(nullptr)
+{
+ // FIXME: See note in GraphicsEnv.h about android_getDriverNamespace().
+ // libgui should already be loaded in any process that uses libEGL, but
+ // if for some reason it isn't, then we're not going to get a driver
+ // namespace anyway, so don't force it to be loaded.
+ mLibGui = dlopen("libgui.so", RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY);
+ if (!mLibGui) {
+ ALOGD("failed to load libgui: %s", dlerror());
+ return;
+ }
+ mGetDriverNamespace = reinterpret_cast<decltype(mGetDriverNamespace)>(
+ dlsym(mLibGui, "android_getDriverNamespace"));
}
Loader::~Loader() {
+ if (mLibGui)
+ dlclose(mLibGui);
}
static void* load_wrapper(const char* path) {
@@ -286,9 +306,7 @@
}
}
-void *Loader::load_driver(const char* kind,
- egl_connection_t* cnx, uint32_t mask)
-{
+static void* load_system_driver(const char* kind) {
class MatchFile {
public:
static String8 find(const char* kind) {
@@ -413,11 +431,55 @@
ALOGD("loaded %s", driver_absolute_path);
+ return dso;
+}
+
+static const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
+ "ro.hardware.egl",
+ "ro.board.platform",
+}};
+
+static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = ns,
+ };
+ void* so = nullptr;
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) > 0) {
+ String8 name;
+ name.appendFormat("lib%s_%s.so", kind, prop);
+ so = android_dlopen_ext(name.string(), RTLD_LOCAL | RTLD_NOW,
+ &dlextinfo);
+ if (so)
+ return so;
+ }
+ }
+ return nullptr;
+}
+
+void *Loader::load_driver(const char* kind,
+ egl_connection_t* cnx, uint32_t mask)
+{
+ void* dso = nullptr;
+ if (mGetDriverNamespace) {
+ android_namespace_t* ns = mGetDriverNamespace();
+ if (ns) {
+ dso = load_updated_driver(kind, ns);
+ }
+ }
+ if (!dso) {
+ dso = load_system_driver(kind);
+ if (!dso)
+ return NULL;
+ }
+
if (mask & EGL) {
getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
ALOGE_IF(!getProcAddress,
- "can't find eglGetProcAddress() in %s", driver_absolute_path);
+ "can't find eglGetProcAddress() in EGL driver library");
egl_t* egl = &cnx->egl;
__eglMustCastToProperFunctionPointerType* curr =
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 94f680e..d0435e7 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -25,6 +25,8 @@
#include <utils/Singleton.h>
#include <utils/String8.h>
+#include <gui/GraphicsEnv.h>
+
#include <EGL/egl.h>
// ----------------------------------------------------------------------------
@@ -53,7 +55,10 @@
};
getProcAddressType getProcAddress;
-
+
+ void* mLibGui;
+ decltype(android_getDriverNamespace)* mGetDriverNamespace;
+
public:
~Loader();
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 4245a92..ee83ada 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -24,10 +24,9 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <android/log.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
-
+#include <log/log.h>
#include <utils/CallStack.h>
#include <utils/String8.h>
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 3af7e93..97343a1 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -27,11 +27,11 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <android/log.h>
#include <cutils/atomic.h>
#include <cutils/compiler.h>
#include <cutils/memory.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <gui/ISurfaceComposer.h>
@@ -2041,10 +2041,13 @@
nsecs_t* requestedPresentTime = nullptr;
nsecs_t* acquireTime = nullptr;
- nsecs_t* refreshStartTime = nullptr;
+ nsecs_t* latchTime = nullptr;
+ nsecs_t* firstRefreshStartTime = nullptr;
nsecs_t* GLCompositionDoneTime = nullptr;
+ nsecs_t* lastRefreshStartTime = nullptr;
nsecs_t* displayPresentTime = nullptr;
nsecs_t* displayRetireTime = nullptr;
+ nsecs_t* dequeueReadyTime = nullptr;
nsecs_t* releaseTime = nullptr;
for (int i = 0; i < numTimestamps; i++) {
@@ -2055,10 +2058,16 @@
case EGL_RENDERING_COMPLETE_TIME_ANDROID:
acquireTime = &values[i];
break;
- case EGL_COMPOSITION_START_TIME_ANDROID:
- refreshStartTime = &values[i];
+ case EGL_COMPOSITION_LATCH_TIME_ANDROID:
+ latchTime = &values[i];
break;
- case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
+ case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
+ firstRefreshStartTime = &values[i];
+ break;
+ case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
+ lastRefreshStartTime = &values[i];
+ break;
+ case EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID:
GLCompositionDoneTime = &values[i];
break;
case EGL_DISPLAY_PRESENT_TIME_ANDROID:
@@ -2067,6 +2076,9 @@
case EGL_DISPLAY_RETIRE_TIME_ANDROID:
displayRetireTime = &values[i];
break;
+ case EGL_DEQUEUE_READY_TIME_ANDROID:
+ dequeueReadyTime = &values[i];
+ break;
case EGL_READS_DONE_TIME_ANDROID:
releaseTime = &values[i];
break;
@@ -2076,9 +2088,9 @@
}
status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo,
- requestedPresentTime, acquireTime, refreshStartTime,
- GLCompositionDoneTime, displayPresentTime, displayRetireTime,
- releaseTime);
+ requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
+ lastRefreshStartTime, GLCompositionDoneTime, displayPresentTime,
+ displayRetireTime, dequeueReadyTime, releaseTime);
switch (ret) {
case NO_ERROR:
@@ -2122,8 +2134,11 @@
#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
case EGL_REQUESTED_PRESENT_TIME_ANDROID:
case EGL_RENDERING_COMPLETE_TIME_ANDROID:
- case EGL_COMPOSITION_START_TIME_ANDROID:
- case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
+ case EGL_COMPOSITION_LATCH_TIME_ANDROID:
+ case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
+ case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
+ case EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID:
+ case EGL_DEQUEUE_READY_TIME_ANDROID:
case EGL_READS_DONE_TIME_ANDROID:
return EGL_TRUE;
case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index 1257004..6de5f27 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -17,9 +17,8 @@
#include <pthread.h>
#include <stdlib.h>
-#include <android/log.h>
#include <cutils/properties.h>
-
+#include <log/log.h>
#include <utils/CallStack.h>
#include <EGL/egl.h>
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index b5b6eb5..7aa0d30 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -69,11 +69,14 @@
EGL_TIMESTAMPS_ANDROID 0x314D
EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
- EGL_COMPOSITION_START_TIME_ANDROID 0x3430
- EGL_COMPOSITION_FINISHED_TIME_ANDROID 0x3431
- EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3432
- EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3433
- EGL_READS_DONE_TIME_ANDROID 0x3434
+ EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
+ EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
+ EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
+ EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
+ EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
+ EGL_READS_DONE_TIME_ANDROID 0x3157
Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
"Surface Attributes", page 43:
@@ -119,16 +122,31 @@
this will correspond to buffer's queue time.
- EGL_RENDERING_COMPLETE_TIME_ANDROID - The time when all of the
application's rendering to the surface was completed.
- - EGL_COMPOSITION_START_TIME_ANDROID - The time at which the compositor
- began preparing composition for this frame.
- - EGL_COMPOSITION_FINISHED_TIME_ANDROID - The time at which the
+ - EGL_COMPOSITION_LATCH_TIME_ANDROID - The time when the compositor
+ selected this frame as the one to use for the next composition. The
+ latch is the earliest indication that the frame was submitted in time
+ to be composited.
+ - EGL_FIRST_COMPOSITION_START_TIME_ANDROID - The first time at which
+ the compositor began preparing composition for this frame.
+ - EGL_LAST_COMPOSITION_START_TIME_ANDROID - The last time at which the
+ compositor began preparing composition for this frame. If this frame
+ is composited only once, it will have the same value as
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID. If the value is not equal,
+ that indicates the subsequent frame was not submitted in time to be
+ latched by the compositor. Note: The value may not be updated for
+ every display refresh if the compositor becomes idle.
+ - EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID - The time at which the
compositor's rendering work for this frame finished. This will be zero
if composition was handled by the display and the compositor didn't do
any rendering.
- EGL_DISPLAY_PRESENT_TIME_ANDROID - The time at which this frame
- started to scan out on the physical display.
+ started to scan out to the physical display.
- EGL_DISPLAY_RETIRE_TIME_ANDROID - The time at which this frame was
replaced by the next frame on-screen.
+ - EGL_DEQUEUE_READY_TIME_ANDROID - The time when the buffer became
+ available for reuse as a buffer the client can target without
+ blocking. This is generally the point when all read commands of the
+ buffer have been submitted, but not necessarily completed.
- EGL_READS_DONE_TIME_ANDROID - The time at which all reads for the
purpose of display/composition were completed for this frame.
@@ -152,3 +170,8 @@
#2 (Brian Anderson, July 22, 2016)
- Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID.
- Add DISPLAY_PRESENT_TIME_ANDROID.
+
+#3 (Brian Anderson, November 30, 2016)
+ - Add EGL_COMPOSITION_LATCH_TIME_ANDROID,
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID, and
+ EGL_DEQUEUE_READY_TIME_ANDROID.
diff --git a/opengl/specs/README b/opengl/specs/README
index 1ee99fb..8a3a7aa 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -22,9 +22,12 @@
0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
0x314E EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
0x314F EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3430 EGL_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3431 EGL_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3432 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3433 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3434 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3435 - 0x343F (unused)
+0x3150 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3151 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3152 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3153 EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3154 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3155 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3156 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3157 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3158 - 0x315F (unused)
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index d69a275..2b9c38e 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -24,6 +24,8 @@
namespace android {
+#define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
+
class EGLTest : public ::testing::Test {
protected:
EGLDisplay mEglDisplay;
@@ -48,7 +50,7 @@
virtual void TearDown() {
EGLBoolean success = eglTerminate(mEglDisplay);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
}
};
@@ -65,20 +67,20 @@
};
success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
ASSERT_GE(numConfigs, 1);
EGLint components[3];
success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
EXPECT_GE(components[0], 8);
@@ -139,23 +141,23 @@
};
success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
ASSERT_GE(numConfigs, 1);
EGLint components[4];
success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
- ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
EXPECT_GE(components[0], 8);
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
index a5a8968..523bc57 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
+++ b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
@@ -28,6 +28,7 @@
public static final int EGL_CONTEXT_MINOR_VERSION_KHR = 0x30FB;
public static final int EGL_CONTEXT_FLAGS_KHR = 0x30FC;
public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
+ public static final int EGL_RECORDABLE_ANDROID = 0x3142;
native private static void _nativeClassInit();
static {
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
index 04dd967..22b084a 100644
--- a/services/audiomanager/Android.bp
+++ b/services/audiomanager/Android.bp
@@ -1,7 +1,10 @@
cc_library_shared {
name: "libaudiomanager",
- srcs: ["IAudioManager.cpp"],
+ srcs: [
+ "IAudioManager.cpp",
+ "IPlayer.cpp",
+ ],
shared_libs: [
"libutils",
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
index a41804f..b9b0706 100644
--- a/services/audiomanager/IAudioManager.cpp
+++ b/services/audiomanager/IAudioManager.cpp
@@ -35,15 +35,16 @@
{
}
- virtual audio_unique_id_t trackPlayer(int playerType, int usage, int content) {
+ virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
+ audio_content_type_t content, const sp<IBinder>& player) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32(1); // non-null PlayerIdCard parcelable
// marshall PlayerIdCard data
data.writeInt32((int32_t) playerType);
// write attributes of PlayerIdCard
- data.writeInt32(usage);
- data.writeInt32(content);
+ data.writeInt32((int32_t) usage);
+ data.writeInt32((int32_t) content);
data.writeInt32(0 /*source: none here, this is a player*/);
data.writeInt32(0 /*flags*/);
// write attributes' tags
@@ -51,6 +52,8 @@
data.writeString16(String16("")); // no tags
// write attributes' bundle
data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
+ // write IPlayer
+ data.writeStrongBinder(player);
// get new PIId in reply
const status_t res = remote()->transact(TRACK_PLAYER, data, &reply, 0);
if (res != OK || reply.readExceptionCode() != 0) {
@@ -63,13 +66,14 @@
}
}
- virtual status_t playerAttributes(audio_unique_id_t piid, int usage, int content) {
+ virtual status_t playerAttributes(audio_unique_id_t piid, audio_usage_t usage,
+ audio_content_type_t content) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
- data.writeInt32(piid);
+ data.writeInt32((int32_t) piid);
data.writeInt32(1); // non-null AudioAttributes parcelable
- data.writeInt32(usage);
- data.writeInt32(content);
+ data.writeInt32((int32_t) usage);
+ data.writeInt32((int32_t) content);
data.writeInt32(0 /*source: none here, this is a player*/);
data.writeInt32(0 /*flags*/);
// write attributes' tags
@@ -80,18 +84,18 @@
return remote()->transact(PLAYER_ATTRIBUTES, data, &reply, IBinder::FLAG_ONEWAY);
}
- virtual status_t playerEvent(int piid, int event) {
+ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
- data.writeInt32(piid);
- data.writeInt32(event);
+ data.writeInt32((int32_t) piid);
+ data.writeInt32((int32_t) event);
return remote()->transact(PLAYER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
- virtual status_t releasePlayer(int piid) {
+ virtual status_t releasePlayer(audio_unique_id_t piid) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
- data.writeInt32(piid);
+ data.writeInt32((int32_t) piid);
return remote()->transact(RELEASE_PLAYER, data, &reply, IBinder::FLAG_ONEWAY);
}
};
diff --git a/services/audiomanager/IPlayer.cpp b/services/audiomanager/IPlayer.cpp
new file mode 100644
index 0000000..3b0b4e9
--- /dev/null
+++ b/services/audiomanager/IPlayer.cpp
@@ -0,0 +1,109 @@
+/*
+**
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "IPlayer"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <audiomanager/IPlayer.h>
+
+namespace android {
+
+enum {
+ START = IBinder::FIRST_CALL_TRANSACTION,
+ PAUSE = IBinder::FIRST_CALL_TRANSACTION + 1,
+ STOP = IBinder::FIRST_CALL_TRANSACTION + 2,
+ SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3,
+};
+
+class BpPlayer : public BpInterface<IPlayer>
+{
+public:
+ explicit BpPlayer(const sp<IBinder>& impl)
+ : BpInterface<IPlayer>(impl)
+ {
+ }
+
+ virtual void start()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
+ remote()->transact(START, data, &reply);
+ }
+
+ virtual void pause()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
+ remote()->transact(PAUSE, data, &reply);
+ }
+
+ virtual void stop()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
+ remote()->transact(STOP, data, &reply);
+ }
+
+ virtual void setVolume(float vol)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
+ data.writeFloat(vol);
+ remote()->transact(SET_VOLUME, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer");
+
+// ----------------------------------------------------------------------
+
+status_t BnPlayer::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case START: {
+ CHECK_INTERFACE(IPlayer, data, reply);
+ start();
+ return NO_ERROR;
+ } break;
+ case PAUSE: {
+ CHECK_INTERFACE(IPlayer, data, reply);
+ pause();
+ return NO_ERROR;
+ }
+ case STOP: {
+ CHECK_INTERFACE(IPlayer, data, reply);
+ stop();
+ return NO_ERROR;
+ } break;
+ case SET_VOLUME: {
+ CHECK_INTERFACE(IPlayer, data, reply);
+ setVolume(data.readFloat());
+ return NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 8d43488..8771d45 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -51,7 +51,7 @@
#include <time.h>
#include <unistd.h>
-#include <android/log.h>
+#include <log/log.h>
#include <utils/Trace.h>
#include <powermanager/PowerManager.h>
#include <ui/Region.h>
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 6fe4d36..519faa6 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -20,7 +20,7 @@
#include "InputManager.h"
-#include <android/log.h>
+#include <log/log.h>
namespace android {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index fbc7b12..c1e6365 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -52,7 +52,7 @@
#include <stdlib.h>
#include <unistd.h>
-#include <android/log.h>
+#include <log/log.h>
#include <input/Keyboard.h>
#include <input/VirtualKeyMap.h>
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index 297b068..5e82d75 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -19,7 +19,7 @@
#include "InputWindow.h"
-#include <android/log.h>
+#include <log/log.h>
#include <ui/Rect.h>
#include <ui/Region.h>
diff --git a/services/inputflinger/host/InputFlinger.cpp b/services/inputflinger/host/InputFlinger.cpp
index 8edea3f..f1d3726 100644
--- a/services/inputflinger/host/InputFlinger.cpp
+++ b/services/inputflinger/host/InputFlinger.cpp
@@ -20,10 +20,10 @@
#include <sys/types.h>
#include <unistd.h>
-#include <android/log.h>
#include <binder/IPCThreadState.h>
#include <binder/PermissionCache.h>
#include <hardware/input.h>
+#include <log/log.h>
#include <private/android_filesystem_config.h>
#include "InputFlinger.h"
diff --git a/services/sensorservice/SensorDeviceTreble.cpp b/services/sensorservice/SensorDeviceTreble.cpp
index 6f946d0..37f0f6c 100644
--- a/services/sensorservice/SensorDeviceTreble.cpp
+++ b/services/sensorservice/SensorDeviceTreble.cpp
@@ -56,6 +56,8 @@
return PERMISSION_DENIED;
case Result::INVALID_OPERATION:
return INVALID_OPERATION;
+ case Result::NO_MEMORY:
+ return NO_MEMORY;
}
}
@@ -79,8 +81,7 @@
mActivationCount.add(list[i].sensorHandle, model);
- /* auto result = */mSensors->activate(
- list[i].sensorHandle, 0 /* enabled */);
+ mSensors->activate(list[i].sensorHandle, 0 /* enabled */);
}
});
}
@@ -89,7 +90,7 @@
if (connected) {
Info model;
mActivationCount.add(handle, model);
- /* auto result = */mSensors->activate(handle, 0 /* enabled */);
+ mSensors->activate(handle, 0 /* enabled */);
} else {
mActivationCount.removeItem(handle);
}
@@ -98,13 +99,6 @@
std::string SensorDevice::dump() const {
if (mSensors == NULL) return "HAL not initialized\n";
-#if 0
- result.appendFormat("HAL: %s (%s), version %#010x\n",
- mSensorModule->common.name,
- mSensorModule->common.author,
- getHalDeviceVersion());
-#endif
-
String8 result;
mSensors->getSensorsList([&](const auto &list) {
const size_t count = list.size();
@@ -240,21 +234,17 @@
// This is the last connection, we need to de-activate the underlying h/w sensor.
actuateHardware = true;
} else {
- const int halVersion = getHalDeviceVersion();
- if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
- // Call batch for this sensor with the previously calculated best effort
- // batch_rate and timeout. One of the apps has unregistered for sensor
- // events, and the best effort batch parameters might have changed.
- ALOGD_IF(DEBUG_CONNECTIONS,
- "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- /* auto result = */mSensors->batch(
- handle,
- info.bestBatchParams.flags,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- }
+ // Call batch for this sensor with the previously calculated best effort
+ // batch_rate and timeout. One of the apps has unregistered for sensor
+ // events, and the best effort batch parameters might have changed.
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ mSensors->batch(
+ handle,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
}
} else {
// sensor wasn't enabled for this ident
@@ -278,13 +268,6 @@
}
}
- // On older devices which do not support batch, call setDelay().
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle,
- info.bestBatchParams.batchDelay);
- /* auto result = */mSensors->setDelay(
- handle, info.bestBatchParams.batchDelay);
- }
return err;
}
@@ -300,12 +283,6 @@
samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
}
- const int halVersion = getHalDeviceVersion();
- if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) {
- // Batch is not supported on older devices return invalid operation.
- return INVALID_OPERATION;
- }
-
ALOGD_IF(DEBUG_CONNECTIONS,
"SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
@@ -334,21 +311,14 @@
status_t err(NO_ERROR);
// If the min period or min timeout has changed since the last batch call, call batch.
if (prevBestBatchParams != info.bestBatchParams) {
- if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- err = StatusFromResult(
- mSensors->batch(
- handle,
- info.bestBatchParams.flags,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout));
- } else {
- // For older devices which do not support batch, call setDelay() after activate() is
- // called. Some older devices may not support calling setDelay before activate(), so
- // call setDelay in SensorDevice::activate() method.
- }
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ err = StatusFromResult(
+ mSensors->batch(
+ handle,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout));
if (err != NO_ERROR) {
ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
mSensors.get(), handle,
@@ -382,7 +352,7 @@
info.selectBatchParams();
return StatusFromResult(
- mSensors->setDelay(handle, info.bestBatchParams.batchDelay));
+ mSensors->batch(handle, info.bestBatchParams.batchDelay, 0));
}
int SensorDevice::getHalDeviceVersion() const {
@@ -391,9 +361,6 @@
}
status_t SensorDevice::flush(void* ident, int handle) {
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
- return INVALID_OPERATION;
- }
if (isClientDisabled(ident)) return INVALID_OPERATION;
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
return StatusFromResult(mSensors->flush(handle));
@@ -412,7 +379,6 @@
Mutex::Autolock _l(mLock);
mDisabledClients.clear();
ALOGI("cleared mDisabledClients");
- const int halVersion = getHalDeviceVersion();
for (size_t i = 0; i< mActivationCount.size(); ++i) {
Info& info = mActivationCount.editValueAt(i);
if (info.batchParams.isEmpty()) continue;
@@ -420,29 +386,18 @@
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
sensor_handle);
- status_t err(NO_ERROR);
- if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
- err = StatusFromResult(
- mSensors->batch(
- sensor_handle,
- info.bestBatchParams.flags,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout));
- ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
- }
+ status_t err = StatusFromResult(
+ mSensors->batch(
+ sensor_handle,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout));
+ ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
if (err == NO_ERROR) {
err = StatusFromResult(
mSensors->activate(sensor_handle, 1 /* enabled */));
ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
}
-
- if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) {
- err = StatusFromResult(
- mSensors->setDelay(
- sensor_handle, info.bestBatchParams.batchDelay));
- ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err));
- }
}
}
@@ -455,8 +410,7 @@
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
sensor_handle);
- /* auto result = */mSensors->activate(
- sensor_handle, 0 /* enabled */);
+ mSensors->activate(sensor_handle, 0 /* enabled */);
// Add all the connections that were registered for this sensor to the disabled
// clients list.
@@ -478,10 +432,6 @@
injected_sensor_event->data[3], injected_sensor_event->data[4],
injected_sensor_event->data[5]);
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
- return INVALID_OPERATION;
- }
-
Event ev;
convertFromSensorEvent(*injected_sensor_event, &ev);
@@ -489,9 +439,6 @@
}
status_t SensorDevice::setMode(uint32_t mode) {
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
- return INVALID_OPERATION;
- }
return StatusFromResult(
mSensors->setOperationMode(
@@ -562,7 +509,7 @@
::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
src, dst);
- if (src.sensorType == SensorType::SENSOR_TYPE_DYNAMIC_SENSOR_META) {
+ if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) {
const DynamicSensorInfo &dyn = src.u.dynamic;
dst->dynamic_sensor_meta.connected = dyn.connected;
diff --git a/services/surfaceflinger/Colorizer.h b/services/surfaceflinger/Colorizer.h
index f2e6491..d56b1c8 100644
--- a/services/surfaceflinger/Colorizer.h
+++ b/services/surfaceflinger/Colorizer.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_SURFACE_FLINGER_COLORIZER_H
#define ANDROID_SURFACE_FLINGER_COLORIZER_H
+#include <utils/String8.h>
+
namespace android {
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DdmConnection.cpp b/services/surfaceflinger/DdmConnection.cpp
index ba09b36..35d55f5 100644
--- a/services/surfaceflinger/DdmConnection.cpp
+++ b/services/surfaceflinger/DdmConnection.cpp
@@ -18,7 +18,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <android/log.h>
+#include <log/log.h>
#include "jni.h"
#include "DdmConnection.h"
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 3229b66..86cf17d 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -24,7 +24,7 @@
#include <algorithm>
-#include <android/log.h>
+#include <log/log.h>
#include <utils/String8.h>
#include <utils/Thread.h>
#include <utils/Trace.h>
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 96dd55f..1998edf 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -24,8 +24,8 @@
#include <stdlib.h>
#include <string.h>
-#include <android/log.h>
#include <utils/String8.h>
+#include <log/log.h>
#include <ui/Rect.h>
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 51e92b2..7322c13 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -28,8 +28,8 @@
#include <cstdlib>
#include <sstream>
-#include <android/log.h>
#include <hardware/hwcomposer.h>
+#include <log/log.h>
#include <utils/Trace.h>
using namespace std::chrono_literals;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 3f38c86..7914770 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -43,8 +43,8 @@
#include <android/configuration.h>
-#include <android/log.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include "HWComposer.h"
#include "HWC2On1Adapter.h"
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index af280a4..cc5578d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -39,8 +39,8 @@
#include <android/configuration.h>
-#include <android/log.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <system/graphics.h>
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9eaf57b..72f6a7e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1796,7 +1796,7 @@
}
#ifdef USE_HWC2
-void Layer::releasePendingBuffer() {
+void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
mSurfaceFlingerConsumer->releasePendingBuffer();
auto releaseFenceTime = std::make_shared<FenceTime>(
mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
@@ -1804,7 +1804,7 @@
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.addRelease(
- mPreviousFrameNumber, std::move(releaseFenceTime));
+ mPreviousFrameNumber, dequeueReadyTime, std::move(releaseFenceTime));
}
#endif
@@ -1981,7 +1981,7 @@
mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
mReleaseTimeline.push(releaseFenceTime);
mFrameEventHistory.addRelease(
- mPreviousFrameNumber, std::move(releaseFenceTime));
+ mPreviousFrameNumber, latchTime, std::move(releaseFenceTime));
#endif
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c3eab37..92d2292 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -286,7 +286,7 @@
#ifdef USE_HWC2
// If a buffer was replaced this frame, release the former buffer
- void releasePendingBuffer();
+ void releasePendingBuffer(nsecs_t dequeueReadyTime);
#endif
/*
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 38a0039..48a8da5 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -16,7 +16,7 @@
#include <stdint.h>
-#include <android/log.h>
+#include <log/log.h>
#include <utils/String8.h>
#include "Program.h"
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 986c6df..9909bf9 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <android/log.h>
+#include <log/log.h>
#include <ui/Rect.h>
#include <ui/Region.h>
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 193b702..5f25ef5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -28,8 +28,8 @@
#include <EGL/egl.h>
-#include <android/log.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -575,10 +575,13 @@
*outSupported = {
FrameEvent::REQUESTED_PRESENT,
FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
FrameEvent::GL_COMPOSITION_DONE,
getHwComposer().presentFenceRepresentsStartOfScanout() ?
FrameEvent::DISPLAY_PRESENT : FrameEvent::DISPLAY_RETIRE,
+ FrameEvent::DEQUEUE_READY,
FrameEvent::RELEASE,
};
return NO_ERROR;
@@ -1226,8 +1229,9 @@
ALOGV("postComposition");
// Release any buffers which were replaced this frame
+ nsecs_t dequeueReadyTime = systemTime();
for (auto& layer : mLayersWithQueuedFrames) {
- layer->releasePendingBuffer();
+ layer->releasePendingBuffer(dequeueReadyTime);
}
const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 5c42450..fcf0185 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -16,19 +16,20 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <dlfcn.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <math.h>
+#include <stdatomic.h>
#include <stdint.h>
#include <sys/types.h>
-#include <errno.h>
-#include <math.h>
+
#include <mutex>
-#include <dlfcn.h>
-#include <inttypes.h>
-#include <stdatomic.h>
#include <EGL/egl.h>
-#include <android/log.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -607,9 +608,12 @@
*outSupported = {
FrameEvent::REQUESTED_PRESENT,
FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
FrameEvent::GL_COMPOSITION_DONE,
FrameEvent::DISPLAY_RETIRE,
+ FrameEvent::DEQUEUE_READY,
FrameEvent::RELEASE,
};
return NO_ERROR;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index a12276a..60bc7f3 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -21,14 +21,12 @@
#include "SurfaceFlinger.h"
#include "SurfaceInterceptor.h"
-#include <android-base/file.h>
-
-#include <cutils/log.h>
-
-#include <utils/Trace.h>
-
#include <fstream>
+#include <android-base/file.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
namespace android {
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 4695138..9af6e61 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -21,6 +21,9 @@
#include <mutex>
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
+
namespace android {
class BufferItem;
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index ed89fc6..df45c20 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -2886,27 +2886,6 @@
platform.HWND hwnd
}
-@extension("VK_KHR_incremental_present")
-class VkRectLayerKHR {
- VkOffset2D offset
- VkExtent2D extent
- uint32_t layer
-}
-
-@extension("VK_KHR_incremental_present")
-class VkPresentRegionKHR {
- uint32_t rectangleCount
- const VkRectLayerKHR* pRectangles
-}
-
-@extension("VK_KHR_incremental_present")
-class VkPresentRegionsKHR {
- VkStructureType sType
- const void* pNext
- uint32_t swapchainCount
- const VkPresentRegionKHR* pRegions
-}
-
@extension("VK_ANDROID_native_buffer")
class VkNativeBufferANDROID {
VkStructureType sType
@@ -2921,34 +2900,35 @@
class VkSwapchainImageCreateInfoANDROID {
VkStructureType sType
const void* pNext
- VkSwapchainImageUsageFlagBitsANDROID flags
+ VkSwapchainImageUsageFlagsANDROID flags
+}
@extension("VK_GOOGLE_display_timing")
class VkRefreshCycleDurationGOOGLE {
- uint64_t minRefreshDuration
- uint64_t maxRefreshDuration
+ u64 minRefreshDuration
+ u64 maxRefreshDuration
}
@extension("VK_GOOGLE_display_timing")
class VkPastPresentationTimingGOOGLE {
- uint32_t presentID
- uint64_t desiredPresentTime
- uint64_t actualPresentTime
- uint64_t earliestPresentTime
- uint64_t presentMargin
+ u32 presentID
+ u64 desiredPresentTime
+ u64 actualPresentTime
+ u64 earliestPresentTime
+ u64 presentMargin
}
@extension("VK_GOOGLE_display_timing")
class VkPresentTimeGOOGLE {
- uint32_t presentID
- uint64_t desiredPresentTime
+ u32 presentID
+ u64 desiredPresentTime
}
@extension("VK_GOOGLE_display_timing")
class VkPresentTimesInfoGOOGLE {
VkStructureType sType
const void* pNext
- uint32_t swapchainCount
+ u32 swapchainCount
const VkPresentTimeGOOGLE* pTimes
}
@@ -5889,18 +5869,6 @@
VkSwapchainKHR swapchain,
u32* pPresentationTimingCount,
VkPastPresentationTimingGOOGLE* pPresentationTimings) {
- deviceObject := GetDevice(device)
-
- count := as!u32(?)
- pPresentationTimingCount[0] = count
- presentationTimings := pPresentationTimings[0:count]
-
- for i in (0 .. count) {
- presentationTiming := ?
- presentationTimings[i] = presentationTiming
- State.Timings[presentationTiming] = new!PresentationTiming(device: device)
- }
-
return ?
}
diff --git a/vulkan/doc/implementors_guide/implementors_guide.adoc b/vulkan/doc/implementors_guide/implementors_guide.adoc
index ce21791..dc18e9d 100644
--- a/vulkan/doc/implementors_guide/implementors_guide.adoc
+++ b/vulkan/doc/implementors_guide/implementors_guide.adoc
@@ -123,7 +123,7 @@
VkStructureType sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
const void* pNext;
- VkSwapchainImageUsageFlagBitsANDROID usage;
+ VkSwapchainImageUsageFlagsANDROID usage;
} VkSwapchainImageCreateInfoANDROID;
----
diff --git a/vulkan/doc/implementors_guide/implementors_guide.html b/vulkan/doc/implementors_guide/implementors_guide.html
index 5ff1269..ce52c7f 100644
--- a/vulkan/doc/implementors_guide/implementors_guide.html
+++ b/vulkan/doc/implementors_guide/implementors_guide.html
@@ -876,7 +876,7 @@
<span style="color: #008080">VkStructureType</span> sType<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">void</span><span style="color: #990000">*</span> pNext<span style="color: #990000">;</span>
- <span style="color: #008080">VkSwapchainImageUsageFlagBitsANDROID</span> usage<span style="color: #990000">;</span>
+ <span style="color: #008080">VkSwapchainImageUsageFlagsANDROID</span> usage<span style="color: #990000">;</span>
<span style="color: #FF0000">}</span> VkSwapchainImageCreateInfoANDROID<span style="color: #990000">;</span></tt></pre></div></div>
<div class="paragraph"><p><span class="monospaced">vkAcquireImageANDROID</span> acquires ownership of a swapchain image and imports an
externally-signalled native fence into both an existing VkSemaphore object
@@ -1052,7 +1052,7 @@
<div id="footer">
<div id="footer-text">
Version 5<br>
-Last updated 2017-01-09 09:52:43 NZDT
+Last updated 2017-01-12 14:25:30 NZDT
</div>
</div>
</body>
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index 0fd041a..a2ab07b 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -32,6 +32,7 @@
#define VK_ANDROID_NATIVE_BUFFER_ENUM(type,id) ((type)(1000000000 + (1000 * (VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER - 1)) + (id)))
#define VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 0)
+#define VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 1)
typedef enum VkSwapchainImageUsageFlagBitsANDROID {
VK_SWAPCHAIN_IMAGE_USAGE_FRONT_BUFFER_BIT_ANDROID = 0x00000001,
@@ -56,7 +57,7 @@
VkStructureType sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
const void* pNext;
- VkSwapchainImageUsageFlagBitsANDROID usage;
+ VkSwapchainImageUsageFlagsANDROID usage;
} VkSwapchainImageCreateInfoANDROID;
typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index ba883f7..746ab4e 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -69,6 +69,7 @@
"vulkan_headers",
],
shared_libs: [
+ "libgui",
"libziparchive",
"libhardware",
"libsync",
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index f5daca7..e05ca5a 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -23,13 +23,14 @@
#include <stdlib.h>
#include <string.h>
+
#include <algorithm>
#include <mutex>
#include <new>
#include <utility>
-#include <android/log.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <vulkan/vk_layer_interface.h>
#include "api.h"
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index b4e256a..b8b7e94 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -17,8 +17,10 @@
// WARNING: This file is generated. See ../README.md for instructions.
#include <string.h>
+
#include <algorithm>
-#include <android/log.h>
+
+#include <log/log.h>
// to catch mismatches between vulkan.h and this file
#undef VK_NO_PROTOTYPES
@@ -425,8 +427,6 @@
VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
-VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
-VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
return GetData(instance).dispatch.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
@@ -1210,14 +1210,6 @@
return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
}
-VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
- return GetData(device).dispatch.GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
-}
-
-VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) {
- return GetData(device).dispatch.GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
-}
-
} // anonymous namespace
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 918c1f5..7f8d274 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -177,8 +177,6 @@
PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
PFN_vkQueuePresentKHR QueuePresentKHR;
- PFN_vkGetRefreshCycleDurationGOOGLE GetRefreshCycleDurationGOOGLE;
- PFN_vkGetPastPresentationTimingGOOGLE GetPastPresentationTimingGOOGLE;
// clang-format on
};
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index 2c70d46..33c5719 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -91,8 +91,10 @@
// WARNING: This file is generated. See ../README.md for instructions.
¶
#include <string.h>
+¶
#include <algorithm>
-#include <android/log.h>
+¶
+#include <log/log.h>
¶
// to catch mismatches between vulkan.h and this file
#undef VK_NO_PROTOTYPES
@@ -270,8 +272,10 @@
// WARNING: This file is generated. See ../README.md for instructions.
¶
#include <string.h>
+¶
#include <algorithm>
-#include <android/log.h>
+¶
+#include <log/log.h>
¶
#include "driver.h"
¶
@@ -700,7 +704,6 @@
VK_KHR_incremental_present
VK_KHR_surface
VK_KHR_swapchain
-VK_KHR_incremental_present
VK_GOOGLE_display_timing
{{end}}
@@ -1148,8 +1151,6 @@
{{ if eq $ext "VK_KHR_surface"}}true
{{else if eq $ext "VK_KHR_swapchain"}}true
{{else if eq $ext "VK_KHR_android_surface"}}true
- {{else if eq $ext "VK_KHR_incremental_present"}}true
- {{else if eq $ext "VK_GOOGLE_display_timing"}}true
{{end}}
{{end}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 8b9b9d2..df2526c 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -14,13 +14,21 @@
* limitations under the License.
*/
+#include <malloc.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/prctl.h>
+
#include <algorithm>
#include <array>
+#include <dlfcn.h>
#include <new>
-#include <malloc.h>
-#include <sys/prctl.h>
+
+#include <log/log.h>
+
+#include <android/dlext.h>
+#include <cutils/properties.h>
+#include <gui/GraphicsEnv.h>
#include "driver.h"
#include "stubhal.h"
@@ -123,17 +131,74 @@
Hal Hal::hal_;
+void* LoadLibrary(const android_dlextinfo& dlextinfo,
+ const char* subname,
+ int subname_len) {
+ const char kLibFormat[] = "vulkan.%*s.so";
+ char* name = static_cast<char*>(
+ alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
+ sprintf(name, kLibFormat, subname_len, subname);
+ return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+}
+
+const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
+ "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
+ "ro.board.platform",
+}};
+
+int LoadUpdatedDriver(const hw_module_t** module) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
+ };
+ if (!dlextinfo.library_namespace)
+ return -ENOENT;
+
+ void* so = nullptr;
+ char prop[PROPERTY_VALUE_MAX];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ int prop_len = property_get(key, prop, nullptr);
+ if (prop_len > 0) {
+ so = LoadLibrary(dlextinfo, prop, prop_len);
+ if (so)
+ break;
+ }
+ }
+ if (!so)
+ return -ENOENT;
+
+ hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
+ if (!hmi) {
+ ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
+ dlclose(so);
+ return -EINVAL;
+ }
+ if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
+ ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
+ dlclose(so);
+ return -EINVAL;
+ }
+ hmi->dso = so;
+ *module = hmi;
+ ALOGD("loaded updated driver");
+ return 0;
+}
+
bool Hal::Open() {
ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
// Use a stub device unless we successfully open a real HAL device.
hal_.dev_ = &stubhal::kDevice;
- const hwvulkan_module_t* module;
- int result =
- hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
+ int result;
+ const hwvulkan_module_t* module = nullptr;
+
+ result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
+ if (result == -ENOENT) {
+ result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
+ }
if (result != 0) {
- ALOGI("no Vulkan HAL present, using stub HAL");
+ ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
return true;
}
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index d74d9e9..e058439 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -22,7 +22,7 @@
#include <bitset>
#include <type_traits>
-#include <android/log.h>
+#include <log/log.h>
#include <vulkan/vulkan.h>
#include <hardware/hwvulkan.h>
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index e27b3d1..cfa9e30 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -17,8 +17,10 @@
// WARNING: This file is generated. See ../README.md for instructions.
#include <string.h>
+
#include <algorithm>
-#include <android/log.h>
+
+#include <log/log.h>
#include "driver.h"
@@ -332,6 +334,7 @@
if (strcmp(name, "VK_ANDROID_native_buffer") == 0) return ProcHook::ANDROID_native_buffer;
if (strcmp(name, "VK_EXT_debug_report") == 0) return ProcHook::EXT_debug_report;
if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
+ if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 167f88c..fa81958 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -36,6 +36,7 @@
ANDROID_native_buffer,
EXT_debug_report,
KHR_android_surface,
+ KHR_incremental_present,
KHR_surface,
KHR_swapchain,
GOOGLE_display_timing,
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 5f6d243..05856d3 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -26,10 +26,10 @@
#include <string>
#include <vector>
-#include <android/log.h>
#include <android/dlext.h>
#include <android-base/strings.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <ziparchive/zip_archive.h>
#include <vulkan/vulkan_loader_data.h>
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
index 3de8970..2926268 100644
--- a/vulkan/libvulkan/stubhal.cpp
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -30,7 +30,7 @@
#include <bitset>
#include <mutex>
-#include <android/log.h>
+#include <log/log.h>
#include <hardware/hwvulkan.h>
#include "stubhal.h"
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 807b81a..296be2d 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -16,7 +16,7 @@
#include <algorithm>
-#include <android/log.h>
+#include <log/log.h>
#include <gui/BufferQueue.h>
#include <sync/sync.h>
#include <utils/StrongPointer.h>
@@ -330,7 +330,6 @@
// TODO(jessehall): I think these are right, but haven't thought hard about
// it. Do we need to query the driver for support of any of these?
// Currently not included:
- // - VK_IMAGE_USAGE_GENERAL: maybe? does this imply cpu mappable?
// - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
// - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
capabilities->supportedUsageFlags =
@@ -587,9 +586,17 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
+ VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0;
int gralloc_usage = 0;
- // TODO(jessehall): Remove conditional once all drivers have been updated
- if (dispatch.GetSwapchainGrallocUsageANDROID) {
+ if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
+ result = dispatch.GetSwapchainGrallocUsage2ANDROID(
+ device, create_info->imageFormat, create_info->imageUsage,
+ swapchain_image_usage, &gralloc_usage);
+ if (result != VK_SUCCESS) {
+ ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
result = dispatch.GetSwapchainGrallocUsageANDROID(
device, create_info->imageFormat, create_info->imageUsage,
&gralloc_usage);
@@ -632,12 +639,20 @@
// -- Dequeue all buffers and create a VkImage for each --
// Any failures during or after this must cancel the dequeued buffers.
+ VkSwapchainImageCreateInfoANDROID swapchain_image_create = {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID,
+#pragma clang diagnostic pop
+ .pNext = nullptr,
+ .usage = swapchain_image_usage,
+ };
VkNativeBufferANDROID image_native_buffer = {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast"
.sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
#pragma clang diagnostic pop
- .pNext = nullptr,
+ .pNext = &swapchain_image_create,
};
VkImageCreateInfo image_create = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 4a520ee..89c65af 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -23,7 +23,7 @@
#include <algorithm>
#include <array>
-#include <android/log.h>
+#include <log/log.h>
#include <utils/Errors.h>
#include "null_driver_gen.h"