Merge "Honor the property overrides for GLES." into qt-dev
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index 009dc52..639df7a 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -20,7 +20,6 @@
 namespace android {
 
 // must be kept in sync with definitions in AudioPlaybackConfiguration.java
-
 #define PLAYER_PIID_INVALID -1
 
 typedef enum {
@@ -40,6 +39,15 @@
     PLAYER_STATE_STOPPED  = 4,
 } player_state_t;
 
+// must be kept in sync with definitions in AudioManager.java
+#define RECORD_RIID_INVALID -1
+
+typedef enum {
+    RECORDER_STATE_UNKNOWN  = -1,
+    RECORDER_STATE_STARTED  = 0,
+    RECORDER_STATE_STOPPED  = 1,
+} recorder_state_t;
+
 }; // namespace android
 
 #endif // ANDROID_AUDIOMANAGER_H
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index d279bbd..d0642c6 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -36,6 +36,8 @@
         PLAYER_ATTRIBUTES                     = IBinder::FIRST_CALL_TRANSACTION + 1,
         PLAYER_EVENT                          = IBinder::FIRST_CALL_TRANSACTION + 2,
         RELEASE_PLAYER                        = IBinder::FIRST_CALL_TRANSACTION + 3,
+        TRACK_RECORDER                        = IBinder::FIRST_CALL_TRANSACTION + 4,
+        RECORDER_EVENT                        = IBinder::FIRST_CALL_TRANSACTION + 5,
     };
 
     DECLARE_META_INTERFACE(AudioManager)
@@ -48,6 +50,8 @@
                 audio_content_type_t content)= 0;
     /*oneway*/ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event) = 0;
     /*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0;
+    virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0;
+    /*oneway*/ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 180fd97..26c2a0d 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -37,6 +37,7 @@
         "/system/bin/surfaceflinger",
         "/system/bin/vehicle_network_service",
         "/vendor/bin/hw/android.hardware.media.omx@1.0-service", // media.codec
+        "/apex/com.android.media.swcodec/bin/mediaswcodec", // media.swcodec
         NULL,
 };
 
@@ -50,10 +51,13 @@
         "android.hardware.graphics.allocator@2.0::IAllocator",
         "android.hardware.graphics.composer@2.1::IComposer",
         "android.hardware.health@2.0::IHealth",
+        "android.hardware.media.c2@1.0::IComponentStore",
         "android.hardware.media.omx@1.0::IOmx",
         "android.hardware.media.omx@1.0::IOmxStore",
+        "android.hardware.power@1.3::IPower",
         "android.hardware.power.stats@1.0::IPowerStats",
         "android.hardware.sensors@1.0::ISensors",
+        "android.hardware.thermal@2.0::IThermal",
         "android.hardware.vr@1.0::IVr",
         NULL,
 };
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 55efcbf..23bfc02 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -84,6 +84,9 @@
     
     explicit SurfaceControl(const sp<SurfaceControl>& other);
 
+    SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
+                   const sp<IGraphicBufferProducer>& gbp, bool owned);
+
 private:
     // can't be copied
     SurfaceControl& operator = (SurfaceControl& rhs);
@@ -92,12 +95,6 @@
     friend class SurfaceComposerClient;
     friend class Surface;
 
-    SurfaceControl(
-            const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& handle,
-            const sp<IGraphicBufferProducer>& gbp,
-            bool owned);
-
     ~SurfaceControl();
 
     sp<Surface> generateSurfaceLocked() const;
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index cd1182c..086a324 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -575,7 +575,9 @@
             float applyCornerRadius(vec2 cropCoords)
             {
                 vec2 position = cropCoords - cropCenter;
-                vec2 dist = abs(position) + vec2(cornerRadius) - cropCenter;
+                // Increase precision here so that a large corner radius doesn't
+                // cause floating point error
+                highp vec2 dist = abs(position) + vec2(cornerRadius) - cropCenter;
                 float plane = length(max(dist, vec2(0.0)));
                 return 1.0 - clamp(plane - cornerRadius, 0.0, 1.0);
             }
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 755418e..0407d88 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -82,6 +82,9 @@
         "frameworks/native/include",
     ],
 
+    // Uncomment the following line to enable VALIDATE_REGIONS traces
+    //defaults: ["libui-validate-regions-defaults"],
+
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
         "android.hardware.graphics.allocator@2.0",
@@ -98,7 +101,6 @@
         "libhwbinder",
         "libsync",
         "libutils",
-        "libutilscallstack",
         "liblog",
     ],
 
@@ -175,6 +177,13 @@
     ],
 }
 
