• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <binder/IInterface.h>
18 #include <binder/IPCThreadState.h>
19 #include <binder/IServiceManager.h>
20 #include <binder/ProcessState.h>
21 #include <gtest/gtest.h>
22 #include <gui/ISurfaceComposer.h>
23 #include <gui/LayerState.h>
24 #include <gui/Surface.h>
25 #include <gui/SurfaceComposerClient.h>
26 #include <ui/DisplayMode.h>
27 #include <utils/String8.h>
28 
29 #include <limits>
30 
31 #include <gui/test/CallbackUtils.h>
32 #include "BufferGenerator.h"
33 #include "utils/ColorUtils.h"
34 #include "utils/TransactionUtils.h"
35 
36 namespace android {
37 
38 namespace test {
39 
40 using Transaction = SurfaceComposerClient::Transaction;
41 using CallbackInfo = SurfaceComposerClient::CallbackInfo;
42 using TCLHash = SurfaceComposerClient::TCLHash;
43 using android::hardware::graphics::common::V1_1::BufferUsage;
44 
45 class TransactionHelper : public Transaction, public Parcelable {
46 public:
TransactionHelper()47     TransactionHelper() : Transaction() {}
getNumListeners()48     size_t getNumListeners() { return mListenerCallbacks.size(); }
49 
50     std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
getListenerCallbacks()51     getListenerCallbacks() {
52         return mListenerCallbacks;
53     }
writeToParcel(Parcel * parcel) const54     status_t writeToParcel(Parcel* parcel) const override {
55         return Transaction::writeToParcel(parcel);
56     }
57 
readFromParcel(const Parcel * parcel)58     status_t readFromParcel(const Parcel* parcel) override {
59         return Transaction::readFromParcel(parcel);
60     }
61 };
62 
63 class IPCTestUtils {
64 public:
65     static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
66                                 bool finalState = false);
67     static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence);
68 };
69 
70 class IIPCTest : public IInterface {
71 public:
72     DECLARE_META_INTERFACE(IPCTest)
73     enum class Tag : uint32_t {
74         SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
75         InitClient,
76         CreateTransaction,
77         MergeAndApply,
78         VerifyCallbacks,
79         CleanUp,
80         Last,
81     };
82 
83     virtual status_t setDeathToken(sp<IBinder>& token) = 0;
84 
85     virtual status_t initClient() = 0;
86 
87     virtual status_t createTransaction(TransactionHelper* outTransaction, uint32_t width,
88                                        uint32_t height) = 0;
89 
90     virtual status_t mergeAndApply(TransactionHelper transaction) = 0;
91 
92     virtual status_t verifyCallbacks() = 0;
93 
94     virtual status_t cleanUp() = 0;
95 };
96 
97 class BpIPCTest : public SafeBpInterface<IIPCTest> {
98 public:
BpIPCTest(const sp<IBinder> & impl)99     explicit BpIPCTest(const sp<IBinder>& impl) : SafeBpInterface<IIPCTest>(impl, "BpIPCTest") {}
100 
setDeathToken(sp<IBinder> & token)101     status_t setDeathToken(sp<IBinder>& token) {
102         return callRemote<decltype(&IIPCTest::setDeathToken)>(Tag::SetDeathToken, token);
103     }
104 
initClient()105     status_t initClient() { return callRemote<decltype(&IIPCTest::initClient)>(Tag::InitClient); }
106 
createTransaction(TransactionHelper * transaction,uint32_t width,uint32_t height)107     status_t createTransaction(TransactionHelper* transaction, uint32_t width, uint32_t height) {
108         return callRemote<decltype(&IIPCTest::createTransaction)>(Tag::CreateTransaction,
109                                                                   transaction, width, height);
110     }
111 
mergeAndApply(TransactionHelper transaction)112     status_t mergeAndApply(TransactionHelper transaction) {
113         return callRemote<decltype(&IIPCTest::mergeAndApply)>(Tag::MergeAndApply, transaction);
114     }
115 
verifyCallbacks()116     status_t verifyCallbacks() {
117         return callRemote<decltype(&IIPCTest::verifyCallbacks)>(Tag::VerifyCallbacks);
118     }
119 
cleanUp()120     status_t cleanUp() { return callRemote<decltype(&IIPCTest::cleanUp)>(Tag::CleanUp); }
121 };
122 
123 IMPLEMENT_META_INTERFACE(IPCTest, "android.gfx.tests.IIPCTest")
124 
125 class onTestDeath : public IBinder::DeathRecipient {
126 public:
binderDied(const wp<IBinder> &)127     void binderDied(const wp<IBinder>& /*who*/) override {
128         ALOGE("onTestDeath::binderDied, exiting");
129         exit(0);
130     }
131 };
132 
getDeathToken()133 sp<onTestDeath> getDeathToken() {
134     static sp<onTestDeath> token = new onTestDeath;
135     return token;
136 }
137 
138 class BnIPCTest : public SafeBnInterface<IIPCTest> {
139 public:
BnIPCTest()140     BnIPCTest() : SafeBnInterface("BnIPCTest") {}
141 
setDeathToken(sp<IBinder> & token)142     status_t setDeathToken(sp<IBinder>& token) override {
143         return token->linkToDeath(getDeathToken());
144     }
145 
initClient()146     status_t initClient() override {
147         mClient = sp<SurfaceComposerClient>::make();
148         auto err = mClient->initCheck();
149         return err;
150     }
151 
createTransaction(TransactionHelper * transaction,uint32_t width,uint32_t height)152     status_t createTransaction(TransactionHelper* transaction, uint32_t width, uint32_t height) {
153         if (transaction == nullptr) {
154             ALOGE("Error in createTransaction: transaction is nullptr");
155             return BAD_VALUE;
156         }
157         mSurfaceControl = mClient->createSurface(String8("parentProcessSurface"), 0, 0,
158                                                  PIXEL_FORMAT_RGBA_8888,
159                                                  ISurfaceComposerClient::eFXSurfaceBufferState,
160                                                  /*parent*/ nullptr);
161         sp<GraphicBuffer> gb;
162         sp<Fence> fence;
163         int err = IPCTestUtils::getBuffer(&gb, &fence);
164         if (err != NO_ERROR) return err;
165 
166         TransactionUtils::fillGraphicBufferColor(gb,
167                                                  {0, 0, static_cast<int32_t>(width),
168                                                   static_cast<int32_t>(height)},
169                                                  Color::RED);
170         transaction->setLayerStack(mSurfaceControl, ui::DEFAULT_LAYER_STACK)
171                 .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
172                 .setBuffer(mSurfaceControl, gb, fence)
173                 .show(mSurfaceControl)
174                 .addTransactionCompletedCallback(mCallbackHelper.function,
175                                                  mCallbackHelper.getContext());
176         return NO_ERROR;
177     }
178 
mergeAndApply(TransactionHelper)179     status_t mergeAndApply(TransactionHelper /*transaction*/) {
180         // transaction.apply();
181         return NO_ERROR;
182     }
183 
verifyCallbacks()184     status_t verifyCallbacks() {
185         ExpectedResult expected;
186         expected.addSurface(ExpectedResult::Transaction::PRESENTED, mSurfaceControl);
187         EXPECT_NO_FATAL_FAILURE(IPCTestUtils::waitForCallback(mCallbackHelper, expected, true));
188         return NO_ERROR;
189     }
190 
cleanUp()191     status_t cleanUp() {
192         if (mClient) mClient->dispose();
193         mSurfaceControl = nullptr;
194         IPCThreadState::self()->stopProcess();
195         return NO_ERROR;
196     }
197 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t)198     status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
199                         uint32_t /*flags*/) override {
200         EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
201         EXPECT_LT(code, static_cast<uint32_t>(IIPCTest::Tag::Last));
202         switch (static_cast<IIPCTest::Tag>(code)) {
203             case IIPCTest::Tag::SetDeathToken:
204                 return callLocal(data, reply, &IIPCTest::setDeathToken);
205             case IIPCTest::Tag::InitClient:
206                 return callLocal(data, reply, &IIPCTest::initClient);
207             case IIPCTest::Tag::CreateTransaction:
208                 return callLocal(data, reply, &IIPCTest::createTransaction);
209             case IIPCTest::Tag::MergeAndApply:
210                 return callLocal(data, reply, &IIPCTest::mergeAndApply);
211             case IIPCTest::Tag::VerifyCallbacks:
212                 return callLocal(data, reply, &IIPCTest::verifyCallbacks);
213             case IIPCTest::Tag::CleanUp:
214                 return callLocal(data, reply, &IIPCTest::cleanUp);
215             default:
216                 return UNKNOWN_ERROR;
217         }
218     }
219 
220 private:
221     sp<SurfaceComposerClient> mClient;
222     sp<SurfaceControl> mSurfaceControl;
223     CallbackHelper mCallbackHelper;
224 };
225 
226 class IPCTest : public ::testing::Test {
227 public:
IPCTest()228     IPCTest() : mDeathRecipient(new BBinder), mRemote(initRemoteService()) {
229         ProcessState::self()->startThreadPool();
230     }
SetUp()231     void SetUp() {
232         mClient = sp<SurfaceComposerClient>::make();
233         ASSERT_EQ(NO_ERROR, mClient->initCheck());
234 
235         const auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
236         ASSERT_FALSE(ids.empty());
237         mPrimaryDisplay = SurfaceComposerClient::getPhysicalDisplayToken(ids.front());
238         ui::DisplayMode mode;
239         mClient->getActiveDisplayMode(mPrimaryDisplay, &mode);
240         mDisplayWidth = mode.resolution.getWidth();
241         mDisplayHeight = mode.resolution.getHeight();
242 
243         Transaction setupTransaction;
244         setupTransaction.setDisplayLayerStack(mPrimaryDisplay, ui::DEFAULT_LAYER_STACK);
245         setupTransaction.apply();
246     }
247 
248 protected:
249     sp<IIPCTest> initRemoteService();
250 
251     sp<IBinder> mDeathRecipient;
252     sp<IIPCTest> mRemote;
253     sp<SurfaceComposerClient> mClient;
254     sp<IBinder> mPrimaryDisplay;
255     uint32_t mDisplayWidth;
256     uint32_t mDisplayHeight;
257     sp<SurfaceControl> sc;
258 };
259 
getBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)260 status_t IPCTestUtils::getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
261     static BufferGenerator bufferGenerator;
262     return bufferGenerator.get(outBuffer, outFence);
263 }
264 
waitForCallback(CallbackHelper & helper,const ExpectedResult & expectedResult,bool finalState)265 void IPCTestUtils::waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
266                                    bool finalState) {
267     CallbackData callbackData;
268     ASSERT_NO_FATAL_FAILURE(helper.getCallbackData(&callbackData));
269     EXPECT_NO_FATAL_FAILURE(expectedResult.verifyCallbackData(callbackData));
270 
271     if (finalState) {
272         ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
273     }
274 }
275 
initRemoteService()276 sp<IIPCTest> IPCTest::initRemoteService() {
277     static std::mutex mMutex;
278     static sp<IIPCTest> remote;
279     const String16 serviceName("IPCTest");
280 
281     std::unique_lock<decltype(mMutex)> lock;
282     if (remote == nullptr) {
283         pid_t forkPid = fork();
284         EXPECT_NE(forkPid, -1);
285 
286         if (forkPid == 0) {
287             sp<IIPCTest> nativeService = new BnIPCTest;
288             if (!nativeService) {
289                 ALOGE("null service...");
290             }
291             status_t err = defaultServiceManager()->addService(serviceName,
292                                                                IInterface::asBinder(nativeService));
293             if (err != NO_ERROR) {
294                 ALOGE("failed to add service: %d", err);
295             }
296             ProcessState::self()->startThreadPool();
297             IPCThreadState::self()->joinThreadPool();
298             [&]() { exit(0); }();
299         }
300         sp<IBinder> binder = defaultServiceManager()->waitForService(serviceName);
301         remote = interface_cast<IIPCTest>(binder);
302         remote->setDeathToken(mDeathRecipient);
303     }
304     return remote;
305 }
306 
TEST_F(IPCTest,MergeBasic)307 TEST_F(IPCTest, MergeBasic) {
308     CallbackHelper helper1;
309     sc = mClient->createSurface(String8("parentProcessSurface"), 0, 0, PIXEL_FORMAT_RGBA_8888,
310                                 ISurfaceComposerClient::eFXSurfaceBufferState,
311                                 /*parent*/ nullptr);
312     sp<GraphicBuffer> gb;
313     sp<Fence> fence;
314     int err = IPCTestUtils::getBuffer(&gb, &fence);
315     ASSERT_EQ(NO_ERROR, err);
316     TransactionUtils::fillGraphicBufferColor(gb,
317                                              {0, 0, static_cast<int32_t>(mDisplayWidth),
318                                               static_cast<int32_t>(mDisplayHeight)},
319                                              Color::RED);
320 
321     Transaction transaction;
322     transaction.setLayerStack(sc, ui::DEFAULT_LAYER_STACK)
323             .setLayer(sc, std::numeric_limits<int32_t>::max() - 1)
324             .setBuffer(sc, gb, fence)
325             .show(sc)
326             .addTransactionCompletedCallback(helper1.function, helper1.getContext());
327 
328     TransactionHelper remote;
329     mRemote->initClient();
330     mRemote->createTransaction(&remote, mDisplayWidth / 2, mDisplayHeight / 2);
331     ASSERT_EQ(1, remote.getNumListeners());
332     auto remoteListenerCallbacks = remote.getListenerCallbacks();
333     auto remoteCallback = remoteListenerCallbacks.begin();
334     auto remoteCallbackInfo = remoteCallback->second;
335     auto remoteListenerScs = remoteCallbackInfo.surfaceControls;
336     ASSERT_EQ(1, remoteCallbackInfo.callbackIds.size());
337     ASSERT_EQ(1, remoteListenerScs.size());
338 
339     sp<SurfaceControl> remoteSc = *(remoteListenerScs.begin());
340     transaction.merge(std::move(remote));
341     transaction.apply();
342 
343     sleep(1);
344     ExpectedResult expected;
345     expected.addSurface(ExpectedResult::Transaction::PRESENTED, sc);
346     expected.addSurface(ExpectedResult::Transaction::PRESENTED, remoteSc);
347     EXPECT_NO_FATAL_FAILURE(IPCTestUtils::waitForCallback(helper1, expected, true));
348 
349     mRemote->verifyCallbacks();
350     mRemote->cleanUp();
351 }
352 
353 } // namespace test
354 } // namespace android
355