1/*
2 * Copyright (C) 2014 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 <errno.h>
18#include <fcntl.h>
19#include <stdio.h>
20#include <stdlib.h>
21
22#include <gtest/gtest.h>
23#include <linux/android/binder.h>
24#include <binder/IBinder.h>
25#include <sys/mman.h>
26#include <poll.h>
27
28#define BINDER_DEV_NAME "/dev/binder"
29
30testing::Environment* binder_env;
31
32class BinderDriverInterfaceTestEnv : public ::testing::Environment {
33        virtual void SetUp() {
34            int ret;
35            uint32_t max_threads = 0;
36
37            m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC);
38            ASSERT_GE(m_binderFd, 0);
39            m_buffer = mmap(NULL, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0);
40            ASSERT_NE(m_buffer, (void *)NULL);
41            ret = ioctl(m_binderFd, BINDER_SET_MAX_THREADS, &max_threads);
42            EXPECT_EQ(0, ret);
43            EnterLooper();
44        }
45        virtual void TearDown() {
46            close(m_binderFd);
47        }
48    private:
49        int m_binderFd;
50        void *m_buffer;
51    public:
52        int getBinderFd(void) {
53            return m_binderFd;
54        }
55        void EnterLooper(void) {
56            int ret;
57            const uint32_t bc[] = {
58                BC_ENTER_LOOPER,
59            };
60            struct binder_write_read bwr = binder_write_read();
61            bwr.write_buffer = (uintptr_t)bc;
62            bwr.write_size = sizeof(bc);
63            ret = ioctl(m_binderFd, BINDER_WRITE_READ, &bwr);
64            EXPECT_EQ(0, ret);
65            if (ret < 0) {
66                    EXPECT_EQ(0, errno);
67            }
68            EXPECT_EQ(sizeof(bc), bwr.write_consumed);
69        }
70};
71
72class BinderDriverInterfaceTest : public ::testing::Test {
73    public:
74        virtual void SetUp() {
75            m_binderFd = static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->getBinderFd();
76        }
77        virtual void TearDown() {
78        }
79    protected:
80        /* The ioctl must either return 0, or if it doesn't errno should be accepted_errno */
81        void binderTestIoctlSuccessOrError(int cmd, void *arg, int accepted_errno) {
82            int ret;
83
84            ret = ioctl(m_binderFd, cmd, arg);
85            if (ret != 0) {
86                EXPECT_EQ(errno, accepted_errno);
87            }
88        }
89
90        void binderTestIoctlRetErr2(int cmd, void *arg, int expect_ret, int expect_errno, int accept_errno) {
91            int ret;
92
93            ret = ioctl(m_binderFd, cmd, arg);
94            EXPECT_EQ(expect_ret, ret);
95            if (ret < 0) {
96                if (errno != accept_errno)
97                    EXPECT_EQ(expect_errno, errno);
98            }
99        }
100        void binderTestIoctlErr2(int cmd, void *arg, int expect_errno, int accept_errno) {
101            binderTestIoctlRetErr2(cmd, arg, -1, expect_errno, accept_errno);
102        }
103        void binderTestIoctlErr1(int cmd, void *arg, int expect_errno) {
104            binderTestIoctlErr2(cmd, arg, expect_errno, expect_errno);
105        }
106        void binderTestIoctl(int cmd, void *arg) {
107            binderTestIoctlRetErr2(cmd, arg, 0, 0, 0);
108        }
109        void binderTestIoctlUnimplemented(int cmd, void *arg) {
110            int ret;
111
112            ret = ioctl(m_binderFd, cmd, arg);
113            if (ret < 0) {
114                /* Not currently implmented. Allow ret == -1, errno == EINVAL */
115                EXPECT_EQ(-1, ret);
116                EXPECT_EQ(EINVAL, errno);
117            }
118        }
119        void binderTestReadEmpty(void) {
120            size_t i;
121            uint32_t br[32];
122            struct binder_write_read bwr = binder_write_read();
123            SCOPED_TRACE("TestReadEmpty");
124            bwr.read_buffer = (uintptr_t)br;
125            bwr.read_size = sizeof(br);
126            binderTestIoctlErr1(BINDER_WRITE_READ, &bwr, EAGAIN);
127            EXPECT_EQ(0u, bwr.read_consumed);
128            for (i = 0; i * sizeof(uint32_t) < bwr.read_consumed; i++) {
129                SCOPED_TRACE(testing::Message() << "i = " << i);
130                EXPECT_EQ(BR_NOOP, br[i]);
131            }
132        }
133        void binderWaitForReadData(int timeout_ms) {
134            int ret;
135            pollfd pfd = pollfd();
136
137            pfd.fd = m_binderFd;
138            pfd.events = POLLIN;
139            ret = poll(&pfd, 1, timeout_ms);
140            EXPECT_EQ(1, ret);
141        }
142    private:
143        int m_binderFd;
144};
145
146TEST_F(BinderDriverInterfaceTest, Version) {
147    struct binder_version version;
148    binderTestIoctl(BINDER_VERSION, &version);
149    ASSERT_EQ(BINDER_CURRENT_PROTOCOL_VERSION, version.protocol_version);
150}
151
152TEST_F(BinderDriverInterfaceTest, OpenNoMmap) {
153    int binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC);
154    ASSERT_GE(binderFd, 0);
155    close(binderFd);
156}
157
158TEST_F(BinderDriverInterfaceTest, WriteReadNull) {
159    binderTestIoctlErr1(BINDER_WRITE_READ, NULL, EFAULT);
160}
161
162TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNull) {
163    binderTestIoctlErr2(BINDER_SET_IDLE_TIMEOUT, NULL, EFAULT, EINVAL);
164}
165
166TEST_F(BinderDriverInterfaceTest, SetMaxThreadsNull) {
167    binderTestIoctlErr2(BINDER_SET_MAX_THREADS, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
168}
169
170TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNull) {
171    binderTestIoctlErr2(BINDER_SET_IDLE_PRIORITY, NULL, EFAULT, EINVAL);
172}
173
174TEST_F(BinderDriverInterfaceTest, VersionNull) {
175    binderTestIoctlErr2(BINDER_VERSION, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
176}
177
178TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNoTest) {
179    int64_t idle_timeout = 100000;
180    binderTestIoctlUnimplemented(BINDER_SET_IDLE_TIMEOUT, &idle_timeout);
181}
182
183TEST_F(BinderDriverInterfaceTest, SetMaxThreads) {
184    uint32_t max_threads = 0;
185    binderTestIoctl(BINDER_SET_MAX_THREADS, &max_threads);
186}
187
188TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNoTest) {
189    int idle_priority = 0;
190    binderTestIoctlUnimplemented(BINDER_SET_IDLE_PRIORITY, &idle_priority);
191}
192
193TEST_F(BinderDriverInterfaceTest, SetContextMgrBusy) {
194    int32_t dummy = 0;
195    binderTestIoctlErr1(BINDER_SET_CONTEXT_MGR, &dummy, EBUSY);
196}
197
198TEST_F(BinderDriverInterfaceTest, ThreadExit) {
199    int32_t dummy = 0;
200    binderTestIoctl(BINDER_THREAD_EXIT, &dummy);
201    static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->EnterLooper();
202}
203
204TEST_F(BinderDriverInterfaceTest, WriteReadEmpty) {
205    struct binder_write_read bwr = binder_write_read();
206    binderTestIoctl(BINDER_WRITE_READ, &bwr);
207}
208
209TEST_F(BinderDriverInterfaceTest, Read) {
210    binderTestReadEmpty();
211}
212
213TEST_F(BinderDriverInterfaceTest, IncRefsAcquireReleaseDecRefs) {
214    const uint32_t bc[] = {
215        BC_INCREFS,
216        0,
217        BC_ACQUIRE,
218        0,
219        BC_RELEASE,
220        0,
221        BC_DECREFS,
222        0,
223    };
224    struct binder_write_read bwr = binder_write_read();
225    bwr.write_buffer = (uintptr_t)bc;
226    bwr.write_size = sizeof(bc);
227    binderTestIoctl(BINDER_WRITE_READ, &bwr);
228    EXPECT_EQ(sizeof(bc), bwr.write_consumed);
229    binderTestReadEmpty();
230}
231
232TEST_F(BinderDriverInterfaceTest, Transaction) {
233    binder_uintptr_t cookie = 1234;
234    struct {
235        uint32_t cmd1;
236        struct binder_transaction_data arg1;
237    } __attribute__((packed)) bc1 = {
238        .cmd1 = BC_TRANSACTION,
239        .arg1 = {
240            .target = { 0 },
241            .cookie = 0,
242            .code = android::IBinder::PING_TRANSACTION,
243            .flags = 0,
244            .sender_pid = 0,
245            .sender_euid = 0,
246            .data_size = 0,
247            .offsets_size = 0,
248            .data = {
249                .ptr = {0, 0},
250            },
251        },
252    };
253    struct {
254        uint32_t cmd0;
255        uint32_t cmd1;
256        uint32_t cmd2;
257        binder_transaction_data arg2;
258        uint32_t pad[16];
259    } __attribute__((packed)) br;
260    struct binder_write_read bwr = binder_write_read();
261
262    bwr.write_buffer = (uintptr_t)&bc1;
263    bwr.write_size = sizeof(bc1);
264    bwr.read_buffer = (uintptr_t)&br;
265    bwr.read_size = sizeof(br);
266
267    {
268        SCOPED_TRACE("1st WriteRead");
269        binderTestIoctlSuccessOrError(BINDER_WRITE_READ, &bwr, EAGAIN);
270    }
271    EXPECT_EQ(sizeof(bc1), bwr.write_consumed);
272    if (bwr.read_consumed < offsetof(typeof(br), pad)) {
273        SCOPED_TRACE("2nd WriteRead");
274        binderWaitForReadData(10000);
275        binderTestIoctl(BINDER_WRITE_READ, &bwr);
276    }
277    EXPECT_EQ(offsetof(typeof(br), pad), bwr.read_consumed);
278    if (bwr.read_consumed > offsetof(typeof(br), cmd0))
279        EXPECT_EQ(BR_NOOP, br.cmd0);
280    if (bwr.read_consumed > offsetof(typeof(br), cmd1))
281        EXPECT_EQ(BR_TRANSACTION_COMPLETE, br.cmd1);
282    if (bwr.read_consumed > offsetof(typeof(br), cmd2))
283        EXPECT_EQ(BR_REPLY, br.cmd2);
284    if (bwr.read_consumed >= offsetof(typeof(br), pad)) {
285        EXPECT_EQ(0u, br.arg2.target.ptr);
286        EXPECT_EQ(0u, br.arg2.cookie);
287        EXPECT_EQ(0u, br.arg2.code);
288        EXPECT_EQ(0u, br.arg2.flags);
289        EXPECT_EQ(0u, br.arg2.data_size);
290        EXPECT_EQ(0u, br.arg2.offsets_size);
291
292        SCOPED_TRACE("3rd WriteRead");
293
294        binderTestReadEmpty();
295
296        struct {
297            uint32_t cmd1;
298            binder_uintptr_t arg1;
299        } __attribute__((packed)) bc2 = {
300            .cmd1 = BC_FREE_BUFFER,
301            .arg1 = br.arg2.data.ptr.buffer,
302        };
303
304        bwr.write_buffer = (uintptr_t)&bc2;
305        bwr.write_size = sizeof(bc2);
306        bwr.write_consumed = 0;
307        bwr.read_size = 0;
308
309        binderTestIoctl(BINDER_WRITE_READ, &bwr);
310        EXPECT_EQ(sizeof(bc2), bwr.write_consumed);
311    }
312    binderTestReadEmpty();
313}
314
315TEST_F(BinderDriverInterfaceTest, RequestDeathNotification) {
316    binder_uintptr_t cookie = 1234;
317    struct {
318        uint32_t cmd0;
319        uint32_t arg0;
320        uint32_t cmd1;
321        struct binder_handle_cookie arg1;
322        uint32_t cmd2;
323        struct binder_handle_cookie arg2;
324        uint32_t cmd3;
325        uint32_t arg3;
326    } __attribute__((packed)) bc = {
327        .cmd0 = BC_INCREFS,
328        .arg0 = 0,
329        .cmd1 = BC_REQUEST_DEATH_NOTIFICATION,
330        .arg1 = {
331            .handle = 0,
332            .cookie = cookie,
333        },
334        .cmd2 = BC_CLEAR_DEATH_NOTIFICATION,
335        .arg2 = {
336            .handle = 0,
337            .cookie = cookie,
338        },
339        .cmd3 = BC_DECREFS,
340        .arg3 = 0,
341    };
342    struct {
343        uint32_t cmd0;
344        uint32_t cmd1;
345        binder_uintptr_t arg1;
346        uint32_t pad[16];
347    } __attribute__((packed)) br;
348    struct binder_write_read bwr = binder_write_read();
349
350    bwr.write_buffer = (uintptr_t)&bc;
351    bwr.write_size = sizeof(bc);
352    bwr.read_buffer = (uintptr_t)&br;
353    bwr.read_size = sizeof(br);
354
355    binderTestIoctl(BINDER_WRITE_READ, &bwr);
356    EXPECT_EQ(sizeof(bc), bwr.write_consumed);
357    EXPECT_EQ(sizeof(br) - sizeof(br.pad), bwr.read_consumed);
358    EXPECT_EQ(BR_NOOP, br.cmd0);
359    EXPECT_EQ(BR_CLEAR_DEATH_NOTIFICATION_DONE, br.cmd1);
360    EXPECT_EQ(cookie, br.arg1);
361    binderTestReadEmpty();
362}
363
364int main(int argc, char **argv) {
365    ::testing::InitGoogleTest(&argc, argv);
366
367    binder_env = AddGlobalTestEnvironment(new BinderDriverInterfaceTestEnv());
368
369    return RUN_ALL_TESTS();
370}
371