Merge "Ensure input has CAP_BLOCK_SUSPEND"
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 7eee749..838d11d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -303,6 +303,9 @@
 // Location of the apex image.
 static const char* kApexImage = "/system/framework/apex.art";
 
+// Phenotype property name for enabling profiling the boot class path.
+static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath";
+
 class RunDex2Oat : public ExecVHelper {
   public:
     RunDex2Oat(int zip_fd,
@@ -402,7 +405,15 @@
             server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,
                                                                  ENABLE_APEX_IMAGE,
                                                                  /*default_value=*/ "");
-        if (use_apex_image == "true") {
+
+        std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", "");
+        profile_boot_class_path =
+            server_configurable_flags::GetServerConfigurableFlag(
+                RUNTIME_NATIVE_BOOT_NAMESPACE,
+                PROFILE_BOOT_CLASS_PATH,
+                /*default_value=*/ profile_boot_class_path);
+
+        if (use_apex_image == "true" || profile_boot_class_path == "true") {
           boot_image = StringPrintf("-Ximage:%s", kApexImage);
         } else {
           boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s");
@@ -709,8 +720,7 @@
                   const unique_fd& reference_profile_fd,
                   const std::vector<unique_fd>& apk_fds,
                   const std::vector<std::string>& dex_locations,
-                  bool copy_and_update,
-                  bool store_aggregation_counters) {
+                  bool copy_and_update) {
 
         // TODO(calin): Assume for now we run in the bg compile job (which is in
         // most of the invocation). With the current data flow, is not very easy or
@@ -742,10 +752,6 @@
             AddArg("--copy-and-update-profile-key");
         }
 
-        if (store_aggregation_counters) {
-            AddArg("--store-aggregation-counters");
-        }
-
         // Do not add after dex2oat_flags, they should override others for debugging.
         PrepareArgs(profman_bin);
     }
@@ -753,14 +759,12 @@
     void SetupMerge(const std::vector<unique_fd>& profiles_fd,
                     const unique_fd& reference_profile_fd,
                     const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
-                    const std::vector<std::string>& dex_locations = std::vector<std::string>(),
-                    bool store_aggregation_counters = false) {
+                    const std::vector<std::string>& dex_locations = std::vector<std::string>()) {
         SetupArgs(profiles_fd,
                   reference_profile_fd,
                   apk_fds,
                   dex_locations,
-                  /*copy_and_update=*/false,
-                  store_aggregation_counters);
+                  /*copy_and_update=*/false);
     }
 
     void SetupCopyAndUpdate(unique_fd&& profile_fd,
@@ -777,8 +781,7 @@
                   reference_profile_fd_,
                   apk_fds_,
                   dex_locations,
-                  /*copy_and_update=*/true,
-                  /*store_aggregation_counters=*/false);
+                  /*copy_and_update=*/true);
     }
 
     void SetupDump(const std::vector<unique_fd>& profiles_fd,
@@ -792,8 +795,7 @@
                   reference_profile_fd,
                   apk_fds,
                   dex_locations,
-                  /*copy_and_update=*/false,
-                  /*store_aggregation_counters=*/false);
+                  /*copy_and_update=*/false);
     }
 
     void Exec() {
@@ -2828,8 +2830,7 @@
         args.SetupMerge(profiles_fd,
                         snapshot_fd,
                         apk_fds,
-                        dex_locations,
-                        /*store_aggregation_counters=*/true);
+                        dex_locations);
         pid_t pid = fork();
         if (pid == 0) {
             /* child -- drop privileges before continuing */
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 129558b..b98e48b 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -34,7 +34,8 @@
     CREATE_WITH_SURFACE_PARENT,
     CLEAR_LAYER_FRAME_STATS,
     GET_LAYER_FRAME_STATS,
-    LAST = GET_LAYER_FRAME_STATS,
+    MIRROR_SURFACE,
+    LAST = MIRROR_SURFACE,
 };
 
 } // Anonymous namespace
@@ -80,6 +81,12 @@
                 &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GET_LAYER_FRAME_STATS, handle,
                                                               outStats);
     }
+
+    status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) override {
+        return callRemote<decltype(&ISurfaceComposerClient::mirrorSurface)>(Tag::MIRROR_SURFACE,
+                                                                            mirrorFromHandle,
+                                                                            outHandle);
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -105,6 +112,8 @@
             return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats);
         case Tag::GET_LAYER_FRAME_STATS:
             return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats);
