Merge "Fix security vulnerability" into nyc-dev am: 2188ad799e am: 80672db6b8
am: 900cd6a1d2

Change-Id: Ieee74bcd82513fc4612c874b966ba9903e26565c
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 9321a00..60460e0 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -35,6 +35,7 @@
 #include <unistd.h>
 
 #include <android-base/stringprintf.h>
+#include <android-base/file.h>
 #include <cutils/properties.h>
 
 #include "private/android_filesystem_config.h"
@@ -179,6 +180,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 (!is_zipping()) {
         MYLOGD("Not dumping systrace because dumpstate is not zipping\n");
@@ -1352,7 +1483,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/data/etc/android.hardware.sensor.heartrate.fitness.xml b/data/etc/android.hardware.sensor.heartrate.fitness.xml
new file mode 100644
index 0000000..aef77b4
--- /dev/null
+++ b/data/etc/android.hardware.sensor.heartrate.fitness.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Feature for devices supporting a fitness heart rate monitor -->
+<permissions>
+    <feature name="android.hardware.sensor.heartrate.fitness" />
+</permissions>
diff --git a/data/etc/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/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index cc5c536..1226feb 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -185,8 +185,12 @@
     // PID of the process which last successfully called connect(...)
     pid_t mConnectedPid;
 
-    // mConnectedProducerToken is used to set a binder death notification on
+    // mLinkedToDeath is used to set a binder death notification on
     // the producer.
+    sp<IProducerListener> mLinkedToDeath;
+
+    // mConnectedProducerListener is used to handle the onBufferReleased
+    // notification.
     sp<IProducerListener> mConnectedProducerListener;
 
     // mSlots is an array of buffer slots that must be mirrored on the producer
diff --git a/include/gui/IProducerListener.h b/include/gui/IProducerListener.h
index 3848a6c..b7826c6 100644
--- a/include/gui/IProducerListener.h
+++ b/include/gui/IProducerListener.h
@@ -41,6 +41,7 @@
     // This is called without any lock held and can be called concurrently by
     // multiple threads.
     virtual void onBufferReleased() = 0; // Asynchronous
+    virtual bool needsReleaseNotify() = 0;
 };
 
 class IProducerListener : public ProducerListener, public IInterface
@@ -54,12 +55,14 @@
 public:
     virtual status_t onTransact(uint32_t code, const Parcel& data,
             Parcel* reply, uint32_t flags = 0);
+    virtual bool needsReleaseNotify();
 };
 
 class DummyProducerListener : public BnProducerListener
 {
 public:
     virtual void onBufferReleased() {}
+    virtual bool needsReleaseNotify() { return false; }
 };
 
 } // namespace android
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index b431bd5..48a7aa3 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -27,6 +27,8 @@
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
+#include <experimental/optional>
+
 struct ANativeWindowBuffer;
 
 namespace android {
@@ -79,6 +81,9 @@
     // becomes signaled when both f1 and f2 are signaled (even if f1 or f2 is
     // destroyed before it becomes signaled).  The name argument specifies the
     // human-readable name to associated with the new Fence object.
+    static sp<Fence> merge(const char* name, const sp<Fence>& f1,
+            const sp<Fence>& f2);
+
     static sp<Fence> merge(const String8& name, const sp<Fence>& f1,
             const sp<Fence>& f2);
 
@@ -93,6 +98,27 @@
     // occurs then -1 is returned.
     nsecs_t getSignalTime() const;
 
+#if __cplusplus > 201103L
+    // hasSignaled returns whether the fence has signaled yet. Prefer this to
+    // getSignalTime() or wait() if all you care about is whether the fence has
+    // signaled. Returns an optional bool, which will have a value if there was
+    // no error.
+    inline std::experimental::optional<bool> hasSignaled() {
+        // The sync_wait call underlying wait() has been measured to be
+        // significantly faster than the sync_fence_info call underlying
+        // getSignalTime(), which might otherwise appear to be the more obvious
+        // way to check whether a fence has signaled.
+        switch (wait(0)) {
+            case NO_ERROR:
+                return true;
+            case -ETIME:
+                return false;
+            default:
+                return {};
+        }
+    }
+#endif
+
     // Flattenable interface
     size_t getFlattenedSize() const;
     size_t getFdCount() const;
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 61f24d6..44d235f 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -140,10 +140,12 @@
     {
         unsigned n;
         for (n = 0; n < 5; n++){
+            if (n > 0) {
+                ALOGI("Waiting for service %s...", String8(name).string());
+                sleep(1);
+            }
             sp<IBinder> svc = checkService(name);
             if (svc != NULL) return svc;
-            ALOGI("Waiting for service %s...\n", String8(name).string());
-            sleep(1);
         }
         return NULL;
     }
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 4f6ecff..c4714e3 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -59,6 +59,7 @@
     mConsumerListener(),
     mConsumerUsageBits(0),
     mConnectedApi(NO_CONNECTED_API),
+    mLinkedToDeath(),
     mConnectedProducerListener(),
     mSlots(),
     mQueue(),
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 05923b5..b2169c8 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1113,18 +1113,22 @@
                     static_cast<uint32_t>(mCore->mQueue.size()),
                     mCore->mFrameCounter + 1);
 
