Merge "Do not blur when doing region sampling"
diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp
index dbd4ef9..6746b0a 100644
--- a/libs/gui/tests/RegionSampling_test.cpp
+++ b/libs/gui/tests/RegionSampling_test.cpp
@@ -240,6 +240,19 @@
     float const luma_gray = 0.50;
 };
 
+TEST_F(RegionSamplingTest, invalidLayerHandle_doesNotCrash) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    const Rect sampleArea{100, 100, 200, 200};
+    // Passing in composer service as the layer handle should not crash, we'll
+    // treat it as a layer that no longer exists and silently allow sampling to
+    // occur.
+    status_t status = composer->addRegionSamplingListener(sampleArea,
+                                                          IInterface::asBinder(composer), listener);
+    ASSERT_EQ(NO_ERROR, status);
+    composer->removeRegionSamplingListener(listener);
+}
+
 TEST_F(RegionSamplingTest, DISABLED_CollectsLuma) {
     fill_render(rgba_green);
 
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 2006fbd..f1f140b 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -869,32 +869,13 @@
     return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
 }
 
-void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /*framebuffer*/) {
+void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
     ATRACE_CALL();
 
     // back to main framebuffer
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
-bool GLESRenderEngine::cleanupPostRender() {
-    ATRACE_CALL();
-
-    if (mPriorResourcesCleaned ||
-        (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled)) {
-        // If we don't have a prior frame needing cleanup, then don't do anything.
-        return false;
-    }
-
-    // Bind the texture to dummy data so that backing image data can be freed.
-    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
-    glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
-    // Release the cached fence here, so that we don't churn reallocations when
-    // we could no-op repeated calls of this method instead.
-    mLastDrawFence = nullptr;
-    mPriorResourcesCleaned = true;
-    return true;
-}
-
 void GLESRenderEngine::checkErrors() const {
     checkErrors(nullptr);
 }
@@ -1184,13 +1165,7 @@
             // us bad parameters, or we messed up our shader generation).
             return INVALID_OPERATION;
         }
-        mLastDrawFence = nullptr;
-    } else {
-        // The caller takes ownership of drawFence, so we need to duplicate the
-        // fd here.
-        mLastDrawFence = new Fence(dup(drawFence->get()));
     }
-    mPriorResourcesCleaned = false;
 
     checkErrors();
     return NO_ERROR;
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 9ab5ee6..d3c94a6 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -17,6 +17,7 @@
 #ifndef SF_GLESRENDERENGINE_H_
 #define SF_GLESRENDERENGINE_H_
 
+#include <stdint.h>
 #include <condition_variable>
 #include <deque>
 #include <mutex>
@@ -75,7 +76,6 @@
                         const std::vector<const LayerSettings*>& layers,
                         const sp<GraphicBuffer>& buffer, const bool useFramebufferCache,
                         base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
-    bool cleanupPostRender() override;
 
     EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
     // Creates an output image for rendering to
@@ -231,17 +231,6 @@
     std::mutex mRenderingMutex;
 
     std::unique_ptr<Framebuffer> mDrawingBuffer;
-    // this is a 1x1 RGB buffer, but over-allocate in case a driver wants more
-    // memory or if it needs to satisfy alignment requirements. In this case:
-    // assume that each channel requires 4 bytes, and add 3 additional bytes to
-    // ensure that we align on a word. Allocating 16 bytes will provide a
-    // guarantee that we don't clobber memory.
-    uint32_t mPlaceholderDrawBuffer[4];
-    sp<Fence> mLastDrawFence;
-    // Store a separate boolean checking if prior resources were cleaned up, as
-    // devices that don't support native sync fences can't rely on a last draw
-    // fence that doesn't exist.
-    bool mPriorResourcesCleaned = true;
 
     // Blur effect processor, only instantiated when a layer requests it.
     BlurFilter* mBlurFilter = nullptr;
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 383486b..cb0d5cf 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -68,11 +68,11 @@
     return true;
 }
 
