Merge "Add media.codec process to native stack dump list" into oc-dev
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d5498ed..6f430a3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -399,6 +399,10 @@
     Transform t = getTransform();
     win = t.transform(win);
 
+    if (!s.finalCrop.isEmpty()) {
+        win.intersect(s.finalCrop, &win);
+    }
+
     const sp<Layer>& p = getParent();
     // Now we need to calculate the parent bounds, so we can clip ourselves to those.
     // When calculating the parent bounds for purposes of clipping,
@@ -2543,7 +2547,25 @@
     }
 
     for (const sp<Layer>& child : mCurrentChildren) {
-        newParent->addChild(child);
+        // We don't call addChild as we need to delay updating the child's parent pointer until
+        // a transaction occurs. Remember a refresh could occur in between now and the next
+        // transaction, in which case the Layer's parent pointer would be updated, but changes
+        // made to the parent in the same transaction would not have applied.
+        // This means that the following kind of scenario wont work:
+        //
+        // 1. Existing and visible child and parent surface exist
+        // 2. Create new surface hidden
+        // 3. Open transaction
+        // 4. Show the new surface, and reparent the old surface's children to it.
+        // 5. Close transaction.
+        //
+        // If we were to update the parent pointer immediately, then the child surface
+        // could disappear for one frame as it pointed at the new parent which
+        // hasn't yet become visible as the transaction hasn't yet occurred.
+        //
+        // Instead we defer the reparenting to commitChildList which happens as part
+        // of the global transaction.
+        newParent->mCurrentChildren.add(child);
 
         sp<Client> client(child->mClientRef.promote());
         if (client != nullptr) {
@@ -2713,6 +2735,8 @@
 void Layer::commitChildList() {
     for (size_t i = 0; i < mCurrentChildren.size(); i++) {
         const auto& child = mCurrentChildren[i];
+        child->setParent(this);
+
         child->commitChildList();
     }
     mDrawingChildren = mCurrentChildren;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 68519a1..b7792c7 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -834,6 +834,38 @@
     }
 }
 
+TEST_F(ChildLayerTest, ChildLayerCropping) {
+    SurfaceComposerClient::openGlobalTransaction();
+    mChild->show();
+    mChild->setPosition(0, 0);
+    mFGSurfaceControl->setPosition(0, 0);
+    mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectChildColor(0, 0);
+        mCapture->expectChildColor(4, 4);
+        mCapture->expectBGColor(5, 5);
+    }
+}
+
+TEST_F(ChildLayerTest, ChildLayerFinalCropping) {
+    SurfaceComposerClient::openGlobalTransaction();
+    mChild->show();
+    mChild->setPosition(0, 0);
+    mFGSurfaceControl->setPosition(0, 0);
+    mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectChildColor(0, 0);
+        mCapture->expectChildColor(4, 4);
+        mCapture->expectBGColor(5, 5);
+    }
+}
+
 TEST_F(ChildLayerTest, ChildLayerConstraints) {
     SurfaceComposerClient::openGlobalTransaction();
     mChild->show();