Merge "Surface: Add force disconnection method." into nyc-mr1-dev
am: 6cc1933af9
Change-Id: Ice30ea86acd7abfa71c0053dc1459361b4bbfb6c
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/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/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/SensorService.cpp b/services/sensorservice/SensorService.cpp
index dbd0624..2930637 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -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());