+        case Tag::MIRROR_SURFACE:
+            return callLocal(data, reply, &ISurfaceComposerClient::mirrorSurface);
     }
 }
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index fb9d742..e490d6d 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1087,6 +1087,12 @@
     case NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT:
         res = dispatchSetDequeueTimeout(args);
         break;
+    case NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION:
+        res = dispatchGetLastDequeueDuration(args);
+        break;
+    case NATIVE_WINDOW_GET_LAST_QUEUE_DURATION:
+        res = dispatchGetLastQueueDuration(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -1303,6 +1309,18 @@
     return setDequeueTimeout(timeout);
 }
 
+int Surface::dispatchGetLastDequeueDuration(va_list args) {
+    int64_t* lastDequeueDuration = va_arg(args, int64_t*);
+    *lastDequeueDuration = mLastDequeueDuration;
+    return NO_ERROR;
+}
+
+int Surface::dispatchGetLastQueueDuration(va_list args) {
+    int64_t* lastQueueDuration = va_arg(args, int64_t*);
+    *lastQueueDuration = mLastQueueDuration;
+    return NO_ERROR;
+}
+
 bool Surface::transformToDisplayInverse() {
     return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
             NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 547e5f1..7b256f5 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1505,6 +1505,20 @@
     return err;
 }
 
+sp<SurfaceControl> SurfaceComposerClient::mirrorSurface(SurfaceControl* mirrorFromSurface) {
+    if (mirrorFromSurface == nullptr) {
+        return nullptr;
+    }
+
+    sp<IBinder> handle;
+    sp<IBinder> mirrorFromHandle = mirrorFromSurface->getHandle();
+    status_t err = mClient->mirrorSurface(mirrorFromHandle, &handle);
+    if (err == NO_ERROR) {
+        return new SurfaceControl(this, handle, nullptr, true /* owned */);
+    }
+    return nullptr;
+}
+
 status_t SurfaceComposerClient::clearLayerFrameStats(const sp<IBinder>& token) const {
     if (mStatus != NO_ERROR) {
         return mStatus;
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 32ac9e8..5fe7ca5 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -76,6 +76,8 @@
      * Requires ACCESS_SURFACE_FLINGER permission
      */
     virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const = 0;
+
+    virtual status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) = 0;
 };
 
 class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 2527ec0..e582509 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -246,6 +246,8 @@
     int dispatchSetAutoPrerotation(va_list args);
     int dispatchGetLastDequeueStartTime(va_list args);
     int dispatchSetDequeueTimeout(va_list args);
+    int dispatchGetLastDequeueDuration(va_list args);
+    int dispatchGetLastQueueDuration(va_list args);
     bool transformToDisplayInverse();
 
 protected:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 15287e2..6676be4 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -245,6 +245,17 @@
                                                LayerMetadata metadata = LayerMetadata() // metadata
     );
 
+    // Creates a mirrored hierarchy for the mirrorFromSurface. This returns a SurfaceControl
+    // which is a parent of the root of the mirrored hierarchy.
+    //
+    //  Real Hierarchy    Mirror
+    //                      SC (value that's returned)
+    //                      |
+    //      A               A'
+    //      |               |
+    //      B               B'
+    sp<SurfaceControl> mirrorSurface(SurfaceControl* mirrorFromSurface);
+
     //! Create a virtual display
     static sp<IBinder> createDisplay(const String8& displayName, bool secure);
 
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index fecfa19..0ba01f4 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -33,6 +33,12 @@
     return res < 0 ? res : value;
 }
 