-void GLFramebuffer::allocateBuffers(uint32_t width, uint32_t height, void* data) {
+void GLFramebuffer::allocateBuffers(uint32_t width, uint32_t height) {
     ATRACE_CALL();
 
     glBindTexture(GL_TEXTURE_2D, mTextureName);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h
index 6757695..b88da3b 100644
--- a/libs/renderengine/gl/GLFramebuffer.h
+++ b/libs/renderengine/gl/GLFramebuffer.h
@@ -39,7 +39,7 @@
 
     bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
                                const bool useFramebufferCache) override;
-    void allocateBuffers(uint32_t width, uint32_t height, void* data = nullptr);
+    void allocateBuffers(uint32_t width, uint32_t height);
     EGLImageKHR getEGLImage() const { return mEGLImage; }
     uint32_t getTextureName() const { return mTextureName; }
     uint32_t getFramebufferName() const { return mFramebufferName; }
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 5349a30..4983cb3 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -111,14 +111,6 @@
     // Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation.
     virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
     virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
-    // Clean-up method that should be called on the main thread after the
-    // drawFence returned by drawLayers fires. This method will free up
-    // resources used by the most recently drawn frame. If the frame is still
-    // being drawn, then this call is silently ignored.
-    //
-    // Returns true if resources were cleaned up, and false if we didn't need to
-    // do any work.
-    virtual bool cleanupPostRender() = 0;
 
     // queries
     virtual size_t getMaxTextureSize() const = 0;
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index d0343ba..7f20c8c 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -22,7 +22,6 @@
 #include <renderengine/Mesh.h>
 #include <renderengine/RenderEngine.h>
 #include <renderengine/Texture.h>
-#include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/Region.h>
 
@@ -56,7 +55,6 @@
     MOCK_CONST_METHOD0(isProtected, bool());
     MOCK_CONST_METHOD0(supportsProtectedContent, bool());
     MOCK_METHOD1(useProtectedContext, bool(bool));
-    MOCK_METHOD0(cleanupPostRender, bool());
     MOCK_METHOD6(drawLayers,
                  status_t(const DisplaySettings&, const std::vector<const LayerSettings*>&,
                           const sp<GraphicBuffer>&, const bool, base::unique_fd&&,
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 31f0966..2bf456b 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -1239,12 +1239,12 @@
     EXPECT_EQ(NO_ERROR, barrier->result);
 }
 
-TEST_F(RenderEngineTest, bindExternalBuffer_withNullBuffer) {
+TEST_F(RenderEngineTest, drawLayers_bindExternalBufferWithNullBuffer) {
     status_t result = sRE->bindExternalTextureBuffer(0, nullptr, nullptr);
     ASSERT_EQ(BAD_VALUE, result);
 }
 
-TEST_F(RenderEngineTest, bindExternalBuffer_cachesImages) {
+TEST_F(RenderEngineTest, drawLayers_bindExternalBufferCachesImages) {
     sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
     uint32_t texName;
     sRE->genTextures(1, &texName);
@@ -1264,7 +1264,7 @@
     EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
 }
 
-TEST_F(RenderEngineTest, cacheExternalBuffer_withNullBuffer) {
+TEST_F(RenderEngineTest, drawLayers_cacheExternalBufferWithNullBuffer) {
     std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
             sRE->cacheExternalTextureBufferForTesting(nullptr);
     std::lock_guard<std::mutex> lock(barrier->mutex);
@@ -1276,7 +1276,7 @@
     EXPECT_EQ(BAD_VALUE, barrier->result);
 }
 
-TEST_F(RenderEngineTest, cacheExternalBuffer_cachesImages) {
+TEST_F(RenderEngineTest, drawLayers_cacheExternalBufferCachesImages) {
     sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
     uint64_t bufferId = buf->getId();
     std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
@@ -1399,33 +1399,6 @@
                       backgroundColor.a);
 }
 
-TEST_F(RenderEngineTest, cleanupPostRender_cleansUpOnce) {
-    renderengine::DisplaySettings settings;
-    settings.physicalDisplay = fullscreenRect();
-    settings.clip = fullscreenRect();
-
-    std::vector<const renderengine::LayerSettings*> layers;
-    renderengine::LayerSettings layer;
-    layer.geometry.boundaries = fullscreenRect().toFloatRect();
-    BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
-    layer.alpha = 1.0;
-    layers.push_back(&layer);
-
-    base::unique_fd fenceOne;
-    sRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fenceOne);
-    base::unique_fd fenceTwo;
-    sRE->drawLayers(settings, layers, mBuffer, true, std::move(fenceOne), &fenceTwo);
-
-    const int fd = fenceTwo.get();
-    if (fd >= 0) {
-        sync_wait(fd, -1);
-    }
-
-    // Only cleanup the first time.
-    EXPECT_TRUE(sRE->cleanupPostRender());
-    EXPECT_FALSE(sRE->cleanupPostRender());
-}
-
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e19802b..5744182 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -318,7 +318,6 @@
     cnx->dso = nullptr;
 
     cnx->shouldUseAngle = false;
-    cnx->angleDecided = false;
     cnx->useAngle = false;
 
     if (cnx->vendorEGL) {
@@ -569,7 +568,6 @@
             android::GraphicsEnv::getInstance().getAngleAppName().c_str());
         cnx->useAngle = false;
     }
-    cnx->angleDecided = true;
 
     return so;
 }
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 7bb9b59..11fefab 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -82,7 +82,6 @@
 
     bool                systemDriverUnloaded;
     bool                shouldUseAngle; // Should we attempt to load ANGLE
-    bool                angleDecided;   // Have we tried to load ANGLE
     bool                useAngle;       // Was ANGLE successfully loaded
     EGLint              angleBackend;
     void*               vendorEGL;
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index e3b5743..45e67f7 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -143,6 +143,25 @@
                 for (size_t i=0 ; i < count; i++) {
                     sensor_t sensor;
                     convertToSensor(convertToOldSensorInfo(list[i]), &sensor);
+
+                    if (sensor.type < static_cast<int>(SensorType::DEVICE_PRIVATE_BASE)) {
+                        if(sensor.resolution == 0) {
+                            // Don't crash here or the device will go into a crashloop.
+                            ALOGW("%s must have a non-zero resolution", sensor.name);
+                            // For simple algos, map their resolution to 1 if it's not specified
+                            sensor.resolution =
+                                    SensorDeviceUtils::defaultResolutionForType(sensor.type);
+                        }
+
+                        double promotedResolution = sensor.resolution;
+                        double promotedMaxRange = sensor.maxRange;
+                        if (fmod(promotedMaxRange, promotedResolution) != 0) {
+                            ALOGW("%s's max range %f is not a multiple of the resolution %f",
+                                    sensor.name, sensor.maxRange, sensor.resolution);
+                            SensorDeviceUtils::quantizeValue(&sensor.maxRange, promotedResolution);
+                        }
+                    }
+
                     // Sanity check and clamp power if it is 0 (or close)
                     if (sensor.power < minPowerMa) {
                         ALOGI("Reported power %f not deemed sane, clamping to %f",
@@ -510,7 +529,7 @@
                     const auto &events,
                     const auto &dynamicSensorsAdded) {
                     if (result == Result::OK) {
-                        convertToSensorEvents(convertToNewEvents(events),
+                        convertToSensorEventsAndQuantize(convertToNewEvents(events),
                                 convertToNewSensorInfos(dynamicSensorsAdded), buffer);
                         err = (ssize_t)events.size();
                     } else {
@@ -573,6 +592,8 @@
 
             for (size_t i = 0; i < eventsToRead; i++) {
                 convertToSensorEvent(mEventBuffer[i], &buffer[i]);
+                android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i],
+                        getResolutionForSensor(buffer[i].sensor));
             }
             eventsRead = eventsToRead;
         } else {
@@ -1144,7 +1165,7 @@
     }
 }
 
-void SensorDevice::convertToSensorEvents(
+void SensorDevice::convertToSensorEventsAndQuantize(
         const hidl_vec<Event> &src,
         const hidl_vec<SensorInfo> &dynamicSensorsAdded,
         sensors_event_t *dst) {
@@ -1155,9 +1176,26 @@
 
     for (size_t i = 0; i < src.size(); ++i) {
         V2_1::implementation::convertToSensorEvent(src[i], &dst[i]);
+        android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i],
+                getResolutionForSensor(dst[i].sensor));
     }
 }
 
+float SensorDevice::getResolutionForSensor(int sensorHandle) {
+    for (size_t i = 0; i < mSensorList.size(); i++) {
+      if (sensorHandle == mSensorList[i].handle) {
+        return mSensorList[i].resolution;
+      }
+    }
+
+    auto it = mConnectedDynamicSensors.find(sensorHandle);
+    if (it != mConnectedDynamicSensors.end()) {
+      return it->second->resolution;
+    }
+
+    return 0;
+}
+
 void SensorDevice::handleHidlDeath(const std::string & detail) {
     if (!mSensors->supportsMessageQueues()) {
         // restart is the only option at present.
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 9d34930..5e7d3da 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -267,11 +267,13 @@
 
     void convertToSensorEvent(const Event &src, sensors_event_t *dst);
 
-    void convertToSensorEvents(
+    void convertToSensorEventsAndQuantize(
             const hardware::hidl_vec<Event> &src,
             const hardware::hidl_vec<SensorInfo> &dynamicSensorsAdded,
             sensors_event_t *dst);
 
+    float getResolutionForSensor(int sensorHandle);
+
     bool mIsDirectReportSupported;
 
     typedef hardware::MessageQueue<uint32_t, hardware::kSynchronizedReadWrite> WakeLockQueue;
diff --git a/services/sensorservice/SensorDeviceUtils.cpp b/services/sensorservice/SensorDeviceUtils.cpp
index dbafffe..0dcf8c0 100644
--- a/services/sensorservice/SensorDeviceUtils.cpp
+++ b/services/sensorservice/SensorDeviceUtils.cpp
@@ -17,17 +17,101 @@
 #include "SensorDeviceUtils.h"
 
 #include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/2.1/ISensors.h>
 #include <utils/Log.h>
 
 #include <chrono>
 #include <thread>
 
 using ::android::hardware::Void;
+using SensorTypeV2_1 = android::hardware::sensors::V2_1::SensorType;
 using namespace android::hardware::sensors::V1_0;
 
 namespace android {
 namespace SensorDeviceUtils {
 
+void quantizeSensorEventValues(sensors_event_t *event, float resolution) {
+    LOG_FATAL_IF(resolution == 0, "Resolution must be specified for all sensors!");
+    if (resolution == 0) {
+        return;
+    }
+
+    size_t axes = 0;
+    switch ((SensorTypeV2_1)event->type) {
+        case SensorTypeV2_1::ACCELEROMETER:
+        case SensorTypeV2_1::MAGNETIC_FIELD:
+        case SensorTypeV2_1::ORIENTATION:
+        case SensorTypeV2_1::GYROSCOPE:
+        case SensorTypeV2_1::GRAVITY:
+        case SensorTypeV2_1::LINEAR_ACCELERATION:
+        case SensorTypeV2_1::MAGNETIC_FIELD_UNCALIBRATED:
+        case SensorTypeV2_1::GYROSCOPE_UNCALIBRATED:
+        case SensorTypeV2_1::ACCELEROMETER_UNCALIBRATED:
+            axes = 3;
+            break;
+        case SensorTypeV2_1::GAME_ROTATION_VECTOR:
+            axes = 4;
+            break;
+        case SensorTypeV2_1::ROTATION_VECTOR:
+        case SensorTypeV2_1::GEOMAGNETIC_ROTATION_VECTOR:
+            axes = 5;
+            break;
+        case SensorTypeV2_1::DEVICE_ORIENTATION:
+        case SensorTypeV2_1::LIGHT:
+        case SensorTypeV2_1::PRESSURE:
+        case SensorTypeV2_1::TEMPERATURE:
+        case SensorTypeV2_1::PROXIMITY:
+        case SensorTypeV2_1::RELATIVE_HUMIDITY:
+        case SensorTypeV2_1::AMBIENT_TEMPERATURE:
+        case SensorTypeV2_1::SIGNIFICANT_MOTION:
+        case SensorTypeV2_1::STEP_DETECTOR:
+        case SensorTypeV2_1::TILT_DETECTOR:
+        case SensorTypeV2_1::WAKE_GESTURE:
+        case SensorTypeV2_1::GLANCE_GESTURE:
+        case SensorTypeV2_1::PICK_UP_GESTURE:
+        case SensorTypeV2_1::WRIST_TILT_GESTURE:
+        case SensorTypeV2_1::STATIONARY_DETECT:
+        case SensorTypeV2_1::MOTION_DETECT:
+        case SensorTypeV2_1::HEART_BEAT:
+        case SensorTypeV2_1::LOW_LATENCY_OFFBODY_DETECT:
+        case SensorTypeV2_1::HINGE_ANGLE:
+            axes = 1;
+            break;
+        case SensorTypeV2_1::POSE_6DOF:
+            axes = 15;
+            break;
+        default:
+            // No other sensors have data that needs to be rounded.
+            break;
+    }
+
+    // sensor_event_t is a union so we're able to perform the same quanitization action for most
+    // sensors by only knowing the number of axes their output data has.
+    for (size_t i = 0; i < axes; i++) {
+        quantizeValue(&event->data[i], resolution);
+    }
+}
+
+float defaultResolutionForType(int type) {
+    switch ((SensorTypeV2_1)type) {
+        case SensorTypeV2_1::SIGNIFICANT_MOTION:
+        case SensorTypeV2_1::STEP_DETECTOR:
+        case SensorTypeV2_1::STEP_COUNTER:
+        case SensorTypeV2_1::TILT_DETECTOR:
+        case SensorTypeV2_1::WAKE_GESTURE:
+        case SensorTypeV2_1::GLANCE_GESTURE:
+        case SensorTypeV2_1::PICK_UP_GESTURE:
+        case SensorTypeV2_1::WRIST_TILT_GESTURE:
+        case SensorTypeV2_1::STATIONARY_DETECT:
+        case SensorTypeV2_1::MOTION_DETECT:
+            return 1.0f;
+        default:
+            // fall through and return 0 for all other types
+            break;
+    }
+    return 0.0f;
+}
+
 HidlServiceRegistrationWaiter::HidlServiceRegistrationWaiter() {
 }
 
diff --git a/services/sensorservice/SensorDeviceUtils.h b/services/sensorservice/SensorDeviceUtils.h
index e2eb606..d7e621c 100644
--- a/services/sensorservice/SensorDeviceUtils.h
+++ b/services/sensorservice/SensorDeviceUtils.h
@@ -18,7 +18,9 @@
 #define ANDROID_SENSOR_DEVICE_UTIL
 
 #include <android/hidl/manager/1.0/IServiceNotification.h>
+#include <hardware/sensors.h>
 
+#include <cmath>
 #include <condition_variable>
 #include <thread>
 
@@ -29,6 +31,21 @@
 namespace android {
 namespace SensorDeviceUtils {
 
+// Quantizes a single value using a sensor's resolution.
+inline void quantizeValue(float *value, double resolution) {
+    // Increase the value of the sensor's nominal resolution to ensure that
+    // sensor accuracy improvements, like runtime calibration, are not masked
+    // during requantization.
+    double incRes = 0.25 * resolution;
+    *value = round(static_cast<double>(*value) / incRes) * incRes;
+}
+
+// Ensures a sensor event doesn't provide values finer grained than its sensor resolution allows.
+void quantizeSensorEventValues(sensors_event_t *event, float resolution);
+
+// Provides a default resolution for simple sensor types if one wasn't provided by the HAL.
+float defaultResolutionForType(int type);
+
 class HidlServiceRegistrationWaiter : public IServiceNotification {
 public:
 
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 6e59034..3e9a2bd 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -199,13 +199,8 @@
     }
 }
 
-void RegionSamplingThread::addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+void RegionSamplingThread::addListener(const Rect& samplingArea, const wp<Layer>& stopLayer,
                                        const sp<IRegionSamplingListener>& listener) {
-    wp<Layer> stopLayer;
-    if (stopLayerHandle != nullptr && stopLayerHandle->localBinder() != nullptr) {
-        stopLayer = static_cast<Layer::Handle*>(stopLayerHandle.get())->owner;
-    }
-
     sp<IBinder> asBinder = IInterface::asBinder(listener);
     asBinder->linkToDeath(this);
     std::lock_guard lock(mSamplingMutex);
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 99c07c2..b9b7a3c 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -69,7 +69,7 @@
 
     // Add a listener to receive luma notifications. The luma reported via listener will
     // report the median luma for the layers under the stopLayerHandle, in the samplingArea region.
-    void addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+    void addListener(const Rect& samplingArea, const wp<Layer>& stopLayer,
                      const sp<IRegionSamplingListener>& listener);
     // Remove the listener to stop receiving median luma notifications.
     void removeListener(const sp<IRegionSamplingListener>& listener);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 25ac802..12ab48e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1458,7 +1458,9 @@
     if (!listener || samplingArea == Rect::INVALID_RECT) {
         return BAD_VALUE;
     }
-    mRegionSamplingThread->addListener(samplingArea, stopLayerHandle, listener);
+
+    const wp<Layer> stopLayer = fromHandle(stopLayerHandle);
+    mRegionSamplingThread->addListener(samplingArea, stopLayer, listener);
     return NO_ERROR;
 }
 
@@ -2334,9 +2336,6 @@
     }
     getBE().mLastSwapTime = currentTime;
 
-    // Cleanup any outstanding resources due to rendering a prior frame.
-    getRenderEngine().cleanupPostRender();
-
     {
         std::lock_guard lock(mTexturePoolMutex);
         if (mTexturePool.size() < mTexturePoolSize) {
@@ -3164,7 +3163,7 @@
         Mutex::Autolock _l(mStateLock);
         sp<Layer> parent;
         if (parentHandle != nullptr) {
-            parent = fromHandle(parentHandle);
+            parent = fromHandleLocked(parentHandle).promote();
             if (parent == nullptr) {
                 return NAME_NOT_FOUND;
             }
@@ -3543,7 +3542,7 @@
 
     sp<Layer> layer = nullptr;
     if (s.surface) {
-        layer = fromHandle(s.surface);
+        layer = fromHandleLocked(s.surface).promote();
     } else {
         // The client may provide us a null handle. Treat it as if the layer was removed.
         ALOGW("Attempt to set client state with a null layer handle");
@@ -3859,7 +3858,7 @@
 
     {
         Mutex::Autolock _l(mStateLock);
-        mirrorFrom = fromHandle(mirrorFromHandle);
+        mirrorFrom = fromHandleLocked(mirrorFromHandle).promote();
         if (!mirrorFrom) {
             return NAME_NOT_FOUND;
         }
@@ -5571,7 +5570,7 @@
     {
         Mutex::Autolock lock(mStateLock);
 
-        parent = fromHandle(layerHandleBinder);
+        parent = fromHandleLocked(layerHandleBinder).promote();
         if (parent == nullptr || parent->isRemovedFromCurrentState()) {
             ALOGE("captureLayers called with an invalid or removed parent");
             return NAME_NOT_FOUND;
@@ -5604,7 +5603,7 @@
         reqHeight = crop.height() * frameScale;
 
         for (const auto& handle : excludeHandles) {
-            sp<Layer> excludeLayer = fromHandle(handle);
+            sp<Layer> excludeLayer = fromHandleLocked(handle).promote();
             if (excludeLayer != nullptr) {
                 excludeLayers.emplace(excludeLayer);
             } else {
@@ -6076,7 +6075,12 @@
     mFlinger->setInputWindowsFinished();
 }
 
-sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
+wp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
+    Mutex::Autolock _l(mStateLock);
+    return fromHandleLocked(handle);
+}
+
+wp<Layer> SurfaceFlinger::fromHandleLocked(const sp<IBinder>& handle) {
     BBinder* b = nullptr;
     if (handle) {
         b = handle->localBinder();
@@ -6086,7 +6090,7 @@
     }
     auto it = mLayersByLocalBinderToken.find(b);
     if (it != mLayersByLocalBinderToken.end()) {
-        return it->second.promote();
+        return it->second;
     }
     return nullptr;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 05cab3d..8612347 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -331,7 +331,12 @@
         return mTransactionCompletedThread;
     }
 
-    sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
+    // Converts from a binder handle to a Layer
+    // Returns nullptr if the handle does not point to an existing layer.
+    // Otherwise, returns a weak reference so that callers off the main-thread
+    // won't accidentally hold onto the last strong reference.
+    wp<Layer> fromHandle(const sp<IBinder>& handle);
+    wp<Layer> fromHandleLocked(const sp<IBinder>& handle) REQUIRES(mStateLock);
 
     // Inherit from ClientCache::ErasedRecipient
     void bufferErased(const client_cache_t& clientCacheId) override;
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 9630645..bf05f70 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -405,7 +405,6 @@
     auto& mutableUseFrameRateApi() { return mFlinger->useFrameRateApi; }
 
     auto fromHandle(const sp<IBinder>& handle) {
-        Mutex::Autolock _l(mFlinger->mStateLock);
         return mFlinger->fromHandle(handle);
     }
 
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index fbbb69c..2a48a22 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -322,7 +322,7 @@
 TEST_F(TransactionApplicationTest, FromHandle) {
     sp<IBinder> badHandle;
     auto ret = mFlinger.fromHandle(badHandle);
-    EXPECT_EQ(nullptr, ret.get());
+    EXPECT_EQ(nullptr, ret.promote().get());
 }
 } // namespace android