+// defaults to enable VALIDATE_REGIONS traces
+cc_defaults {
+    name: "libui-validate-regions-defaults",
+    shared_libs: ["libutilscallstack"],
+    cflags: ["-DVALIDATE_REGIONS"],
+}
+
 subdirs = [
     "tests",
     "tools",
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 224dc2c..55e3b99 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -22,7 +22,6 @@
 #include <android-base/stringprintf.h>
 
 #include <utils/Log.h>
-#include <utils/CallStack.h>
 
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -31,10 +30,18 @@
 #include <private/ui/RegionHelper.h>
 
 // ----------------------------------------------------------------------------
-#define VALIDATE_REGIONS        (false)
+
+// ### VALIDATE_REGIONS ###
+// To enable VALIDATE_REGIONS traces, use the "libui-validate-regions-defaults"
+// in Android.bp. Do not #define VALIDATE_REGIONS here as it requires extra libs.
+
 #define VALIDATE_WITH_CORECG    (false)
 // ----------------------------------------------------------------------------
 
+#if defined(VALIDATE_REGIONS)
+#include <utils/CallStack.h>
+#endif
+
 #if VALIDATE_WITH_CORECG
 #include <core/SkRegion.h>
 #endif
@@ -67,7 +74,7 @@
 Region::Region(const Region& rhs)
     : mStorage(rhs.mStorage)
 {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(rhs, "rhs copy-ctor");
 #endif
 }
@@ -203,7 +210,7 @@
             outputRegion.mStorage, direction_LTR);
     outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds
 
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(outputRegion, "T-Junction free region");
 #endif
 
@@ -212,7 +219,7 @@
 
 Region& Region::operator = (const Region& rhs)
 {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(*this, "this->operator=");
     validate(rhs, "rhs.operator=");
 #endif
@@ -599,10 +606,12 @@
         result = false;
         ALOGE_IF(!silent, "%s: mStorage size is 2, which is never valid", name);
     }
+#if defined(VALIDATE_REGIONS)
     if (result == false && !silent) {
         reg.dump(name);
         CallStack stack(LOG_TAG);
     }
+#endif
     return result;
 }
 
@@ -610,7 +619,7 @@
         const Region& lhs,
         const Region& rhs, int dx, int dy)
 {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(lhs, "boolean_operation (before): lhs");
     validate(rhs, "boolean_operation (before): rhs");
     validate(dst, "boolean_operation (before): dst");
@@ -630,7 +639,7 @@
         operation(r);
     }
 
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(lhs, "boolean_operation: lhs");
     validate(rhs, "boolean_operation: rhs");
     validate(dst, "boolean_operation: dst");
@@ -728,7 +737,7 @@
         return;
     }
 
-#if VALIDATE_WITH_CORECG || VALIDATE_REGIONS
+#if VALIDATE_WITH_CORECG || defined(VALIDATE_REGIONS)
     boolean_operation(op, dst, lhs, Region(rhs), dx, dy);
 #else
     size_t lhs_count;
@@ -760,7 +769,7 @@
 void Region::translate(Region& reg, int dx, int dy)
 {
     if ((dx || dy) && !reg.isEmpty()) {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
         validate(reg, "translate (before)");
 #endif
         size_t count = reg.mStorage.size();
@@ -770,7 +779,7 @@
             rects++;
             count--;
         }
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
         validate(reg, "translate (after)");
 #endif
     }