+static int64_t query64(ANativeWindow* window, int what) {
+    int64_t value;
+    int res = window->perform(window, what, &value);
+    return res < 0 ? res : value;
+}
+
 static bool isDataSpaceValid(ANativeWindow* window, int32_t dataSpace) {
     bool supported = false;
     switch (dataSpace) {
@@ -271,18 +277,16 @@
  * apex-stable
  **************************************************************************************************/
 
-int ANativeWindow_getLastDequeueDuration(ANativeWindow* window) {
-    return query(window, NATIVE_WINDOW_LAST_DEQUEUE_DURATION);
+int64_t ANativeWindow_getLastDequeueDuration(ANativeWindow* window) {
+    return query64(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION);
 }
 
-int ANativeWindow_getLastQueueDuration(ANativeWindow* window) {
-    return query(window, NATIVE_WINDOW_LAST_QUEUE_DURATION);
+int64_t ANativeWindow_getLastQueueDuration(ANativeWindow* window) {
+    return query64(window, NATIVE_WINDOW_GET_LAST_QUEUE_DURATION);
 }
 
 int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window) {
-    int64_t time;
-    int success = window->perform(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_START, &time);
-    return success < 0 ? success : time;
+    return query64(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_START);
 }
 
 int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout) {
diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h
index 9798c2f..869b22e 100644
--- a/libs/nativewindow/include/apex/window.h
+++ b/libs/nativewindow/include/apex/window.h
@@ -27,17 +27,17 @@
  * Retrieves how long it took for the last time a buffer was dequeued.
  *
  * \return a negative value on error, otherwise returns the duration in
- * microseconds.
+ * nanoseconds
  */
-int ANativeWindow_getLastDequeueDuration(ANativeWindow* window);
+int64_t ANativeWindow_getLastDequeueDuration(ANativeWindow* window);
 
 /**
  * Retrieves how long it took for the last time a buffer was queued.
  *
  * \return a negative value on error, otherwise returns the duration in
- * microseconds
+ * nanoseconds.
  */
-int ANativeWindow_getLastQueueDuration(ANativeWindow* window);
+int64_t ANativeWindow_getLastQueueDuration(ANativeWindow* window);
 
 /**
  * Retrieves the system time in nanoseconds when the last time a buffer
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 8f85007..1814ab5 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -63,9 +63,9 @@
 
 /* attributes queriable with query() */
 enum {
-    NATIVE_WINDOW_WIDTH     = 0,
-    NATIVE_WINDOW_HEIGHT    = 1,
-    NATIVE_WINDOW_FORMAT    = 2,
+    NATIVE_WINDOW_WIDTH = 0,
+    NATIVE_WINDOW_HEIGHT = 1,
+    NATIVE_WINDOW_FORMAT = 2,
 
     /* see ANativeWindowQuery in vndk/window.h */
     NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS = ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS,
@@ -147,11 +147,15 @@
 
     /*
      * Returns the duration of the last dequeueBuffer call in microseconds
+     * Deprecated: please use NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION in
+     * perform() instead, which supports nanosecond precision.
      */
     NATIVE_WINDOW_LAST_DEQUEUE_DURATION = 14,
 
     /*
      * Returns the duration of the last queueBuffer call in microseconds
+     * Deprecated: please use NATIVE_WINDOW_GET_LAST_QUEUE_DURATION in
+     * perform() instead, which supports nanosecond precision.
      */
     NATIVE_WINDOW_LAST_QUEUE_DURATION = 15,
 
@@ -241,6 +245,8 @@
     NATIVE_WINDOW_SET_AUTO_PREROTATION            = 35,
     NATIVE_WINDOW_GET_LAST_DEQUEUE_START          = 36,    /* private */
     NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT             = 37,    /* private */
+    NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION       = 38,    /* private */
+    NATIVE_WINDOW_GET_LAST_QUEUE_DURATION         = 39,    /* private */
     // clang-format on
 };
 
diff --git a/libs/nativewindow/tests/ANativeWindowTest.cpp b/libs/nativewindow/tests/ANativeWindowTest.cpp
index 4d2b8c8..6cf8291 100644
--- a/libs/nativewindow/tests/ANativeWindowTest.cpp
+++ b/libs/nativewindow/tests/ANativeWindowTest.cpp
@@ -74,7 +74,7 @@
 TEST_F(ANativeWindowTest, getLastDequeueDuration_noDequeue_returnsZero) {
     int result = ANativeWindow_getLastDequeueDuration(mWindow.get());
     EXPECT_EQ(0, result);
-    EXPECT_EQ(0, mWindow->getLastDequeueDuration() / 1000);
+    EXPECT_EQ(0, mWindow->getLastDequeueDuration());
 }
 
 TEST_F(ANativeWindowTest, getLastDequeueDuration_withDequeue_returnsTime) {
@@ -86,7 +86,7 @@
 
     result = ANativeWindow_getLastDequeueDuration(mWindow.get());
     EXPECT_GT(result, 0);
-    EXPECT_EQ(result, mWindow->getLastDequeueDuration() / 1000);
+    EXPECT_EQ(result, mWindow->getLastDequeueDuration());
 }
 
 TEST_F(ANativeWindowTest, getLastQueueDuration_noDequeue_returnsZero) {
@@ -118,7 +118,7 @@
 
     result = ANativeWindow_getLastQueueDuration(mWindow.get());
     EXPECT_GT(result, 0);
-    EXPECT_EQ(result, mWindow->getLastQueueDuration() / 1000);
+    EXPECT_EQ(result, mWindow->getLastQueueDuration());
 }
 
 TEST_F(ANativeWindowTest, getLastDequeueStartTime_noDequeue_returnsZero) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index aa51e23..4db9ae2 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2772,7 +2772,7 @@
           "yCursorPosition=%f, downTime=%" PRId64,
           args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
           args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
-          args->edgeFlags, args->xPrecision, args->yPrecision, arg->xCursorPosition,
+          args->edgeFlags, args->xPrecision, args->yPrecision, args->xCursorPosition,
           args->yCursorPosition, args->downTime);
     for (uint32_t i = 0; i < args->pointerCount; i++) {
         ALOGD("  Pointer %d: id=%d, toolType=%d, "
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 6bfd302..c7ed9b0 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -106,6 +106,10 @@
                                  nullptr, layer);
 }
 
+status_t Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) {
+    return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle);
+}
+
 status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
     sp<Layer> layer = getLayerUser(handle);
     if (layer == nullptr) {
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 74e4818..7d7cef8 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -62,6 +62,8 @@
                                              LayerMetadata metadata, sp<IBinder>* handle,
                                              sp<IGraphicBufferProducer>* gbp);
 
