diff options
| -rw-r--r-- | cmds/atrace/atrace.rc | 2 | ||||
| -rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 287 | ||||
| -rw-r--r-- | cmds/dumpstate/dumpstate.rc | 8 | ||||
| -rw-r--r-- | cmds/dumpstate/utils.cpp | 3 | ||||
| -rw-r--r-- | include/binder/IPCThreadState.h | 1 | ||||
| -rw-r--r-- | include/gui/GraphicsEnv.h | 59 | ||||
| -rw-r--r-- | libs/binder/IPCThreadState.cpp | 162 | ||||
| -rw-r--r-- | libs/gui/Android.mk | 2 | ||||
| -rw-r--r-- | libs/gui/GLConsumer.cpp | 11 | ||||
| -rw-r--r-- | libs/gui/GraphicsEnv.cpp | 81 | ||||
| -rw-r--r-- | opengl/libs/EGL/Loader.cpp | 96 | ||||
| -rw-r--r-- | opengl/libs/EGL/Loader.h | 7 | ||||
| -rw-r--r-- | opengl/libs/EGL/eglApi.cpp | 7 | ||||
| -rw-r--r-- | opengl/libs/EGL/egl_display.cpp | 3 | ||||
| -rw-r--r-- | opengl/specs/EGL_ANDROID_create_native_client_buffer.txt | 11 | ||||
| -rw-r--r-- | services/sensorservice/BatteryService.cpp | 24 | ||||
| -rw-r--r-- | services/sensorservice/BatteryService.h | 1 | ||||
| -rw-r--r-- | services/sensorservice/SensorService.cpp | 11 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 1 | ||||
| -rw-r--r-- | vulkan/libvulkan/Android.mk | 2 | ||||
| -rw-r--r-- | vulkan/libvulkan/driver.cpp | 70 | ||||
| -rw-r--r-- | vulkan/libvulkan/swapchain.cpp | 2 |
22 files changed, 621 insertions, 230 deletions
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc index e3cc9da5f3..747cc69282 100644 --- a/cmds/atrace/atrace.rc +++ b/cmds/atrace/atrace.rc @@ -1,6 +1,6 @@ ## Permissions to allow system-wide tracing to the kernel trace buffer. ## -on fs +on post-fs # Allow writing to the kernel trace log. chmod 0222 /sys/kernel/debug/tracing/trace_marker diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 60460e0122..0929d9b9e9 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -34,8 +34,9 @@ #include <sys/wait.h> #include <unistd.h> -#include <android-base/stringprintf.h> #include <android-base/file.h> +#include <android-base/stringprintf.h> +#include <android-base/strings.h> #include <cutils/properties.h> #include "private/android_filesystem_config.h" @@ -385,6 +386,83 @@ static void dump_raft() { } } +/** + * 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); @@ -830,9 +908,63 @@ static void dump_iptables() { 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); @@ -867,42 +999,16 @@ static void dumpstate(const std::string& screenshot_path, const std::string& ver for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS"); for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)"); + /* Dump Bluetooth HCI logs */ + add_dir("/data/misc/bluetooth/logs", true); + if (!screenshot_path.empty()) { MYLOGI("taking late screenshot\n"); take_screenshot(screenshot_path); 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) { @@ -970,23 +1076,7 @@ static void dumpstate(const std::string& screenshot_path, const std::string& ver 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. */ @@ -1119,6 +1209,10 @@ static void dumpstate(const std::string& screenshot_path, const std::string& ver 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", @@ -1130,14 +1224,15 @@ static void dumpstate(const std::string& screenshot_path, const std::string& ver 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)" @@ -1234,6 +1329,8 @@ int main(int argc, char *argv[]) { 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); @@ -1274,9 +1371,10 @@ int main(int argc, char *argv[]) { 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; @@ -1373,6 +1471,9 @@ int main(int argc, char *argv[]) { 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: @@ -1482,48 +1583,60 @@ int main(int argc, char *argv[]) { // 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(); - } - - // 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); + 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(); + } - /* collect stack traces from Dalvik and native processes (needs root) */ - dump_traces_path = dump_traces(); + // 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(); - /* 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); - // 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); - // 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; + } - if (!drop_root_user()) { - return -1; + dumpstate(do_early_screenshot ? "": screenshot_path, version); } - dumpstate(do_early_screenshot ? "": screenshot_path, version); - /* close output if needed */ if (is_redirecting) { fclose(stdout); diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc index 3448e91088..336db9fcd1 100644 --- a/cmds/dumpstate/dumpstate.rc +++ b/cmds/dumpstate/dumpstate.rc @@ -46,3 +46,11 @@ service bugreportwear /system/bin/dumpstate -d -B -P -p -z \ 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 fd6413d562..af6c6660c4 100644 --- a/cmds/dumpstate/utils.cpp +++ b/cmds/dumpstate/utils.cpp @@ -828,7 +828,8 @@ bool drop_root_user() { } gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW, - AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC }; + 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; diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h index 1853cff235..7b826d6dcd 100644 --- a/include/binder/IPCThreadState.h +++ b/include/binder/IPCThreadState.h @@ -115,7 +115,6 @@ private: void* cookie); const sp<ProcessState> mProcess; - const pid_t mMyThreadId; Vector<BBinder*> mPendingStrongDerefs; Vector<RefBase::weakref_type*> mPendingWeakDerefs; diff --git a/include/gui/GraphicsEnv.h b/include/gui/GraphicsEnv.h new file mode 100644 index 0000000000..4c7366f094 --- /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/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index d90798f51e..eccc400c09 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -46,6 +46,7 @@ #define IF_LOG_COMMANDS() if (false) #define LOG_REMOTEREFS(...) #define IF_LOG_REMOTEREFS() if (false) + #define LOG_THREADPOOL(...) #define LOG_ONEWAY(...) @@ -152,7 +153,7 @@ static const void* printReturnCommand(TextOutput& out, const void* _cmd) return cmd; } out << kReturnStrings[cmdIndex]; - + switch (code) { case BR_TRANSACTION: case BR_REPLY: { @@ -160,12 +161,12 @@ static const void* printReturnCommand(TextOutput& out, const void* _cmd) cmd = (const int32_t *)printBinderTransactionData(out, cmd); out << dedent; } break; - + case BR_ACQUIRE_RESULT: { const int32_t res = *cmd++; out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); } break; - + case BR_INCREFS: case BR_ACQUIRE: case BR_RELEASE: @@ -174,7 +175,7 @@ static const void* printReturnCommand(TextOutput& out, const void* _cmd) const int32_t c = *cmd++; out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")"; } break; - + case BR_ATTEMPT_ACQUIRE: { const int32_t p = *cmd++; const int32_t b = *cmd++; @@ -194,7 +195,7 @@ static const void* printReturnCommand(TextOutput& out, const void* _cmd) // BR_TRANSACTION_COMPLETE, BR_FINISHED break; } - + out << endl; return cmd; } @@ -219,17 +220,17 @@ static const void* printCommand(TextOutput& out, const void* _cmd) cmd = (const int32_t *)printBinderTransactionData(out, cmd); out << dedent; } break; - + case BC_ACQUIRE_RESULT: { const int32_t res = *cmd++; out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); } break; - + case BC_FREE_BUFFER: { const int32_t buf = *cmd++; out << ": buffer=" << (void*)(long)buf; } break; - + case BC_INCREFS: case BC_ACQUIRE: case BC_RELEASE: @@ -237,20 +238,20 @@ static const void* printCommand(TextOutput& out, const void* _cmd) const int32_t d = *cmd++; out << ": desc=" << d; } break; - + case BC_INCREFS_DONE: case BC_ACQUIRE_DONE: { const int32_t b = *cmd++; const int32_t c = *cmd++; out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")"; } break; - + case BC_ATTEMPT_ACQUIRE: { const int32_t p = *cmd++; const int32_t d = *cmd++; out << ": desc=" << d << ", pri=" << p; } break; - + case BC_REQUEST_DEATH_NOTIFICATION: case BC_CLEAR_DEATH_NOTIFICATION: { const int32_t h = *cmd++; @@ -268,7 +269,7 @@ static const void* printCommand(TextOutput& out, const void* _cmd) // BC_EXIT_LOOPER break; } - + out << endl; return cmd; } @@ -288,12 +289,12 @@ restart: if (st) return st; return new IPCThreadState; } - + if (gShutdown) { ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n"); return NULL; } - + pthread_mutex_lock(&gTLSMutex); if (!gHaveTLS) { int key_create_value = pthread_key_create(&gTLS, threadDestructor); @@ -322,7 +323,7 @@ IPCThreadState* IPCThreadState::selfOrNull() void IPCThreadState::shutdown() { gShutdown = true; - + if (gHaveTLS) { // XXX Need to wait for all thread pool threads to exit! IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS); @@ -457,15 +458,6 @@ status_t IPCThreadState::getAndExecuteCommand() } pthread_cond_broadcast(&mProcess->mThreadCountDecrement); pthread_mutex_unlock(&mProcess->mThreadCountLock); - - // After executing the command, ensure that the thread is returned to the - // foreground cgroup before rejoining the pool. The driver takes care of - // restoring the priority, but doesn't do anything with cgroups so we - // need to take care of that here in userspace. Note that we do make - // sure to go in the foreground after executing a transaction, but - // there are other callbacks into user code that could have changed - // our group so we want to make absolutely sure it is put back. - set_sched_policy(mMyThreadId, SP_FOREGROUND); } return result; @@ -500,12 +492,7 @@ void IPCThreadState::joinThreadPool(bool isMain) LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); - - // This thread may have been spawned by a thread that was in the background - // scheduling group, so first we will make sure it is in the foreground - // one to avoid performing an initial transaction in the background. - set_sched_policy(mMyThreadId, SP_FOREGROUND); - + status_t result; do { processPendingDerefs(); @@ -517,7 +504,7 @@ void IPCThreadState::joinThreadPool(bool isMain) mProcess->mDriverFD, result); abort(); } - + // Let this thread exit the thread pool if it is no longer // needed and it is not the main process thread. if(result == TIMED_OUT && !isMain) { @@ -580,18 +567,18 @@ status_t IPCThreadState::transact(int32_t handle, << handle << " / code " << TypeCode(code) << ": " << indent << data << dedent << endl; } - + if (err == NO_ERROR) { LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); } - + if (err != NO_ERROR) { if (reply) reply->setError(err); return (mLastError = err); } - + if ((flags & TF_ONE_WAY) == 0) { #if 0 if (code == 4) { // relayout @@ -613,7 +600,7 @@ status_t IPCThreadState::transact(int32_t handle, ALOGI("<<<<<< RETURNING transaction %d", code); } #endif - + IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " @@ -624,7 +611,7 @@ status_t IPCThreadState::transact(int32_t handle, } else { err = waitForResponse(NULL, NULL); } - + return err; } @@ -664,14 +651,14 @@ status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) mOut.writeInt32(0); // xxx was thread priority mOut.writeInt32(handle); status_t result = UNKNOWN_ERROR; - + waitForResponse(NULL, &result); - + #if LOG_REFCOUNTS printf("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n", handle, result == NO_ERROR ? "SUCCESS" : "FAILURE"); #endif - + return result; #else (void)handle; @@ -706,7 +693,6 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), - mMyThreadId(gettid()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { @@ -726,7 +712,7 @@ status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags) status_t statusBuffer; err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer); if (err < NO_ERROR) return err; - + return waitForResponse(NULL, NULL); } @@ -740,9 +726,9 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) err = mIn.errorCheck(); if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; - + cmd = (uint32_t)mIn.readInt32(); - + IF_LOG_COMMANDS() { alog << "Processing waitForResponse Command: " << getReturnString(cmd) << endl; @@ -752,7 +738,7 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) case BR_TRANSACTION_COMPLETE: if (!reply && !acquireResult) goto finish; break; - + case BR_DEAD_REPLY: err = DEAD_OBJECT; goto finish; @@ -760,7 +746,7 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) case BR_FAILED_REPLY: err = FAILED_TRANSACTION; goto finish; - + case BR_ACQUIRE_RESULT: { ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); @@ -769,7 +755,7 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) *acquireResult = result ? NO_ERROR : INVALID_OPERATION; } goto finish; - + case BR_REPLY: { binder_transaction_data tr; @@ -817,7 +803,7 @@ finish: if (reply) reply->setError(err); mLastError = err; } - + return err; } @@ -826,17 +812,17 @@ status_t IPCThreadState::talkWithDriver(bool doReceive) if (mProcess->mDriverFD <= 0) { return -EBADF; } - + binder_write_read bwr; - + // Is the read buffer empty? const bool needRead = mIn.dataPosition() >= mIn.dataSize(); - + // We don't want to write anything if we are still reading // from data left in the input buffer and the caller // has requested to read the next data. const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; - + bwr.write_size = outAvail; bwr.write_buffer = (uintptr_t)mOut.data(); @@ -862,7 +848,7 @@ status_t IPCThreadState::talkWithDriver(bool doReceive) alog << "Size of receive buffer: " << bwr.read_size << ", needRead: " << needRead << ", doReceive: " << doReceive << endl; } - + // Return immediately if there is nothing to do. if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR; @@ -918,7 +904,7 @@ status_t IPCThreadState::talkWithDriver(bool doReceive) } return NO_ERROR; } - + return err; } @@ -934,7 +920,7 @@ status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, tr.cookie = 0; tr.sender_pid = 0; tr.sender_euid = 0; - + const status_t err = data.errorCheck(); if (err == NO_ERROR) { tr.data_size = data.ipcDataSize(); @@ -951,10 +937,10 @@ status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, } else { return (mLastError = err); } - + mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr)); - + return NO_ERROR; } @@ -970,15 +956,15 @@ status_t IPCThreadState::executeCommand(int32_t cmd) BBinder* obj; RefBase::weakref_type* refs; status_t result = NO_ERROR; - + switch ((uint32_t)cmd) { case BR_ERROR: result = mIn.readInt32(); break; - + case BR_OK: break; - + case BR_ACQUIRE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); @@ -994,7 +980,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mOut.writePointer((uintptr_t)refs); mOut.writePointer((uintptr_t)obj); break; - + case BR_RELEASE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); @@ -1007,7 +993,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) } mPendingStrongDerefs.push(obj); break; - + case BR_INCREFS: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); @@ -1016,7 +1002,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mOut.writePointer((uintptr_t)refs); mOut.writePointer((uintptr_t)obj); break; - + case BR_DECREFS: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); @@ -1028,22 +1014,22 @@ status_t IPCThreadState::executeCommand(int32_t cmd) // refs, obj, refs->refBase()); mPendingWeakDerefs.push(refs); break; - + case BR_ATTEMPT_ACQUIRE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); - + { const bool success = refs->attemptIncStrong(mProcess.get()); ALOG_ASSERT(success && refs->refBase() == obj, "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)", refs, obj, refs->refBase()); - + mOut.writeInt32(BC_ACQUIRE_RESULT); mOut.writeInt32((int32_t)success); } break; - + case BR_TRANSACTION: { binder_transaction_data tr; @@ -1051,14 +1037,14 @@ status_t IPCThreadState::executeCommand(int32_t cmd) ALOG_ASSERT(result == NO_ERROR, "Not enough command data for brTRANSACTION"); if (result != NO_ERROR) break; - + Parcel buffer; buffer.ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer, this); - + const pid_t origPid = mCallingPid; const uid_t origUid = mCallingUid; const int32_t origStrictModePolicy = mStrictModePolicy; @@ -1068,26 +1054,6 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingUid = tr.sender_euid; mLastTransactionBinderFlags = tr.flags; - int curPrio = getpriority(PRIO_PROCESS, mMyThreadId); - if (gDisableBackgroundScheduling) { - if (curPrio > ANDROID_PRIORITY_NORMAL) { - // We have inherited a reduced priority from the caller, but do not - // want to run in that state in this process. The driver set our - // priority already (though not our scheduling class), so bounce - // it back to the default before invoking the transaction. - setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL); - } - } else { - if (curPrio >= ANDROID_PRIORITY_BACKGROUND) { - // We want to use the inherited priority from the caller. - // Ensure this thread is in the background scheduling class, - // since the driver won't modify scheduling classes for us. - // The scheduling group is reset to default by the caller - // once this method returns after the transaction is complete. - set_sched_policy(mMyThreadId, SP_BACKGROUND); - } - } - //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); Parcel reply; @@ -1121,7 +1087,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n", // mCallingPid, origPid, origUid); - + if ((tr.flags & TF_ONE_WAY) == 0) { LOG_ONEWAY("Sending reply to %d!", mCallingPid); if (error < NO_ERROR) reply.setError(error); @@ -1129,7 +1095,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) } else { LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); } - + mCallingPid = origPid; mCallingUid = origUid; mStrictModePolicy = origStrictModePolicy; @@ -1140,10 +1106,10 @@ status_t IPCThreadState::executeCommand(int32_t cmd) alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " << tr.target.ptr << ": " << indent << reply << dedent << endl; } - + } break; - + case BR_DEAD_BINDER: { BpBinder *proxy = (BpBinder*)mIn.readPointer(); @@ -1151,24 +1117,24 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mOut.writeInt32(BC_DEAD_BINDER_DONE); mOut.writePointer((uintptr_t)proxy); } break; - + case BR_CLEAR_DEATH_NOTIFICATION_DONE: { BpBinder *proxy = (BpBinder*)mIn.readPointer(); proxy->getWeakRefs()->decWeak(proxy); } break; - + case BR_FINISHED: result = TIMED_OUT; break; - + case BR_NOOP: break; - + case BR_SPAWN_LOOPER: mProcess->spawnPooledThread(false); break; - + default: printf("*** BAD COMMAND %d received from Binder driver\n", cmd); result = UNKNOWN_ERROR; @@ -1178,7 +1144,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) if (result != NO_ERROR) { mLastError = result; } - + return result; } diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index 46feb1cc36..9e2fc2b040 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -54,6 +54,7 @@ LOCAL_SRC_FILES := \ DisplayEventReceiver.cpp \ GLConsumer.cpp \ GraphicBufferAlloc.cpp \ + GraphicsEnv.cpp \ GuiConfig.cpp \ IDisplayEventConnection.cpp \ IGraphicBufferAlloc.cpp \ @@ -75,6 +76,7 @@ LOCAL_SRC_FILES := \ SyncFeatures.cpp \ LOCAL_SHARED_LIBRARIES := \ + libnativeloader \ libbinder \ libcutils \ libEGL \ diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index aa0db4506c..10e999c228 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -1228,14 +1228,19 @@ EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, EGL_NONE, }; if (!crop.isValid()) { - // No crop rect to set, so terminate the attrib array before the crop. - attrs[2] = EGL_NONE; + // No crop rect to set, so leave the crop out of the attrib array. Make + // sure to propagate the protected content attrs if they are set. + attrs[2] = attrs[10]; + attrs[3] = attrs[11]; + attrs[4] = EGL_NONE; } else if (!isEglImageCroppable(crop)) { // The crop rect is not at the origin, so we can't set the crop on the // EGLImage because that's not allowed by the EGL_ANDROID_image_crop // extension. In the future we can add a layered extension that // removes this restriction if there is hardware that can support it. - attrs[2] = EGL_NONE; + attrs[2] = attrs[10]; + attrs[3] = attrs[11]; + attrs[4] = EGL_NONE; } eglInitialize(dpy, 0, 0); EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, diff --git a/libs/gui/GraphicsEnv.cpp b/libs/gui/GraphicsEnv.cpp new file mode 100644 index 0000000000..68f0f988e2 --- /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/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index 49f501d3a6..ca5e6e8180 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 <stdlib.h> #include <stdio.h> @@ -23,8 +27,10 @@ #include <limits.h> #include <dirent.h> +#include <android/dlext.h> #include <cutils/log.h> #include <cutils/properties.h> +#include <utils/Trace.h> #include <EGL/egl.h> @@ -114,6 +120,11 @@ static char const * getProcessCmdline() { 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 @@ status_t Loader::driver_t::set(void* hnd, int32_t api) // ---------------------------------------------------------------------------- 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 @@ static void setEmulatorGlesValue(void) { void* Loader::open(egl_connection_t* cnx) { + ATRACE_CALL(); + void* dso; driver_t* hnd = 0; @@ -253,6 +282,8 @@ void Loader::init_api(void* dso, __eglMustCastToProperFunctionPointerType* curr, getProcAddressType getProcAddress) { + ATRACE_CALL(); + const ssize_t SIZE = 256; char scrap[SIZE]; while (*api) { @@ -304,9 +335,8 @@ void Loader::init_api(void* dso, } } -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 @@ void *Loader::load_driver(const char* kind, } 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 @@ void *Loader::load_driver(const char* kind, 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 8cefe32764..04a8e413ad 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 @@ class Loader : public Singleton<Loader> }; 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 f41e6e2311..436ea30800 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -272,6 +272,7 @@ static inline EGLContext getContext() { return egl_tls_t::getContext(); } EGLDisplay eglGetDisplay(EGLNativeDisplayType display) { + ATRACE_CALL(); clearError(); uintptr_t index = reinterpret_cast<uintptr_t>(display); @@ -1848,12 +1849,6 @@ EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list) if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) { usage |= GRALLOC_USAGE_HW_TEXTURE; } - // The buffer must be used for either a texture or a - // renderbuffer. - if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) && - (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) { - return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); - } break; default: return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 1e39aae40d..acd70d19b4 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::getFromNativeDisplay(EGLNativeDisplayType disp) { EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) { Mutex::Autolock _l(lock); + ATRACE_CALL(); // get our driver loader Loader& loader(Loader::getInstance()); diff --git a/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt index a6fae80d7d..51c6c61782 100644 --- a/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt +++ b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt @@ -124,12 +124,10 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) desirable) do not route the entire composition to the external sink. EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID: The buffer will be - used to create a renderbuffer. This flag must not be set if - EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID is set. + used to create a color-renderable texture. EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID: The buffer will be used to - create a texture. This flag must not be set if - EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID is set. + create a filterable texture. Errors @@ -149,11 +147,6 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) with the value of EGL_FORMAT, the error EGL_BAD_PARAMETER is Generated. - * If both the EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID and - EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID are set in the value of - EGL_NATIVE_BUFFER_USAGE_ANDROID, the error EGL_BAD_PARAMETER is - Generated." - Issues 1. Should this extension define what combinations of formats and usage flags diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp index 81f32cdc58..452c8c64b0 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 @@ bool BatteryService::removeSensor(uid_t uid, int handle) { 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::enableSensorImpl(uid_t uid, int handle) { } } 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::disableSensorImpl(uid_t uid, int handle) { } 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 @@ void BatteryService::cleanupImpl(uid_t uid) { } } +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 08ba857518..43a750c6c2 100644 --- a/services/sensorservice/BatteryService.h +++ b/services/sensorservice/BatteryService.h @@ -49,6 +49,7 @@ class BatteryService : public Singleton<BatteryService> { 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/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 614a9b11b9..99da2c4974 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -868,7 +868,7 @@ void SensorService::makeUuidsIntoIdsForSensorList(Vector<Sensor> &sensorList) co } } -Vector<Sensor> SensorService::getSensorList(const String16& /* opPackageName */) { +Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) { char value[PROPERTY_VALUE_MAX]; property_get("debug.sensors", value, "0"); const Vector<Sensor>& initialSensorList = (atoi(value)) ? @@ -876,7 +876,14 @@ Vector<Sensor> SensorService::getSensorList(const String16& /* opPackageName */) Vector<Sensor> accessibleSensorList; for (size_t i = 0; i < initialSensorList.size(); i++) { Sensor sensor = initialSensorList[i]; - accessibleSensorList.add(sensor); + if (canAccessSensor(sensor, "getSensorList", opPackageName)) { + accessibleSensorList.add(sensor); + } else { + ALOGI("Skipped sensor %s because it requires permission %s and app op %d", + sensor.getName().string(), + sensor.getRequiredPermission().string(), + sensor.getRequiredAppOp()); + } } makeUuidsIntoIdsForSensorList(accessibleSensorList); return accessibleSensorList; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index dfece935b1..3ffa6554ad 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1364,6 +1364,7 @@ void Layer::pushPendingState() { // Wake us up to check if the frame has been received setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); } mPendingStates.push_back(mCurrentState); } diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk index d2e28ff665..b7d6791a4e 100644 --- a/vulkan/libvulkan/Android.mk +++ b/vulkan/libvulkan/Android.mk @@ -51,7 +51,7 @@ LOCAL_SRC_FILES := \ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := libziparchive -LOCAL_SHARED_LIBRARIES := libhardware libsync libbase liblog libutils libcutils libz +LOCAL_SHARED_LIBRARIES := libgui libhardware libsync libbase liblog libutils libcutils libz LOCAL_MODULE := libvulkan include $(BUILD_SHARED_LIBRARY) diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 25552724d5..741a0ce15c 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -18,10 +18,15 @@ #include <string.h> #include <algorithm> #include <array> +#include <dlfcn.h> #include <new> #include <malloc.h> #include <sys/prctl.h> +#include <android/dlext.h> +#include <cutils/properties.h> +#include <gui/GraphicsEnv.h> + #include "driver.h" #include "stubhal.h" @@ -123,17 +128,74 @@ class CreateInfoWrapper { 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/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index adc7d5cf1c..03d37fa895 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -719,6 +719,8 @@ void DestroySwapchainKHR(VkDevice device, const VkAllocationCallbacks* allocator) { const auto& dispatch = GetData(device).driver; Swapchain* swapchain = SwapchainFromHandle(swapchain_handle); + if (!swapchain) + return; bool active = swapchain->surface.swapchain_handle == swapchain_handle; ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr; |