Merge "Add new AINPUT_SOURCE_BLUETOOTH_STYLUS" into mnc-dev
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 88fc242..1d9e6b8 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -109,6 +110,7 @@
 }
 
 static const char mmcblk0[] = "/sys/block/mmcblk0/";
+unsigned long worst_write_perf = 20000; /* in KB/s */
 
 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
     unsigned long fields[11], read_perf, write_perf;
@@ -157,11 +159,111 @@
         write_perf = 512 * fields[6] / fields[7];
     }
     printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf);
+    if ((write_perf > 1) && (write_perf < worst_write_perf)) {
+        worst_write_perf = write_perf;
+    }
     return 0;
 }
 
+/* Copied policy from system/core/logd/LogBuffer.cpp */
+
+#define LOG_BUFFER_SIZE (256 * 1024)
+#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
+#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
+
+static bool valid_size(unsigned long value) {
+    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
+        return false;
+    }
+
+    long pages = sysconf(_SC_PHYS_PAGES);
+    if (pages < 1) {
+        return true;
+    }
+
+    long pagesize = sysconf(_SC_PAGESIZE);
+    if (pagesize <= 1) {
+        pagesize = PAGE_SIZE;
+    }
+
+    // maximum memory impact a somewhat arbitrary ~3%
+    pages = (pages + 31) / 32;
+    unsigned long maximum = pages * pagesize;
+
+    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
+        return true;
+    }
+
+    return value <= maximum;
+}
+
+static unsigned long property_get_size(const char *key) {
+    unsigned long value;
+    char *cp, property[PROPERTY_VALUE_MAX];
+
+    property_get(key, property, "");
+    value = strtoul(property, &cp, 10);
+
+    switch(*cp) {
+    case 'm':
+    case 'M':
+        value *= 1024;
+    /* FALLTHRU */
+    case 'k':
+    case 'K':
+        value *= 1024;
+    /* FALLTHRU */
+    case '\0':
+        break;
+
+    default:
+        value = 0;
+    }
+
+    if (!valid_size(value)) {
+        value = 0;
+    }
+
+    return value;
+}
+
+/* timeout in ms */
+static unsigned long logcat_timeout(char *name) {
+    static const char global_tuneable[] = "persist.logd.size"; // Settings App
+    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
+    char key[PROP_NAME_MAX];
+    unsigned long property_size, default_size;
+
+    default_size = property_get_size(global_tuneable);
+    if (!default_size) {
+        default_size = property_get_size(global_default);
+    }
+
+    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
+    property_size = property_get_size(key);
+
+    if (!property_size) {
+        snprintf(key, sizeof(key), "%s.%s", global_default, name);
+        property_size = property_get_size(key);
+    }
+
+    if (!property_size) {
+        property_size = default_size;
+    }
+
+    if (!property_size) {
+        property_size = LOG_BUFFER_SIZE;
+    }
+
+    /* Engineering margin is ten-fold our guess */
+    return 10 * (property_size + worst_write_perf) / worst_write_perf;
+}
+
+/* End copy from system/core/logd/LogBuffer.cpp */
+
 /* dumps the current system state to stdout */
 static void dumpstate() {
+    unsigned long timeout;
     time_t now = time(NULL);
     char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
     char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
@@ -210,7 +312,6 @@
     dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
     dump_file("KERNEL SYNC", "/d/sync");
-    dump_file("KERNEL BLUEDROID", "/d/bluedroid");
 
     run_command("PROCESSES", 10, "ps", "-P", NULL);
     run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
@@ -230,9 +331,22 @@
     }
 
     // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
-    run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
-    run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
-    run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
+    // 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", "-d", "*:v", NULL);
+    timeout = logcat_timeout("events");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
+    timeout = logcat_timeout("radio");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
 
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index ebd71a0..faf48ef 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -745,6 +745,15 @@
     ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
 }
 
+static bool check_boolean_property(const char* property_name, bool default_value = false) {
+    char tmp_property_value[PROPERTY_VALUE_MAX];
+    bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0;
+    if (!have_property) {
+        return default_value;
+    }
+    return strcmp(tmp_property_value, "true") == 0;
+}
+
 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
     const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
     bool vm_safe_mode, bool debuggable)
@@ -805,9 +814,8 @@
                              (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
                              (strcmp(vold_decrypt, "1") == 0)));
 
-    char use_jit_property[PROPERTY_VALUE_MAX];
-    bool have_jit_property = property_get("debug.usejit", use_jit_property, NULL) > 0;
-    bool use_jit = have_jit_property && strcmp(use_jit_property, "true") == 0;
+    bool use_jit = check_boolean_property("debug.usejit");
+    bool generate_debug_info = check_boolean_property("debug.generate-debug-info");
 
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
 
@@ -900,6 +908,7 @@
                      + (have_dex2oat_threads_flag ? 1 : 0)
                      + (have_dex2oat_swap_fd ? 1 : 0)
                      + (have_dex2oat_relocation_skip_flag ? 2 : 0)
+                     + (generate_debug_info ? 1 : 0)
                      + (debuggable ? 1 : 0)
                      + dex2oat_flags_count];
     int i = 0;
@@ -938,6 +947,9 @@
     if (have_dex2oat_swap_fd) {
         argv[i++] = dex2oat_swap_fd;
     }
+    if (generate_debug_info) {
+        argv[i++] = "--generate-debug-info";
+    }
     if (debuggable) {
         argv[i++] = "--debuggable";
     }
diff --git a/include/input/Input.h b/include/input/Input.h
index 1da8356..4a67f47 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -383,6 +383,8 @@
 
     inline int32_t getActionButton() const { return mActionButton; }
 
+    inline void setActionButton(int32_t button) { mActionButton = button; }
+
     inline float getXOffset() const { return mXOffset; }
 
     inline float getYOffset() const { return mYOffset; }
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 9fcac2d..757e08a 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -901,14 +901,18 @@
 
         // The crop is too wide
         if (newWidth < currentWidth) {
-            uint32_t dw = (currentWidth - newWidth) / 2;
-            outCrop.left += dw;
-            outCrop.right -= dw;
+            uint32_t dw = currentWidth - newWidth;
+            auto halfdw = dw / 2;
+            outCrop.left += halfdw;
+            // Not halfdw because it would subtract 1 too few when dw is odd
+            outCrop.right -= (dw - halfdw);
         // The crop is too tall
         } else if (newHeight < currentHeight) {
-            uint32_t dh = (currentHeight - newHeight) / 2;
-            outCrop.top += dh;
-            outCrop.bottom -= dh;
+            uint32_t dh = currentHeight - newHeight;
+            auto halfdh = dh / 2;
+            outCrop.top += halfdh;
+            // Not halfdh because it would subtract 1 too few when dh is odd
+            outCrop.bottom -= (dh - halfdh);
         }
 
         GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 6267a4c..dd1bccf 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -89,7 +89,7 @@
         result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
                             info.batchParams.size());
         for (size_t j = 0; j < info.batchParams.size(); j++) {
-            BatchParams params = info.batchParams.valueAt(j);
+            const BatchParams& params = info.batchParams.valueAt(j);
             result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
                                 j < info.batchParams.size() - 1 ? ", " : "");
         }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index cf750ee..45d467d 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -195,9 +195,14 @@
             mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
             mCurrentOperatingMode = NORMAL;
 
+            mNextSensorRegIndex = 0;
+            for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
+                mLastNSensorRegistrations.push();
+            }
+
+            mInitCheck = NO_ERROR;
             mAckReceiver = new SensorEventAckReceiver(this);
             mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
-            mInitCheck = NO_ERROR;
             run("SensorService", PRIORITY_URGENT_DISPLAY);
         }
     }
@@ -322,11 +327,14 @@
                     result.appendFormat("non-wakeUp | ");
                 }
 