+    status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* handle);
+
     virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const;
 
     virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8b2f5e1..b9e95a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3397,6 +3397,35 @@
     return flags;
 }
 
+status_t SurfaceFlinger::mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
+                                     sp<IBinder>* outHandle) {
+    if (!mirrorFromHandle) {
+        return NAME_NOT_FOUND;
+    }
+
+    sp<Layer> mirrorLayer;
+    sp<Layer> mirrorFrom;
+    String8 uniqueName = getUniqueLayerName(String8("MirrorRoot"));
+
+    {
+        Mutex::Autolock _l(mStateLock);
+        mirrorFrom = fromHandle(mirrorFromHandle);
+        if (!mirrorFrom) {
+            return NAME_NOT_FOUND;
+        }
+
+        status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(),
+                                               outHandle, &mirrorLayer);
+        if (result != NO_ERROR) {
+            return result;
+        }
+
+        mirrorLayer->mClonedChild = mirrorFrom->createClone();
+    }
+
+    return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, nullptr, false);
+}
+
 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,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2ea8f78..a9a4276 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -623,6 +623,9 @@
                                   uint32_t h, uint32_t flags, LayerMetadata metadata,
                                   sp<IBinder>* outHandle, sp<Layer>* outLayer);
 
+    status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
+                         sp<IBinder>* outHandle);
+
     String8 getUniqueLayerName(const String8& name);
 
     // called when all clients have released all their references to
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index f422939..d021fc2 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -28,6 +28,7 @@
         "LayerTypeAndRenderTypeTransaction_test.cpp",
         "LayerTypeTransaction_test.cpp",
         "LayerUpdate_test.cpp",
