Surface: Add force disconnection method.
am: 97b9c86338
Change-Id: Ia9f9dbdcbd9527d54dacb2cdc90eda443230e8d9
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index facf300..5885738 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -102,6 +102,7 @@
{ "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } },
{ "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } },
{ "database", "Database", ATRACE_TAG_DATABASE, { } },
+ { "network", "Network", ATRACE_TAG_NETWORK, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 791a7c4..7a9f9ad 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -14,7 +14,7 @@
LOCAL_MODULE := dumpstate
-LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux libbase
+LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux libbase libhardware_legacy
# ZipArchive support, the order matters here to get all symbols.
LOCAL_STATIC_LIBRARIES := libziparchive libz libmincrypt
LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 23629b3..97dfd92 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -22,6 +22,7 @@
#include <memory>
#include <regex>
#include <set>
+#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -35,7 +36,9 @@
#include <unistd.h>
#include <android-base/stringprintf.h>
+#include <android-base/file.h>
#include <cutils/properties.h>
+#include <hardware_legacy/power.h>
#include "private/android_filesystem_config.h"
@@ -81,6 +84,7 @@
#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];
@@ -179,6 +183,136 @@
closedir(d);
}
+// return pid of a userspace process. If not found or error, return 0.
+static unsigned int pid_of_process(const char* ps_name) {
+ DIR *proc_dir;
+ struct dirent *ps;
+ unsigned int pid;
+ std::string cmdline;
+
+ if (!(proc_dir = opendir("/proc"))) {
+ MYLOGE("Can't open /proc\n");
+ return 0;
+ }
+
+ while ((ps = readdir(proc_dir))) {
+ if (!(pid = atoi(ps->d_name))) {
+ continue;
+ }
+ android::base::ReadFileToString("/proc/"
+ + std::string(ps->d_name) + "/cmdline", &cmdline);
+ if (cmdline.find(ps_name) == std::string::npos) {
+ continue;
+ } else {
+ closedir(proc_dir);
+ return pid;
+ }
+ }
+ closedir(proc_dir);
+ return 0;
+}
+
+// dump anrd's trace and add to the zip file.
+// 1. check if anrd is running on this device.
+// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
+// 3. wait until the trace generation completes and add to the zip file.
+static bool dump_anrd_trace() {
+ unsigned int pid;
+ char buf[50], path[PATH_MAX];
+ struct dirent *trace;
+ struct stat st;
+ DIR *trace_dir;
+ int retry = 5;
+ long max_ctime = 0, old_mtime;
+ long long cur_size = 0;
+ const char *trace_path = "/data/misc/anrd/";
+
+ if (!zip_writer) {
+ MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
+ return false;
+ }
+
+ // find anrd's pid if it is running.
+ pid = pid_of_process("/system/xbin/anrd");
+
+ if (pid > 0) {
+ if (stat(trace_path, &st) == 0) {
+ old_mtime = st.st_mtime;
+ } else {
+ MYLOGE("Failed to find: %s\n", trace_path);
+ return false;
+ }
+
+ // send SIGUSR1 to the anrd to generate a trace.
+ sprintf(buf, "%u", pid);
+ if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
+ MYLOGE("anrd signal timed out. Please manually collect trace\n");
+ return false;
+ }
+
+ while (retry-- > 0 && old_mtime == st.st_mtime) {
+ sleep(1);
+ stat(trace_path, &st);
+ }
+
+ if (retry < 0 && old_mtime == st.st_mtime) {
+ MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
+ return false;
+ }
+
+ // identify the trace file by its creation time.
+ if (!(trace_dir = opendir(trace_path))) {
+ MYLOGE("Can't open trace file under %s\n", trace_path);
+ }
+ while ((trace = readdir(trace_dir))) {
+ if (strcmp(trace->d_name, ".") == 0
+ || strcmp(trace->d_name, "..") == 0) {
+ continue;
+ }
+ sprintf(path, "%s%s", trace_path, trace->d_name);
+ if (stat(path, &st) == 0) {
+ if (st.st_ctime > max_ctime) {
+ max_ctime = st.st_ctime;
+ sprintf(buf, "%s", trace->d_name);
+ }
+ }
+ }
+ closedir(trace_dir);
+
+ // Wait until the dump completes by checking the size of the trace.
+ if (max_ctime > 0) {
+ sprintf(path, "%s%s", trace_path, buf);
+ while(true) {
+ sleep(1);
+ if (stat(path, &st) == 0) {
+ if (st.st_size == cur_size) {
+ break;
+ } else if (st.st_size > cur_size) {
+ cur_size = st.st_size;
+ } else {
+ return false;
+ }
+ } else {
+ MYLOGE("Cant stat() %s anymore\n", path);
+ return false;
+ }
+ }
+ // Add to the zip file.
+ if (!add_zip_entry("anrd_trace.txt", path)) {
+ MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
+ } else {
+ if (remove(path)) {
+ MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
+ }
+ return true;
+ }
+ } else {
+ MYLOGE("Can't stats any trace file under %s\n", trace_path);
+ }
+ }
+ return false;
+}
+
static void dump_systrace() {
if (!zip_writer) {
MYLOGD("Not dumping systrace because zip_writer is not set\n");
@@ -1016,11 +1150,31 @@
VERSION_DEFAULT.c_str());
}
-static void sigpipe_handler(int n) {
- // don't complain to stderr or stdout
+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();
_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.
*/
@@ -1088,7 +1242,6 @@
}
int main(int argc, char *argv[]) {
- struct sigaction sigact;
int do_add_date = 0;
int do_zip_file = 0;
int do_vibrate = 1;
@@ -1105,6 +1258,14 @@
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");
@@ -1113,11 +1274,6 @@
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);
@@ -1348,7 +1504,11 @@
print_header(version);
// Dumps systrace right away, otherwise it will be filled with unnecessary events.
- dump_systrace();
+ // 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();
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index fd6413d..1035cde 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -828,7 +828,7 @@
}
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_WAKELOCK };
if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
return false;
@@ -849,8 +849,10 @@
capheader.version = _LINUX_CAPABILITY_VERSION_3;
capheader.pid = 0;
- 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[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[0].inheritable = 0;
capdata[1].inheritable = 0;
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 2014e99..4ed8997 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -99,23 +99,64 @@
return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
}
-static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid,
- const char* pkgname, const char* seinfo) {
+/**
+ * Perform restorecon of the given path, but only perform recursive restorecon
+ * if the label of that top-level file actually changed. This can save us
+ * significant time by avoiding no-op traversals of large filesystem trees.
+ */
+static int restorecon_app_data_lazy(const char* path, const char* seinfo, uid_t uid) {
+ int res = 0;
+ char* before = nullptr;
+ char* after = nullptr;
+
+ // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by
+ // libselinux. Not needed here.
+
+ if (lgetfilecon(path, &before) < 0) {
+ PLOG(ERROR) << "Failed before getfilecon for " << path;
+ goto fail;
+ }
+ if (selinux_android_restorecon_pkgdir(path, seinfo, uid, 0) < 0) {
+ PLOG(ERROR) << "Failed top-level restorecon for " << path;
+ goto fail;
+ }
+ if (lgetfilecon(path, &after) < 0) {
+ PLOG(ERROR) << "Failed after getfilecon for " << path;
+ goto fail;
+ }
+
+ // If the initial top-level restorecon above changed the label, then go
+ // back and restorecon everything recursively
+ if (strcmp(before, after)) {
+ LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path
+ << "; running recursive restorecon";
+ if (selinux_android_restorecon_pkgdir(path, seinfo, uid,
+ SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
+ PLOG(ERROR) << "Failed recursive restorecon for " << path;
+ goto fail;
+ }
+ }
+
+ goto done;
+fail:
+ res = -1;
+done:
+ free(before);
+ free(after);
+ return res;
+}
+
+static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) {
if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
PLOG(ERROR) << "Failed to prepare " << path;
return -1;
}
- if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) {
- PLOG(ERROR) << "Failed to setfilecon " << path;
- return -1;
- }
return 0;
}
static int prepare_app_dir(const std::string& parent, const char* name, mode_t target_mode,
- uid_t uid, const char* pkgname, const char* seinfo) {
- return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid, pkgname,
- seinfo);
+ uid_t uid) {
+ return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid);
}
int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
@@ -124,9 +165,14 @@
mode_t target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
if (flags & FLAG_STORAGE_CE) {
auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
- if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo) ||
- prepare_app_dir(path, "cache", 0771, uid, pkgname, seinfo) ||
- prepare_app_dir(path, "code_cache", 0771, uid, pkgname, seinfo)) {
+ if (prepare_app_dir(path, target_mode, uid) ||
+ prepare_app_dir(path, "cache", 0771, uid) ||
+ prepare_app_dir(path, "code_cache", 0771, uid)) {
+ return -1;
+ }
+
+ // Consider restorecon over contents if label changed
+ if (restorecon_app_data_lazy(path.c_str(), seinfo, uid)) {
return -1;
}
@@ -139,11 +185,16 @@
}
if (flags & FLAG_STORAGE_DE) {
auto path = create_data_user_de_package_path(uuid, userid, pkgname);
- if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo)) {
+ if (prepare_app_dir(path, target_mode, uid)) {
// TODO: include result once 25796509 is fixed
return 0;
}
+ // Consider restorecon over contents if label changed
+ if (restorecon_app_data_lazy(path.c_str(), seinfo, uid)) {
+ return -1;
+ }
+
if (property_get_bool("dalvik.vm.usejitprofiles")) {
const std::string profile_path = create_data_user_profile_package_path(userid, pkgname);
// read-write-execute only for the app user.
@@ -2186,6 +2237,9 @@
bool art_success = true;
if (!a_image_path.empty()) {
art_success = move_ab_path(b_image_path, a_image_path);
+ if (!art_success) {
+ unlink(a_image_path.c_str());
+ }
}
success = art_success || kIgnoreAppImageFailure;
@@ -2199,5 +2253,35 @@
return success ? 0 : -1;
}
+bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir) {
+ // Delete the oat/odex file.
+ char out_path[PKG_PATH_MAX];
+ if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_path)) {
+ return false;
+ }
+
+ // In case of a permission failure report the issue. Otherwise just print a warning.
+ auto unlink_and_check = [](const char* path) -> bool {
+ int result = unlink(path);
+ if (result != 0) {
+ if (errno == EACCES || errno == EPERM) {
+ PLOG(ERROR) << "Could not unlink " << path;
+ return false;
+ }
+ PLOG(WARNING) << "Could not unlink " << path;
+ }
+ return true;
+ };
+
+ // Delete the oat/odex file.
+ bool return_value_oat = unlink_and_check(out_path);
+
+ // Derive and delete the app image.
+ bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
+
+ // Report success.
+ return return_value_oat && return_value_art;
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index e990f1b..ba27517 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -85,6 +85,9 @@
// Move a B version over to the A location. Only works for oat_dir != nullptr.
int move_ab(const char *apk_path, const char *instruction_set, const char* oat_dir);
+// Delete odex files generated by dexopt.
+bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir);
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index facbc72..8f883db 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -418,6 +418,11 @@
return move_ab(arg[0], arg[1], arg[2]);
}
+static int do_delete_odex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+ // apk_path, instruction_set, oat_dir
+ return delete_odex(arg[0], arg[1], arg[2]) ? 0 : -1;
+}
+
struct cmdinfo {
const char *name;
unsigned numargs;
@@ -453,6 +458,7 @@
{ "move_ab", 3, do_move_ab },
{ "merge_profiles", 2, do_merge_profiles },
{ "dump_profiles", 3, do_dump_profiles },
+ { "delete_odex", 3, do_delete_odex },
};
static int readx(int s, void *_buf, int count)
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 4ff00b5..84230da 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -24,6 +24,7 @@
<feature name="android.hardware.location" />
<!-- devices supporting compass/magnitometer sensor must include
android.hardware.sensor.compass.xml -->
+ <feature name="android.hardware.sensor.gyroscope" />
<feature name="android.hardware.sensor.accelerometer" />
<feature name="android.hardware.bluetooth" />
<feature name="android.hardware.touchscreen" />
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index dddcf92..5311c59 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -115,13 +115,13 @@
EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255));
EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
- EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255));
- EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255));
- EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255));
- EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255));
- EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255));
- EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255));
- EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255));
+ EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255, 3));
+ EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255, 3));
+ EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255, 3));
+ EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255, 3));
+ EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255, 3));
+ EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255, 3));
+ EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255, 3));
}
TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp
index 754b603..62e9ce0 100644
--- a/services/sensorservice/RecentEventLogger.cpp
+++ b/services/sensorservice/RecentEventLogger.cpp
@@ -31,7 +31,7 @@
RecentEventLogger::RecentEventLogger(int sensorType) :
mSensorType(sensorType), mEventSize(eventSizeBySensorType(mSensorType)),
- mRecentEvents(logSizeBySensorType(sensorType)) {
+ mRecentEvents(logSizeBySensorType(sensorType)), mMaskData(false) {
// blank
}
@@ -60,18 +60,30 @@
(int) ns2ms(ev.mWallTime.tv_nsec));
// data
- if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
- buffer.appendFormat("%" PRIu64 ", ", ev.mEvent.u64.step_counter);
- } else {
- for (size_t k = 0; k < mEventSize; ++k) {
- buffer.appendFormat("%.2f, ", ev.mEvent.data[k]);
+ if (!mMaskData) {
+ if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+ buffer.appendFormat("%" PRIu64 ", ", ev.mEvent.u64.step_counter);
+ } else {
+ for (size_t k = 0; k < mEventSize; ++k) {
+ buffer.appendFormat("%.2f, ", ev.mEvent.data[k]);
+ }
}
+ } else {
+ buffer.append("[value masked]");
}
buffer.append("\n");
}
return std::string(buffer.string());
}
+void RecentEventLogger::setFormat(std::string format) {
+ if (format == "mask_data" ) {
+ mMaskData = true;
+ } else {
+ mMaskData = false;
+ }
+}
+
bool RecentEventLogger::populateLastEvent(sensors_event_t *event) const {
std::lock_guard<std::mutex> lk(mLock);
diff --git a/services/sensorservice/RecentEventLogger.h b/services/sensorservice/RecentEventLogger.h
index 4f9bc4a..8b15e5a 100644
--- a/services/sensorservice/RecentEventLogger.h
+++ b/services/sensorservice/RecentEventLogger.h
@@ -43,6 +43,7 @@
// Dumpable interface
virtual std::string dump() const override;
+ virtual void setFormat(std::string format) override;
protected:
struct SensorEventLog {
@@ -57,6 +58,8 @@
mutable std::mutex mLock;
RingBuffer<SensorEventLog> mRecentEvents;
+ bool mMaskData;
+
private:
static size_t logSizeBySensorType(int sensorType);
};
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index c1e1bad..f2f1444 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -206,7 +206,7 @@
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch,
- SensorEventConnection const * const * mapFlushEventsToConnections) {
+ wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
// filter out events not for this connection
int count = 0;
Mutex::Autolock _l(mConnectionLock);
@@ -234,7 +234,7 @@
FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
// Check if there is a pending flush_complete event for this sensor on this connection.
if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
- this == mapFlushEventsToConnections[i]) {
+ mapFlushEventsToConnections[i] == this) {
flushInfo.mFirstFlushPending = false;
ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
buffer[i].meta_data.sensor);
@@ -255,7 +255,7 @@
// from the same sensor_handle AND the current connection is mapped to the
// corresponding flush_complete_event.
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
- if (this == mapFlushEventsToConnections[i]) {
+ if (mapFlushEventsToConnections[i] == this) {
scratch[count++] = buffer[i];
}
++i;
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index b796cc0..883c16e 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -52,7 +52,7 @@
bool isDataInjectionMode, const String16& opPackageName);
status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
- SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
+ wp<const SensorEventConnection> const * mapFlushEventsToConnections = NULL);
bool hasSensor(int32_t handle) const;
bool hasAnySensor() const;
bool hasOneShotSensors() const;
diff --git a/services/sensorservice/SensorRecord.cpp b/services/sensorservice/SensorRecord.cpp
index 644cfb0..53fb9de 100644
--- a/services/sensorservice/SensorRecord.cpp
+++ b/services/sensorservice/SensorRecord.cpp
@@ -21,13 +21,13 @@
namespace android {
SensorService::SensorRecord::SensorRecord(
- const sp<SensorEventConnection>& connection)
+ const sp<const SensorEventConnection>& connection)
{
mConnections.add(connection);
}
bool SensorService::SensorRecord::addConnection(
- const sp<SensorEventConnection>& connection)
+ const sp<const SensorEventConnection>& connection)
{
if (mConnections.indexOf(connection) < 0) {
mConnections.add(connection);
@@ -37,16 +37,16 @@
}
bool SensorService::SensorRecord::removeConnection(
- const wp<SensorEventConnection>& connection)
+ const wp<const SensorEventConnection>& connection)
{
ssize_t index = mConnections.indexOf(connection);
if (index >= 0) {
mConnections.removeItemsAt(index, 1);
}
// Remove this connections from the queue of flush() calls made on this sensor.
- for (Vector< wp<SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
+ for (Vector< wp<const SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
it != mPendingFlushConnections.end(); ) {
- if (it->unsafe_get() == connection.unsafe_get()) {
+ if (*it == connection) {
it = mPendingFlushConnections.erase(it);
} else {
++it;
@@ -56,7 +56,7 @@
}
void SensorService::SensorRecord::addPendingFlushConnection(
- const sp<SensorEventConnection>& connection) {
+ const sp<const SensorEventConnection>& connection) {
mPendingFlushConnections.add(connection);
}
@@ -66,10 +66,10 @@
}
}
-SensorService::SensorEventConnection *
+wp<const SensorService::SensorEventConnection>
SensorService::SensorRecord::getFirstPendingFlushConnection() {
if (mPendingFlushConnections.size() > 0) {
- return mPendingFlushConnections[0].unsafe_get();
+ return mPendingFlushConnections[0];
}
return NULL;
}
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
index 29b970d..5a35410 100644
--- a/services/sensorservice/SensorRecord.h
+++ b/services/sensorservice/SensorRecord.h
@@ -25,20 +25,20 @@
class SensorService::SensorRecord {
public:
- SensorRecord(const sp<SensorEventConnection>& connection);
- bool addConnection(const sp<SensorEventConnection>& connection);
- bool removeConnection(const wp<SensorEventConnection>& connection);
+ SensorRecord(const sp<const SensorEventConnection>& connection);
+ bool addConnection(const sp<const SensorEventConnection>& connection);
+ bool removeConnection(const wp<const SensorEventConnection>& connection);
size_t getNumConnections() const { return mConnections.size(); }
- void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+ void addPendingFlushConnection(const sp<const SensorEventConnection>& connection);
void removeFirstPendingFlushConnection();
- SensorEventConnection * getFirstPendingFlushConnection();
+ wp<const SensorEventConnection> getFirstPendingFlushConnection();
void clearAllPendingFlushConnections();
private:
- SortedVector< wp<SensorEventConnection> > mConnections;
+ SortedVector< wp<const SensorEventConnection> > mConnections;
// A queue of all flush() calls made on this sensor. Flush complete events
// will be sent in this order.
- Vector< wp<SensorEventConnection> > mPendingFlushConnections;
+ Vector< wp<const SensorEventConnection> > mPendingFlushConnections;
};
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index a24740b..2930637 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -260,7 +260,7 @@
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
- mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
+ mMapFlushEventsToConnections = new wp<const SensorEventConnection> [minBufferSize];
mCurrentOperatingMode = NORMAL;
mNextSensorRegIndex = 0;
@@ -322,6 +322,7 @@
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
} else {
+ bool privileged = IPCThreadState::self()->getCallingUid() == 0;
if (args.size() > 2) {
return INVALID_OPERATION;
}
@@ -393,8 +394,12 @@
result.append("Recent Sensor events:\n");
for (auto&& i : mRecentEvent) {
sp<SensorInterface> s = mSensors.getInterface(i.first);
- if (!i.second->isEmpty() &&
- s->getSensor().getRequiredPermission().isEmpty()) {
+ if (!i.second->isEmpty()) {
+ if (privileged || s->getSensor().getRequiredPermission().isEmpty()) {
+ i.second->setFormat("normal");
+ } else {
+ i.second->setFormat("mask_data");
+ }
// if there is events and sensor does not need special permission.
result.appendFormat("%s: ", s->getSensor().getName().string());
result.append(i.second->dump().c_str());
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 1e1ea5a..4a63ef0 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -237,7 +237,7 @@
SortedVector< wp<SensorEventConnection> > mActiveConnections;
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
- SensorEventConnection const **mMapFlushEventsToConnections;
+ wp<const SensorEventConnection> * mMapFlushEventsToConnections;
std::unordered_map<int, RecentEventLogger*> mRecentEvent;
Mode mCurrentOperatingMode;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index dc5e97b..ffda035 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -79,18 +79,36 @@
LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
endif
-# See build/target/board/generic/BoardConfig.mk for a description of this setting.
+# The following two BoardConfig variables define (respectively):
+#
+# - The phase offset between hardware vsync and when apps are woken up by the
+# Choreographer callback
+# - The phase offset between hardware vsync and when SurfaceFlinger wakes up
+# to consume input
+#
+# Their values can be tuned to trade off between display pipeline latency (both
+# overall latency and the lengths of the app --> SF and SF --> display phases)
+# and frame delivery jitter (which typically manifests as "jank" or "jerkiness"
+# while interacting with the device). The default values should produce a
+# relatively low amount of jitter at the expense of roughly two frames of
+# app --> display latency, and unless significant testing is performed to avoid
+# increased display jitter (both manual investigation using systrace [1] and
+# automated testing using dumpsys gfxinfo [2] are recommended), they should not
+# be modified.
+#
+# [1] https://developer.android.com/studio/profile/systrace.html
+# [2] https://developer.android.com/training/testing/performance.html
+
ifneq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=$(VSYNC_EVENT_PHASE_OFFSET_NS)
else
- LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=0
+ LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=1000000
endif
-# See build/target/board/generic/BoardConfig.mk for a description of this setting.
ifneq ($(SF_VSYNC_EVENT_PHASE_OFFSET_NS),)
LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS)
else
- LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=0
+ LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=1000000
endif
ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),)
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index c67feb3..1a9820d 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -385,7 +385,7 @@
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
// set DispSync to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
- param.sched_priority = 1;
+ param.sched_priority = 2;
if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 8bcee39..cc0dfb0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -2305,7 +2305,14 @@
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
break;
case Composition::SolidColor:
- hwc1Layer.compositionType = HWC_BACKGROUND;
+ // In theory the following line should work, but since the HWC1
+ // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
+ // devices may not work correctly. To be on the safe side, we
+ // fall back to client composition.
+ //
+ // hwc1Layer.compositionType = HWC_BACKGROUND;
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
break;
case Composition::Cursor:
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 785df1a..dfece93 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -591,19 +591,25 @@
const Transform& tr(displayDevice->getTransform());
Rect transformedFrame = tr.transform(frame);
auto error = hwcLayer->setDisplayFrame(transformedFrame);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set display frame "
- "[%d, %d, %d, %d]: %s (%d)", mName.string(), transformedFrame.left,
- transformedFrame.top, transformedFrame.right,
- transformedFrame.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
+ mName.string(), transformedFrame.left, transformedFrame.top,
+ transformedFrame.right, transformedFrame.bottom,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ } else {
+ hwcInfo.displayFrame = transformedFrame;
+ }
FloatRect sourceCrop = computeCrop(displayDevice);
error = hwcLayer->setSourceCrop(sourceCrop);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set source crop "
- "[%.3f, %.3f, %.3f, %.3f]: %s (%d)", mName.string(),
- sourceCrop.left, sourceCrop.top, sourceCrop.right,
- sourceCrop.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
+ "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top,
+ sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ } else {
+ hwcInfo.sourceCrop = sourceCrop;
+ }
error = hwcLayer->setPlaneAlpha(s.alpha);
ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
@@ -2235,6 +2241,54 @@
}
}
+#ifdef USE_HWC2
+void Layer::miniDumpHeader(String8& result) {
+ result.append("----------------------------------------");
+ result.append("---------------------------------------\n");
+ result.append(" Layer name\n");
+ result.append(" Z | ");
+ result.append(" Comp Type | ");
+ result.append(" Disp Frame (LTRB) | ");
+ result.append(" Source Crop (LTRB)\n");
+ result.append("----------------------------------------");
+ result.append("---------------------------------------\n");
+}
+
+void Layer::miniDump(String8& result, int32_t hwcId) const {
+ if (mHwcLayers.count(hwcId) == 0) {
+ return;
+ }
+
+ String8 name;
+ if (mName.length() > 77) {
+ std::string shortened;
+ shortened.append(mName.string(), 36);
+ shortened.append("[...]");
+ shortened.append(mName.string() + (mName.length() - 36), 36);
+ name = shortened.c_str();
+ } else {
+ name = mName;
+ }
+
+ result.appendFormat(" %s\n", name.string());
+
+ const Layer::State& layerState(getDrawingState());
+ const HWCInfo& hwcInfo = mHwcLayers.at(hwcId);
+ result.appendFormat(" %10u | ", layerState.z);
+ result.appendFormat("%10s | ",
+ to_string(getCompositionType(hwcId)).c_str());
+ const Rect& frame = hwcInfo.displayFrame;
+ result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top,
+ frame.right, frame.bottom);
+ const FloatRect& crop = hwcInfo.sourceCrop;
+ result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top,
+ crop.right, crop.bottom);
+
+ result.append("- - - - - - - - - - - - - - - - - - - - ");
+ result.append("- - - - - - - - - - - - - - - - - - - -\n");
+}
+#endif
+
void Layer::dumpFrameStats(String8& result) const {
mFrameTracker.dumpStats(result);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6533953..2ce1340 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -402,6 +402,10 @@
/* always call base class first */
void dump(String8& result, Colorizer& colorizer) const;
+#ifdef USE_HWC2
+ static void miniDumpHeader(String8& result);
+ void miniDump(String8& result, int32_t hwcId) const;
+#endif
void dumpFrameStats(String8& result) const;
void clearFrameStats();
void logFrameStats();
@@ -588,6 +592,8 @@
bool forceClientComposition;
HWC2::Composition compositionType;
bool clearClientTarget;
+ Rect displayFrame;
+ FloatRect sourceCrop;
};
std::unordered_map<int32_t, HWCInfo> mHwcLayers;
#else
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2a67f4c..8db071e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -471,7 +471,7 @@
// set SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
- param.sched_priority = 1;
+ param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}
@@ -3057,6 +3057,26 @@
* VSYNC state
*/
mEventThread->dump(result);
+ result.append("\n");
+
+ /*
+ * HWC layer minidump
+ */
+ for (size_t d = 0; d < mDisplays.size(); d++) {
+ const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
+ int32_t hwcId = displayDevice->getHwcDisplayId();
+ if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+ continue;
+ }
+
+ result.appendFormat("Display %d HWC layers:\n", hwcId);
+ Layer::miniDumpHeader(result);
+ for (size_t l = 0; l < count; l++) {
+ const sp<Layer>& layer(currentLayers[l]);
+ layer->miniDump(result, hwcId);
+ }
+ result.append("\n");
+ }
/*
* Dump HWComposer state
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 650d6b4..b0f418c 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -467,7 +467,7 @@
// set SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
- param.sched_priority = 1;
+ param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}