-            // Set up a death notification so that we can disconnect
-            // automatically if the remote producer dies
-            if (listener != NULL &&
-                    IInterface::asBinder(listener)->remoteBinder() != NULL) {
-                status = IInterface::asBinder(listener)->linkToDeath(
-                        static_cast<IBinder::DeathRecipient*>(this));
-                if (status != NO_ERROR) {
-                    BQ_LOGE("connect: linkToDeath failed: %s (%d)",
-                            strerror(-status), status);
+            if (listener != NULL) {
+                // Set up a death notification so that we can disconnect
+                // automatically if the remote producer dies
+                if (IInterface::asBinder(listener)->remoteBinder() != NULL) {
+                    status = IInterface::asBinder(listener)->linkToDeath(
+                            static_cast<IBinder::DeathRecipient*>(this));
+                    if (status != NO_ERROR) {
+                        BQ_LOGE("connect: linkToDeath failed: %s (%d)",
+                                strerror(-status), status);
+                    }
+                    mCore->mLinkedToDeath = listener;
+                }
+                if (listener->needsReleaseNotify()) {
+                    mCore->mConnectedProducerListener = listener;
                 }
             }
-            mCore->mConnectedProducerListener = listener;
             break;
         default:
             BQ_LOGE("connect: unknown API %d", api);
@@ -1186,9 +1190,9 @@
                     mCore->freeAllBuffersLocked();
 
                     // Remove our death notification callback if we have one
-                    if (mCore->mConnectedProducerListener != NULL) {
+                    if (mCore->mLinkedToDeath != NULL) {
                         sp<IBinder> token =
-                                IInterface::asBinder(mCore->mConnectedProducerListener);
+                                IInterface::asBinder(mCore->mLinkedToDeath);
                         // This can fail if we're here because of the death
                         // notification, but we just ignore it
                         token->unlinkToDeath(
@@ -1196,6 +1200,7 @@
                     }
                     mCore->mSharedBufferSlot =
                             BufferQueueCore::INVALID_BUFFER_SLOT;
+                    mCore->mLinkedToDeath = NULL;
                     mCore->mConnectedProducerListener = NULL;
                     mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
                     mCore->mConnectedPid = -1;
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index a1bdf4a..65e4fee 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -314,10 +314,23 @@
 
     if (!mSlots[slot].mFence.get()) {
         mSlots[slot].mFence = fence;
+        return OK;
+    }
+
+    auto signaled = mSlots[slot].mFence->hasSignaled();
+
+    if (!signaled) {
+        CB_LOGE("fence has invalid state");
+        return BAD_VALUE;
+    }
+
+    if (*signaled) {
+        mSlots[slot].mFence = fence;
     } else {
+        char fenceName[32] = {};
+        snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
         sp<Fence> mergedFence = Fence::merge(
-                String8::format("%.28s:%d", mName.string(), slot),
-                mSlots[slot].mFence, fence);
+                fenceName, mSlots[slot].mFence, fence);
         if (!mergedFence.get()) {
             CB_LOGE("failed to merge release fences");
             // synchronization is broken, the best we can do is hope fences
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 81adc95..da54ce1 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -22,6 +22,7 @@
 
 enum {
     ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
+    NEEDS_RELEASE_NOTIFY,
 };
 
 class BpProducerListener : public BpInterface<IProducerListener>
@@ -37,6 +38,23 @@
         data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
         remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    virtual bool needsReleaseNotify() {
+        bool result;
+        Parcel data, reply;
+        data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
+        status_t err = remote()->transact(NEEDS_RELEASE_NOTIFY, data, &reply);
+        if (err != NO_ERROR) {
+            ALOGE("IProducerListener: binder call \'needsReleaseNotify\' failed");
+            return true;
+        }
+        err = reply.readBool(&result);
+        if (err != NO_ERROR) {
+            ALOGE("IProducerListener: malformed binder reply");
+            return true;
+        }
+        return result;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -52,8 +70,16 @@
             CHECK_INTERFACE(IProducerListener, data, reply);
             onBufferReleased();
             return NO_ERROR;
+        case NEEDS_RELEASE_NOTIFY:
+            CHECK_INTERFACE(IProducerListener, data, reply);
+            reply->writeBool(needsReleaseNotify());
+            return NO_ERROR;
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
 
+bool BnProducerListener::needsReleaseNotify() {
+    return true;
+}
+
 } // namespace android
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 225bfa8..9fcf9ab 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -194,7 +194,8 @@
         // a non_wake-up version.
         if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
             type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE ||
-            type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE) {
+            type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE ||
+            type == SENSOR_TYPE_WRIST_TILT_GESTURE) {
             wakeUpSensor = true;
         }
         // For now we just return the first sensor of that type we find.
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index bf24ffb..7cf8233 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -72,7 +72,7 @@
     return err < 0 ? -errno : status_t(NO_ERROR);
 }
 
-sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
+sp<Fence> Fence::merge(const char* name, const sp<Fence>& f1,
         const sp<Fence>& f2) {
     ATRACE_CALL();
     int result;
@@ -80,24 +80,29 @@
     // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
     // that a new fence with the given name is created.
     if (f1->isValid() && f2->isValid()) {
-        result = sync_merge(name.string(), f1->mFenceFd, f2->mFenceFd);
+        result = sync_merge(name, f1->mFenceFd, f2->mFenceFd);
     } else if (f1->isValid()) {
-        result = sync_merge(name.string(), f1->mFenceFd, f1->mFenceFd);
+        result = sync_merge(name, f1->mFenceFd, f1->mFenceFd);
     } else if (f2->isValid()) {
-        result = sync_merge(name.string(), f2->mFenceFd, f2->mFenceFd);
+        result = sync_merge(name, f2->mFenceFd, f2->mFenceFd);
     } else {
         return NO_FENCE;
     }
     if (result == -1) {
         status_t err = -errno;
         ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
-                name.string(), f1->mFenceFd, f2->mFenceFd,
+                name, f1->mFenceFd, f2->mFenceFd,
                 strerror(-err), err);
         return NO_FENCE;
     }
     return sp<Fence>(new Fence(result));
 }
 
+sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
+        const sp<Fence>& f2) {
+    return merge(name.string(), f1, f2);
+}
+
 int Fence::dup() const {
     return ::dup(mFenceFd);
 }
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index d5b88de..ec7df31 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -288,6 +288,7 @@
 gralloc1_error_t Gralloc1On0Adapter::retain(
         const std::shared_ptr<Buffer>& buffer)
 {
+    std::lock_guard<std::mutex> lock(mBufferMutex);
     buffer->retain();
     return GRALLOC1_ERROR_NONE;
 }
@@ -295,6 +296,7 @@
 gralloc1_error_t Gralloc1On0Adapter::release(
         const std::shared_ptr<Buffer>& buffer)
 {
+    std::lock_guard<std::mutex> lock(mBufferMutex);
     if (!buffer->release()) {
         return GRALLOC1_ERROR_NONE;
     }
@@ -314,7 +316,6 @@
         }
     }
 