+        "MirrorLayer_test.cpp",
         "MultiDisplayLayerBounds_test.cpp",
         "RelativeZ_test.cpp",
         "SetGeometry_test.cpp",
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
new file mode 100644
index 0000000..0bcac1a
--- /dev/null
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -0,0 +1,226 @@
+/*
+ * 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 "LayerTransactionTest.h"
+
+namespace android {
+
+class MirrorLayerTest : public LayerTransactionTest {
+protected:
+    virtual void SetUp() {
+        LayerTransactionTest::SetUp();
+        ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+        const auto display = SurfaceComposerClient::getInternalDisplayToken();
+        ASSERT_FALSE(display == nullptr);
+
+        mParentLayer = createColorLayer("Parent layer", Color::RED);
+        mChildLayer = createColorLayer("Child layer", Color::GREEN, mParentLayer.get());
+        asTransaction([&](Transaction& t) {
+            t.setDisplayLayerStack(display, 0);
+            t.setLayer(mParentLayer, INT32_MAX - 2).show(mParentLayer);
+            t.setCrop_legacy(mChildLayer, Rect(0, 0, 400, 400)).show(mChildLayer);
+            t.setPosition(mChildLayer, 50, 50);
+            t.setFlags(mParentLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
+            t.setFlags(mChildLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
+        });
+    }
+
+    virtual void TearDown() {
+        LayerTransactionTest::TearDown();
+        mParentLayer = 0;
+        mChildLayer = 0;
+    }
+
+    sp<SurfaceControl> mParentLayer;
+    sp<SurfaceControl> mChildLayer;
+};
+
+TEST_F(MirrorLayerTest, MirrorColorLayer) {
+    sp<SurfaceControl> grandchild =
+            createColorLayer("Grandchild layer", Color::BLUE, mChildLayer.get());
+    Transaction()
+            .setFlags(grandchild, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque)
+            .setCrop_legacy(grandchild, Rect(0, 0, 200, 200))
+            .show(grandchild)
+            .apply();
+
+    // Mirror mChildLayer
+    sp<SurfaceControl> mirrorLayer = mClient->mirrorSurface(mChildLayer.get());
+    ASSERT_NE(mirrorLayer, nullptr);
+
+    // Add mirrorLayer as child of mParentLayer so it's shown on the display
+    Transaction()
+            .reparent(mirrorLayer, mParentLayer->getHandle())
+            .setPosition(mirrorLayer, 500, 500)
+            .show(mirrorLayer)
+            .apply();
+
+    {
+        SCOPED_TRACE("Initial Mirror");
+        auto shot = screenshot();
+        // Grandchild mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+
+    // Set color to white on grandchild layer.
+    Transaction().setColor(grandchild, half3{1, 1, 1}).apply();
+    {
+        SCOPED_TRACE("Updated Grandchild Layer Color");
+        auto shot = screenshot();
+        // Grandchild mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+
+    // Set color to black on child layer.
+    Transaction().setColor(mChildLayer, half3{0, 0, 0}).apply();
+    {
+        SCOPED_TRACE("Updated Child Layer Color");
+        auto shot = screenshot();
+        // Grandchild mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK);
+    }
+
+    // Remove grandchild layer
+    Transaction().reparent(grandchild, nullptr).apply();
+    {
+        SCOPED_TRACE("Removed Grandchild Layer");
+        auto shot = screenshot();
+        // Grandchild mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::BLACK);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK);
+    }
+
+    // Remove child layer
+    Transaction().reparent(mChildLayer, nullptr).apply();
+    {
+        SCOPED_TRACE("Removed Child Layer");
+        auto shot = screenshot();
+        // Grandchild mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::RED);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::RED);
+    }
+
+    // Add grandchild layer to offscreen layer
+    Transaction().reparent(grandchild, mChildLayer->getHandle()).apply();
+    {
+        SCOPED_TRACE("Added Grandchild Layer");
+        auto shot = screenshot();
+        // Grandchild mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::RED);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::RED);
+    }
+
+    // Add child layer
+    Transaction().reparent(mChildLayer, mParentLayer->getHandle()).apply();
+    {
+        SCOPED_TRACE("Added Child Layer");
+        auto shot = screenshot();
+        // Grandchild mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK);
+    }
+}
+
+TEST_F(MirrorLayerTest, MirrorBufferLayer) {
+    sp<SurfaceControl> bufferQueueLayer =
+            createLayer("BufferQueueLayer", 200, 200, 0, mChildLayer.get());
+    fillBufferQueueLayerColor(bufferQueueLayer, Color::BLUE, 200, 200);
+    Transaction().show(bufferQueueLayer).apply();
+
+    sp<SurfaceControl> mirrorLayer = mClient->mirrorSurface(mChildLayer.get());
+    Transaction()
+            .reparent(mirrorLayer, mParentLayer->getHandle())
+            .setPosition(mirrorLayer, 500, 500)
+            .show(mirrorLayer)
+            .apply();
+
+    {
+        SCOPED_TRACE("Initial Mirror BufferQueueLayer");
+        auto shot = screenshot();
+        // Buffer mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+
+    fillBufferQueueLayerColor(bufferQueueLayer, Color::WHITE, 200, 200);
+    {
+        SCOPED_TRACE("Update BufferQueueLayer");
+        auto shot = screenshot();
+        // Buffer mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+
+    Transaction().reparent(bufferQueueLayer, nullptr).apply();
+    {
+        SCOPED_TRACE("Removed BufferQueueLayer");
+        auto shot = screenshot();
+        // Buffer mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::GREEN);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+
+    sp<SurfaceControl> bufferStateLayer =
+            createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState,
+                        mChildLayer.get());
+    fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200);
+    Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply();
+
+    {
+        SCOPED_TRACE("Initial Mirror BufferStateLayer");
+        auto shot = screenshot();
+        // Buffer mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+
+    fillBufferStateLayerColor(bufferStateLayer, Color::WHITE, 200, 200);
+    {
+        SCOPED_TRACE("Update BufferStateLayer");
+        auto shot = screenshot();
+        // Buffer mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+
+    Transaction().reparent(bufferStateLayer, nullptr).apply();
+    {
+        SCOPED_TRACE("Removed BufferStateLayer");
+        auto shot = screenshot();
+        // Buffer mirror
+        shot->expectColor(Rect(550, 550, 750, 750), Color::GREEN);
+        // Child mirror
+        shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
+    }
+}
+
+} // namespace android