-                const CircularBuffer* buf = mLastEventSeen.valueFor(s.getHandle());
-                if (buf != NULL && s.getRequiredPermission().isEmpty()) {
-                    buf->printBuffer(result);
-                } else {
-                    result.append("last=<> \n");
+                int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
+                if (bufIndex >= 0) {
+                    const CircularBuffer* buf = mLastEventSeen.valueAt(bufIndex);
+                    if (buf != NULL && s.getRequiredPermission().isEmpty()) {
+                        buf->printBuffer(result);
+                    } else {
+                        result.append("last=<> \n");
+                    }
                 }
                 result.append("\n");
             }
@@ -344,7 +352,8 @@
 
             result.appendFormat("Socket Buffer size = %d events\n",
                                 mSocketBufferSize/sizeof(sensors_event_t));
-            result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
+            result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" :
+                    "not held");
             result.appendFormat("Mode :");
             switch(mCurrentOperatingMode) {
                case NORMAL:
@@ -365,6 +374,34 @@
                     connection->dump(result);
                 }
             }
+
+            result.appendFormat("Previous Registrations:\n");
+            // Log in the reverse chronological order.
+            int currentIndex = (mNextSensorRegIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+                SENSOR_REGISTRATIONS_BUF_SIZE;
+            const int startIndex = currentIndex;
+            do {
+                const SensorRegistrationInfo& reg_info = mLastNSensorRegistrations[currentIndex];
+                if (SensorRegistrationInfo::isSentinel(reg_info)) {
+                    // Ignore sentinel, proceed to next item.
+                    currentIndex = (currentIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+                        SENSOR_REGISTRATIONS_BUF_SIZE;
+                    continue;
+                }
+                if (reg_info.mActivated) {
+                   result.appendFormat("%02d:%02d:%02d activated package=%s handle=0x%08x "
+                           "samplingRate=%dus maxReportLatency=%dus\n",
+                           reg_info.mHour, reg_info.mMin, reg_info.mSec,
+                           reg_info.mPackageName.string(), reg_info.mSensorHandle,
+                           reg_info.mSamplingRateUs, reg_info.mMaxReportLatencyUs);
+                } else {
+                   result.appendFormat("%02d:%02d:%02d de-activated package=%s handle=0x%08x\n",
+                           reg_info.mHour, reg_info.mMin, reg_info.mSec,
+                           reg_info.mPackageName.string(), reg_info.mSensorHandle);
+                }
+                currentIndex = (currentIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+                        SENSOR_REGISTRATIONS_BUF_SIZE;
+            } while(startIndex != currentIndex);
         }
     }
     write(fd, result.string(), result.size());
@@ -888,6 +925,19 @@
 
     if (err == NO_ERROR) {
         connection->updateLooperRegistration(mLooper);
+        SensorRegistrationInfo &reg_info =
+            mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex);
+        reg_info.mSensorHandle = handle;
+        reg_info.mSamplingRateUs = samplingPeriodNs/1000;
+        reg_info.mMaxReportLatencyUs = maxBatchReportLatencyNs/1000;
+        reg_info.mActivated = true;
+        reg_info.mPackageName = connection->getPackageName();
+        time_t rawtime = time(NULL);
+        struct tm * timeinfo = localtime(&rawtime);
+        reg_info.mHour = timeinfo->tm_hour;
+        reg_info.mMin = timeinfo->tm_min;
+        reg_info.mSec = timeinfo->tm_sec;
+        mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE;
     }
 
     if (err != NO_ERROR) {
@@ -908,6 +958,20 @@
     if (err == NO_ERROR) {
         SensorInterface* sensor = mSensorMap.valueFor(handle);
         err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+
+    }
+    if (err == NO_ERROR) {
+        SensorRegistrationInfo &reg_info =
+            mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex);
+        reg_info.mActivated = false;
+        reg_info.mPackageName= connection->getPackageName();
+        reg_info.mSensorHandle = handle;
+        time_t rawtime = time(NULL);
+        struct tm * timeinfo = localtime(&rawtime);
+        reg_info.mHour = timeinfo->tm_hour;
+        reg_info.mMin = timeinfo->tm_min;
+        reg_info.mSec = timeinfo->tm_sec;
+        mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE;
     }
     return err;
 }