-    std::lock_guard<std::mutex> lock(mBufferMutex);
     mBuffers.erase(handle);
     return GRALLOC1_ERROR_NONE;
 }
diff --git a/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/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 4fbaa50..ac03742 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -475,6 +475,11 @@
     return idx;
 }
 
+void SensorDevice::notifyConnectionDestroyed(void* ident) {
+    Mutex::Autolock _l(mLock);
+    mDisabledClients.remove(ident);
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 68bb853..d340da3 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -51,6 +51,7 @@
     void enableAllSensors();
     void autoDisable(void *ident, int handle);
     status_t injectSensorData(const sensors_event_t *event);
+    void notifyConnectionDestroyed(void *ident);
 
     // Dumpable
     virtual std::string dump() const;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index dbd0624..614a9b1 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());
@@ -863,7 +868,7 @@
     }
 }
 
-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)) ?
@@ -871,14 +876,7 @@
     Vector<Sensor> accessibleSensorList;
     for (size_t i = 0; i < initialSensorList.size(); i++) {
         Sensor sensor = initialSensorList[i];
-        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());
-        }
+        accessibleSensorList.add(sensor);
     }
     makeUuidsIntoIdsForSensorList(accessibleSensorList);
     return accessibleSensorList;
@@ -990,6 +988,9 @@
     if (c->needsWakeLock()) {
         checkWakeLockStateLocked();
     }
+
+    SensorDevice& dev(SensorDevice::getInstance());
+    dev.notifyConnectionDestroyed(c);
 }
 
 sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {