Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 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 | |
Ruchir Rastogi | cc7a746 | 2020-01-31 14:29:15 -0800 | [diff] [blame] | 17 | #include <IBinderNdkUnitTest.h> |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 18 | #include <aidl/BnBinderNdkUnitTest.h> |
| 19 | #include <aidl/BnEmpty.h> |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 20 | #include <android-base/logging.h> |
Steven Moreland | 02f7565 | 2018-09-18 14:08:30 -0700 | [diff] [blame] | 21 | #include <android/binder_ibinder_jni.h> |
Steven Moreland | 2f405f5 | 2020-07-08 22:24:29 +0000 | [diff] [blame] | 22 | #include <android/binder_ibinder_platform.h> |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 23 | #include <android/binder_manager.h> |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 24 | #include <android/binder_process.h> |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 25 | #include <gtest/gtest.h> |
| 26 | #include <iface/iface.h> |
| 27 | |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 28 | // warning: this is assuming that libbinder_ndk is using the same copy |
| 29 | // of libbinder that we are. |
| 30 | #include <binder/IPCThreadState.h> |
Ruchir Rastogi | cc7a746 | 2020-01-31 14:29:15 -0800 | [diff] [blame] | 31 | #include <binder/IResultReceiver.h> |
| 32 | #include <binder/IServiceManager.h> |
| 33 | #include <binder/IShellCallback.h> |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 34 | |
Steven Moreland | f92c1fa | 2020-01-24 13:25:15 -0800 | [diff] [blame] | 35 | #include <sys/prctl.h> |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 36 | #include <chrono> |
| 37 | #include <condition_variable> |
Steven Moreland | 2f405f5 | 2020-07-08 22:24:29 +0000 | [diff] [blame] | 38 | #include <iostream> |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 39 | #include <mutex> |
| 40 | |
Ruchir Rastogi | cc7a746 | 2020-01-31 14:29:15 -0800 | [diff] [blame] | 41 | using namespace android; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 42 | |
| 43 | constexpr char kExistingNonNdkService[] = "SurfaceFlinger"; |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 44 | constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest"; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 45 | |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 46 | class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { |
Steven Moreland | b2de953 | 2020-05-29 21:44:41 +0000 | [diff] [blame] | 47 | ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) { |
| 48 | *out = in; |
| 49 | return ndk::ScopedAStatus::ok(); |
| 50 | } |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 51 | ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) { |
| 52 | (void)empty; |
| 53 | return ndk::ScopedAStatus::ok(); |
| 54 | } |
| 55 | ndk::ScopedAStatus forceFlushCommands() { |
| 56 | // warning: this is assuming that libbinder_ndk is using the same copy |
| 57 | // of libbinder that we are. |
| 58 | android::IPCThreadState::self()->flushCommands(); |
| 59 | return ndk::ScopedAStatus::ok(); |
| 60 | } |
Steven Moreland | 2f405f5 | 2020-07-08 22:24:29 +0000 | [diff] [blame] | 61 | ndk::ScopedAStatus getsRequestedSid(bool* out) { |
| 62 | const char* sid = AIBinder_getCallingSid(); |
| 63 | std::cout << "Got security context: " << (sid ?: "null") << std::endl; |
| 64 | *out = sid != nullptr; |
| 65 | return ndk::ScopedAStatus::ok(); |
| 66 | } |
Ruchir Rastogi | cc7a746 | 2020-01-31 14:29:15 -0800 | [diff] [blame] | 67 | binder_status_t handleShellCommand(int /*in*/, int out, int /*err*/, const char** args, |
| 68 | uint32_t numArgs) override { |
| 69 | for (uint32_t i = 0; i < numArgs; i++) { |
| 70 | dprintf(out, "%s", args[i]); |
| 71 | } |
| 72 | fsync(out); |
| 73 | return STATUS_OK; |
| 74 | } |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 75 | }; |
| 76 | |
| 77 | int generatedService() { |
| 78 | ABinderProcess_setThreadPoolMaxThreadCount(0); |
| 79 | |
| 80 | auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>(); |
Steven Moreland | 2f405f5 | 2020-07-08 22:24:29 +0000 | [diff] [blame] | 81 | auto binder = service->asBinder(); |
| 82 | |
| 83 | AIBinder_setRequestingSid(binder.get(), true); |
| 84 | |
| 85 | binder_status_t status = AServiceManager_addService(binder.get(), kBinderNdkUnitTestService); |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 86 | |
| 87 | if (status != STATUS_OK) { |
| 88 | LOG(FATAL) << "Could not register: " << status << " " << kBinderNdkUnitTestService; |
| 89 | } |
| 90 | |
| 91 | ABinderProcess_joinThreadPool(); |
| 92 | |
| 93 | return 1; // should not return |
| 94 | } |
| 95 | |
| 96 | // manually-written parceling class considered bad practice |
Steven Moreland | f92c1fa | 2020-01-24 13:25:15 -0800 | [diff] [blame] | 97 | class MyFoo : public IFoo { |
| 98 | binder_status_t doubleNumber(int32_t in, int32_t* out) override { |
| 99 | *out = 2 * in; |
| 100 | LOG(INFO) << "doubleNumber (" << in << ") => " << *out; |
| 101 | return STATUS_OK; |
| 102 | } |
| 103 | |
| 104 | binder_status_t die() override { |
| 105 | LOG(FATAL) << "IFoo::die called!"; |
| 106 | return STATUS_UNKNOWN_ERROR; |
| 107 | } |
| 108 | }; |
| 109 | |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 110 | int manualService(const char* instance) { |
Steven Moreland | f92c1fa | 2020-01-24 13:25:15 -0800 | [diff] [blame] | 111 | ABinderProcess_setThreadPoolMaxThreadCount(0); |
| 112 | |
| 113 | // Strong reference to MyFoo kept by service manager. |
| 114 | binder_status_t status = (new MyFoo)->addService(instance); |
| 115 | |
| 116 | if (status != STATUS_OK) { |
| 117 | LOG(FATAL) << "Could not register: " << status << " " << instance; |
| 118 | } |
| 119 | |
| 120 | ABinderProcess_joinThreadPool(); |
| 121 | |
| 122 | return 1; // should not return |
| 123 | } |
| 124 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 125 | // This is too slow |
| 126 | // TEST(NdkBinder, GetServiceThatDoesntExist) { |
| 127 | // sp<IFoo> foo = IFoo::getService("asdfghkl;"); |
| 128 | // EXPECT_EQ(nullptr, foo.get()); |
| 129 | // } |
| 130 | |
Steven Moreland | dea68bb | 2019-02-15 10:53:08 -0800 | [diff] [blame] | 131 | TEST(NdkBinder, CheckServiceThatDoesntExist) { |
| 132 | AIBinder* binder = AServiceManager_checkService("asdfghkl;"); |
| 133 | ASSERT_EQ(nullptr, binder); |
| 134 | } |
| 135 | |
| 136 | TEST(NdkBinder, CheckServiceThatDoesExist) { |
| 137 | AIBinder* binder = AServiceManager_checkService(kExistingNonNdkService); |
| 138 | EXPECT_NE(nullptr, binder); |
| 139 | EXPECT_EQ(STATUS_OK, AIBinder_ping(binder)); |
| 140 | |
| 141 | AIBinder_decStrong(binder); |
| 142 | } |
| 143 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 144 | TEST(NdkBinder, DoubleNumber) { |
| 145 | sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName); |
| 146 | ASSERT_NE(foo, nullptr); |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 147 | |
| 148 | int32_t out; |
| 149 | EXPECT_EQ(STATUS_OK, foo->doubleNumber(1, &out)); |
| 150 | EXPECT_EQ(2, out); |
| 151 | } |
| 152 | |
| 153 | void LambdaOnDeath(void* cookie) { |
| 154 | auto onDeath = static_cast<std::function<void(void)>*>(cookie); |
| 155 | (*onDeath)(); |
| 156 | }; |
| 157 | TEST(NdkBinder, DeathRecipient) { |
| 158 | using namespace std::chrono_literals; |
| 159 | |
| 160 | AIBinder* binder; |
| 161 | sp<IFoo> foo = IFoo::getService(IFoo::kInstanceNameToDieFor, &binder); |
| 162 | ASSERT_NE(nullptr, foo.get()); |
| 163 | ASSERT_NE(nullptr, binder); |
| 164 | |
| 165 | std::mutex deathMutex; |
| 166 | std::condition_variable deathCv; |
| 167 | bool deathRecieved = false; |
| 168 | |
| 169 | std::function<void(void)> onDeath = [&] { |
| 170 | std::cerr << "Binder died (as requested)." << std::endl; |
| 171 | deathRecieved = true; |
| 172 | deathCv.notify_one(); |
| 173 | }; |
| 174 | |
| 175 | AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(LambdaOnDeath); |
| 176 | |
| 177 | EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(&onDeath))); |
| 178 | |
| 179 | // the binder driver should return this if the service dies during the transaction |
| 180 | EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die()); |
| 181 | |
Steven Moreland | 64127ca | 2019-03-13 09:25:44 -0700 | [diff] [blame] | 182 | foo = nullptr; |
Steven Moreland | 64127ca | 2019-03-13 09:25:44 -0700 | [diff] [blame] | 183 | |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 184 | std::unique_lock<std::mutex> lock(deathMutex); |
| 185 | EXPECT_TRUE(deathCv.wait_for(lock, 1s, [&] { return deathRecieved; })); |
| 186 | EXPECT_TRUE(deathRecieved); |
| 187 | |
| 188 | AIBinder_DeathRecipient_delete(recipient); |
Steven Moreland | 6bd0919 | 2020-01-24 13:06:57 -0800 | [diff] [blame] | 189 | AIBinder_decStrong(binder); |
| 190 | binder = nullptr; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 191 | } |
| 192 | |
| 193 | TEST(NdkBinder, RetrieveNonNdkService) { |
| 194 | AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); |
| 195 | ASSERT_NE(nullptr, binder); |
Steven Moreland | 65867d7 | 2018-09-04 14:22:26 -0700 | [diff] [blame] | 196 | EXPECT_TRUE(AIBinder_isRemote(binder)); |
| 197 | EXPECT_TRUE(AIBinder_isAlive(binder)); |
Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 198 | EXPECT_EQ(STATUS_OK, AIBinder_ping(binder)); |
Steven Moreland | 65867d7 | 2018-09-04 14:22:26 -0700 | [diff] [blame] | 199 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 200 | AIBinder_decStrong(binder); |
| 201 | } |
| 202 | |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 203 | void OnBinderDeath(void* cookie) { |
| 204 | LOG(ERROR) << "BINDER DIED. COOKIE: " << cookie; |
| 205 | } |
| 206 | |
| 207 | TEST(NdkBinder, LinkToDeath) { |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 208 | AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); |
| 209 | ASSERT_NE(nullptr, binder); |
| 210 | |
| 211 | AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath); |
| 212 | ASSERT_NE(nullptr, recipient); |
| 213 | |
Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 214 | EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr)); |
| 215 | EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr)); |
| 216 | EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr)); |
| 217 | EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr)); |
| 218 | EXPECT_EQ(STATUS_NAME_NOT_FOUND, AIBinder_unlinkToDeath(binder, recipient, nullptr)); |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 219 | |
Steven Moreland | 9b80e28 | 2018-09-19 13:57:23 -0700 | [diff] [blame] | 220 | AIBinder_DeathRecipient_delete(recipient); |
Steven Moreland | 901c745 | 2018-09-04 16:17:28 -0700 | [diff] [blame] | 221 | AIBinder_decStrong(binder); |
| 222 | } |
| 223 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 224 | class MyTestFoo : public IFoo { |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 225 | binder_status_t doubleNumber(int32_t in, int32_t* out) override { |
| 226 | *out = 2 * in; |
| 227 | LOG(INFO) << "doubleNumber (" << in << ") => " << *out; |
| 228 | return STATUS_OK; |
| 229 | } |
| 230 | binder_status_t die() override { |
| 231 | ADD_FAILURE() << "die called on local instance"; |
| 232 | return STATUS_OK; |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 233 | } |
| 234 | }; |
| 235 | |
| 236 | TEST(NdkBinder, GetServiceInProcess) { |
| 237 | static const char* kInstanceName = "test-get-service-in-process"; |
| 238 | |
| 239 | sp<IFoo> foo = new MyTestFoo; |
Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 240 | EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName)); |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 241 | |
| 242 | sp<IFoo> getFoo = IFoo::getService(kInstanceName); |
| 243 | EXPECT_EQ(foo.get(), getFoo.get()); |
| 244 | |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 245 | int32_t out; |
| 246 | EXPECT_EQ(STATUS_OK, getFoo->doubleNumber(1, &out)); |
| 247 | EXPECT_EQ(2, out); |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 248 | } |
| 249 | |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame] | 250 | TEST(NdkBinder, EqualityOfRemoteBinderPointer) { |
| 251 | AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService); |
| 252 | ASSERT_NE(nullptr, binderA); |
| 253 | |
| 254 | AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService); |
| 255 | ASSERT_NE(nullptr, binderB); |
| 256 | |
| 257 | EXPECT_EQ(binderA, binderB); |
| 258 | |
| 259 | AIBinder_decStrong(binderA); |
| 260 | AIBinder_decStrong(binderB); |
| 261 | } |
| 262 | |
Steven Moreland | 02f7565 | 2018-09-18 14:08:30 -0700 | [diff] [blame] | 263 | TEST(NdkBinder, ToFromJavaNullptr) { |
| 264 | EXPECT_EQ(nullptr, AIBinder_toJavaBinder(nullptr, nullptr)); |
| 265 | EXPECT_EQ(nullptr, AIBinder_fromJavaBinder(nullptr, nullptr)); |
| 266 | } |
| 267 | |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame] | 268 | TEST(NdkBinder, ABpBinderRefCount) { |
| 269 | AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); |
| 270 | AIBinder_Weak* wBinder = AIBinder_Weak_new(binder); |
| 271 | |
| 272 | ASSERT_NE(nullptr, binder); |
| 273 | EXPECT_EQ(1, AIBinder_debugGetRefCount(binder)); |
| 274 | |
| 275 | AIBinder_decStrong(binder); |
| 276 | |
| 277 | // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here |
| 278 | ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder)); |
| 279 | |
Steven Moreland | 9b80e28 | 2018-09-19 13:57:23 -0700 | [diff] [blame] | 280 | AIBinder_Weak_delete(wBinder); |
Steven Moreland | 9496895 | 2018-09-05 14:42:59 -0700 | [diff] [blame] | 281 | } |
| 282 | |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 283 | TEST(NdkBinder, AddServiceMultipleTimes) { |
| 284 | static const char* kInstanceName1 = "test-multi-1"; |
| 285 | static const char* kInstanceName2 = "test-multi-2"; |
| 286 | sp<IFoo> foo = new MyTestFoo; |
Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 287 | EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName1)); |
| 288 | EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName2)); |
Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 289 | EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2)); |
| 290 | } |
Steven Moreland | 2648d20 | 2018-08-28 01:23:02 -0700 | [diff] [blame] | 291 | |
Steven Moreland | 2f405f5 | 2020-07-08 22:24:29 +0000 | [diff] [blame] | 292 | TEST(NdkBinder, RequestedSidWorks) { |
| 293 | ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService)); |
| 294 | std::shared_ptr<aidl::IBinderNdkUnitTest> service = |
| 295 | aidl::IBinderNdkUnitTest::fromBinder(binder); |
| 296 | |
| 297 | bool gotSid = false; |
| 298 | EXPECT_TRUE(service->getsRequestedSid(&gotSid).isOk()); |
| 299 | EXPECT_TRUE(gotSid); |
| 300 | } |
| 301 | |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 302 | TEST(NdkBinder, SentAidlBinderCanBeDestroyed) { |
| 303 | static volatile bool destroyed = false; |
| 304 | static std::mutex dMutex; |
| 305 | static std::condition_variable cv; |
| 306 | |
| 307 | class MyEmpty : public aidl::BnEmpty { |
| 308 | virtual ~MyEmpty() { |
| 309 | destroyed = true; |
| 310 | cv.notify_one(); |
| 311 | } |
| 312 | }; |
| 313 | |
| 314 | std::shared_ptr<MyEmpty> empty = ndk::SharedRefBase::make<MyEmpty>(); |
| 315 | |
| 316 | ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService)); |
| 317 | std::shared_ptr<aidl::IBinderNdkUnitTest> service = |
| 318 | aidl::IBinderNdkUnitTest::fromBinder(binder); |
| 319 | |
| 320 | EXPECT_FALSE(destroyed); |
| 321 | |
| 322 | service->takeInterface(empty); |
| 323 | service->forceFlushCommands(); |
| 324 | empty = nullptr; |
| 325 | |
| 326 | // give other binder thread time to process commands |
| 327 | { |
| 328 | using namespace std::chrono_literals; |
| 329 | std::unique_lock<std::mutex> lk(dMutex); |
| 330 | cv.wait_for(lk, 1s, [] { return destroyed; }); |
| 331 | } |
| 332 | |
| 333 | EXPECT_TRUE(destroyed); |
| 334 | } |
| 335 | |
Steven Moreland | b2de953 | 2020-05-29 21:44:41 +0000 | [diff] [blame] | 336 | TEST(NdkBinder, ConvertToPlatformBinder) { |
| 337 | for (const ndk::SpAIBinder& binder : |
| 338 | {// remote |
| 339 | ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)), |
| 340 | // local |
| 341 | ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) { |
| 342 | // convert to platform binder |
| 343 | EXPECT_NE(binder.get(), nullptr); |
| 344 | sp<IBinder> platformBinder = AIBinder_toPlatformBinder(binder.get()); |
| 345 | EXPECT_NE(platformBinder.get(), nullptr); |
| 346 | auto proxy = interface_cast<IBinderNdkUnitTest>(platformBinder); |
| 347 | EXPECT_NE(proxy, nullptr); |
| 348 | |
| 349 | // use platform binder |
| 350 | int out; |
| 351 | EXPECT_TRUE(proxy->repeatInt(4, &out).isOk()); |
| 352 | EXPECT_EQ(out, 4); |
| 353 | |
| 354 | // convert back |
| 355 | ndk::SpAIBinder backBinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(platformBinder)); |
| 356 | EXPECT_EQ(backBinder.get(), binder.get()); |
| 357 | } |
| 358 | } |
| 359 | |
Ruchir Rastogi | cc7a746 | 2020-01-31 14:29:15 -0800 | [diff] [blame] | 360 | class MyResultReceiver : public BnResultReceiver { |
| 361 | public: |
| 362 | Mutex mMutex; |
| 363 | Condition mCondition; |
| 364 | bool mHaveResult = false; |
| 365 | int32_t mResult = 0; |
| 366 | |
| 367 | virtual void send(int32_t resultCode) { |
| 368 | AutoMutex _l(mMutex); |
| 369 | mResult = resultCode; |
| 370 | mHaveResult = true; |
| 371 | mCondition.signal(); |
| 372 | } |
| 373 | |
| 374 | int32_t waitForResult() { |
| 375 | AutoMutex _l(mMutex); |
| 376 | while (!mHaveResult) { |
| 377 | mCondition.wait(mMutex); |
| 378 | } |
| 379 | return mResult; |
| 380 | } |
| 381 | }; |
| 382 | |
| 383 | class MyShellCallback : public BnShellCallback { |
| 384 | public: |
| 385 | virtual int openFile(const String16& /*path*/, const String16& /*seLinuxContext*/, |
| 386 | const String16& /*mode*/) { |
| 387 | // Empty implementation. |
| 388 | return 0; |
| 389 | } |
| 390 | }; |
| 391 | |
| 392 | bool ReadFdToString(int fd, std::string* content) { |
| 393 | char buf[64]; |
| 394 | ssize_t n; |
| 395 | while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) { |
| 396 | content->append(buf, n); |
| 397 | } |
| 398 | return (n == 0) ? true : false; |
| 399 | } |
| 400 | |
| 401 | std::string shellCmdToString(sp<IBinder> unitTestService, const std::vector<const char*>& args) { |
| 402 | int inFd[2] = {-1, -1}; |
| 403 | int outFd[2] = {-1, -1}; |
| 404 | int errFd[2] = {-1, -1}; |
| 405 | |
| 406 | EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, inFd)); |
| 407 | EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, outFd)); |
| 408 | EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, errFd)); |
| 409 | |
| 410 | sp<MyShellCallback> cb = new MyShellCallback(); |
| 411 | sp<MyResultReceiver> resultReceiver = new MyResultReceiver(); |
| 412 | |
| 413 | Vector<String16> argsVec; |
| 414 | for (int i = 0; i < args.size(); i++) { |
| 415 | argsVec.add(String16(args[i])); |
| 416 | } |
| 417 | status_t error = IBinder::shellCommand(unitTestService, inFd[0], outFd[0], errFd[0], argsVec, |
| 418 | cb, resultReceiver); |
| 419 | EXPECT_EQ(error, android::OK); |
| 420 | |
| 421 | status_t res = resultReceiver->waitForResult(); |
| 422 | EXPECT_EQ(res, android::OK); |
| 423 | |
| 424 | close(inFd[0]); |
| 425 | close(inFd[1]); |
| 426 | close(outFd[0]); |
| 427 | close(errFd[0]); |
| 428 | close(errFd[1]); |
| 429 | |
| 430 | std::string ret; |
| 431 | EXPECT_TRUE(ReadFdToString(outFd[1], &ret)); |
| 432 | close(outFd[1]); |
| 433 | return ret; |
| 434 | } |
| 435 | |
| 436 | TEST(NdkBinder, UseHandleShellCommand) { |
| 437 | static const sp<android::IServiceManager> sm(android::defaultServiceManager()); |
| 438 | sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestService)); |
| 439 | |
| 440 | EXPECT_EQ("", shellCmdToString(testService, {})); |
| 441 | EXPECT_EQ("", shellCmdToString(testService, {"", ""})); |
| 442 | EXPECT_EQ("Hello world!", shellCmdToString(testService, {"Hello ", "world!"})); |
| 443 | EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"})); |
| 444 | } |
| 445 | |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 446 | int main(int argc, char* argv[]) { |
| 447 | ::testing::InitGoogleTest(&argc, argv); |
| 448 | |
Steven Moreland | f92c1fa | 2020-01-24 13:25:15 -0800 | [diff] [blame] | 449 | if (fork() == 0) { |
| 450 | prctl(PR_SET_PDEATHSIG, SIGHUP); |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 451 | return manualService(IFoo::kInstanceNameToDieFor); |
Steven Moreland | f92c1fa | 2020-01-24 13:25:15 -0800 | [diff] [blame] | 452 | } |
| 453 | if (fork() == 0) { |
| 454 | prctl(PR_SET_PDEATHSIG, SIGHUP); |
Steven Moreland | 169bb8f | 2020-01-29 10:21:35 -0800 | [diff] [blame] | 455 | return manualService(IFoo::kSomeInstanceName); |
| 456 | } |
| 457 | if (fork() == 0) { |
| 458 | prctl(PR_SET_PDEATHSIG, SIGHUP); |
| 459 | return generatedService(); |
Steven Moreland | f92c1fa | 2020-01-24 13:25:15 -0800 | [diff] [blame] | 460 | } |
| 461 | |
Steven Moreland | 507547f | 2018-11-06 15:58:05 -0800 | [diff] [blame] | 462 | ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications/callbacks |
| 463 | ABinderProcess_startThreadPool(); |
| 464 | |
| 465 | return RUN_ALL_TESTS(); |
| 466 | } |
| 467 | |
Steven Moreland | 2648d20 | 2018-08-28 01:23:02 -0700 | [diff] [blame] | 468 | #include <android/binder_auto_utils.h> |
| 469 | #include <android/binder_interface_utils.h> |
Steven Moreland | a884566 | 2018-10-12 11:53:03 -0700 | [diff] [blame] | 470 | #include <android/binder_parcel_utils.h> |