@@ -789,7 +798,7 @@
 }
 
 status_t Region::flatten(void* buffer, size_t size) const {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(*this, "Region::flatten");
 #endif
     if (size < getFlattenedSize()) {
@@ -836,7 +845,7 @@
         result.mStorage.push_back(rect);
     }
 
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(result, "Region::unflatten");
 #endif
 
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
index b9b0706..f5d4826 100644
--- a/services/audiomanager/IAudioManager.cpp
+++ b/services/audiomanager/IAudioManager.cpp
@@ -98,6 +98,30 @@
         data.writeInt32((int32_t) piid);
         return remote()->transact(RELEASE_PLAYER, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeStrongBinder(recorder);
+        // get new RIId in reply
+        const status_t res = remote()->transact(TRACK_RECORDER, data, &reply, 0);
+        if (res != OK || reply.readExceptionCode() != 0) {
+            ALOGE("trackRecorder() failed, riid is %d", RECORD_RIID_INVALID);
+            return RECORD_RIID_INVALID;
+        } else {
+            const audio_unique_id_t riid = (audio_unique_id_t) reply.readInt32();
+            ALOGV("trackRecorder() returned riid %d", riid);
+            return riid;
+        }
+    }
+
+    virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32((int32_t) riid);
+        data.writeInt32((int32_t) event);
+        return remote()->transact(RECORDER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 2549d9b..b874411 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -3214,17 +3214,29 @@
 
             std::vector<sp<InputWindowHandle>> newHandles;
             for (const sp<InputWindowHandle>& handle : inputWindowHandles) {
-                if (!handle->updateInfo() || (getInputChannelLocked(handle->getToken()) == nullptr
-                        && handle->getInfo()->portalToDisplayId == ADISPLAY_ID_NONE)) {
-                    ALOGE("Window handle %s has no registered input channel",
-                            handle->getName().c_str());
+                if (!handle->updateInfo()) {
+                    // handle no longer valid
+                    continue;
+                }
+                const InputWindowInfo* info = handle->getInfo();
+
+                if ((getInputChannelLocked(handle->getToken()) == nullptr &&
+                     info->portalToDisplayId == ADISPLAY_ID_NONE)) {
+                    const bool noInputChannel =
+                            info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
+                    const bool canReceiveInput =
+                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
+                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
+                    if (canReceiveInput && !noInputChannel) {
+                        ALOGE("Window handle %s has no registered input channel",
+                              handle->getName().c_str());
+                    }
                     continue;
                 }
 
-                if (handle->getInfo()->displayId != displayId) {
+                if (info->displayId != displayId) {
                     ALOGE("Window %s updated by wrong display %d, should belong to display %d",
-                        handle->getName().c_str(), displayId,
-                        handle->getInfo()->displayId);
+                          handle->getName().c_str(), displayId, info->displayId);
                     continue;
                 }
 
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 6570704..659329e 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -767,6 +767,10 @@
                     checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
             ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
         }
+
+        if (err == NO_ERROR) {
+            info.isActive = true;
+        }
     }
 }
 
@@ -774,7 +778,7 @@
     if (mSensors == nullptr) return;
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i< mActivationCount.size(); ++i) {
-        const Info& info = mActivationCount.valueAt(i);
+        Info& info = mActivationCount.editValueAt(i);
         // Check if this sensor has been activated previously and disable it.
         if (info.batchParams.size() > 0) {
            const int sensor_handle = mActivationCount.keyAt(i);
@@ -788,6 +792,8 @@
                mDisabledClients.add(info.batchParams.keyAt(j));
                ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
            }
+
+           info.isActive = false;
         }
     }
 }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index cbdd473..0269990 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1381,15 +1381,6 @@
             ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
             mActiveSensors.removeItemsAt(i, 1);
             mActiveVirtualSensors.erase(handle);
-
-            // If this is the last connection, then mark the RecentEventLogger as stale. This is
-            // critical for on-change events since the previous event is sent to a client if the
-            // sensor is already active. If two clients request the sensor at the same time, one
-            // of the clients would receive a stale event.
-            auto logger = mRecentEvent.find(handle);
-            if (logger != mRecentEvent.end()) {
-                logger->second->setLastEventStale();
-            }
             delete rec;
             size--;
         } else {
@@ -1444,6 +1435,20 @@
         if (sensor->isVirtual()) {
             mActiveVirtualSensors.emplace(handle);
         }
+
+        // There was no SensorRecord for this sensor which means it was previously disabled. Mark
+        // the recent event as stale to ensure that the previous event is not sent to a client. This
+        // ensures on-change events that were generated during a previous sensor activation are not
+        // erroneously sent to newly connected clients, especially if a second client registers for
+        // an on-change sensor before the first client receives the updated event. Once an updated
+        // event is received, the recent events will be marked as current, and any new clients will
+        // immediately receive the most recent event.
+        if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
+            auto logger = mRecentEvent.find(handle);
+            if (logger != mRecentEvent.end()) {
+                logger->second->setLastEventStale();
+            }
+        }
     } else {
         if (rec->addConnection(connection)) {
             // this sensor is already activated, but we are adding a connection that uses it.
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index e54b460..482c723 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -76,18 +76,9 @@
                                uint32_t flags, const sp<IBinder>& parentHandle,
                                LayerMetadata metadata, sp<IBinder>* handle,
                                sp<IGraphicBufferProducer>* gbp) {
-    sp<Layer> parent = nullptr;
-    if (parentHandle != nullptr) {
-        auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
-        parent = layerHandle->owner.promote();
-        if (parent == nullptr) {
-            return NAME_NOT_FOUND;
-        }
-    }
-
     // We rely on createLayer to check permissions.
     return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
-                                 &parent);
+                                 parentHandle);
 }
 
 status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
@@ -104,9 +95,8 @@
         return BAD_VALUE;
     }
 
-    sp<IBinder> parentHandle = layer->getHandle();
-
-    return createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), handle, gbp);
+    return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
+                                 nullptr, layer);
 }
 
 status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
index 67bea4b..ab01c20 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
@@ -33,12 +33,6 @@
 
     LayerFECompositionState frontEnd;
 
-    /*
-     * RE state
-     */
-
-    renderengine::Mesh reMesh{renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2};
-
     // Debugging
     void dump(std::string& result) const;
 };
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b6323a2..46ca0b6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -130,7 +130,6 @@
     }
 
     mFrameTracker.logAndResetStats(mName);
-
     mFlinger->onLayerDestroyed();
 }
 
@@ -205,6 +204,11 @@
 
 sp<IBinder> Layer::getHandle() {
     Mutex::Autolock _l(mLock);
+    if (mGetHandleCalled) {
+        ALOGE("Get handle called twice" );
+        return nullptr;
+    }
+    mGetHandleCalled = true;
     return new Handle(mFlinger, this);
 }
 
@@ -382,13 +386,6 @@
     win.right -= roundedCornersCrop.left;
     win.top -= roundedCornersCrop.top;
     win.bottom -= roundedCornersCrop.top;
-
-    renderengine::Mesh::VertexArray<vec2> cropCoords(
-            getCompositionLayer()->editState().reMesh.getCropCoordArray<vec2>());
-    cropCoords[0] = vec2(win.left, win.top);
-    cropCoords[1] = vec2(win.left, win.top + win.getHeight());
-    cropCoords[2] = vec2(win.right, win.top + win.getHeight());
-    cropCoords[3] = vec2(win.right, win.top);
 }
 
 void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const {
@@ -540,18 +537,6 @@
     return true;
 }
 
-void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
-                            float alpha) const {
-    auto& engine(mFlinger->getRenderEngine());
-    computeGeometry(renderArea, getCompositionLayer()->editState().reMesh, false);
-    engine.setupFillWithColor(red, green, blue, alpha);
-    engine.drawMesh(getCompositionLayer()->getState().reMesh);
-}
-
-void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
-    clearWithOpenGL(renderArea, 0, 0, 0, 0);
-}
-
 void Layer::setCompositionType(const sp<const DisplayDevice>& display,
                                Hwc2::IComposerClient::Composition type) {
     const auto outputLayer = findOutputLayerForDisplay(display);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c76394c..3712b2a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -603,9 +603,6 @@
     bool hasHwcLayer(const sp<const DisplayDevice>& displayDevice);
     HWC2::Layer* getHwcLayer(const sp<const DisplayDevice>& displayDevice);
 
-    // -----------------------------------------------------------------------
-    void clearWithOpenGL(const RenderArea& renderArea) const;
-
     inline const State& getDrawingState() const { return mDrawingState; }
     inline const State& getCurrentState() const { return mCurrentState; }
     inline State& getCurrentState() { return mCurrentState; }
@@ -729,12 +726,7 @@
      * crop coordinates, transforming them into layer space.
      */
     void setupRoundedCornersCropCoordinates(Rect win, const FloatRect& roundedCornersCrop) const;
-
-    // drawing
-    void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
-                         float alpha) const;
     void setParent(const sp<Layer>& layer);
-
     LayerVector makeTraversalList(LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers);
     void addZOrderRelative(const wp<Layer>& relative);
     void removeZOrderRelative(const wp<Layer>& relative);
@@ -799,6 +791,8 @@
         wp<Layer> owner;
     };
 
+    // Creates a new handle each time, so we only expect
+    // this to be called once.
     sp<IBinder> getHandle();
     const String8& getName() const;
     virtual void notifyAvailableFrames() {}
@@ -932,6 +926,8 @@
     FloatRect mScreenBounds;
 
     void setZOrderRelativeOf(const wp<Layer>& relativeOf);
+
+    bool mGetHandleCalled = false;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index e70bfe4..fcde8da 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -31,9 +31,9 @@
     const status_t ret =
             mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0,
                                  PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor,
-                                 LayerMetadata(), &mIBinder, &mGbp, &mLayer);
+                                 LayerMetadata(), &mIBinder, &mGbp, nullptr);
     if (ret) {
-        ALOGE("failed to color layer");
+        ALOGE("failed to create color layer");
         return false;
     }
 
@@ -47,7 +47,7 @@
 void RefreshRateOverlay::changeRefreshRate(RefreshRateType type) {
     const half3& color = (type == RefreshRateType::PERFORMANCE) ? GREEN : RED;
     mLayer->setColor(color);
-    mFlinger.setTransactionFlags(eTransactionMask);
+    mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
 }
 
 }; // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 1b154a4..88d2638 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -318,12 +318,24 @@
 
 void Scheduler::updateFpsBasedOnContent() {
     uint32_t refreshRate = std::round(mLayerHistory.getDesiredRefreshRate());
-    ATRACE_INT("ContentFPS", refreshRate);
-    if (refreshRate > 0) {
-        contentChangeRefreshRate(ContentFeatureState::CONTENT_DETECTION_ON, refreshRate);
-    } else {
-        contentChangeRefreshRate(ContentFeatureState::CONTENT_DETECTION_OFF, 0);
+    RefreshRateType newRefreshRateType;
+    {
+        std::lock_guard<std::mutex> lock(mFeatureStateLock);
+        if (mContentRefreshRate == refreshRate) {
+            return;
+        }
+        mContentRefreshRate = refreshRate;
+        ATRACE_INT("ContentFPS", mContentRefreshRate);
+
+        mCurrentContentFeatureState = refreshRate > 0 ? ContentFeatureState::CONTENT_DETECTION_ON
+                                                      : ContentFeatureState::CONTENT_DETECTION_OFF;
+        newRefreshRateType = calculateRefreshRateType();
+        if (mRefreshRateType == newRefreshRateType) {
+            return;
+        }
+        mRefreshRateType = newRefreshRateType;
     }
+    changeRefreshRate(newRefreshRateType, ConfigEvent::Changed);
 }
 
 void Scheduler::setChangeRefreshRateCallback(
@@ -365,24 +377,19 @@
     return stream.str();
 }
 
-void Scheduler::contentChangeRefreshRate(ContentFeatureState contentFeatureState,
-                                         uint32_t refreshRate) {
-    RefreshRateType newRefreshRateType;
-    {
-        std::lock_guard<std::mutex> lock(mFeatureStateLock);
-        mCurrentContentFeatureState = contentFeatureState;
-        mContentRefreshRate = refreshRate;
-        newRefreshRateType = calculateRefreshRateType();
-    }
-    changeRefreshRate(newRefreshRateType, ConfigEvent::Changed);
-}
-
 void Scheduler::timerChangeRefreshRate(IdleTimerState idleTimerState) {
     RefreshRateType newRefreshRateType;
     {
         std::lock_guard<std::mutex> lock(mFeatureStateLock);
+        if (mCurrentIdleTimerState == idleTimerState) {
+            return;
+        }
         mCurrentIdleTimerState = idleTimerState;
         newRefreshRateType = calculateRefreshRateType();
+        if (mRefreshRateType == newRefreshRateType) {
+            return;
+        }
+        mRefreshRateType = newRefreshRateType;
     }
     changeRefreshRate(newRefreshRateType, ConfigEvent::None);
 }
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 134dc0b..34327b5 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -193,8 +193,6 @@
     void expiredTimerCallback();
     // Sets vsync period.
     void setVsyncPeriod(const nsecs_t period);
-    // Media feature's function to change the refresh rate.
-    void contentChangeRefreshRate(ContentFeatureState contentFeatureState, uint32_t refreshRate);
     // Idle timer feature's function to change the refresh rate.
     void timerChangeRefreshRate(IdleTimerState idleTimerState);
     // Calculate the new refresh rate type
@@ -254,7 +252,8 @@
     ContentFeatureState mCurrentContentFeatureState GUARDED_BY(mFeatureStateLock) =
             ContentFeatureState::CONTENT_DETECTION_OFF;
     IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET;
-    uint32_t mContentRefreshRate;
+    uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock);
+    RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock);
 
     const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
 };
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3744f8b..d5a38e9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -980,7 +980,7 @@
         if (mPreviousPresentFence != Fence::NO_FENCE &&
             (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled)) {
             // fence has not signaled yet. wait for the next invalidate
-            repaintEverythingForHWC();
+            mEventQueue->invalidateForHWC();
             return true;
         }
 
@@ -1005,6 +1005,7 @@
         // display is not valid or we are already in the requested mode
         // on both cases there is nothing left to do
         std::lock_guard<std::mutex> lock(mActiveConfigLock);
+        mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
         mDesiredActiveConfigChanged = false;
         ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
         return false;
@@ -1017,6 +1018,8 @@
         std::lock_guard<std::mutex> lock(mActiveConfigLock);
         mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
         mDesiredActiveConfig.configId = display->getActiveConfig();
+        mDesiredActiveConfigChanged = false;
+        ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
         return false;
     }
     mUpcomingActiveConfig = desiredActiveConfig;
@@ -1028,7 +1031,7 @@
 
     // we need to submit an empty frame to HWC to start the process
     mCheckPendingFence = true;
-
+    mEventQueue->invalidateForHWC();
     return false;
 }
 
@@ -1444,10 +1447,6 @@
         return;
     }
 
-    if (desiredConfigId == display->getActiveConfig()) {
-        return;
-    }
-
     setDesiredActiveConfig({refreshRate, desiredConfigId, event});
 }
 
@@ -3398,21 +3397,31 @@
     engine.fillRegionWithColor(region, 0, 0, 0, 0);
 }
 
-status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
-        const sp<IBinder>& handle,
-        const sp<IGraphicBufferProducer>& gbc,
-        const sp<Layer>& lbc,
-        const sp<Layer>& parent,
-        bool addToCurrentState)
-{
+status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
+                                        const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
+                                        const sp<IBinder>& parentHandle,
+                                        const sp<Layer>& parentLayer, bool addToCurrentState) {
     // add this layer to the current state list
     {
         Mutex::Autolock _l(mStateLock);
+        sp<Layer> parent;
+        if (parentHandle != nullptr) {
+            parent = fromHandle(parentHandle);
+            if (parent == nullptr) {
+                return NAME_NOT_FOUND;
+            }
+        } else {
+            parent = parentLayer;
+        }
+
         if (mNumLayers >= MAX_LAYERS) {
             ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
                   MAX_LAYERS);
             return NO_MEMORY;
         }
+
+        mLayersByLocalBinderToken.emplace(handle->localBinder(), lbc);
+
         if (parent == nullptr && addToCurrentState) {
             mCurrentState.layersSortedByZ.add(lbc);
         } else if (parent == nullptr) {
@@ -3486,7 +3495,12 @@
             flushedATransaction = true;
         }
 
-        it = (transactionQueue.empty()) ? mTransactionQueues.erase(it) : std::next(it, 1);
+        if (transactionQueue.empty()) {
+            it = mTransactionQueues.erase(it);
+            mTransactionCV.broadcast();
+        } else {
+            std::next(it, 1);
+        }
     }
     return flushedATransaction;
 }
@@ -3559,7 +3573,22 @@
     }
 
     // If its TransactionQueue already has a pending TransactionState or if it is pending
-    if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
+    auto itr = mTransactionQueues.find(applyToken);
+    // if this is an animation frame, wait until prior animation frame has
+    // been applied by SF
+    if (flags & eAnimation) {
+        while (itr != mTransactionQueues.end()) {
+            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+            if (CC_UNLIKELY(err != NO_ERROR)) {
+                ALOGW_IF(err == TIMED_OUT,
+                         "setTransactionState timed out "
+                         "waiting for animation frame to apply");
+                break;
+            }
+            itr = mTransactionQueues.find(applyToken);
+        }
+    }
+    if (itr != mTransactionQueues.end() ||
         !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
         mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
                                                uncacheBuffer, listenerCallbacks, postTime,
@@ -4018,13 +4047,19 @@
 status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
                                      uint32_t h, PixelFormat format, uint32_t flags,
                                      LayerMetadata metadata, sp<IBinder>* handle,
-                                     sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
+                                     sp<IGraphicBufferProducer>* gbp,
+                                     const sp<IBinder>& parentHandle,
+                                     const sp<Layer>& parentLayer) {
     if (int32_t(w|h) < 0) {
         ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                 int(w), int(h));
         return BAD_VALUE;
     }
 
+    ALOG_ASSERT(parentLayer == nullptr || parentHandle == nullptr,
+            "Expected only one of parentLayer or parentHandle to be non-null. "
+            "Programmer error?");
+
     status_t result = NO_ERROR;
 
     sp<Layer> layer;
@@ -4088,8 +4123,8 @@
     }
 
     bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
-    result = addClientLayer(client, *handle, *gbp, layer, *parent,
-            addToCurrentState);
+    result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
+                            addToCurrentState);
     if (result != NO_ERROR) {
         return result;
     }
@@ -4206,6 +4241,16 @@
         mCurrentState.layersSortedByZ.remove(layer);
     }
     markLayerPendingRemovalLocked(layer);
+
+    auto it = mLayersByLocalBinderToken.begin();
+    while (it != mLayersByLocalBinderToken.end()) {
+        if (it->second == layer) {
+            it = mLayersByLocalBinderToken.erase(it);
+        } else {
+            it++;
+        }
+    }
+
     layer.clear();
 }
 
@@ -4856,6 +4901,9 @@
     result.append(mScheduler->doDump() + "\n");
     StringAppendF(&result, "+  Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off");
     result.append(mRefreshRateStats.doDump() + "\n");