@@ -1180,14 +1244,38 @@
     mPendingFlushConnections.clear();
 }
 
+
+// ---------------------------------------------------------------------------
+SensorService::TrimmedSensorEvent::TrimmedSensorEvent(int sensorType) {
+    mTimestamp = -1;
+    const int numData = SensorService::getNumEventsForSensorType(sensorType);
+    if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
+        mStepCounter = 0;
+    } else {
+        mData = new float[numData];
+        for (int i = 0; i < numData; ++i) {
+            mData[i] = -1.0;
+        }
+    }
+    mHour = mMin = mSec = INT32_MIN;
+}
+
+bool SensorService::TrimmedSensorEvent::isSentinel(const TrimmedSensorEvent& event) {
+    return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
+}
 // --------------------------------------------------------------------------
 SensorService::CircularBuffer::CircularBuffer(int sensor_event_type) {
     mNextInd = 0;
-    mTrimmedSensorEventArr = new TrimmedSensorEvent *[CIRCULAR_BUF_SIZE];
+    mBufSize = CIRCULAR_BUF_SIZE;
+    if (sensor_event_type == SENSOR_TYPE_STEP_COUNTER ||
+            sensor_event_type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+            sensor_event_type == SENSOR_TYPE_ACCELEROMETER) {
+        mBufSize = CIRCULAR_BUF_SIZE * 5;
+    }
+    mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
     mSensorType = sensor_event_type;
-    const int numData = SensorService::getNumEventsForSensorType(mSensorType);
-    for (int i = 0; i < CIRCULAR_BUF_SIZE; ++i) {
-        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(numData, mSensorType);
+    for (int i = 0; i < mBufSize; ++i) {
+        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
     }
 }
 
@@ -1205,17 +1293,17 @@
     curr_event->mHour = timeinfo->tm_hour;
     curr_event->mMin = timeinfo->tm_min;
     curr_event->mSec = timeinfo->tm_sec;
-    mNextInd = (mNextInd + 1) % CIRCULAR_BUF_SIZE;
+    mNextInd = (mNextInd + 1) % mBufSize;
 }
 
 void SensorService::CircularBuffer::printBuffer(String8& result) const {
     const int numData = SensorService::getNumEventsForSensorType(mSensorType);
     int i = mNextInd, eventNum = 1;
-    result.appendFormat("last %d events = < ", CIRCULAR_BUF_SIZE);
+    result.appendFormat("last %d events = < ", mBufSize);
     do {
-        if (mTrimmedSensorEventArr[i]->mTimestamp == -1) {
+        if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
             // Sentinel, ignore.
-            i = (i + 1) % CIRCULAR_BUF_SIZE;
+            i = (i + 1) % mBufSize;
             continue;
         }
         result.appendFormat("%d) ", eventNum++);
@@ -1229,15 +1317,15 @@
         result.appendFormat("%lld %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
                 mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
                 mTrimmedSensorEventArr[i]->mSec);
-        i = (i + 1) % CIRCULAR_BUF_SIZE;
+        i = (i + 1) % mBufSize;
     } while (i != mNextInd);
     result.appendFormat(">\n");
 }
 
 bool SensorService::CircularBuffer::populateLastEvent(sensors_event_t *event) {
-    int lastEventInd = (mNextInd - 1 + CIRCULAR_BUF_SIZE) % CIRCULAR_BUF_SIZE;
+    int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
     // Check if the buffer is empty.
-    if (mTrimmedSensorEventArr[lastEventInd]->mTimestamp == -1) {
+    if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
         return false;
     }
     event->version = sizeof(sensors_event_t);
@@ -1253,7 +1341,7 @@
 }
 
 SensorService::CircularBuffer::~CircularBuffer() {
-    for (int i = 0; i < CIRCULAR_BUF_SIZE; ++i) {
+    for (int i = 0; i < mBufSize; ++i) {
         delete mTrimmedSensorEventArr[i];
     }
     delete [] mTrimmedSensorEventArr;
@@ -1299,8 +1387,9 @@
 void SensorService::SensorEventConnection::dump(String8& result) {
     Mutex::Autolock _l(mConnectionLock);
     result.appendFormat("Operating Mode: %s\n", mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
-    result.appendFormat("\t%s | WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
-            mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize);
+    result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
+            "max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
+            mMaxCacheSize);
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
         const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
         result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 7c466c1..0a7abe8 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -54,6 +54,7 @@
 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
 
 #define CIRCULAR_BUF_SIZE 10
+#define SENSOR_REGISTRATIONS_BUF_SIZE 20
 
 struct sensors_poll_device_t;
 struct sensors_module_t;
@@ -272,18 +273,8 @@
         // for debugging.
         int32_t mHour, mMin, mSec;
 
-        TrimmedSensorEvent(int numData, int sensorType) {
-            mTimestamp = -1;
-            if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
-                mStepCounter = 0;
-            } else {
-                mData = new float[numData];
-                for (int i = 0; i < numData; ++i) {
-                    mData[i] = -1.0;
-                }
-            }
-            mHour = mMin = mSec = 0;
-        }
+        TrimmedSensorEvent(int sensorType);
+        static bool isSentinel(const TrimmedSensorEvent& event);
 
         ~TrimmedSensorEvent() {
             delete [] mData;
@@ -297,6 +288,7 @@
     class CircularBuffer {
         int mNextInd;
         int mSensorType;
+        int mBufSize;
         TrimmedSensorEvent ** mTrimmedSensorEventArr;
     public:
         CircularBuffer(int sensor_event_type);
@@ -306,6 +298,25 @@
         ~CircularBuffer();
     };
 
+    struct SensorRegistrationInfo {
+        int32_t mSensorHandle;
+        String8 mPackageName;
+        bool mActivated;
+        int32_t mSamplingRateUs;
+        int32_t mMaxReportLatencyUs;
+        int32_t mHour, mMin, mSec;
+
+        SensorRegistrationInfo() : mPackageName() {
+            mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
+            mHour = mMin = mSec = INT32_MIN;
+            mActivated = false;
+        }
+
+        static bool isSentinel(const SensorRegistrationInfo& info) {
+           return (info.mHour == INT32_MIN && info.mMin == INT32_MIN && info.mSec == INT32_MIN);
+        }
+    };
+
     static int getNumEventsForSensorType(int sensor_event_type);
     String8 getSensorName(int handle) const;
     bool isVirtualSensor(int handle) const;
@@ -387,6 +398,8 @@
     // The size of this vector is constant, only the items are mutable
     KeyedVector<int32_t, CircularBuffer *> mLastEventSeen;
 
+    int mNextSensorRegIndex;
+    Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
 public:
     void cleanupConnection(SensorEventConnection* connection);
     status_t enable(const sp<SensorEventConnection>& connection, int handle,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 02c31ff..2dad005 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -635,6 +635,7 @@
 }
 
 status_t HWComposer::prepare() {
+    Mutex::Autolock _l(mDisplayLock);
     for (size_t i=0 ; i<mNumDisplays ; i++) {
         DisplayData& disp(mDisplayData[i]);
         if (disp.framebufferTarget) {
@@ -1145,6 +1146,7 @@
 }
 
 void HWComposer::dump(String8& result) const {
+    Mutex::Autolock _l(mDisplayLock);
     if (mHwc) {
         result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
         result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 28d8c65..cc98b4c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -354,6 +354,8 @@
     // mLists[i>0] can be NULL. that display is to be ignored
     struct hwc_display_contents_1*  mLists[MAX_HWC_DISPLAYS];
     DisplayData                     mDisplayData[MAX_HWC_DISPLAYS];
+    // protect mDisplayData from races between prepare and dump
+    mutable Mutex mDisplayLock;
     size_t                          mNumDisplays;
 
     cb_context*                     mCBContext;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a426ad6..a332cda 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -550,7 +550,7 @@
 
 status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
         Vector<DisplayInfo>* configs) {
-    if (configs == NULL) {
+    if ((configs == NULL) || (display.get() == NULL)) {
         return BAD_VALUE;
     }