Only send surfaces to Listener that registered or applied transaction

We must not leak surface controls to processes that shouldn't know about
them.  With this change, we limit the listeners that receive a callback
for a surface control to those that 1) registered the surface control
for callback or 2) received and merged a transaction containing that surface
control to apply

Bug: 139439952
Test: build, boot, IPC_test, SurfaceFlinger_test, libsurfaceflinger_unittest

Change-Id: I4eccc3e72d60729c2f3aa7788db0c5c39fbf46b7
diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp
new file mode 100644
index 0000000..8a756a6
--- /dev/null
+++ b/services/surfaceflinger/tests/IPC_test.cpp
@@ -0,0 +1,351 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <limits>
+
+#include <ui/DisplayInfo.h>
+
+#include <utils/String8.h>
+
+#include "BufferGenerator.h"
+#include "utils/CallbackUtils.h"
+#include "utils/ColorUtils.h"
+#include "utils/TransactionUtils.h"
+
+namespace android {
+
+namespace test {
+
+using Transaction = SurfaceComposerClient::Transaction;
+using CallbackInfo = SurfaceComposerClient::CallbackInfo;
+using TCLHash = SurfaceComposerClient::TCLHash;
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+class TransactionHelper : public Transaction {
+public:
+    size_t getNumListeners() { return mListenerCallbacks.size(); }
+
+    std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
+    getListenerCallbacks() {
+        return mListenerCallbacks;
+    }
+};
+
+class IPCTestUtils {
+public:
+    static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
+                                bool finalState = false);
+    static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence);
+};
+
+class IIPCTest : public IInterface {
+public:
+    DECLARE_META_INTERFACE(IPCTest)
+    enum class Tag : uint32_t {
+        SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
+        InitClient,
+        CreateTransaction,
+        MergeAndApply,
+        VerifyCallbacks,
+        CleanUp,
+        Last,
+    };
+
+    virtual status_t setDeathToken(sp<IBinder>& token) = 0;
+
+    virtual status_t initClient() = 0;
+
+    virtual status_t createTransaction(TransactionHelper* outTransaction, uint32_t width,
+                                       uint32_t height) = 0;
+
+    virtual status_t mergeAndApply(TransactionHelper transaction) = 0;
+
+    virtual status_t verifyCallbacks() = 0;
+
+    virtual status_t cleanUp() = 0;
+};
+
+class BpIPCTest : public SafeBpInterface<IIPCTest> {
+public:
+    explicit BpIPCTest(const sp<IBinder>& impl) : SafeBpInterface<IIPCTest>(impl, "BpIPCTest") {}
+
+    status_t setDeathToken(sp<IBinder>& token) {
+        return callRemote<decltype(&IIPCTest::setDeathToken)>(Tag::SetDeathToken, token);
+    }
+
+    status_t initClient() { return callRemote<decltype(&IIPCTest::initClient)>(Tag::InitClient); }
+
+    status_t createTransaction(TransactionHelper* transaction, uint32_t width, uint32_t height) {
+        return callRemote<decltype(&IIPCTest::createTransaction)>(Tag::CreateTransaction,
+                                                                  transaction, width, height);
+    }
+
+    status_t mergeAndApply(TransactionHelper transaction) {
+        return callRemote<decltype(&IIPCTest::mergeAndApply)>(Tag::MergeAndApply, transaction);
+    }
+
+    status_t verifyCallbacks() {
+        return callRemote<decltype(&IIPCTest::verifyCallbacks)>(Tag::VerifyCallbacks);
+    }
+
+    status_t cleanUp() { return callRemote<decltype(&IIPCTest::cleanUp)>(Tag::CleanUp); }
+};
+
+IMPLEMENT_META_INTERFACE(IPCTest, "android.gfx.tests.IIPCTest")
+
+class onTestDeath : public IBinder::DeathRecipient {
+public:
+    void binderDied(const wp<IBinder>& /*who*/) override {
+        ALOGE("onTestDeath::binderDied, exiting");
+        exit(0);
+    }
+};
+
+sp<onTestDeath> getDeathToken() {
+    static sp<onTestDeath> token = new onTestDeath;
+    return token;
+}
+
+class BnIPCTest : public SafeBnInterface<IIPCTest> {
+public:
+    BnIPCTest() : SafeBnInterface("BnIPCTest") {}
+
+    status_t setDeathToken(sp<IBinder>& token) override {
+        return token->linkToDeath(getDeathToken());
+    }
+
+    status_t initClient() override {
+        mClient = new SurfaceComposerClient;
+        auto err = mClient->initCheck();
+        return err;
+    }
+
+    status_t createTransaction(TransactionHelper* transaction, uint32_t width, uint32_t height) {
+        if (transaction == nullptr) {
+            ALOGE("Error in createTransaction: transaction is nullptr");
+            return BAD_VALUE;
+        }
+        mSurfaceControl = mClient->createSurface(String8("parentProcessSurface"), 0, 0,
+                                                 PIXEL_FORMAT_RGBA_8888,
+                                                 ISurfaceComposerClient::eFXSurfaceBufferState,
+                                                 /*parent*/ nullptr);
+        sp<GraphicBuffer> gb;
+        sp<Fence> fence;
+        int err = IPCTestUtils::getBuffer(&gb, &fence);
+        if (err != NO_ERROR) return err;
+
+        TransactionUtils::fillGraphicBufferColor(gb,
+                                                 {0, 0, static_cast<int32_t>(width),
+                                                  static_cast<int32_t>(height)},
+                                                 Color::RED);
+        transaction->setLayerStack(mSurfaceControl, 0)
+                .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
+                .setFrame(mSurfaceControl, Rect(0, 0, width, height))
+                .setBuffer(mSurfaceControl, gb)
+                .setAcquireFence(mSurfaceControl, fence)
+                .show(mSurfaceControl)
+                .addTransactionCompletedCallback(mCallbackHelper.function,
+                                                 mCallbackHelper.getContext());
+        return NO_ERROR;
+    }
+
+    status_t mergeAndApply(TransactionHelper /*transaction*/) {
+        // transaction.apply();
+        return NO_ERROR;
+    }
+
+    status_t verifyCallbacks() {
+        ExpectedResult expected;
+        expected.addSurface(ExpectedResult::Transaction::PRESENTED, mSurfaceControl);
+        EXPECT_NO_FATAL_FAILURE(IPCTestUtils::waitForCallback(mCallbackHelper, expected, true));
+        return NO_ERROR;
+    }
+
+    status_t cleanUp() {
+        if (mClient) mClient->dispose();
+        mSurfaceControl = nullptr;
+        IPCThreadState::self()->stopProcess();
+        return NO_ERROR;
+    }
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                        uint32_t /*flags*/) override {
+        EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
+        EXPECT_LT(code, static_cast<uint32_t>(IIPCTest::Tag::Last));
+        switch (static_cast<IIPCTest::Tag>(code)) {
+            case IIPCTest::Tag::SetDeathToken:
+                return callLocal(data, reply, &IIPCTest::setDeathToken);
+            case IIPCTest::Tag::InitClient:
+                return callLocal(data, reply, &IIPCTest::initClient);
+            case IIPCTest::Tag::CreateTransaction:
+                return callLocal(data, reply, &IIPCTest::createTransaction);
+            case IIPCTest::Tag::MergeAndApply:
+                return callLocal(data, reply, &IIPCTest::mergeAndApply);
+            case IIPCTest::Tag::VerifyCallbacks:
+                return callLocal(data, reply, &IIPCTest::verifyCallbacks);
+            case IIPCTest::Tag::CleanUp:
+                return callLocal(data, reply, &IIPCTest::cleanUp);
+            default:
+                return UNKNOWN_ERROR;
+        }
+    }
+
+private:
+    sp<SurfaceComposerClient> mClient;
+    sp<SurfaceControl> mSurfaceControl;
+    CallbackHelper mCallbackHelper;
+};
+
+class IPCTest : public ::testing::Test {
+public:
+    IPCTest() : mDeathRecipient(new BBinder), mRemote(initRemoteService()) {
+        ProcessState::self()->startThreadPool();
+    }
+    void SetUp() {
+        mClient = new SurfaceComposerClient;
+        ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+        mPrimaryDisplay = mClient->getInternalDisplayToken();
+        DisplayInfo info;
+        mClient->getDisplayInfo(mPrimaryDisplay, &info);
+        mDisplayWidth = info.w;
+        mDisplayHeight = info.h;
+
+        Transaction setupTransaction;
+        setupTransaction.setDisplayLayerStack(mPrimaryDisplay, 0);
+        setupTransaction.apply();
+    }
+
+protected:
+    sp<IIPCTest> initRemoteService();
+
+    sp<IBinder> mDeathRecipient;
+    sp<IIPCTest> mRemote;
+    sp<SurfaceComposerClient> mClient;
+    sp<IBinder> mPrimaryDisplay;
+    uint32_t mDisplayWidth;
+    uint32_t mDisplayHeight;
+    sp<SurfaceControl> sc;
+};
+
+status_t IPCTestUtils::getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+    static BufferGenerator bufferGenerator;
+    return bufferGenerator.get(outBuffer, outFence);
+}
+
+void IPCTestUtils::waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
+                                   bool finalState) {
+    CallbackData callbackData;
+    ASSERT_NO_FATAL_FAILURE(helper.getCallbackData(&callbackData));
+    EXPECT_NO_FATAL_FAILURE(expectedResult.verifyCallbackData(callbackData));
+
+    if (finalState) {
+        ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
+    }
+}
+
+sp<IIPCTest> IPCTest::initRemoteService() {
+    static std::mutex mMutex;
+    static sp<IIPCTest> remote;
+    const String16 serviceName("IPCTest");
+
+    std::unique_lock<decltype(mMutex)> lock;
+    if (remote == nullptr) {
+        pid_t forkPid = fork();
+        EXPECT_NE(forkPid, -1);
+
+        if (forkPid == 0) {
+            sp<IIPCTest> nativeService = new BnIPCTest;
+            if (!nativeService) {
+                ALOGE("null service...");
+            }
+            status_t err = defaultServiceManager()->addService(serviceName,
+                                                               IInterface::asBinder(nativeService));
+            if (err != NO_ERROR) {
+                ALOGE("failed to add service: %d", err);
+            }
+            ProcessState::self()->startThreadPool();
+            IPCThreadState::self()->joinThreadPool();
+            [&]() { exit(0); }();
+        }
+        sp<IBinder> binder = defaultServiceManager()->getService(serviceName);
+        remote = interface_cast<IIPCTest>(binder);
+        remote->setDeathToken(mDeathRecipient);
+    }
+    return remote;
+}
+
+TEST_F(IPCTest, MergeBasic) {
+    CallbackHelper helper1;
+    sc = mClient->createSurface(String8("parentProcessSurface"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+                                ISurfaceComposerClient::eFXSurfaceBufferState,
+                                /*parent*/ nullptr);
+    sp<GraphicBuffer> gb;
+    sp<Fence> fence;
+    int err = IPCTestUtils::getBuffer(&gb, &fence);
+    ASSERT_EQ(NO_ERROR, err);
+    TransactionUtils::fillGraphicBufferColor(gb,
+                                             {0, 0, static_cast<int32_t>(mDisplayWidth),
+                                              static_cast<int32_t>(mDisplayHeight)},
+                                             Color::RED);
+
+    Transaction transaction;
+    transaction.setLayerStack(sc, 0)
+            .setLayer(sc, std::numeric_limits<int32_t>::max() - 1)
+            .setBuffer(sc, gb)
+            .setAcquireFence(sc, fence)
+            .show(sc)
+            .addTransactionCompletedCallback(helper1.function, helper1.getContext());
+
+    TransactionHelper remote;
+    mRemote->initClient();
+    mRemote->createTransaction(&remote, mDisplayWidth / 2, mDisplayHeight / 2);
+    ASSERT_EQ(1, remote.getNumListeners());
+    auto remoteListenerCallbacks = remote.getListenerCallbacks();
+    auto remoteCallback = remoteListenerCallbacks.begin();
+    auto remoteCallbackInfo = remoteCallback->second;
+    auto remoteListenerScs = remoteCallbackInfo.surfaceControls;
+    ASSERT_EQ(1, remoteCallbackInfo.callbackIds.size());
+    ASSERT_EQ(1, remoteListenerScs.size());
+
+    sp<SurfaceControl> remoteSc = *(remoteListenerScs.begin());
+    transaction.merge(std::move(remote));
+    transaction.apply();
+
+    sleep(1);
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, sc);
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, remoteSc);
+    EXPECT_NO_FATAL_FAILURE(IPCTestUtils::waitForCallback(helper1, expected, true));
+
+    mRemote->verifyCallbacks();
+    mRemote->cleanUp();
+}
+
+} // namespace test
+} // namespace android