+
+    result.append(mTimeStats->miniDump());
+    result.append("\n");
 }
 
 const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) {
@@ -5486,34 +5534,50 @@
         const bool mChildrenOnly;
     };
 
-    auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
-    auto parent = layerHandle->owner.promote();
-
-    if (parent == nullptr || parent->isRemovedFromCurrentState()) {
-        ALOGE("captureLayers called with a removed parent");
-        return NAME_NOT_FOUND;
-    }
-
-    const int uid = IPCThreadState::self()->getCallingUid();
-    const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
-    if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
-        ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
-        return PERMISSION_DENIED;
-    }
-
+    int reqWidth = 0;
+    int reqHeight = 0;
+    sp<Layer> parent;
     Rect crop(sourceCrop);
-    if (sourceCrop.width() <= 0) {
-        crop.left = 0;
-        crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
-    }
+    std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
 
-    if (sourceCrop.height() <= 0) {
-        crop.top = 0;
-        crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
-    }
+    {
+        Mutex::Autolock _l(mStateLock);
 
-    int32_t reqWidth = crop.width() * frameScale;
-    int32_t reqHeight = crop.height() * frameScale;
+        parent = fromHandle(layerHandleBinder);
+        if (parent == nullptr || parent->isRemovedFromCurrentState()) {
+            ALOGE("captureLayers called with an invalid or removed parent");
+            return NAME_NOT_FOUND;
+        }
+
+        const int uid = IPCThreadState::self()->getCallingUid();
+        const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
+        if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
+            ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
+            return PERMISSION_DENIED;
+        }
+
+        if (sourceCrop.width() <= 0) {
+            crop.left = 0;
+            crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
+        }
+
+        if (sourceCrop.height() <= 0) {
+            crop.top = 0;
+            crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
+        }
+        reqWidth = crop.width() * frameScale;
+        reqHeight = crop.height() * frameScale;
+
+        for (const auto& handle : excludeHandles) {
+            sp<Layer> excludeLayer = fromHandle(handle);
+            if (excludeLayer != nullptr) {
+                excludeLayers.emplace(excludeLayer);
+            } else {
+                ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
+                return NAME_NOT_FOUND;
+            }
+        }
+    } // mStateLock
 
     // really small crop or frameScale
     if (reqWidth <= 0) {
@@ -5523,18 +5587,6 @@
         reqHeight = 1;
     }
 
-    std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
-    for (const auto& handle : excludeHandles) {
-        BBinder* local = handle->localBinder();
-        if (local != nullptr) {
-            auto layerHandle = reinterpret_cast<Layer::Handle*>(local);
-            excludeLayers.emplace(layerHandle->owner.promote());
-        } else {
-            ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
-            return NAME_NOT_FOUND;
-        }
-    }
-
     LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly);
     auto traverseLayers = [parent, childrenOnly,
                            &excludeLayers](const LayerVector::Visitor& visitor) {
@@ -5889,6 +5941,18 @@
     mFlinger->setInputWindowsFinished();
 }
 
+sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
+    BBinder *b = handle->localBinder();
+    if (b == nullptr) {
+        return nullptr;
+    }
+    auto it = mLayersByLocalBinderToken.find(b);
+    if (it != mLayersByLocalBinderToken.end()) {
+        return it->second.promote();
+    }
+    return nullptr;
+}
+
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 13b2182..72e2ff9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -314,6 +314,8 @@
         return mTransactionCompletedThread;
     }
 
+    sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
+
 private:
     friend class BufferLayer;
     friend class BufferQueueLayer;
@@ -576,7 +578,8 @@
      */
     status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
                          PixelFormat format, uint32_t flags, LayerMetadata metadata,
-                         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
+                         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp,
+                         const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer = nullptr);
 
     status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
                                     uint32_t h, uint32_t flags, LayerMetadata metadata,
@@ -604,12 +607,10 @@
     void markLayerPendingRemovalLocked(const sp<Layer>& layer);
 
     // add a layer to SurfaceFlinger
-    status_t addClientLayer(const sp<Client>& client,
-            const sp<IBinder>& handle,
-            const sp<IGraphicBufferProducer>& gbc,
-            const sp<Layer>& lbc,
-            const sp<Layer>& parent,
-            bool addToCurrentState);
+    status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
+                            const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
+                            const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer,
+                            bool addToCurrentState);
 
     // Traverse through all the layers and compute and cache its bounds.
     void computeLayerBounds();
@@ -982,6 +983,9 @@
     std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays;
     std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
 
