Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 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 | |
Tomasz Wasilczyk | b70f471 | 2024-06-21 11:58:54 -0700 | [diff] [blame] | 22 | #include <binder/IBinder.h> |
Yu-Ting Tseng | d5fc446 | 2024-04-30 15:07:13 -0700 | [diff] [blame] | 23 | #include <binder/ProcessState.h> |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 24 | #include <gtest/gtest.h> |
Dan Willemsen | e05dc6d | 2016-07-25 17:13:45 -0700 | [diff] [blame] | 25 | #include <linux/android/binder.h> |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 26 | #include <poll.h> |
Tomasz Wasilczyk | b70f471 | 2024-06-21 11:58:54 -0700 | [diff] [blame] | 27 | #include <sys/ioctl.h> |
| 28 | #include <sys/mman.h> |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 29 | |
Yu-Ting Tseng | d5fc446 | 2024-04-30 15:07:13 -0700 | [diff] [blame] | 30 | #include "../binder_module.h" |
| 31 | |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 32 | #define BINDER_DEV_NAME "/dev/binder" |
| 33 | |
| 34 | testing::Environment* binder_env; |
| 35 | |
| 36 | class BinderDriverInterfaceTestEnv : public ::testing::Environment { |
| 37 | virtual void SetUp() { |
| 38 | int ret; |
| 39 | uint32_t max_threads = 0; |
| 40 | |
Nick Kralevich | 0fe7ce3 | 2015-12-23 18:58:05 -0800 | [diff] [blame] | 41 | m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 42 | ASSERT_GE(m_binderFd, 0); |
Yi Kong | fdd8da9 | 2018-06-07 17:52:27 -0700 | [diff] [blame] | 43 | m_buffer = mmap(nullptr, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0); |
| 44 | ASSERT_NE(m_buffer, (void *)nullptr); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 45 | ret = ioctl(m_binderFd, BINDER_SET_MAX_THREADS, &max_threads); |
| 46 | EXPECT_EQ(0, ret); |
| 47 | EnterLooper(); |
| 48 | } |
| 49 | virtual void TearDown() { |
| 50 | close(m_binderFd); |
| 51 | } |
| 52 | private: |
| 53 | int m_binderFd; |
| 54 | void *m_buffer; |
| 55 | public: |
| 56 | int getBinderFd(void) { |
| 57 | return m_binderFd; |
| 58 | } |
| 59 | void EnterLooper(void) { |
| 60 | int ret; |
| 61 | const uint32_t bc[] = { |
| 62 | BC_ENTER_LOOPER, |
| 63 | }; |
| 64 | struct binder_write_read bwr = binder_write_read(); |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 65 | bwr.write_buffer = (uintptr_t)bc; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 66 | bwr.write_size = sizeof(bc); |
| 67 | ret = ioctl(m_binderFd, BINDER_WRITE_READ, &bwr); |
| 68 | EXPECT_EQ(0, ret); |
| 69 | if (ret < 0) { |
| 70 | EXPECT_EQ(0, errno); |
| 71 | } |
| 72 | EXPECT_EQ(sizeof(bc), bwr.write_consumed); |
| 73 | } |
| 74 | }; |
| 75 | |
| 76 | class BinderDriverInterfaceTest : public ::testing::Test { |
| 77 | public: |
| 78 | virtual void SetUp() { |
| 79 | m_binderFd = static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->getBinderFd(); |
| 80 | } |
| 81 | virtual void TearDown() { |
| 82 | } |
| 83 | protected: |
Martijn Coenen | 2b39df7 | 2017-12-11 11:10:34 +0100 | [diff] [blame] | 84 | /* The ioctl must either return 0, or if it doesn't errno should be accepted_errno */ |
| 85 | void binderTestIoctlSuccessOrError(int cmd, void *arg, int accepted_errno) { |
| 86 | int ret; |
| 87 | |
| 88 | ret = ioctl(m_binderFd, cmd, arg); |
| 89 | if (ret != 0) { |
| 90 | EXPECT_EQ(errno, accepted_errno); |
| 91 | } |
| 92 | } |
| 93 | |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 94 | void binderTestIoctlRetErr2(int cmd, void *arg, int expect_ret, int expect_errno, int accept_errno) { |
| 95 | int ret; |
| 96 | |
| 97 | ret = ioctl(m_binderFd, cmd, arg); |
| 98 | EXPECT_EQ(expect_ret, ret); |
| 99 | if (ret < 0) { |
Tomasz Wasilczyk | 370408e | 2024-06-21 15:45:26 -0700 | [diff] [blame] | 100 | if (errno != accept_errno) { |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 101 | EXPECT_EQ(expect_errno, errno); |
Tomasz Wasilczyk | 370408e | 2024-06-21 15:45:26 -0700 | [diff] [blame] | 102 | } |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 103 | } |
| 104 | } |
| 105 | void binderTestIoctlErr2(int cmd, void *arg, int expect_errno, int accept_errno) { |
| 106 | binderTestIoctlRetErr2(cmd, arg, -1, expect_errno, accept_errno); |
| 107 | } |
| 108 | void binderTestIoctlErr1(int cmd, void *arg, int expect_errno) { |
| 109 | binderTestIoctlErr2(cmd, arg, expect_errno, expect_errno); |
| 110 | } |
| 111 | void binderTestIoctl(int cmd, void *arg) { |
| 112 | binderTestIoctlRetErr2(cmd, arg, 0, 0, 0); |
| 113 | } |
| 114 | void binderTestIoctlUnimplemented(int cmd, void *arg) { |
| 115 | int ret; |
| 116 | |
| 117 | ret = ioctl(m_binderFd, cmd, arg); |
| 118 | if (ret < 0) { |
| 119 | /* Not currently implmented. Allow ret == -1, errno == EINVAL */ |
| 120 | EXPECT_EQ(-1, ret); |
| 121 | EXPECT_EQ(EINVAL, errno); |
| 122 | } |
| 123 | } |
| 124 | void binderTestReadEmpty(void) { |
| 125 | size_t i; |
| 126 | uint32_t br[32]; |
| 127 | struct binder_write_read bwr = binder_write_read(); |
| 128 | SCOPED_TRACE("TestReadEmpty"); |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 129 | bwr.read_buffer = (uintptr_t)br; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 130 | bwr.read_size = sizeof(br); |
| 131 | binderTestIoctlErr1(BINDER_WRITE_READ, &bwr, EAGAIN); |
Riley Andrews | 50bcb00 | 2015-01-12 18:14:55 -0800 | [diff] [blame] | 132 | EXPECT_EQ(0u, bwr.read_consumed); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 133 | for (i = 0; i * sizeof(uint32_t) < bwr.read_consumed; i++) { |
| 134 | SCOPED_TRACE(testing::Message() << "i = " << i); |
| 135 | EXPECT_EQ(BR_NOOP, br[i]); |
| 136 | } |
| 137 | } |
| 138 | void binderWaitForReadData(int timeout_ms) { |
| 139 | int ret; |
| 140 | pollfd pfd = pollfd(); |
| 141 | |
| 142 | pfd.fd = m_binderFd; |
| 143 | pfd.events = POLLIN; |
| 144 | ret = poll(&pfd, 1, timeout_ms); |
| 145 | EXPECT_EQ(1, ret); |
| 146 | } |
| 147 | private: |
| 148 | int m_binderFd; |
| 149 | }; |
| 150 | |
| 151 | TEST_F(BinderDriverInterfaceTest, Version) { |
| 152 | struct binder_version version; |
| 153 | binderTestIoctl(BINDER_VERSION, &version); |
| 154 | ASSERT_EQ(BINDER_CURRENT_PROTOCOL_VERSION, version.protocol_version); |
| 155 | } |
| 156 | |
Sherry Yang | 2437b32 | 2017-08-29 16:07:57 -0700 | [diff] [blame] | 157 | TEST_F(BinderDriverInterfaceTest, OpenNoMmap) { |
| 158 | int binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC); |
| 159 | ASSERT_GE(binderFd, 0); |
| 160 | close(binderFd); |
| 161 | } |
| 162 | |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 163 | TEST_F(BinderDriverInterfaceTest, WriteReadNull) { |
Yi Kong | fdd8da9 | 2018-06-07 17:52:27 -0700 | [diff] [blame] | 164 | binderTestIoctlErr1(BINDER_WRITE_READ, nullptr, EFAULT); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNull) { |
Yi Kong | fdd8da9 | 2018-06-07 17:52:27 -0700 | [diff] [blame] | 168 | binderTestIoctlErr2(BINDER_SET_IDLE_TIMEOUT, nullptr, EFAULT, EINVAL); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | TEST_F(BinderDriverInterfaceTest, SetMaxThreadsNull) { |
Yi Kong | fdd8da9 | 2018-06-07 17:52:27 -0700 | [diff] [blame] | 172 | binderTestIoctlErr2(BINDER_SET_MAX_THREADS, nullptr, EFAULT, EINVAL); /* TODO: don't accept EINVAL */ |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNull) { |
Yi Kong | fdd8da9 | 2018-06-07 17:52:27 -0700 | [diff] [blame] | 176 | binderTestIoctlErr2(BINDER_SET_IDLE_PRIORITY, nullptr, EFAULT, EINVAL); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | TEST_F(BinderDriverInterfaceTest, VersionNull) { |
Yi Kong | fdd8da9 | 2018-06-07 17:52:27 -0700 | [diff] [blame] | 180 | binderTestIoctlErr2(BINDER_VERSION, nullptr, EFAULT, EINVAL); /* TODO: don't accept EINVAL */ |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 181 | } |
| 182 | |
| 183 | TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNoTest) { |
| 184 | int64_t idle_timeout = 100000; |
| 185 | binderTestIoctlUnimplemented(BINDER_SET_IDLE_TIMEOUT, &idle_timeout); |
| 186 | } |
| 187 | |
| 188 | TEST_F(BinderDriverInterfaceTest, SetMaxThreads) { |
| 189 | uint32_t max_threads = 0; |
| 190 | binderTestIoctl(BINDER_SET_MAX_THREADS, &max_threads); |
| 191 | } |
| 192 | |
| 193 | TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNoTest) { |
| 194 | int idle_priority = 0; |
| 195 | binderTestIoctlUnimplemented(BINDER_SET_IDLE_PRIORITY, &idle_priority); |
| 196 | } |
| 197 | |
| 198 | TEST_F(BinderDriverInterfaceTest, SetContextMgrBusy) { |
| 199 | int32_t dummy = 0; |
| 200 | binderTestIoctlErr1(BINDER_SET_CONTEXT_MGR, &dummy, EBUSY); |
| 201 | } |
| 202 | |
| 203 | TEST_F(BinderDriverInterfaceTest, ThreadExit) { |
| 204 | int32_t dummy = 0; |
| 205 | binderTestIoctl(BINDER_THREAD_EXIT, &dummy); |
| 206 | static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->EnterLooper(); |
| 207 | } |
| 208 | |
| 209 | TEST_F(BinderDriverInterfaceTest, WriteReadEmpty) { |
| 210 | struct binder_write_read bwr = binder_write_read(); |
| 211 | binderTestIoctl(BINDER_WRITE_READ, &bwr); |
| 212 | } |
| 213 | |
| 214 | TEST_F(BinderDriverInterfaceTest, Read) { |
| 215 | binderTestReadEmpty(); |
| 216 | } |
| 217 | |
| 218 | TEST_F(BinderDriverInterfaceTest, IncRefsAcquireReleaseDecRefs) { |
| 219 | const uint32_t bc[] = { |
| 220 | BC_INCREFS, |
| 221 | 0, |
| 222 | BC_ACQUIRE, |
| 223 | 0, |
| 224 | BC_RELEASE, |
| 225 | 0, |
| 226 | BC_DECREFS, |
| 227 | 0, |
| 228 | }; |
| 229 | struct binder_write_read bwr = binder_write_read(); |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 230 | bwr.write_buffer = (uintptr_t)bc; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 231 | bwr.write_size = sizeof(bc); |
| 232 | binderTestIoctl(BINDER_WRITE_READ, &bwr); |
| 233 | EXPECT_EQ(sizeof(bc), bwr.write_consumed); |
| 234 | binderTestReadEmpty(); |
| 235 | } |
| 236 | |
| 237 | TEST_F(BinderDriverInterfaceTest, Transaction) { |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 238 | struct { |
| 239 | uint32_t cmd1; |
| 240 | struct binder_transaction_data arg1; |
| 241 | } __attribute__((packed)) bc1 = { |
| 242 | .cmd1 = BC_TRANSACTION, |
| 243 | .arg1 = { |
| 244 | .target = { 0 }, |
| 245 | .cookie = 0, |
| 246 | .code = android::IBinder::PING_TRANSACTION, |
| 247 | .flags = 0, |
| 248 | .sender_pid = 0, |
| 249 | .sender_euid = 0, |
| 250 | .data_size = 0, |
| 251 | .offsets_size = 0, |
Wei Wang | 78f2a37 | 2016-10-20 23:18:17 -0700 | [diff] [blame] | 252 | .data = { |
| 253 | .ptr = {0, 0}, |
| 254 | }, |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 255 | }, |
| 256 | }; |
| 257 | struct { |
| 258 | uint32_t cmd0; |
| 259 | uint32_t cmd1; |
| 260 | uint32_t cmd2; |
| 261 | binder_transaction_data arg2; |
| 262 | uint32_t pad[16]; |
| 263 | } __attribute__((packed)) br; |
| 264 | struct binder_write_read bwr = binder_write_read(); |
| 265 | |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 266 | bwr.write_buffer = (uintptr_t)&bc1; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 267 | bwr.write_size = sizeof(bc1); |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 268 | bwr.read_buffer = (uintptr_t)&br; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 269 | bwr.read_size = sizeof(br); |
| 270 | |
| 271 | { |
| 272 | SCOPED_TRACE("1st WriteRead"); |
Martijn Coenen | 2b39df7 | 2017-12-11 11:10:34 +0100 | [diff] [blame] | 273 | binderTestIoctlSuccessOrError(BINDER_WRITE_READ, &bwr, EAGAIN); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 274 | } |
| 275 | EXPECT_EQ(sizeof(bc1), bwr.write_consumed); |
| 276 | if (bwr.read_consumed < offsetof(typeof(br), pad)) { |
| 277 | SCOPED_TRACE("2nd WriteRead"); |
| 278 | binderWaitForReadData(10000); |
| 279 | binderTestIoctl(BINDER_WRITE_READ, &bwr); |
| 280 | } |
| 281 | EXPECT_EQ(offsetof(typeof(br), pad), bwr.read_consumed); |
Tomasz Wasilczyk | 370408e | 2024-06-21 15:45:26 -0700 | [diff] [blame] | 282 | if (bwr.read_consumed > offsetof(typeof(br), cmd0)) { |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 283 | EXPECT_EQ(BR_NOOP, br.cmd0); |
Tomasz Wasilczyk | 370408e | 2024-06-21 15:45:26 -0700 | [diff] [blame] | 284 | } |
| 285 | if (bwr.read_consumed > offsetof(typeof(br), cmd1)) { |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 286 | EXPECT_EQ(BR_TRANSACTION_COMPLETE, br.cmd1); |
Tomasz Wasilczyk | 370408e | 2024-06-21 15:45:26 -0700 | [diff] [blame] | 287 | } |
| 288 | if (bwr.read_consumed > offsetof(typeof(br), cmd2)) { |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 289 | EXPECT_EQ(BR_REPLY, br.cmd2); |
Tomasz Wasilczyk | 370408e | 2024-06-21 15:45:26 -0700 | [diff] [blame] | 290 | } |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 291 | if (bwr.read_consumed >= offsetof(typeof(br), pad)) { |
Riley Andrews | 50bcb00 | 2015-01-12 18:14:55 -0800 | [diff] [blame] | 292 | EXPECT_EQ(0u, br.arg2.target.ptr); |
| 293 | EXPECT_EQ(0u, br.arg2.cookie); |
| 294 | EXPECT_EQ(0u, br.arg2.code); |
| 295 | EXPECT_EQ(0u, br.arg2.flags); |
Steven Moreland | 6e69d65 | 2019-07-10 14:17:55 -0700 | [diff] [blame] | 296 | EXPECT_EQ(0u, br.arg2.data_size); |
Riley Andrews | 50bcb00 | 2015-01-12 18:14:55 -0800 | [diff] [blame] | 297 | EXPECT_EQ(0u, br.arg2.offsets_size); |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 298 | |
| 299 | SCOPED_TRACE("3rd WriteRead"); |
| 300 | |
| 301 | binderTestReadEmpty(); |
| 302 | |
| 303 | struct { |
| 304 | uint32_t cmd1; |
| 305 | binder_uintptr_t arg1; |
| 306 | } __attribute__((packed)) bc2 = { |
| 307 | .cmd1 = BC_FREE_BUFFER, |
| 308 | .arg1 = br.arg2.data.ptr.buffer, |
| 309 | }; |
| 310 | |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 311 | bwr.write_buffer = (uintptr_t)&bc2; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 312 | bwr.write_size = sizeof(bc2); |
| 313 | bwr.write_consumed = 0; |
| 314 | bwr.read_size = 0; |
| 315 | |
| 316 | binderTestIoctl(BINDER_WRITE_READ, &bwr); |
| 317 | EXPECT_EQ(sizeof(bc2), bwr.write_consumed); |
| 318 | } |
| 319 | binderTestReadEmpty(); |
| 320 | } |
| 321 | |
| 322 | TEST_F(BinderDriverInterfaceTest, RequestDeathNotification) { |
| 323 | binder_uintptr_t cookie = 1234; |
| 324 | struct { |
| 325 | uint32_t cmd0; |
| 326 | uint32_t arg0; |
| 327 | uint32_t cmd1; |
| 328 | struct binder_handle_cookie arg1; |
| 329 | uint32_t cmd2; |
| 330 | struct binder_handle_cookie arg2; |
| 331 | uint32_t cmd3; |
| 332 | uint32_t arg3; |
| 333 | } __attribute__((packed)) bc = { |
| 334 | .cmd0 = BC_INCREFS, |
| 335 | .arg0 = 0, |
| 336 | .cmd1 = BC_REQUEST_DEATH_NOTIFICATION, |
| 337 | .arg1 = { |
| 338 | .handle = 0, |
| 339 | .cookie = cookie, |
| 340 | }, |
| 341 | .cmd2 = BC_CLEAR_DEATH_NOTIFICATION, |
| 342 | .arg2 = { |
| 343 | .handle = 0, |
| 344 | .cookie = cookie, |
| 345 | }, |
| 346 | .cmd3 = BC_DECREFS, |
| 347 | .arg3 = 0, |
| 348 | }; |
| 349 | struct { |
| 350 | uint32_t cmd0; |
| 351 | uint32_t cmd1; |
| 352 | binder_uintptr_t arg1; |
| 353 | uint32_t pad[16]; |
| 354 | } __attribute__((packed)) br; |
| 355 | struct binder_write_read bwr = binder_write_read(); |
| 356 | |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 357 | bwr.write_buffer = (uintptr_t)&bc; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 358 | bwr.write_size = sizeof(bc); |
Riley Andrews | 29d8cf9 | 2015-01-12 18:16:29 -0800 | [diff] [blame] | 359 | bwr.read_buffer = (uintptr_t)&br; |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 360 | bwr.read_size = sizeof(br); |
| 361 | |
| 362 | binderTestIoctl(BINDER_WRITE_READ, &bwr); |
| 363 | EXPECT_EQ(sizeof(bc), bwr.write_consumed); |
| 364 | EXPECT_EQ(sizeof(br) - sizeof(br.pad), bwr.read_consumed); |
| 365 | EXPECT_EQ(BR_NOOP, br.cmd0); |
| 366 | EXPECT_EQ(BR_CLEAR_DEATH_NOTIFICATION_DONE, br.cmd1); |
| 367 | EXPECT_EQ(cookie, br.arg1); |
| 368 | binderTestReadEmpty(); |
| 369 | } |
| 370 | |
Yu-Ting Tseng | d5fc446 | 2024-04-30 15:07:13 -0700 | [diff] [blame] | 371 | TEST_F(BinderDriverInterfaceTest, RequestFrozenNotification) { |
| 372 | if (!android::ProcessState::isDriverFeatureEnabled( |
| 373 | android::ProcessState::DriverFeature::FREEZE_NOTIFICATION)) { |
| 374 | GTEST_SKIP() << "Skipping test for kernels that support freeze notification"; |
| 375 | return; |
| 376 | } |
| 377 | binder_uintptr_t cookie = 1234; |
| 378 | struct { |
| 379 | uint32_t cmd0; |
| 380 | uint32_t arg0; |
| 381 | uint32_t cmd1; |
| 382 | struct binder_handle_cookie arg1; |
| 383 | } __attribute__((packed)) bc1 = { |
| 384 | .cmd0 = BC_INCREFS, |
| 385 | .arg0 = 0, |
| 386 | .cmd1 = BC_REQUEST_FREEZE_NOTIFICATION, |
| 387 | .arg1 = |
| 388 | { |
| 389 | .handle = 0, |
| 390 | .cookie = cookie, |
| 391 | }, |
| 392 | }; |
| 393 | struct { |
| 394 | uint32_t cmd0; |
| 395 | // Expecting a BR_FROZEN_BINDER since BC_REQUEST_FREEZE_NOTIFICATION |
| 396 | // above should lead to an immediate notification of the current state. |
| 397 | uint32_t cmd1; |
| 398 | struct binder_frozen_state_info arg1; |
| 399 | uint32_t pad[16]; |
| 400 | } __attribute__((packed)) br1; |
| 401 | struct { |
| 402 | uint32_t cmd2; |
| 403 | binder_uintptr_t arg2; |
| 404 | uint32_t cmd3; |
| 405 | struct binder_handle_cookie arg3; |
| 406 | uint32_t cmd4; |
| 407 | uint32_t arg4; |
| 408 | } __attribute__((packed)) bc2 = { |
| 409 | // Tell kernel that userspace has done handling BR_FROZEN_BINDER. |
| 410 | .cmd2 = BC_FREEZE_NOTIFICATION_DONE, |
| 411 | .arg2 = cookie, |
| 412 | .cmd3 = BC_CLEAR_FREEZE_NOTIFICATION, |
| 413 | .arg3 = |
| 414 | { |
| 415 | .handle = 0, |
| 416 | .cookie = cookie, |
| 417 | }, |
| 418 | .cmd4 = BC_DECREFS, |
| 419 | .arg4 = 0, |
| 420 | }; |
| 421 | struct { |
| 422 | uint32_t cmd2; |
| 423 | uint32_t cmd3; |
| 424 | binder_uintptr_t arg3; |
| 425 | uint32_t pad[16]; |
| 426 | } __attribute__((packed)) br2; |
| 427 | |
| 428 | struct binder_write_read bwr1 = binder_write_read(); |
| 429 | bwr1.write_buffer = (uintptr_t)&bc1; |
| 430 | bwr1.write_size = sizeof(bc1); |
| 431 | bwr1.read_buffer = (uintptr_t)&br1; |
| 432 | bwr1.read_size = sizeof(br1); |
| 433 | binderTestIoctl(BINDER_WRITE_READ, &bwr1); |
| 434 | EXPECT_EQ(sizeof(bc1), bwr1.write_consumed); |
| 435 | EXPECT_EQ(sizeof(br1) - sizeof(br1.pad), bwr1.read_consumed); |
| 436 | EXPECT_EQ(BR_NOOP, br1.cmd0); |
| 437 | ASSERT_EQ(BR_FROZEN_BINDER, br1.cmd1); |
| 438 | EXPECT_FALSE(br1.arg1.is_frozen); |
| 439 | |
| 440 | struct binder_write_read bwr2 = binder_write_read(); |
| 441 | bwr2.write_buffer = (uintptr_t)&bc2; |
| 442 | bwr2.write_size = sizeof(bc2); |
| 443 | bwr2.read_buffer = (uintptr_t)&br2; |
| 444 | bwr2.read_size = sizeof(br2); |
| 445 | binderTestIoctl(BINDER_WRITE_READ, &bwr2); |
| 446 | EXPECT_EQ(sizeof(bc2), bwr2.write_consumed); |
| 447 | EXPECT_EQ(sizeof(br2) - sizeof(br2.pad), bwr2.read_consumed); |
| 448 | EXPECT_EQ(BR_NOOP, br2.cmd2); |
| 449 | EXPECT_EQ(BR_CLEAR_FREEZE_NOTIFICATION_DONE, br2.cmd3); |
| 450 | EXPECT_EQ(cookie, br2.arg3); |
| 451 | |
| 452 | binderTestReadEmpty(); |
| 453 | } |
| 454 | |
| 455 | TEST_F(BinderDriverInterfaceTest, OverwritePendingFrozenNotification) { |
| 456 | if (!android::ProcessState::isDriverFeatureEnabled( |
| 457 | android::ProcessState::DriverFeature::FREEZE_NOTIFICATION)) { |
| 458 | GTEST_SKIP() << "Skipping test for kernels that support freeze notification"; |
| 459 | return; |
| 460 | } |
| 461 | binder_uintptr_t cookie = 1234; |
| 462 | struct { |
| 463 | uint32_t cmd0; |
| 464 | uint32_t arg0; |
| 465 | uint32_t cmd1; |
| 466 | struct binder_handle_cookie arg1; |
| 467 | uint32_t cmd2; |
| 468 | struct binder_handle_cookie arg2; |
| 469 | uint32_t cmd3; |
| 470 | uint32_t arg3; |
| 471 | } __attribute__((packed)) bc = { |
| 472 | .cmd0 = BC_INCREFS, |
| 473 | .arg0 = 0, |
| 474 | .cmd1 = BC_REQUEST_FREEZE_NOTIFICATION, |
| 475 | // This BC_REQUEST_FREEZE_NOTIFICATION should lead to a pending |
| 476 | // frozen notification inserted into the queue. |
| 477 | .arg1 = |
| 478 | { |
| 479 | .handle = 0, |
| 480 | .cookie = cookie, |
| 481 | }, |
| 482 | // Send BC_CLEAR_FREEZE_NOTIFICATION before the above frozen |
| 483 | // notification has a chance of being sent. The notification should |
| 484 | // be overwritten. Userspace is expected to only receive |
| 485 | // BR_CLEAR_FREEZE_NOTIFICATION_DONE. |
| 486 | .cmd2 = BC_CLEAR_FREEZE_NOTIFICATION, |
| 487 | .arg2 = |
| 488 | { |
| 489 | .handle = 0, |
| 490 | .cookie = cookie, |
| 491 | }, |
| 492 | .cmd3 = BC_DECREFS, |
| 493 | .arg3 = 0, |
| 494 | }; |
| 495 | struct { |
| 496 | uint32_t cmd0; |
| 497 | uint32_t cmd1; |
| 498 | binder_uintptr_t arg1; |
| 499 | uint32_t pad[16]; |
| 500 | } __attribute__((packed)) br; |
| 501 | struct binder_write_read bwr = binder_write_read(); |
| 502 | |
| 503 | bwr.write_buffer = (uintptr_t)&bc; |
| 504 | bwr.write_size = sizeof(bc); |
| 505 | bwr.read_buffer = (uintptr_t)&br; |
| 506 | bwr.read_size = sizeof(br); |
| 507 | |
| 508 | binderTestIoctl(BINDER_WRITE_READ, &bwr); |
| 509 | EXPECT_EQ(sizeof(bc), bwr.write_consumed); |
| 510 | EXPECT_EQ(sizeof(br) - sizeof(br.pad), bwr.read_consumed); |
| 511 | EXPECT_EQ(BR_NOOP, br.cmd0); |
| 512 | EXPECT_EQ(BR_CLEAR_FREEZE_NOTIFICATION_DONE, br.cmd1); |
| 513 | EXPECT_EQ(cookie, br.arg1); |
| 514 | binderTestReadEmpty(); |
| 515 | } |
| 516 | |
| 517 | TEST_F(BinderDriverInterfaceTest, ResendFrozenNotification) { |
| 518 | if (!android::ProcessState::isDriverFeatureEnabled( |
| 519 | android::ProcessState::DriverFeature::FREEZE_NOTIFICATION)) { |
| 520 | GTEST_SKIP() << "Skipping test for kernels that support freeze notification"; |
| 521 | return; |
| 522 | } |
| 523 | binder_uintptr_t cookie = 1234; |
| 524 | struct { |
| 525 | uint32_t cmd0; |
| 526 | uint32_t arg0; |
| 527 | uint32_t cmd1; |
| 528 | struct binder_handle_cookie arg1; |
| 529 | } __attribute__((packed)) bc1 = { |
| 530 | .cmd0 = BC_INCREFS, |
| 531 | .arg0 = 0, |
| 532 | .cmd1 = BC_REQUEST_FREEZE_NOTIFICATION, |
| 533 | .arg1 = |
| 534 | { |
| 535 | .handle = 0, |
| 536 | .cookie = cookie, |
| 537 | }, |
| 538 | }; |
| 539 | struct { |
| 540 | uint32_t cmd0; |
| 541 | uint32_t cmd1; |
| 542 | struct binder_frozen_state_info arg1; |
| 543 | uint32_t pad[16]; |
| 544 | } __attribute__((packed)) br1; |
| 545 | struct { |
| 546 | uint32_t cmd2; |
| 547 | struct binder_handle_cookie arg2; |
| 548 | } __attribute__((packed)) bc2 = { |
| 549 | // Clear the notification before acknowledging the in-flight |
| 550 | // BR_FROZEN_BINDER. Kernel should hold off sending |
| 551 | // BR_CLEAR_FREEZE_NOTIFICATION_DONE until the acknowledgement |
| 552 | // reaches kernel. |
| 553 | .cmd2 = BC_CLEAR_FREEZE_NOTIFICATION, |
| 554 | .arg2 = |
| 555 | { |
| 556 | .handle = 0, |
| 557 | .cookie = cookie, |
| 558 | }, |
| 559 | }; |
| 560 | struct { |
| 561 | uint32_t pad[16]; |
| 562 | } __attribute__((packed)) br2; |
| 563 | struct { |
| 564 | uint32_t cmd3; |
| 565 | binder_uintptr_t arg3; |
| 566 | uint32_t cmd4; |
| 567 | uint32_t arg4; |
| 568 | } __attribute__((packed)) bc3 = { |
| 569 | // Send the acknowledgement. Now the kernel should send out |
| 570 | // BR_CLEAR_FREEZE_NOTIFICATION_DONE. |
| 571 | .cmd3 = BC_FREEZE_NOTIFICATION_DONE, |
| 572 | .arg3 = cookie, |
| 573 | .cmd4 = BC_DECREFS, |
| 574 | .arg4 = 0, |
| 575 | }; |
| 576 | struct { |
| 577 | uint32_t cmd2; |
| 578 | uint32_t cmd3; |
| 579 | binder_uintptr_t arg3; |
| 580 | uint32_t pad[16]; |
| 581 | } __attribute__((packed)) br3; |
| 582 | |
| 583 | struct binder_write_read bwr1 = binder_write_read(); |
| 584 | bwr1.write_buffer = (uintptr_t)&bc1; |
| 585 | bwr1.write_size = sizeof(bc1); |
| 586 | bwr1.read_buffer = (uintptr_t)&br1; |
| 587 | bwr1.read_size = sizeof(br1); |
| 588 | binderTestIoctl(BINDER_WRITE_READ, &bwr1); |
| 589 | EXPECT_EQ(sizeof(bc1), bwr1.write_consumed); |
| 590 | EXPECT_EQ(sizeof(br1) - sizeof(br1.pad), bwr1.read_consumed); |
| 591 | EXPECT_EQ(BR_NOOP, br1.cmd0); |
| 592 | ASSERT_EQ(BR_FROZEN_BINDER, br1.cmd1); |
| 593 | EXPECT_FALSE(br1.arg1.is_frozen); |
| 594 | |
| 595 | struct binder_write_read bwr2 = binder_write_read(); |
| 596 | bwr2.write_buffer = (uintptr_t)&bc2; |
| 597 | bwr2.write_size = sizeof(bc2); |
| 598 | bwr2.read_buffer = (uintptr_t)&br2; |
| 599 | bwr2.read_size = sizeof(br2); |
| 600 | binderTestIoctlSuccessOrError(BINDER_WRITE_READ, &bwr2, EAGAIN); |
| 601 | binderTestReadEmpty(); |
| 602 | |
| 603 | struct binder_write_read bwr3 = binder_write_read(); |
| 604 | bwr3.write_buffer = (uintptr_t)&bc3; |
| 605 | bwr3.write_size = sizeof(bc3); |
| 606 | bwr3.read_buffer = (uintptr_t)&br3; |
| 607 | bwr3.read_size = sizeof(br3); |
| 608 | binderTestIoctl(BINDER_WRITE_READ, &bwr3); |
| 609 | EXPECT_EQ(sizeof(bc3), bwr3.write_consumed); |
| 610 | EXPECT_EQ(sizeof(br3) - sizeof(br3.pad), bwr3.read_consumed); |
| 611 | EXPECT_EQ(BR_CLEAR_FREEZE_NOTIFICATION_DONE, br3.cmd3); |
| 612 | EXPECT_EQ(cookie, br3.arg3); |
| 613 | binderTestReadEmpty(); |
| 614 | } |
| 615 | |
Steven Moreland | 68275d7 | 2023-04-21 22:12:45 +0000 | [diff] [blame] | 616 | int main(int argc, char** argv) { |
Riley Andrews | dc9b148 | 2014-12-18 11:54:32 -0800 | [diff] [blame] | 617 | ::testing::InitGoogleTest(&argc, argv); |
| 618 | |
| 619 | binder_env = AddGlobalTestEnvironment(new BinderDriverInterfaceTestEnv()); |
| 620 | |
| 621 | return RUN_ALL_TESTS(); |
| 622 | } |