1 /*
2  * Copyright (C) 2018 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 #define LOG_TAG "SurfaceParcelable_test"
18 
19 #include <gtest/gtest.h>
20 
21 #include <binder/IServiceManager.h>
22 #include <binder/ProcessState.h>
23 #include <gui/BufferHubProducer.h>
24 #include <gui/BufferQueue.h>
25 #include <gui/view/Surface.h>
26 #include <utils/Log.h>
27 
28 namespace android {
29 
30 static const String16 kTestServiceName = String16("SurfaceParcelableTestService");
31 static const String16 kSurfaceName = String16("TEST_SURFACE");
32 static const uint32_t kBufferWidth = 100;
33 static const uint32_t kBufferHeight = 1;
34 static const uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
35 
36 enum SurfaceParcelableTestServiceCode {
37     CREATE_BUFFER_QUEUE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
38     CREATE_BUFFER_HUB_SURFACE,
39 };
40 
41 class SurfaceParcelableTestService : public BBinder {
42 public:
SurfaceParcelableTestService()43     SurfaceParcelableTestService() {
44         // BufferQueue
45         BufferQueue::createBufferQueue(&mBufferQueueProducer, &mBufferQueueConsumer);
46 
47         // BufferHub
48         dvr::ProducerQueueConfigBuilder configBuilder;
49         mProducerQueue = dvr::ProducerQueue::Create(configBuilder.SetDefaultWidth(kBufferWidth)
50                                                             .SetDefaultHeight(kBufferHeight)
51                                                             .SetDefaultFormat(kBufferFormat)
52                                                             .Build(),
53                                                     dvr::UsagePolicy{});
54         mBufferHubProducer = BufferHubProducer::Create(mProducerQueue);
55     }
56 
57     ~SurfaceParcelableTestService() = default;
58 
onTransact(uint32_t code,const Parcel &,Parcel * reply,uint32_t=0)59     virtual status_t onTransact(uint32_t code, const Parcel& /*data*/, Parcel* reply,
60                                 uint32_t /*flags*/ = 0) {
61         switch (code) {
62             case CREATE_BUFFER_QUEUE_SURFACE: {
63                 view::Surface surfaceShim;
64                 surfaceShim.name = kSurfaceName;
65                 surfaceShim.graphicBufferProducer = mBufferQueueProducer;
66                 return surfaceShim.writeToParcel(reply);
67             }
68             case CREATE_BUFFER_HUB_SURFACE: {
69                 view::Surface surfaceShim;
70                 surfaceShim.name = kSurfaceName;
71                 surfaceShim.graphicBufferProducer = mBufferHubProducer;
72                 return surfaceShim.writeToParcel(reply);
73             }
74             default:
75                 return UNKNOWN_TRANSACTION;
76         };
77     }
78 
79 protected:
80     sp<IGraphicBufferProducer> mBufferQueueProducer;
81     sp<IGraphicBufferConsumer> mBufferQueueConsumer;
82 
83     std::shared_ptr<dvr::ProducerQueue> mProducerQueue;
84     sp<IGraphicBufferProducer> mBufferHubProducer;
85 };
86 
runBinderServer()87 static int runBinderServer() {
88     ProcessState::self()->startThreadPool();
89 
90     sp<IServiceManager> sm = defaultServiceManager();
91     sp<SurfaceParcelableTestService> service = new SurfaceParcelableTestService;
92     sm->addService(kTestServiceName, service, false);
93 
94     ALOGI("Binder server running...");
95 
96     while (true) {
97         int stat, retval;
98         retval = wait(&stat);
99         if (retval == -1 && errno == ECHILD) {
100             break;
101         }
102     }
103 
104     ALOGI("Binder server exiting...");
105     return 0;
106 }
107 
108 class SurfaceParcelableTest : public ::testing::TestWithParam<uint32_t> {
109 protected:
SetUp()110     virtual void SetUp() {
111         mService = defaultServiceManager()->getService(kTestServiceName);
112         if (mService == nullptr) {
113             ALOGE("Failed to connect to the test service.");
114             return;
115         }
116 
117         ALOGI("Binder service is ready for client.");
118     }
119 
GetSurface(view::Surface * surfaceShim)120     status_t GetSurface(view::Surface* surfaceShim) {
121         ALOGI("...Test: %d", GetParam());
122 
123         uint32_t opCode = GetParam();
124         Parcel data;
125         Parcel reply;
126         status_t error = mService->transact(opCode, data, &reply);
127         if (error != NO_ERROR) {
128             ALOGE("Failed to get surface over binder, error=%d.", error);
129             return error;
130         }
131 
132         error = surfaceShim->readFromParcel(&reply);
133         if (error != NO_ERROR) {
134             ALOGE("Failed to get surface from parcel, error=%d.", error);
135             return error;
136         }
137 
138         return NO_ERROR;
139     }
140 
141 private:
142     sp<IBinder> mService;
143 };
144 
TEST_P(SurfaceParcelableTest,SendOverBinder)145 TEST_P(SurfaceParcelableTest, SendOverBinder) {
146     view::Surface surfaceShim;
147     EXPECT_EQ(GetSurface(&surfaceShim), NO_ERROR);
148     EXPECT_EQ(surfaceShim.name, kSurfaceName);
149     EXPECT_FALSE(surfaceShim.graphicBufferProducer == nullptr);
150 }
151 
152 INSTANTIATE_TEST_CASE_P(SurfaceBackends, SurfaceParcelableTest,
153                         ::testing::Values(CREATE_BUFFER_QUEUE_SURFACE, CREATE_BUFFER_HUB_SURFACE));
154 
155 } // namespace android
156 
main(int argc,char ** argv)157 int main(int argc, char** argv) {
158     pid_t pid = fork();
159     if (pid == 0) {
160         android::ProcessState::self()->startThreadPool();
161         ::testing::InitGoogleTest(&argc, argv);
162         return RUN_ALL_TESTS();
163 
164     } else {
165         ALOGI("Test process pid: %d.", pid);
166         return android::runBinderServer();
167     }
168 }
169