Merge "installd create_data_user_ce_path uses dir instead of symlink"
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index c89e3b1..a2560e3 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -7,7 +7,6 @@
shared_libs: [
"libbinder",
"libhwbinder",
- "android.hidl.manager@1.0",
"libhidlbase",
"libhidltransport",
"liblog",
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index acf63c3..add5285 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -26,7 +26,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/sendfile.h>
#include <time.h>
#include <unistd.h>
#include <zlib.h>
@@ -974,11 +973,16 @@
fprintf(stderr, "error cleaning up zlib: %d\n", result);
}
} else {
- ssize_t sent = 0;
- while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
- if (sent == -1) {
- fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
- errno);
+ char buf[4096];
+ ssize_t rc;
+ while ((rc = TEMP_FAILURE_RETRY(read(traceFD, buf, sizeof(buf)))) > 0) {
+ if (!android::base::WriteFully(outFd, buf, rc)) {
+ fprintf(stderr, "error writing trace: %s\n", strerror(errno));
+ break;
+ }
+ }
+ if (rc == -1) {
+ fprintf(stderr, "error dumping trace: %s\n", strerror(errno));
}
}
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index fc4977c..b6aacb5 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -6,7 +6,7 @@
LOCAL_MODULE := dumpstate
-LOCAL_SHARED_LIBRARIES := libcutils libdebuggerd_client liblog libselinux libbase libhardware_legacy
+LOCAL_SHARED_LIBRARIES := libcutils libdebuggerd_client liblog libselinux libbase
# ZipArchive support, the order matters here to get all symbols.
LOCAL_STATIC_LIBRARIES := libziparchive libz libcrypto_static
LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index b1205fe..bb56984 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -23,7 +23,6 @@
#include <memory>
#include <regex>
#include <set>
-#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -36,11 +35,11 @@
#include <sys/wait.h>
#include <unistd.h>
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
#include <cutils/properties.h>
-#include <hardware_legacy/power.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
@@ -83,7 +82,6 @@
#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
#define NUM_TOMBSTONES 10
#define WLUTIL "/vendor/xbin/wlutil"
-#define WAKE_LOCK_NAME "dumpstate_wakelock"
typedef struct {
char name[TOMBSTONE_MAX_LEN];
@@ -152,7 +150,7 @@
}
void add_mountinfo() {
- if (!zip_writer) return;
+ if (!is_zipping()) return;
const char *title = "MOUNT INFO";
mount_points.clear();
DurationReporter duration_reporter(title, NULL);
@@ -313,8 +311,8 @@
}
static void dump_systrace() {
- if (!zip_writer) {
- MYLOGD("Not dumping systrace because zip_writer is not set\n");
+ if (!is_zipping()) {
+ MYLOGD("Not dumping systrace because dumpstate is not zipping\n");
return;
}
std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
@@ -370,7 +368,7 @@
return;
}
- if (!zip_writer) {
+ if (!is_zipping()) {
// Write compressed and encoded raft logs to stdout if not zip_writer.
run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
return;
@@ -387,6 +385,83 @@
}
}
+/**
+ * Finds the last modified file in the directory dir whose name starts with file_prefix
+ * Function returns empty string when it does not find a file
+ */
+static std::string get_last_modified_file_matching_prefix(const std::string& dir,
+ const std::string& file_prefix) {
+ std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dir.c_str()), closedir);
+ if (d == nullptr) {
+ MYLOGD("Error %d opening %s\n", errno, dir.c_str());
+ return "";
+ }
+
+ // Find the newest file matching the file_prefix in dir
+ struct dirent *de;
+ time_t last_modified = 0;
+ std::string last_modified_file = "";
+ struct stat s;
+
+ while ((de = readdir(d.get()))) {
+ std::string file = std::string(de->d_name);
+ if (!file_prefix.empty()) {
+ if (!android::base::StartsWith(file, file_prefix.c_str())) continue;
+ }
+ file = dir + "/" + file;
+ int ret = stat(file.c_str(), &s);
+
+ if ((ret == 0) && (s.st_mtime > last_modified)) {
+ last_modified_file = file;
+ last_modified = s.st_mtime;
+ }
+ }
+
+ return last_modified_file;
+}
+
+void dump_modem_logs() {
+ DurationReporter duration_reporter("dump_modem_logs");
+ if (is_user_build()) {
+ return;
+ }
+
+ if (!is_zipping()) {
+ MYLOGD("Not dumping modem logs. dumpstate is not generating a zipping bugreport\n");
+ return;
+ }
+
+ char property[PROPERTY_VALUE_MAX];
+ property_get("ro.radio.log_prefix", property, "");
+ std::string file_prefix = std::string(property);
+ if(file_prefix.empty()) {
+ MYLOGD("No modem log : file_prefix is empty\n");
+ return;
+ }
+
+ MYLOGD("dump_modem_logs: directory is %s and file_prefix is %s\n",
+ bugreport_dir.c_str(), file_prefix.c_str());
+
+ std::string modem_log_file =
+ get_last_modified_file_matching_prefix(bugreport_dir, file_prefix);
+
+ struct stat s;
+ if (modem_log_file.empty() || stat(modem_log_file.c_str(), &s) != 0) {
+ MYLOGD("Modem log %s does not exist\n", modem_log_file.c_str());
+ return;
+ }
+
+ std::string filename = basename(modem_log_file.c_str());
+ if (!add_zip_entry(filename, modem_log_file)) {
+ MYLOGE("Unable to add modem log %s to zip file\n", modem_log_file.c_str());
+ } else {
+ MYLOGD("Modem Log %s is added to zip\n", modem_log_file.c_str());
+ if (remove(modem_log_file.c_str())) {
+ MYLOGE("Error removing modem log %s\n", modem_log_file.c_str());
+ }
+ }
+}
+
static bool skip_not_stat(const char *path) {
static const char stat[] = "/stat";
size_t len = strlen(path);
@@ -620,8 +695,8 @@
};
bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
- if (!zip_writer) {
- MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
+ if (!is_zipping()) {
+ MYLOGD("Not adding entry %s from fd because dumpstate is not zipping\n",
entry_name.c_str());
return false;
}
@@ -691,8 +766,8 @@
// TODO: move to util.cpp
void add_dir(const char *dir, bool recursive) {
- if (!zip_writer) {
- MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
+ if (!is_zipping()) {
+ MYLOGD("Not adding dir %s because dumpstate is not zipping\n", dir);
return;
}
MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
@@ -700,10 +775,14 @@
dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
}
+bool is_zipping() {
+ return zip_writer != nullptr;
+}
+
/* adds a text entry entry to the existing zip file. */
static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
- if (!zip_writer) {
- MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
+ if (!is_zipping()) {
+ MYLOGD("Not adding text entry %s because dumpstate is not zipping\n", entry_name.c_str());
return false;
}
MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
@@ -741,9 +820,63 @@
run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
}
+static void do_kmsg() {
+ struct stat st;
+ if (!stat(PSTORE_LAST_KMSG, &st)) {
+ /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
+ dump_file("LAST KMSG", PSTORE_LAST_KMSG);
+ } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
+ dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
+ } else {
+ /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
+ dump_file("LAST KMSG", "/proc/last_kmsg");
+ }
+}
+
+static void do_logcat() {
+ unsigned long timeout;
+ // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
+ // calculate timeout
+ timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
+ "-v", "printable",
+ "-d",
+ "*:v", NULL);
+ timeout = logcat_timeout("events");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
+ "-v", "threadtime",
+ "-v", "printable",
+ "-d",
+ "*:v", NULL);
+ timeout = logcat_timeout("radio");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
+ "-v", "threadtime",
+ "-v", "printable",
+ "-d",
+ "*:v", NULL);
+
+ run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
+
+ /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
+ run_command("LAST LOGCAT", 10, "logcat", "-L",
+ "-b", "all",
+ "-v", "threadtime",
+ "-v", "printable",
+ "-d",
+ "*:v", NULL);
+}
+
static void dumpstate(const std::string& screenshot_path, const std::string& version) {
DurationReporter duration_reporter("DUMPSTATE");
- unsigned long timeout;
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
run_command("UPTIME", 10, "uptime", NULL);
@@ -789,36 +922,7 @@
MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
}
- // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
- // calculate timeout
- timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
- if (timeout < 20000) {
- timeout = 20000;
- }
- run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
- "-v", "printable",
- "-d",
- "*:v", NULL);
- timeout = logcat_timeout("events");
- if (timeout < 20000) {
- timeout = 20000;
- }
- run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
- "-v", "threadtime",
- "-v", "printable",
- "-d",
- "*:v", NULL);
- timeout = logcat_timeout("radio");
- if (timeout < 20000) {
- timeout = 20000;
- }
- run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
- "-v", "threadtime",
- "-v", "printable",
- "-d",
- "*:v", NULL);
-
- run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
+ do_logcat();
/* show the traces we collected in main(), if that was done */
if (dump_traces_path != NULL) {
@@ -886,23 +990,7 @@
dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
- if (!stat(PSTORE_LAST_KMSG, &st)) {
- /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
- dump_file("LAST KMSG", PSTORE_LAST_KMSG);
- } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
- dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
- } else {
- /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
- dump_file("LAST KMSG", "/proc/last_kmsg");
- }
-
- /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
- run_command("LAST LOGCAT", 10, "logcat", "-L",
- "-b", "all",
- "-v", "threadtime",
- "-v", "printable",
- "-d",
- "*:v", NULL);
+ do_kmsg();
/* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
@@ -1014,6 +1102,10 @@
run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
+ // dump_modem_logs adds the modem logs if available to the bugreport.
+ // Do this at the end to allow for sufficient time for the modem logs to be
+ // collected.
+ dump_modem_logs();
printf("========================================================\n");
printf("== Final progress (pid %d): %d/%d (originally %d)\n",
@@ -1025,14 +1117,15 @@
static void usage() {
fprintf(stderr,
- "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
- "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
+ "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-t]"
+ "[-z] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
" -h: display this help message\n"
" -b: play sound file instead of vibrate, at beginning of job\n"
" -e: play sound file instead of vibrate, at end of job\n"
" -o: write to file (instead of stdout)\n"
" -d: append date to filename (requires -o)\n"
" -p: capture screenshot to filename.png (requires -o)\n"
+ " -t: only captures telephony sections\n"
" -z: generate zipped file (requires -o)\n"
" -s: write output to control socket (for init)\n"
" -S: write file location to control socket (for init; requires -o and -z)"
@@ -1046,31 +1139,11 @@
VERSION_DEFAULT.c_str());
}
-static void wake_lock_releaser() {
- if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
- MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
- } else {
- MYLOGD("Wake lock released.\n");
- }
-}
-
-static void sig_handler(int signo) {
- wake_lock_releaser();
+static void sigpipe_handler(int n) {
+ // don't complain to stderr or stdout
_exit(EXIT_FAILURE);
}
-static void register_sig_handler() {
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = sig_handler;
- sigaction(SIGPIPE, &sa, NULL); // broken pipe
- sigaction(SIGSEGV, &sa, NULL); // segment fault
- sigaction(SIGINT, &sa, NULL); // ctrl-c
- sigaction(SIGTERM, &sa, NULL); // killed
- sigaction(SIGQUIT, &sa, NULL); // quit
-}
-
/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
temporary file.
*/
@@ -1139,6 +1212,7 @@
}
int main(int argc, char *argv[]) {
+ struct sigaction sigact;
int do_add_date = 0;
int do_zip_file = 0;
int do_vibrate = 1;
@@ -1149,20 +1223,14 @@
int do_broadcast = 0;
int do_early_screenshot = 0;
int is_remote_mode = 0;
+ bool telephony_only = false;
+
std::string version = VERSION_DEFAULT;
now = time(NULL);
MYLOGI("begin\n");
- if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
- MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
- } else {
- MYLOGD("Wake lock acquired.\n");
- atexit(wake_lock_releaser);
- register_sig_handler();
- }
-
/* gets the sequential id */
char last_id[PROPERTY_VALUE_MAX];
property_get("dumpstate.last_id", last_id, "0");
@@ -1171,6 +1239,11 @@
property_set("dumpstate.last_id", last_id);
MYLOGI("dumpstate id: %lu\n", id);
+ /* clear SIGPIPE handler */
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = sigpipe_handler;
+ sigaction(SIGPIPE, &sigact, NULL);
+
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
@@ -1192,9 +1265,10 @@
format_args(argc, const_cast<const char **>(argv), &args);
MYLOGD("Dumpstate command line: %s\n", args.c_str());
int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
+ while ((c = getopt(argc, argv, "dho:svqzptPBRSV:")) != -1) {
switch (c) {
case 'd': do_add_date = 1; break;
+ case 't': telephony_only = true; break;
case 'z': do_zip_file = 1; break;
case 'o': use_outfile = optarg; break;
case 's': use_socket = 1; break;
@@ -1291,6 +1365,9 @@
char build_id[PROPERTY_VALUE_MAX];
property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
base_name = base_name + "-" + build_id;
+ if (telephony_only) {
+ base_name = base_name + "-telephony";
+ }
if (do_fb) {
// TODO: if dumpstate was an object, the paths could be internal variables and then
// we could have a function to calculate the derived values, such as:
@@ -1400,48 +1477,60 @@
// duration is logged into MYLOG instead.
print_header(version);
- // 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) {
+ dump_iptables();
+ if (!drop_root_user()) {
+ return -1;
+ }
+ do_dmesg();
+ do_logcat();
+ do_kmsg();
+ dumpstate_board();
+ dump_modem_logs();
+ } 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();
+ }
+
+ // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
+ dump_raft();
+
+ // Invoking the following dumpsys calls before dump_traces() to try and
+ // keep the system stats as close to its initial state as possible.
+ run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
+ run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
+
+ /* 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);
+ add_dir(RECOVERY_DIR, true);
+ add_dir(RECOVERY_DATA_DIR, true);
+ add_dir(LOGPERSIST_DATA_DIR, false);
+ if (!is_user_build()) {
+ add_dir(PROFILE_DATA_DIR_CUR, true);
+ add_dir(PROFILE_DATA_DIR_REF, true);
+ }
+ add_mountinfo();
+ dump_iptables();
+
+ // Capture any IPSec policies in play. No keys are exposed here.
+ run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
+
+ // Run ss as root so we can see socket marks.
+ run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
+
+ if (!drop_root_user()) {
+ return -1;
+ }
+
+ dumpstate(do_early_screenshot ? "": screenshot_path, version);
}
- // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
- dump_raft();
-
- // Invoking the following dumpsys calls before dump_traces() to try and
- // keep the system stats as close to its initial state as possible.
- run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
- run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
-
- /* 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);
- add_dir(RECOVERY_DIR, true);
- add_dir(RECOVERY_DATA_DIR, true);
- add_dir(LOGPERSIST_DATA_DIR, false);
- if (!is_user_build()) {
- add_dir(PROFILE_DATA_DIR_CUR, true);
- add_dir(PROFILE_DATA_DIR_REF, true);
- }
- add_mountinfo();
- dump_iptables();
-
- // Capture any IPSec policies in play. No keys are exposed here.
- run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
-
- // Run ss as root so we can see socket marks.
- run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
-
- if (!drop_root_user()) {
- return -1;
- }
-
- dumpstate(do_early_screenshot ? "": screenshot_path, version);
-
/* close output if needed */
if (is_redirecting) {
fclose(stdout);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 5ed9023..0b6aaab 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -87,6 +87,9 @@
/* root dir for all files copied as-is into the bugreport. */
extern const std::string ZIP_ROOT_DIR;
+/* Checkes whether dumpstate is generating a zipped bugreport. */
+bool is_zipping();
+
/* adds a new entry to the existing zip file. */
bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 3448e91..336db9f 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -46,3 +46,11 @@
class main
disabled
oneshot
+
+# bugreportelefony is a lightweight version of bugreport that only includes a few, urgent
+# sections used to report telephony bugs.
+service bugreportelefony /system/bin/dumpstate -t -d -B -z \
+ -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+ class main
+ disabled
+ oneshot
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index bbe48be..6ec636e 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -829,8 +829,7 @@
}
gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
- AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC, AID_WAKELOCK,
- AID_BLUETOOTH };
+ AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC, AID_BLUETOOTH };
if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
return false;
@@ -851,10 +850,8 @@
capheader.version = _LINUX_CAPABILITY_VERSION_3;
capheader.pid = 0;
- capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted =
- (CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_BLOCK_SUSPEND));
- capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective =
- (CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_BLOCK_SUSPEND));
+ capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
+ capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
capdata[0].inheritable = 0;
capdata[1].inheritable = 0;
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f7e8d13..5af8c5f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -184,9 +184,20 @@
return count;
}
+static const char* get_location_from_path(const char* path) {
+ static constexpr char kLocationSeparator = '/';
+ const char *location = strrchr(path, kLocationSeparator);
+ if (location == NULL) {
+ return path;
+ } else {
+ // Skip the separator character.
+ return location + 1;
+ }
+}
+
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,
+ const char* instruction_set, const char* compiler_filter, bool vm_safe_mode,
bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -196,6 +207,9 @@
return;
}
+ // Get the relative path to the input file.
+ const char* relative_input_file_name = get_location_from_path(input_file_name);
+
char dex2oat_Xms_flag[kPropertyValueMax];
bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
@@ -286,7 +300,7 @@
char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
- sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
+ sprintf(zip_location_arg, "--zip-location=%s", relative_input_file_name);
sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
@@ -314,11 +328,11 @@
bool have_dex2oat_compiler_filter_flag;
if (skip_compilation) {
- strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
+ strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract");
have_dex2oat_compiler_filter_flag = true;
have_dex2oat_relocation_skip_flag = true;
} else if (vm_safe_mode) {
- strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
+ strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=quicken");
have_dex2oat_compiler_filter_flag = true;
} else if (compiler_filter != nullptr &&
strlen(compiler_filter) + strlen("--compiler-filter=") <
@@ -348,8 +362,18 @@
sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
}
+ // Get the directory of the apk to pass as a base classpath directory.
+ char base_dir[arraysize("--classpath-dir=") + PKG_PATH_MAX];
+ std::string apk_dir(input_file_name);
+ unsigned long dir_index = apk_dir.rfind('/');
+ bool has_base_dir = dir_index != std::string::npos;
+ if (has_base_dir) {
+ apk_dir = apk_dir.substr(0, dir_index);
+ sprintf(base_dir, "--classpath-dir=%s", apk_dir.c_str());
+ }
- ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
+
+ ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, relative_input_file_name, output_file_name);
const char* argv[9 // program name, mandatory arguments and the final NULL
+ (have_dex2oat_isa_variant ? 1 : 0)
@@ -367,6 +391,7 @@
+ dex2oat_flags_count
+ (profile_fd == -1 ? 0 : 1)
+ (shared_libraries != nullptr ? 4 : 0)
+ + (has_base_dir ? 1 : 0)
+ (have_dex2oat_large_app_threshold ? 1 : 0)];
int i = 0;
argv[i++] = DEX2OAT_BIN;
@@ -431,6 +456,9 @@
argv[i++] = RUNTIME_ARG;
argv[i++] = shared_libraries;
}
+ if (has_base_dir) {
+ argv[i++] = base_dir;
+ }
// Do not add after dex2oat_flags, they should override others for debugging.
argv[i] = NULL;
@@ -768,17 +796,6 @@
exit(68); /* only get here on exec failure */
}
-static const char* get_location_from_path(const char* path) {
- static constexpr char kLocationSeparator = '/';
- const char *location = strrchr(path, kLocationSeparator);
- if (location == NULL) {
- return path;
- } else {
- // Skip the separator character.
- return location + 1;
- }
-}
-
bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
std::vector<unique_fd> profile_fds;
unique_fd reference_profile_fd;
@@ -1139,8 +1156,8 @@
// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
- const char* instruction_set, bool is_public, bool profile_guided,
- int uid, bool is_secondary_dex, Dex2oatFileWrapper* in_vdex_wrapper_fd,
+ const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
+ Dex2oatFileWrapper* in_vdex_wrapper_fd,
Dex2oatFileWrapper* out_vdex_wrapper_fd) {
CHECK(in_vdex_wrapper_fd != nullptr);
CHECK(out_vdex_wrapper_fd != nullptr);
@@ -1150,9 +1167,7 @@
int dexopt_action = abs(dexopt_needed);
bool is_odex_location = dexopt_needed < 0;
std::string in_vdex_path_str;
- // Disable passing an input vdex when the compilation is profile-guided. The dexlayout
- // optimization in dex2oat is incompatible with it. b/35872504.
- if (dexopt_action != DEX2OAT_FROM_SCRATCH && !profile_guided) {
+ 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) {
@@ -1511,8 +1526,8 @@
// Open vdex files.
Dex2oatFileWrapper in_vdex_fd;
Dex2oatFileWrapper out_vdex_fd;
- if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public,
- profile_guided, uid, is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
+ if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
+ is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
return -1;
}
@@ -1540,14 +1555,12 @@
_exit(67);
}
- // Pass dex2oat the relative path to the input file.
- const char *input_file_name = get_location_from_path(dex_path);
run_dex2oat(input_fd.get(),
out_oat_fd.get(),
in_vdex_fd.get(),
out_vdex_fd.get(),
image_fd.get(),
- input_file_name,
+ dex_path,
out_oat_path,
swap_fd.get(),
instruction_set,
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 4740202..df4941c 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -22,7 +22,6 @@
"libhidltransport",
"libhidl-gen-utils",
"libvintf",
- "android.hidl.manager@1.0",
],
srcs: [
"Lshal.cpp",
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 420ec3c..d6caf5f 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -163,6 +163,7 @@
return true;
}
+// Must process hwbinder services first, then passthrough services.
void Lshal::forEachTable(const std::function<void(Table &)> &f) {
f(mServicesTable);
f(mPassthroughRefTable);
@@ -243,6 +244,18 @@
}
void Lshal::dumpVintf() const {
+ mOut << "<!-- " << std::endl
+ << " This is a skeleton device manifest. Notes: " << std::endl
+ << " 1. android.hidl.*, android.frameworks.*, android.system.* are not included." << std::endl
+ << " 2. If a HAL is supported in both hwbinder and passthrough transport, " << std::endl
+ << " only hwbinder is shown." << std::endl
+ << " 3. It is likely that HALs in passthrough transport does not have" << std::endl
+ << " <interface> declared; users will have to write them by hand." << std::endl
+ << " 4. sepolicy version is set to 0.0. It is recommended that the entry" << std::endl
+ << " is removed from the manifest file and written by assemble_vintf" << std::endl
+ << " at build time." << std::endl
+ << "-->" << std::endl;
+
vintf::HalManifest manifest;
forEachTable([this, &manifest] (const Table &table) {
for (const TableEntry &entry : table) {
@@ -271,6 +284,8 @@
std::string instanceName =
&table == &mImplementationsTable ? "" : splittedFqInstanceName.second;
+ vintf::Version version{fqName.getPackageMajorVersion(),
+ fqName.getPackageMinorVersion()};
vintf::Transport transport;
vintf::Arch arch;
if (entry.transport == "hwbinder") {
@@ -296,35 +311,33 @@
continue;
}
- vintf::ManifestHal *hal = manifest.getHal(fqName.package());
- if (hal == nullptr) {
- if (!manifest.add(vintf::ManifestHal{
+ bool done = false;
+ for (vintf::ManifestHal *hal : manifest.getHals(fqName.package())) {
+ if (hal->transport() != transport) {
+ if (transport != vintf::Transport::PASSTHROUGH) {
+ mErr << "Fatal: should not reach here. Generated result may be wrong."
+ << std::endl;
+ }
+ done = true;
+ break;
+ }
+ if (hal->hasVersion(version)) {
+ hal->interfaces[interfaceName].name = interfaceName;
+ hal->interfaces[interfaceName].instances.insert(instanceName);
+ done = true;
+ break;
+ }
+ }
+ if (done) {
+ continue; // to next TableEntry
+ }
+ if (!manifest.add(vintf::ManifestHal{
.format = vintf::HalFormat::HIDL,
.name = fqName.package(),
- .impl = {.implLevel = vintf::ImplLevel::GENERIC, .impl = ""},
- .transportArch = {transport, arch}
- })) {
- mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
- continue;
- }
- hal = manifest.getHal(fqName.package());
- }
- if (hal == nullptr) {
- mErr << "Warning: cannot get hal '" << fqInstanceName
- << "' after adding it" << std::endl;
- continue;
- }
- vintf::Version version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()};
- if (std::find(hal->versions.begin(), hal->versions.end(), version) == hal->versions.end()) {
- hal->versions.push_back(version);
- }
- if (&table != &mImplementationsTable) {
- auto it = hal->interfaces.find(interfaceName);
- if (it == hal->interfaces.end()) {
- hal->interfaces.insert({interfaceName, {interfaceName, {{instanceName}}}});
- } else {
- it->second.instances.insert(instanceName);
- }
+ .versions = {version},
+ .transportArch = {transport, arch},
+ .interfaces = {{interfaceName, {interfaceName, {{instanceName}}}}}})) {
+ mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
}
}
});
@@ -672,6 +685,7 @@
<< " -c, --clients: print the client PIDs, or client cmdlines if -m is set"
<< std::endl
<< " -m, --cmdline: print cmdline instead of PIDs" << std::endl
+ << " -d, --debug: emit debug info from IBase::debug" << std::endl
<< " --sort=i, --sort=interface: sort by interface name" << std::endl
<< " --sort=p, --sort=pid: sort by server pid" << std::endl
<< " --init-vintf=path: form a skeleton HAL manifest to specified file " << std::endl
diff --git a/data/etc/android.hardware.sensor.heartrate.fitness.xml b/data/etc/android.hardware.sensor.heartrate.fitness.xml
new file mode 100644
index 0000000..aef77b4
--- /dev/null
+++ b/data/etc/android.hardware.sensor.heartrate.fitness.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Feature for devices supporting a fitness heart rate monitor -->
+<permissions>
+ <feature name="android.hardware.sensor.heartrate.fitness" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 9cb4d6d..f9464e8 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -50,8 +50,8 @@
<!-- Feature to specify if the device support managed users. -->
<feature name="android.software.managed_users" />
- <!-- Feature to specify if the device supports a VR mode. -->
- <feature name="android.software.vr.mode" />
+ <!-- Feature to specify if the device supports a VR mode.
+ feature name="android.software.vr.mode" -->
<!-- Devices with all optimizations required to be a "VR Ready" device that
pass all CTS tests for this feature must include feature
android.hardware.vr.high_performance -->
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 4a00818..6c12972 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -48,6 +48,7 @@
*
*/
+#include <stdbool.h>
#include <sys/types.h>
#include <android/looper.h>
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 74e75d7..b0d53ef 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -681,8 +681,16 @@
return UNEXPECTED_NULL;
}
+ if (val->max_size() < static_cast<size_t>(size)) {
+ return NO_MEMORY;
+ }
+
val->resize(static_cast<size_t>(size));
+ if (val->size() < static_cast<size_t>(size)) {
+ return NO_MEMORY;
+ }
+
for (auto& v: *val) {
status = (this->*read_func)(&v);
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/ui/Fence.h b/include/ui/Fence.h
index 2fbc9ef..1df15f8 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -27,6 +27,8 @@
#include <utils/String8.h>
#include <utils/Timers.h>
+#include <experimental/optional>
+
struct ANativeWindowBuffer;
namespace android {
@@ -96,16 +98,26 @@
// occurs then -1 is returned.
nsecs_t getSignalTime() const;
+#if __cplusplus > 201103L
// hasSignaled returns whether the fence has signaled yet. Prefer this to
// getSignalTime() or wait() if all you care about is whether the fence has
- // signaled.
- inline bool hasSignaled() {
+ // signaled. Returns an optional bool, which will have a value if there was
+ // no error.
+ inline std::experimental::optional<bool> hasSignaled() {
// The sync_wait call underlying wait() has been measured to be
// significantly faster than the sync_fence_info call underlying
// getSignalTime(), which might otherwise appear to be the more obvious
// way to check whether a fence has signaled.
- return wait(0) == NO_ERROR;
+ switch (wait(0)) {
+ case NO_ERROR:
+ return true;
+ case -ETIME:
+ return false;
+ default:
+ return {};
+ }
}
+#endif
// Flattenable interface
size_t getFlattenedSize() const;
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index e9859fe..a7eb871 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -44,13 +44,9 @@
template <typename T>
inline Rect(T w, T h) {
if (w > INT32_MAX) {
- ALOG(LOG_WARN, "Rect",
- "Width %u too large for Rect class, clamping", w);
w = INT32_MAX;
}
if (h > INT32_MAX) {
- ALOG(LOG_WARN, "Rect",
- "Height %u too large for Rect class, clamping", h);
h = INT32_MAX;
}
left = top = 0;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 4780757..f7347ae 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -15,6 +15,9 @@
cc_library {
name: "libbinder",
+ // for vndbinder
+ vendor_available: true,
+
srcs: [
"AppOpsManager.cpp",
"Binder.cpp",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 2062b3b..3aeff2e 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -135,10 +135,12 @@
{
unsigned n;
for (n = 0; n < 5; n++){
+ if (n > 0) {
+ ALOGI("Waiting for service %s...", String8(name).string());
+ sleep(1);
+ }
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
- ALOGI("Waiting for service %s...\n", String8(name).string());
- sleep(1);
}
return NULL;
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 061cb08..d753eb5 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -514,7 +514,7 @@
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
size_t newSize = ((mObjectsSize + numObjects)*3)/2;
- if (newSize < mObjectsSize) return NO_MEMORY; // overflow
+ if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow
binder_size_t *objects =
(binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
if (objects == (binder_size_t*)0) {
@@ -1308,7 +1308,7 @@
}
if (!enoughObjects) {
size_t newSize = ((mObjectsSize+2)*3)/2;
- if (newSize < mObjectsSize) return NO_MEMORY; // overflow
+ if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow
binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
if (objects == NULL) return NO_MEMORY;
mObjects = objects;
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 2152206..acd0538 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -61,3 +61,13 @@
"libbase",
],
}
+
+cc_test {
+ name: "schd-dbg",
+ srcs: ["schd-dbg.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ "libbase",
+ ],
+}
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
new file mode 100644
index 0000000..2732071
--- /dev/null
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -0,0 +1,426 @@
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include <iomanip>
+#include <iostream>
+#include <tuple>
+#include <vector>
+
+#include <pthread.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+using namespace std;
+using namespace android;
+
+enum BinderWorkerServiceCode {
+ BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+#define ASSERT(cond) \
+ do { \
+ if (!(cond)) { \
+ cerr << __func__ << ":" << __LINE__ << " condition:" << #cond \
+ << " failed\n" \
+ << endl; \
+ exit(EXIT_FAILURE); \
+ } \
+ } while (0)
+
+vector<sp<IBinder> > workers;
+
+// the ratio that the service is synced on the same cpu beyond
+// GOOD_SYNC_MIN is considered as good
+#define GOOD_SYNC_MIN (0.6)
+
+#define DUMP_PRICISION 3
+
+// the default value
+int no_process = 2;
+int iterations = 100;
+int payload_size = 16;
+int no_inherent = 0;
+int no_sync = 0;
+int verbose = 0;
+
+// the deadline latency that we are interested in
+uint64_t deadline_us = 2500;
+
+int thread_pri() {
+ struct sched_param param;
+ int policy;
+ ASSERT(!pthread_getschedparam(pthread_self(), &policy, ¶m));
+ return param.sched_priority;
+}
+
+void thread_dump(const char* prefix) {
+ struct sched_param param;
+ int policy;
+ if (!verbose) return;
+ cout << "--------------------------------------------------" << endl;
+ cout << setw(12) << left << prefix << " pid: " << getpid()
+ << " tid: " << gettid() << " cpu: " << sched_getcpu() << endl;
+ ASSERT(!pthread_getschedparam(pthread_self(), &policy, ¶m));
+ string s = (policy == SCHED_OTHER)
+ ? "SCHED_OTHER"
+ : (policy == SCHED_FIFO)
+ ? "SCHED_FIFO"
+ : (policy == SCHED_RR) ? "SCHED_RR" : "???";
+ cout << setw(12) << left << s << param.sched_priority << endl;
+ return;
+}
+
+class BinderWorkerService : public BBinder {
+ public:
+ BinderWorkerService() {
+ }
+ ~BinderWorkerService() {
+ }
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) {
+ (void)flags;
+ (void)data;
+ (void)reply;
+ switch (code) {
+ // The transaction format is like
+ //
+ // data[in]: int32: caller priority
+ // int32: caller cpu
+ //
+ // reply[out]: int32: 1 if caller's priority != callee's priority
+ // int32: 1 if caller's cpu != callee's cpu
+ //
+ // note the caller cpu read here is not always correct
+ // there're still chances that the caller got switched out
+ // right after it read the cpu number and still before the transaction.
+ case BINDER_NOP: {
+ thread_dump("binder");
+ int priority = thread_pri();
+ int priority_caller = data.readInt32();
+ int h = 0, s = 0;
+ if (priority_caller != priority) {
+ h++;
+ if (verbose) {
+ cout << "err priority_caller:" << priority_caller
+ << ", priority:" << priority << endl;
+ }
+ }
+ if (priority == sched_get_priority_max(SCHED_FIFO)) {
+ int cpu = sched_getcpu();
+ int cpu_caller = data.readInt32();
+ if (cpu != cpu_caller) {
+ s++;
+ }
+ }
+ reply->writeInt32(h);
+ reply->writeInt32(s);
+ return NO_ERROR;
+ }
+ default:
+ return UNKNOWN_TRANSACTION;
+ };
+ }
+};
+
+class Pipe {
+ int m_readFd;
+ int m_writeFd;
+ Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {
+ }
+ Pipe(const Pipe&) = delete;
+ Pipe& operator=(const Pipe&) = delete;
+ Pipe& operator=(const Pipe&&) = delete;
+
+ public:
+ Pipe(Pipe&& rval) noexcept {
+ m_readFd = rval.m_readFd;
+ m_writeFd = rval.m_writeFd;
+ rval.m_readFd = 0;
+ rval.m_writeFd = 0;
+ }
+ ~Pipe() {
+ if (m_readFd) close(m_readFd);
+ if (m_writeFd) close(m_writeFd);
+ }
+ void signal() {
+ bool val = true;
+ int error = write(m_writeFd, &val, sizeof(val));
+ ASSERT(error >= 0);
+ };
+ void wait() {
+ bool val = false;
+ int error = read(m_readFd, &val, sizeof(val));
+ ASSERT(error >= 0);
+ }
+ template <typename T>
+ void send(const T& v) {
+ int error = write(m_writeFd, &v, sizeof(T));
+ ASSERT(error >= 0);
+ }
+ template <typename T>
+ void recv(T& v) {
+ int error = read(m_readFd, &v, sizeof(T));
+ ASSERT(error >= 0);
+ }
+ static tuple<Pipe, Pipe> createPipePair() {
+ int a[2];
+ int b[2];
+
+ int error1 = pipe(a);
+ int error2 = pipe(b);
+ ASSERT(error1 >= 0);
+ ASSERT(error2 >= 0);
+
+ return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
+ }
+};
+
+typedef chrono::time_point<chrono::high_resolution_clock> Tick;
+
+static inline Tick tickNow() {
+ return chrono::high_resolution_clock::now();
+}
+
+static inline uint64_t tickNano(Tick& sta, Tick& end) {
+ return uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - sta).count());
+}
+
+struct Results {
+ uint64_t m_best = 0xffffffffffffffffULL;
+ uint64_t m_worst = 0;
+ uint64_t m_transactions = 0;
+ uint64_t m_total_time = 0;
+ uint64_t m_miss = 0;
+
+ void add_time(uint64_t nano) {
+ m_best = min(nano, m_best);
+ m_worst = max(nano, m_worst);
+ m_transactions += 1;
+ m_total_time += nano;
+ if (nano > deadline_us * 1000) m_miss++;
+ }
+ void dump() {
+ double best = (double)m_best / 1.0E6;
+ double worst = (double)m_worst / 1.0E6;
+ double average = (double)m_total_time / m_transactions / 1.0E6;
+ // FIXME: libjson?
+ cout << std::setprecision(DUMP_PRICISION) << "{ \"avg\":" << setw(5) << left
+ << average << ", \"wst\":" << setw(5) << left << worst
+ << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << m_miss
+ << "}";
+ }
+};
+
+String16 generateServiceName(int num) {
+ char num_str[32];
+ snprintf(num_str, sizeof(num_str), "%d", num);
+ String16 serviceName = String16("binderWorker") + String16(num_str);
+ return serviceName;
+}
+
+static void parcel_fill(Parcel& data, int sz, int priority, int cpu) {
+ ASSERT(sz >= (int)sizeof(uint32_t) * 2);
+ data.writeInt32(priority);
+ data.writeInt32(cpu);
+ sz -= sizeof(uint32_t);
+ while (sz > (int)sizeof(uint32_t)) {
+ data.writeInt32(0);
+ sz -= sizeof(uint32_t);
+ }
+}
+
+static void* thread_start(void* p) {
+ Results* results_fifo = (Results*)p;
+ Parcel data, reply;
+ Tick sta, end;
+
+ parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
+ thread_dump("fifo-caller");
+
+ sta = tickNow();
+ status_t ret = workers[0]->transact(BINDER_NOP, data, &reply);
+ end = tickNow();
+ results_fifo->add_time(tickNano(sta, end));
+
+ no_inherent += reply.readInt32();
+ no_sync += reply.readInt32();
+ return 0;
+}
+
+// create a fifo thread to transact and wait it to finished
+static void thread_transaction(Results* results_fifo) {
+ void* dummy;
+ pthread_t thread;
+ pthread_attr_t attr;
+ struct sched_param param;
+ ASSERT(!pthread_attr_init(&attr));
+ ASSERT(!pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
+ param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ ASSERT(!pthread_attr_setschedparam(&attr, ¶m));
+ ASSERT(!pthread_create(&thread, &attr, &thread_start, results_fifo));
+ ASSERT(!pthread_join(thread, &dummy));
+}
+
+#define is_client(_num) ((_num) >= (no_process / 2))
+
+void worker_fx(int num, int no_process, int iterations, int payload_size,
+ Pipe p) {
+ int dummy;
+ Results results_other, results_fifo;
+
+ // Create BinderWorkerService and for go.
+ ProcessState::self()->startThreadPool();
+ sp<IServiceManager> serviceMgr = defaultServiceManager();
+ sp<BinderWorkerService> service = new BinderWorkerService;
+ serviceMgr->addService(generateServiceName(num), service);
+ p.signal();
+ p.wait();
+
+ // If client/server pairs, then half the workers are
+ // servers and half are clients
+ int server_count = no_process / 2;
+
+ for (int i = 0; i < server_count; i++) {
+ // self service is in-process so just skip
+ if (num == i) continue;
+ workers.push_back(serviceMgr->getService(generateServiceName(i)));
+ }
+
+ // Client for each pair iterates here
+ // each iterations contains exatcly 2 transactions
+ for (int i = 0; is_client(num) && i < iterations; i++) {
+ Parcel data, reply;
+ Tick sta, end;
+ // the target is paired to make it easier to diagnose
+ int target = num % server_count;
+
+ // 1. transaction by fifo thread
+ thread_transaction(&results_fifo);
+ parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
+ thread_dump("other-caller");
+
+ // 2. transaction by other thread
+ sta = tickNow();
+ ASSERT(NO_ERROR == workers[target]->transact(BINDER_NOP, data, &reply));
+ end = tickNow();
+ results_other.add_time(tickNano(sta, end));
+
+ no_inherent += reply.readInt32();
+ no_sync += reply.readInt32();
+ }
+ // Signal completion to master and wait.
+ p.signal();
+ p.wait();
+
+ p.send(&dummy);
+ p.wait();
+ // Client for each pair dump here
+ if (is_client(num)) {
+ int no_trans = iterations * 2;
+ double sync_ratio = (1.0 - (double)no_sync / no_trans);
+ // FIXME: libjson?
+ cout << "\"P" << (num - server_count) << "\":{\"SYNC\":\""
+ << ((sync_ratio > GOOD_SYNC_MIN) ? "GOOD" : "POOR") << "\","
+ << "\"S\":" << (no_trans - no_sync) << ",\"I\":" << no_trans << ","
+ << "\"R\":" << sync_ratio << "," << endl;
+
+ cout << " \"other_ms\":";
+ results_other.dump();
+ cout << "," << endl;
+ cout << " \"fifo_ms\": ";
+ results_fifo.dump();
+ cout << endl;
+ cout << "}," << endl;
+ }
+ exit(no_inherent);
+}
+
+Pipe make_process(int num, int iterations, int no_process, int payload_size) {
+ auto pipe_pair = Pipe::createPipePair();
+ pid_t pid = fork();
+ if (pid) {
+ // parent
+ return move(get<0>(pipe_pair));
+ } else {
+ // child
+ thread_dump(is_client(num) ? "client" : "server");
+ worker_fx(num, no_process, iterations, payload_size,
+ move(get<1>(pipe_pair)));
+ // never get here
+ return move(get<0>(pipe_pair));
+ }
+}
+
+void wait_all(vector<Pipe>& v) {
+ for (size_t i = 0; i < v.size(); i++) {
+ v[i].wait();
+ }
+}
+
+void signal_all(vector<Pipe>& v) {
+ for (size_t i = 0; i < v.size(); i++) {
+ v[i].signal();
+ }
+}
+
+// This test is modified from binderThroughputTest.cpp
+int main(int argc, char** argv) {
+ for (int i = 1; i < argc; i++) {
+ if (string(argv[i]) == "-i") {
+ iterations = atoi(argv[i + 1]);
+ i++;
+ continue;
+ }
+ if (string(argv[i]) == "-pair") {
+ no_process = 2 * atoi(argv[i + 1]);
+ i++;
+ continue;
+ }
+ if (string(argv[i]) == "-deadline_us") {
+ deadline_us = atoi(argv[i + 1]);
+ i++;
+ continue;
+ }
+ if (string(argv[i]) == "-v") {
+ verbose = 1;
+ i++;
+ }
+ }
+ vector<Pipe> pipes;
+ thread_dump("main");
+ // FIXME: libjson?
+ cout << "{" << endl;
+ cout << "\"cfg\":{\"pair\":" << (no_process / 2)
+ << ",\"iterations\":" << iterations << ",\"deadline_us\":" << deadline_us
+ << "}," << endl;
+
+ // the main process fork 2 processes for each pairs
+ // 1 server + 1 client
+ // each has a pipe to communicate with
+ for (int i = 0; i < no_process; i++) {
+ pipes.push_back(make_process(i, iterations, no_process, payload_size));
+ }
+ wait_all(pipes);
+ signal_all(pipes);
+ wait_all(pipes);
+ signal_all(pipes);
+ for (int i = 0; i < no_process; i++) {
+ int status;
+ pipes[i].signal();
+ wait(&status);
+ // the exit status is number of transactions without priority inheritance
+ // detected in the child process
+ no_inherent += status;
+ }
+ // FIXME: libjson?
+ cout << "\"inheritance\": " << (no_inherent == 0 ? "\"PASS\"" : "\"FAIL\"")
+ << endl;
+ cout << "}" << endl;
+ return -no_inherent;
+}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 8e8bb80..7ac03f1 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -73,6 +73,7 @@
"DisplayEventReceiver.cpp",
"GLConsumer.cpp",
"GraphicBufferAlloc.cpp",
+ "GraphicsEnv.cpp",
"GuiConfig.cpp",
"IDisplayEventConnection.cpp",
"IGraphicBufferAlloc.cpp",
@@ -95,6 +96,7 @@
],
shared_libs: [
+ "libnativeloader",
"libbinder",
"libcutils",
"libEGL",
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 7fbf312..ee4c58c 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -716,6 +716,7 @@
}
sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
+ Mutex::Autolock lock(mCore->mMutex);
return mCore->mSidebandStream;
}
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index d74d32c..6e6cce2 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -93,6 +93,7 @@
mSharedBufferSlot(INVALID_BUFFER_SLOT),
mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
HAL_DATASPACE_UNKNOWN),
+ mLastQueuedSlot(INVALID_BUFFER_SLOT),
mUniqueId(getUniqueId())
{
if (allocator == NULL) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index f8f3872..f0e701e 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -721,6 +721,7 @@
mSlots[*outSlot].mFence = Fence::NO_FENCE;
mSlots[*outSlot].mRequestBufferCalled = true;
mSlots[*outSlot].mAcquireCalled = false;
+ mSlots[*outSlot].mNeedsReallocation = false;
mCore->mActiveBuffers.insert(found);
VALIDATE_CONSISTENCY();
@@ -1358,6 +1359,7 @@
String8 BufferQueueProducer::getConsumerName() const {
ATRACE_CALL();
+ Mutex::Autolock lock(mCore->mMutex);
BQ_LOGV("getConsumerName: %s", mConsumerName.string());
return mConsumerName;
}
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 5546d54..3cf3078 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -314,6 +314,18 @@
if (!mSlots[slot].mFence.get()) {
mSlots[slot].mFence = fence;
+ return OK;
+ }
+
+ auto signaled = mSlots[slot].mFence->hasSignaled();
+
+ if (!signaled) {
+ CB_LOGE("fence has invalid state");
+ return BAD_VALUE;
+ }
+
+ if (*signaled) {
+ mSlots[slot].mFence = fence;
} else {
char fenceName[32] = {};
snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
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/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 5338034..57c3073 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -194,7 +194,8 @@
// a non_wake-up version.
if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE ||
- type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE) {
+ type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE ||
+ type == SENSOR_TYPE_WRIST_TILT_GESTURE) {
wakeUpSensor = true;
}
// For now we just return the first sensor of that type we find.
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index d5b88de..ec7df31 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -288,6 +288,7 @@
gralloc1_error_t Gralloc1On0Adapter::retain(
const std::shared_ptr<Buffer>& buffer)
{
+ std::lock_guard<std::mutex> lock(mBufferMutex);
buffer->retain();
return GRALLOC1_ERROR_NONE;
}
@@ -295,6 +296,7 @@
gralloc1_error_t Gralloc1On0Adapter::release(
const std::shared_ptr<Buffer>& buffer)
{
+ std::lock_guard<std::mutex> lock(mBufferMutex);
if (!buffer->release()) {
return GRALLOC1_ERROR_NONE;
}
@@ -314,7 +316,6 @@
}
}
- std::lock_guard<std::mutex> lock(mBufferMutex);
mBuffers.erase(handle);
return GRALLOC1_ERROR_NONE;
}
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 60c4b36..c1056a7 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -23,28 +23,28 @@
// The headers modules are in frameworks/native/opengl/Android.bp.
ndk_library {
- name: "libEGL.ndk",
+ name: "libEGL",
symbol_file: "libEGL.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv1_CM.ndk",
+ name: "libGLESv1_CM",
symbol_file: "libGLESv1_CM.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv2.ndk",
+ name: "libGLESv2",
symbol_file: "libGLESv2.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv3.ndk",
+ name: "libGLESv3",
symbol_file: "libGLESv3.map.txt",
first_version: "18",
unversioned_until: "current",
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 218ab35..69e3c13 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -14,6 +14,10 @@
** limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <array>
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
@@ -23,8 +27,10 @@
#include <stdlib.h>
#include <string.h>
+#include <android/dlext.h>
#include <cutils/properties.h>
#include <log/log.h>
+#include <utils/Trace.h>
#include <EGL/egl.h>
@@ -114,6 +120,11 @@
return NULL;
}
+static void* do_dlopen(const char* path, int mode) {
+ ATRACE_CALL();
+ return dlopen(path, mode);
+}
+
// ----------------------------------------------------------------------------
Loader::driver_t::driver_t(void* gles)
@@ -154,14 +165,30 @@
// ----------------------------------------------------------------------------
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) {
- void* so = dlopen(path, RTLD_NOW | RTLD_LOCAL);
+ void* so = do_dlopen(path, RTLD_NOW | RTLD_LOCAL);
ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror());
return so;
}
@@ -208,6 +235,8 @@
void* Loader::open(egl_connection_t* cnx)
{
+ ATRACE_CALL();
+
void* dso;
driver_t* hnd = 0;
@@ -253,6 +282,8 @@
__eglMustCastToProperFunctionPointerType* curr,
getProcAddressType getProcAddress)
{
+ ATRACE_CALL();
+
const ssize_t SIZE = 256;
char scrap[SIZE];
while (*api) {
@@ -304,9 +335,8 @@
}
}
-void *Loader::load_driver(const char* kind,
- egl_connection_t* cnx, uint32_t mask)
-{
+static void* load_system_driver(const char* kind) {
+ ATRACE_CALL();
class MatchFile {
public:
static String8 find(const char* kind) {
@@ -422,7 +452,7 @@
}
const char* const driver_absolute_path = absolutePath.string();
- void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
+ void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
if (dso == 0) {
const char* err = dlerror();
ALOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown");
@@ -431,11 +461,63 @@
ALOGD("loaded %s", driver_absolute_path);
+ return dso;
+}
+
+static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
+ ATRACE_CALL();
+ return android_dlopen_ext(path, mode, info);
+}
+
+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) {
+ ATRACE_CALL();
+ 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 = do_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)
+{
+ ATRACE_CALL();
+
+ 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/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index a42b3f1..f8e25b4 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -267,6 +267,7 @@
EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
{
+ ATRACE_CALL();
clearError();
uintptr_t index = reinterpret_cast<uintptr_t>(display);
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index a32f037..d7df40c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -15,6 +15,7 @@
*/
#define __STDC_LIMIT_MACROS 1
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <string.h>
@@ -26,6 +27,7 @@
#include "egl_tls.h"
#include "Loader.h"
#include <cutils/properties.h>
+#include <utils/Trace.h>
// ----------------------------------------------------------------------------
namespace android {
@@ -103,6 +105,7 @@
EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
Mutex::Autolock _l(lock);
+ ATRACE_CALL();
// get our driver loader
Loader& loader(Loader::getInstance());
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
new file mode 100644
index 0000000..4fd98e2
--- /dev/null
+++ b/services/inputflinger/Android.bp
@@ -0,0 +1,51 @@
+// 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.
+
+cc_library_shared {
+ name: "libinputflinger",
+
+ srcs: [
+ "EventHub.cpp",
+ "InputApplication.cpp",
+ "InputDispatcher.cpp",
+ "InputListener.cpp",
+ "InputManager.cpp",
+ "InputReader.cpp",
+ "InputWindow.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libcrypto",
+ "libcutils",
+ "libinput",
+ "liblog",
+ "libutils",
+ "libui",
+ "libhardware_legacy",
+ ],
+
+ cflags: [
+ "-Wno-unused-parameter",
+ // TODO: Move inputflinger to its own process and mark it hidden
+ //-fvisibility=hidden
+ ],
+
+ export_include_dirs: ["."],
+}
+
+subdirs = [
+ "host",
+ "tests",
+]
diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk
deleted file mode 100644
index ed867d8..0000000
--- a/services/inputflinger/Android.mk
+++ /dev/null
@@ -1,49 +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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- EventHub.cpp \
- InputApplication.cpp \
- InputDispatcher.cpp \
- InputListener.cpp \
- InputManager.cpp \
- InputReader.cpp \
- InputWindow.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libcrypto \
- libcutils \
- libinput \
- liblog \
- libutils \
- libui \
- libhardware_legacy
-
-
-# TODO: Move inputflinger to its own process and mark it hidden
-#LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_MODULE := libinputflinger
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
new file mode 100644
index 0000000..b8e9bce
--- /dev/null
+++ b/services/inputflinger/host/Android.bp
@@ -0,0 +1,57 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+ name: "libinputflingerhost",
+
+ srcs: [
+ "InputFlinger.cpp",
+ "InputDriver.cpp",
+ "InputHost.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libcrypto",
+ "libcutils",
+ "libinput",
+ "liblog",
+ "libutils",
+ "libhardware",
+ ],
+
+ cflags: [
+ "-Wno-unused-parameter",
+ // TODO: Move inputflinger to its own process and mark it hidden
+ //-fvisibility=hidden
+ ],
+
+ export_include_dirs: ["."],
+}
+
+//#######################################################################
+// build input flinger executable
+cc_binary {
+ name: "inputflinger",
+
+ srcs: ["main.cpp"],
+
+ shared_libs: [
+ "libbinder",
+ "libinputflingerhost",
+ "libutils",
+ ],
+
+ init_rc: ["inputflinger.rc"],
+}
diff --git a/services/inputflinger/host/Android.mk b/services/inputflinger/host/Android.mk
deleted file mode 100644
index 0a7fc27..0000000
--- a/services/inputflinger/host/Android.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_SRC_FILES:= \
- InputFlinger.cpp \
- InputDriver.cpp \
- InputHost.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libcrypto \
- libcutils \
- libinput \
- liblog \
- libutils \
- libhardware
-
-
-# TODO: Move inputflinger to its own process and mark it hidden
-#LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_MODULE := libinputflingerhost
-
-include $(BUILD_SHARED_LIBRARY)
-
-########################################################################
-# build input flinger executable
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_SRC_FILES:= \
- main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libinputflingerhost \
- libutils
-
-LOCAL_MODULE := inputflinger
-LOCAL_INIT_RC := inputflinger.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
new file mode 100644
index 0000000..29d93f0
--- /dev/null
+++ b/services/inputflinger/tests/Android.bp
@@ -0,0 +1,23 @@
+// Build the unit tests.
+
+cc_test {
+ name: "inputflinger_tests",
+ srcs: [
+ "InputReader_test.cpp",
+ "InputDispatcher_test.cpp",
+ ],
+ test_per_src: true,
+ cflags: ["-Wno-unused-parameter"],
+ shared_libs = [
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libhardware",
+ "libhardware_legacy",
+ "libui",
+ "libskia",
+ "libinput",
+ "libinputflinger",
+ "libinputservice",
+ ],
+}
diff --git a/services/inputflinger/tests/Android.mk b/services/inputflinger/tests/Android.mk
deleted file mode 100644
index 4c43392..0000000
--- a/services/inputflinger/tests/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# Build the unit tests.
-test_src_files := \
- InputReader_test.cpp \
- InputDispatcher_test.cpp
-
-shared_libraries := \
- libcutils \
- liblog \
- libutils \
- libhardware \
- libhardware_legacy \
- libui \
- libskia \
- libinput \
- libinputflinger \
- libinputservice
-
-c_includes := \
- external/skia/include/core
-
-
-module_tags := tests
-
-$(foreach file,$(test_src_files), \
- $(eval include $(CLEAR_VARS)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
- $(eval LOCAL_C_INCLUDES := $(c_includes)) \
- $(eval LOCAL_CFLAGS += -Wno-unused-parameter) \
- $(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
- $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
- $(eval include $(BUILD_NATIVE_TEST)) \
-)
-
-# Build the manual test programs.
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 81f32cd..452c8c6 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -30,12 +30,7 @@
namespace android {
// ---------------------------------------------------------------------------
-BatteryService::BatteryService() {
- const sp<IServiceManager> sm(defaultServiceManager());
- if (sm != NULL) {
- const String16 name("batterystats");
- mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name));
- }
+BatteryService::BatteryService() : mBatteryStatService(nullptr) {
}
bool BatteryService::addSensor(uid_t uid, int handle) {
@@ -61,7 +56,7 @@
void BatteryService::enableSensorImpl(uid_t uid, int handle) {
- if (mBatteryStatService != 0) {
+ if (checkService()) {
if (addSensor(uid, handle)) {
int64_t identity = IPCThreadState::self()->clearCallingIdentity();
mBatteryStatService->noteStartSensor(uid, handle);
@@ -70,7 +65,7 @@
}
}
void BatteryService::disableSensorImpl(uid_t uid, int handle) {
- if (mBatteryStatService != 0) {
+ if (checkService()) {
if (removeSensor(uid, handle)) {
int64_t identity = IPCThreadState::self()->clearCallingIdentity();
mBatteryStatService->noteStopSensor(uid, handle);
@@ -80,7 +75,7 @@
}
void BatteryService::cleanupImpl(uid_t uid) {
- if (mBatteryStatService != 0) {
+ if (checkService()) {
Mutex::Autolock _l(mActivationsLock);
int64_t identity = IPCThreadState::self()->clearCallingIdentity();
for (size_t i=0 ; i<mActivations.size() ; i++) {
@@ -95,6 +90,17 @@
}
}
+bool BatteryService::checkService() {
+ if (mBatteryStatService == nullptr) {
+ const sp<IServiceManager> sm(defaultServiceManager());
+ if (sm != NULL) {
+ const String16 name("batterystats");
+ mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name));
+ }
+ }
+ return mBatteryStatService != nullptr;
+}
+
ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/BatteryService.h b/services/sensorservice/BatteryService.h
index 08ba857..43a750c 100644
--- a/services/sensorservice/BatteryService.h
+++ b/services/sensorservice/BatteryService.h
@@ -49,6 +49,7 @@
SortedVector<Info> mActivations;
bool addSensor(uid_t uid, int handle);
bool removeSensor(uid_t uid, int handle);
+ bool checkService();
public:
static void enableSensor(uid_t uid, int handle) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0de5abc..0a795aa 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1362,6 +1362,7 @@
// Wake us up to check if the frame has been received
setTransactionFlags(eTransactionNeeded);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
}
mPendingStates.push_back(mCurrentState);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5eea3d9..deeb456 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2292,8 +2292,7 @@
if (s.client != NULL) {
sp<IBinder> binder = IInterface::asBinder(s.client);
if (binder != NULL) {
- String16 desc(binder->getInterfaceDescriptor());
- if (desc == ISurfaceComposerClient::descriptor) {
+ if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
sp<Client> client( static_cast<Client *>(s.client.get()) );
transactionFlags |= setClientStateLocked(client, s.state);
}
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 6710bca..2d36b54 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -2203,8 +2203,7 @@
if (s.client != NULL) {
sp<IBinder> binder = IInterface::asBinder(s.client);
if (binder != NULL) {
- String16 desc(binder->getInterfaceDescriptor());
- if (desc == ISurfaceComposerClient::descriptor) {
+ if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
sp<Client> client( static_cast<Client *>(s.client.get()) );
transactionFlags |= setClientStateLocked(client, s.state);
}
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 3f077a2..f5be518 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -26,6 +26,7 @@
cc_library_static {
name: "vulkan_headers",
export_include_dirs: ["include"],
+ vendor_available: true,
}
subdirs = [
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 088d001..0616711 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
// API version (major.minor.patch)
define VERSION_MAJOR 1
define VERSION_MINOR 0
-define VERSION_PATCH 43
+define VERSION_PATCH 46
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -93,7 +93,7 @@
@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME "VK_ANDROID_native_buffer"
// 12
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 5
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 6
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME "VK_EXT_debug_report"
// 13
@@ -248,6 +248,10 @@
@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
+// 85
+@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+
// 86
@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
@@ -304,6 +308,10 @@
@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
+// 105
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_SPEC_VERSION 2
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
+
// 106
@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
@@ -1023,6 +1031,9 @@
//@extension("VK_KHR_push_descriptor") // 81
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
+ //@extension("VK_KHR_incremental_present") // 85
+ VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
+
//@extension("VK_KHR_descriptor_update_template") // 86
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
@@ -1158,6 +1169,21 @@
@extension("VK_KHR_surface") // 1
enum VkColorSpaceKHR {
VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0x00000000,
+
+ //@extension("VK_EXT_swapchain_colorspace") // 105
+ VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
+ VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
+ VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003,
+ VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
+ VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
+ VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
+ VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
+ VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
+ VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
+ VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
+ VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
+ VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
+ VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
}
@extension("VK_EXT_debug_report") // 12
@@ -1195,6 +1221,9 @@
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
+
+ //extension("VK_KHR_descriptor_update_template") // 86
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
}
@extension("VK_EXT_debug_report") // 12
@@ -3657,7 +3686,7 @@
@extension("VK_KHX_device_group_creation") // 71
class VkPhysicalDeviceGroupPropertiesKHX {
VkStructureType sType
- const void* pNext
+ void* pNext
u32 physicalDeviceCount
VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE_KHX] physicalDevices
VkBool32 subsetAllocation
@@ -3858,6 +3887,27 @@
u32 maxPushDescriptors
}
+@extension("VK_KHR_incremental_present") // 85
+class VkRectLayerKHR {
+ VkOffset2D offset
+ VkExtent2D extent
+ u32 layer
+}
+
+@extension("VK_KHR_incremental_present") // 85
+class VkPresentRegionKHR {
+ u32 rectangleCount
+ const VkRectLayerKHR* pRectangles
+}
+
+@extension("VK_KHR_incremental_present") // 85
+class VkPresentRegionsKHR {
+ VkStructureType sType
+ const void* pNext
+ u32 swapchainCount
+ const VkPresentRegionKHR* pRegions
+}
+
@extension("VK_KHR_descriptor_update_template") // 86
class VkDescriptorUpdateTemplateEntryKHR {
u32 dstBinding
@@ -4124,7 +4174,7 @@
@extension("VK_EXT_discard_rectangles") // 100
class VkPhysicalDeviceDiscardRectanglePropertiesEXT {
VkStructureType sType
- const void* pNext
+ void* pNext
u32 maxDiscardRectangles
}
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index dc1ede1..ef0c246 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,7 +43,7 @@
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 43
+#define VK_HEADER_VERSION 46
#define VK_NULL_HANDLE 0
@@ -281,6 +281,7 @@
VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHX = 1000078002,
VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHX = 1000079000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
+ VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
@@ -3298,6 +3299,19 @@
typedef enum VkColorSpaceKHR {
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
+ VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
+ VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
+ VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003,
+ VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
+ VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
+ VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
+ VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
+ VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
+ VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
+ VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
+ VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
+ VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
+ VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
@@ -3991,6 +4005,30 @@
const VkWriteDescriptorSet* pDescriptorWrites);
#endif
+#define VK_KHR_incremental_present 1
+#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+
+typedef struct VkRectLayerKHR {
+ VkOffset2D offset;
+ VkExtent2D extent;
+ uint32_t layer;
+} VkRectLayerKHR;
+
+typedef struct VkPresentRegionKHR {
+ uint32_t rectangleCount;
+ const VkRectLayerKHR* pRectangles;
+} VkPresentRegionKHR;
+
+typedef struct VkPresentRegionsKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const VkPresentRegionKHR* pRegions;
+} VkPresentRegionsKHR;
+
+
+
#define VK_KHR_descriptor_update_template 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplateKHR)
@@ -4066,7 +4104,7 @@
#define VK_EXT_debug_report 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 5
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 6
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
@@ -4105,6 +4143,7 @@
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
@@ -4761,7 +4800,7 @@
typedef struct VkPhysicalDeviceGroupPropertiesKHX {
VkStructureType sType;
- const void* pNext;
+ void* pNext;
uint32_t physicalDeviceCount;
VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE_KHX];
VkBool32 subsetAllocation;
@@ -4886,7 +4925,7 @@
-#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHX
#define VK_KHX_external_memory_win32 1
#define VK_KHX_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
#define VK_KHX_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHX_external_memory_win32"
@@ -4929,7 +4968,7 @@
HANDLE handle,
VkMemoryWin32HandlePropertiesKHX* pMemoryWin32HandleProperties);
#endif
-#endif /* VK_USE_PLATFORM_WIN32_KHR */
+#endif /* VK_USE_PLATFORM_WIN32_KHX */
#define VK_KHX_external_memory_fd 1
#define VK_KHX_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
@@ -5663,7 +5702,7 @@
typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT {
VkStructureType sType;
- const void* pNext;
+ void* pNext;
uint32_t maxDiscardRectangles;
} VkPhysicalDeviceDiscardRectanglePropertiesEXT;
@@ -5687,6 +5726,11 @@
const VkRect2D* pDiscardRectangles);
#endif
+#define VK_EXT_swapchain_colorspace 1
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 2
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
+
+
#define VK_EXT_hdr_metadata 1
#define VK_EXT_HDR_METADATA_SPEC_VERSION 1
#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 147cc56..e1f164a 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -14,7 +14,7 @@
// Headers module is in frameworks/native/vulkan/Android.bp.
ndk_library {
- name: "libvulkan.ndk",
+ name: "libvulkan",
symbol_file: "libvulkan.map.txt",
first_version: "24",
unversioned_until: "current",
@@ -69,6 +69,7 @@
"libziparchive",
],
shared_libs: [
+ "libgui",
"libhardware",
"libsync",
"libbase",
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 7610c01..ea6fadc 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -110,7 +110,7 @@
// clang-format on
-} // anonymous
+} // namespace
bool InitDispatchTable(
VkInstance instance,
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 56396f4..f9d3de1 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -21,10 +21,15 @@
#include <algorithm>
#include <array>
+#include <dlfcn.h>
#include <new>
#include <log/log.h>
+#include <android/dlext.h>
+#include <cutils/properties.h>
+#include <gui/GraphicsEnv.h>
+
#include "driver.h"
#include "stubhal.h"
@@ -126,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_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 8cbd398..e9cbceb 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -278,7 +278,7 @@
// clang-format on
};
-} // anonymous
+} // namespace
const ProcHook* GetProcHook(const char* name) {
const auto& begin = g_proc_hooks;