+    // protected by mStateLock
+    std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken;
+
     // don't use a lock for these, we don't care
     int mDebugRegion = 0;
     bool mDebugDisableHWC = false;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 740099e..c97a19b 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -67,6 +67,16 @@
     }
 }
 
+std::string TimeStats::miniDump() {
+    ATRACE_CALL();
+
+    std::string result = "TimeStats miniDump:\n";
+    std::lock_guard<std::mutex> lock(mMutex);
+    android::base::StringAppendF(&result, "Number of tracked layers is %zu\n",
+                                 mTimeStatsTracker.size());
+    return result;
+}
+
 void TimeStats::incrementTotalFrames() {
     if (!mEnabled.load()) return;
 
@@ -252,7 +262,8 @@
           postTime);
 
     std::lock_guard<std::mutex> lock(mMutex);
-    if (!mTimeStatsTracker.count(layerID) && layerNameIsValid(layerName)) {
+    if (!mTimeStatsTracker.count(layerID) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS &&
+        layerNameIsValid(layerName)) {
         mTimeStatsTracker[layerID].layerName = layerName;
     }
     if (!mTimeStatsTracker.count(layerID)) return;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index d8c0786..4e040a3 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -41,6 +41,7 @@
 
     virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
     virtual bool isEnabled() = 0;
+    virtual std::string miniDump();
 
     virtual void incrementTotalFrames() = 0;
     virtual void incrementMissedFrames() = 0;
@@ -112,6 +113,7 @@
 
     void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
     bool isEnabled() override;
+    std::string miniDump() override;
 
     void incrementTotalFrames() override;
     void incrementMissedFrames() override;
@@ -137,8 +139,6 @@
     void recordRefreshRate(uint32_t fps, nsecs_t duration) override;
     void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override;
 
-    // TODO(zzyiwei): Bound the timeStatsTracker with weighted LRU
-    // static const size_t MAX_NUM_LAYER_RECORDS = 200;
     static const size_t MAX_NUM_TIME_RECORDS = 64;
 
 private:
@@ -159,6 +159,8 @@
     std::unordered_map<int32_t, LayerRecord> mTimeStatsTracker;
     PowerTime mPowerTime;
     GlobalRecord mGlobalRecord;
+
+    static const size_t MAX_NUM_LAYER_RECORDS = 200;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 003ae7f..53a3611 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -19,6 +19,7 @@
     srcs: [
         "BufferGenerator.cpp",
         "Credentials_test.cpp",
+        "InvalidHandles_test.cpp",
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
         "Transaction_test.cpp",
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
new file mode 100644
index 0000000..42d1f5a
--- /dev/null
+++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <binder/Binder.h>
+
+#include <gtest/gtest.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
+#include <ui/Rect.h>
+
+namespace android {
+namespace {
+
+class NotALayer : public BBinder {};
+
+/**
+ * For all of these tests we make a SurfaceControl with an invalid layer handle
+ * and verify we aren't able to trick SurfaceFlinger.
+ */
+class InvalidHandleTest : public ::testing::Test {
+protected:
+    sp<SurfaceComposerClient> mScc;
+    sp<SurfaceControl> mNotSc;
+    void SetUp() override {
+        mScc = new SurfaceComposerClient;
+        ASSERT_EQ(NO_ERROR, mScc->initCheck());
+        mNotSc = makeNotSurfaceControl();
+    }
+
+    sp<SurfaceControl> makeNotSurfaceControl() {
+        return new SurfaceControl(mScc, new NotALayer(), nullptr, true);
+    }
+};
+
+TEST_F(InvalidHandleTest, createSurfaceInvalidHandle) {
+    auto notSc = makeNotSurfaceControl();
+    ASSERT_EQ(nullptr,
+              mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0,
+                                  notSc.get())
+                      .get());
+}
+
+TEST_F(InvalidHandleTest, captureLayersInvalidHandle) {
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    sp<GraphicBuffer> outBuffer;
+
+    ASSERT_EQ(NAME_NOT_FOUND,
+              sf->captureLayers(mNotSc->getHandle(), &outBuffer, Rect::EMPTY_RECT, 1.0f));
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 08fdb9d..b1634a8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -30,6 +30,7 @@
 
     MOCK_METHOD3(parseArgs, void(bool, const Vector<String16>&, std::string&));
     MOCK_METHOD0(isEnabled, bool());
+    MOCK_METHOD0(miniDump, std::string());
     MOCK_METHOD0(incrementTotalFrames, void());
     MOCK_METHOD0(incrementMissedFrames, void());
     MOCK_METHOD0(incrementClientCompositionFrames, void());