blob: dc22647b85090befdedd39b5c0e413be165c486e [file] [log] [blame]
Andrei Homescu2a298012022-06-15 01:08:54 +00001/*
2 * Copyright (C) 2022 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#pragma once
18
19#include <BinderRpcTestClientInfo.h>
20#include <BinderRpcTestServerConfig.h>
21#include <BinderRpcTestServerInfo.h>
22#include <BnBinderRpcCallback.h>
23#include <BnBinderRpcSession.h>
24#include <BnBinderRpcTest.h>
Andrei Homescu9d8adb12022-08-02 04:38:30 +000025#include <binder/Binder.h>
26#include <binder/BpBinder.h>
27#include <binder/IPCThreadState.h>
28#include <binder/IServiceManager.h>
29#include <binder/RpcServer.h>
30#include <binder/RpcSession.h>
31#include <binder/RpcThreads.h>
32#include <binder/RpcTransport.h>
33#include <binder/RpcTransportRaw.h>
34#include <unistd.h>
35#include <cinttypes>
36#include <string>
37#include <vector>
38
Tomasz Wasilczykc2b71d52023-11-06 16:32:12 -080039#ifdef __ANDROID__
40#include <android-base/properties.h>
41#endif
42
Andrei Homescu9d8adb12022-08-02 04:38:30 +000043#ifndef __TRUSTY__
Andrei Homescu2a298012022-06-15 01:08:54 +000044#include <android/binder_auto_utils.h>
45#include <android/binder_libbinder.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000046#include <binder/ProcessState.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000047#include <binder/RpcTlsTestUtils.h>
48#include <binder/RpcTlsUtils.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000049#include <binder/RpcTransportTls.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000050
51#include <signal.h>
52
David Brazdil21c887c2022-09-23 12:25:18 +010053#include "../OS.h" // for testing UnixBootstrap clients
Andrei Homescu2a298012022-06-15 01:08:54 +000054#include "../RpcSocketAddress.h" // for testing preconnected clients
Andrei Homescu2a298012022-06-15 01:08:54 +000055#include "../vm_sockets.h" // for VMADDR_*
Andrei Homescu9d8adb12022-08-02 04:38:30 +000056#endif // __TRUSTY__
57
58#include "../BuildFlags.h"
59#include "../FdTrigger.h"
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -070060#include "../FdUtils.h"
Andrei Homescu9d8adb12022-08-02 04:38:30 +000061#include "../RpcState.h" // for debugging
Tomasz Wasilczyk26db5e42023-11-02 11:45:11 -070062#include "FileUtils.h"
Andrei Homescu2a298012022-06-15 01:08:54 +000063#include "utils/Errors.h"
64
65namespace android {
66
Tomasz Wasilczyk2265ad92024-05-01 12:54:46 -070067#ifdef BINDER_NO_KERNEL_IPC_TESTING
68constexpr bool kEnableKernelIpcTesting = false;
69#else
70constexpr bool kEnableKernelIpcTesting = true;
71#endif
72
Andrei Homescu2a298012022-06-15 01:08:54 +000073constexpr char kLocalInetAddress[] = "127.0.0.1";
74
75enum class RpcSecurity { RAW, TLS };
76
77static inline std::vector<RpcSecurity> RpcSecurityValues() {
78 return {RpcSecurity::RAW, RpcSecurity::TLS};
79}
80
Tomasz Wasilczyk2265ad92024-05-01 12:54:46 -070081static inline std::vector<bool> noKernelValues() {
82 std::vector<bool> values = {true};
83 if (kEnableKernelIpcTesting) {
84 values.push_back(false);
85 }
86 return values;
87}
88
Steven Moreland0884c552023-10-17 18:23:31 +000089static inline bool hasExperimentalRpc() {
Andrei Homescu331c67e2024-03-27 23:07:01 +000090#ifdef BINDER_RPC_TO_TRUSTY_TEST
91 // Trusty services do not support the experimental version,
92 // so that we can update the prebuilts separately.
93 // This covers the binderRpcToTrustyTest case on Android.
94 return false;
95#endif
Steven Moreland0884c552023-10-17 18:23:31 +000096#ifdef __ANDROID__
97 return base::GetProperty("ro.build.version.codename", "") != "REL";
98#else
Steven Moreland687728e2023-10-28 01:07:40 +000099 return false;
Steven Moreland0884c552023-10-17 18:23:31 +0000100#endif
101}
102
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000103static inline std::vector<uint32_t> testVersions() {
104 std::vector<uint32_t> versions;
105 for (size_t i = 0; i < RPC_WIRE_PROTOCOL_VERSION_NEXT; i++) {
106 versions.push_back(i);
107 }
Steven Moreland0884c552023-10-17 18:23:31 +0000108 if (hasExperimentalRpc()) {
109 versions.push_back(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
110 }
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000111 return versions;
112}
113
114static inline std::string trustyIpcPort(uint32_t serverVersion) {
Tomasz Wasilczyk68c42082024-05-20 11:59:35 -0700115 return "com.android.trusty.binderRpcTestService.V" + std::to_string(serverVersion);
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000116}
117
Andrei Homescu2a298012022-06-15 01:08:54 +0000118enum class SocketType {
119 PRECONNECTED,
120 UNIX,
David Brazdil21c887c2022-09-23 12:25:18 +0100121 UNIX_BOOTSTRAP,
Alice Wang893a9912022-10-24 10:44:09 +0000122 UNIX_RAW,
Andrei Homescu2a298012022-06-15 01:08:54 +0000123 VSOCK,
124 INET,
Andrei Homescu68a55612022-08-02 01:25:15 +0000125 TIPC,
Andrei Homescu2a298012022-06-15 01:08:54 +0000126};
David Brazdil21c887c2022-09-23 12:25:18 +0100127
Andrei Homescu2a298012022-06-15 01:08:54 +0000128static inline std::string PrintToString(SocketType socketType) {
129 switch (socketType) {
130 case SocketType::PRECONNECTED:
131 return "preconnected_uds";
132 case SocketType::UNIX:
133 return "unix_domain_socket";
David Brazdil21c887c2022-09-23 12:25:18 +0100134 case SocketType::UNIX_BOOTSTRAP:
135 return "unix_domain_socket_bootstrap";
Alice Wang893a9912022-10-24 10:44:09 +0000136 case SocketType::UNIX_RAW:
137 return "raw_uds";
Andrei Homescu2a298012022-06-15 01:08:54 +0000138 case SocketType::VSOCK:
139 return "vm_socket";
140 case SocketType::INET:
141 return "inet_socket";
Andrei Homescu68a55612022-08-02 01:25:15 +0000142 case SocketType::TIPC:
143 return "trusty_ipc";
Andrei Homescu2a298012022-06-15 01:08:54 +0000144 default:
145 LOG_ALWAYS_FATAL("Unknown socket type");
146 return "";
147 }
148}
149
Andrei Homescu9a9b1b42022-10-14 01:40:59 +0000150static inline size_t epochMillis() {
151 using std::chrono::duration_cast;
152 using std::chrono::milliseconds;
153 using std::chrono::seconds;
154 using std::chrono::system_clock;
155 return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
156}
157
Andrei Homescu2a298012022-06-15 01:08:54 +0000158struct BinderRpcOptions {
159 size_t numThreads = 1;
160 size_t numSessions = 1;
Steven Moreland67f85902023-03-15 01:13:49 +0000161 // right now, this can be empty, or length numSessions, where each value
162 // represents the info for the corresponding session, but we should
163 // probably switch this to be a list of sessions options so that other
164 // options can all be specified per session
165 std::vector<size_t> numIncomingConnectionsBySession = {};
Andrei Homescu2a298012022-06-15 01:08:54 +0000166 size_t numOutgoingConnections = SIZE_MAX;
167 RpcSession::FileDescriptorTransportMode clientFileDescriptorTransportMode =
168 RpcSession::FileDescriptorTransportMode::NONE;
169 std::vector<RpcSession::FileDescriptorTransportMode>
170 serverSupportedFileDescriptorTransportModes = {
171 RpcSession::FileDescriptorTransportMode::NONE};
172
173 // If true, connection failures will result in `ProcessSession::sessions` being empty
174 // instead of a fatal error.
175 bool allowConnectFailure = false;
176};
177
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000178#ifndef __TRUSTY__
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -0700179static inline void writeString(binder::borrowed_fd fd, std::string_view str) {
Andrei Homescu2a298012022-06-15 01:08:54 +0000180 uint64_t length = str.length();
Tomasz Wasilczyk26db5e42023-11-02 11:45:11 -0700181 LOG_ALWAYS_FATAL_IF(!android::binder::WriteFully(fd, &length, sizeof(length)));
182 LOG_ALWAYS_FATAL_IF(!android::binder::WriteFully(fd, str.data(), str.length()));
Andrei Homescu2a298012022-06-15 01:08:54 +0000183}
184
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -0700185static inline std::string readString(binder::borrowed_fd fd) {
Andrei Homescu2a298012022-06-15 01:08:54 +0000186 uint64_t length;
Tomasz Wasilczyk26db5e42023-11-02 11:45:11 -0700187 LOG_ALWAYS_FATAL_IF(!android::binder::ReadFully(fd, &length, sizeof(length)));
Andrei Homescu2a298012022-06-15 01:08:54 +0000188 std::string ret(length, '\0');
Tomasz Wasilczyk26db5e42023-11-02 11:45:11 -0700189 LOG_ALWAYS_FATAL_IF(!android::binder::ReadFully(fd, ret.data(), length));
Andrei Homescu2a298012022-06-15 01:08:54 +0000190 return ret;
191}
192
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -0700193static inline void writeToFd(binder::borrowed_fd fd, const Parcelable& parcelable) {
Andrei Homescu2a298012022-06-15 01:08:54 +0000194 Parcel parcel;
Tomasz Wasilczyke3de8802023-11-01 11:05:27 -0700195 LOG_ALWAYS_FATAL_IF(OK != parcelable.writeToParcel(&parcel));
Andrei Homescu2a298012022-06-15 01:08:54 +0000196 writeString(fd, std::string(reinterpret_cast<const char*>(parcel.data()), parcel.dataSize()));
197}
198
199template <typename T>
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -0700200static inline T readFromFd(binder::borrowed_fd fd) {
Andrei Homescu2a298012022-06-15 01:08:54 +0000201 std::string data = readString(fd);
202 Parcel parcel;
Tomasz Wasilczyke3de8802023-11-01 11:05:27 -0700203 LOG_ALWAYS_FATAL_IF(OK !=
204 parcel.setData(reinterpret_cast<const uint8_t*>(data.data()), data.size()));
Andrei Homescu2a298012022-06-15 01:08:54 +0000205 T object;
Tomasz Wasilczyke3de8802023-11-01 11:05:27 -0700206 LOG_ALWAYS_FATAL_IF(OK != object.readFromParcel(&parcel));
Andrei Homescu2a298012022-06-15 01:08:54 +0000207 return object;
208}
209
Andrei Homescuf30148c2023-03-10 00:31:45 +0000210static inline std::unique_ptr<RpcTransportCtxFactory> newTlsFactory(
Andrei Homescu2a298012022-06-15 01:08:54 +0000211 RpcSecurity rpcSecurity, std::shared_ptr<RpcCertificateVerifier> verifier = nullptr,
212 std::unique_ptr<RpcAuth> auth = nullptr) {
213 switch (rpcSecurity) {
214 case RpcSecurity::RAW:
215 return RpcTransportCtxFactoryRaw::make();
216 case RpcSecurity::TLS: {
217 if (verifier == nullptr) {
218 verifier = std::make_shared<RpcCertificateVerifierSimple>();
219 }
220 if (auth == nullptr) {
221 auth = std::make_unique<RpcAuthSelfSigned>();
222 }
223 return RpcTransportCtxFactoryTls::make(std::move(verifier), std::move(auth));
224 }
225 default:
Tomasz Wasilczyke97f3a82024-04-30 10:37:32 -0700226 LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", static_cast<int>(rpcSecurity));
Andrei Homescu2a298012022-06-15 01:08:54 +0000227 }
228}
229
230// Create an FD that returns `contents` when read.
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -0700231static inline binder::unique_fd mockFileDescriptor(std::string contents) {
232 binder::unique_fd readFd, writeFd;
233 LOG_ALWAYS_FATAL_IF(!binder::Pipe(&readFd, &writeFd), "%s", strerror(errno));
Andrei Homescu2a298012022-06-15 01:08:54 +0000234 RpcMaybeThread([writeFd = std::move(writeFd), contents = std::move(contents)]() {
235 signal(SIGPIPE, SIG_IGN); // ignore possible SIGPIPE from the write
Tomasz Wasilczyk26db5e42023-11-02 11:45:11 -0700236 if (!android::binder::WriteStringToFd(contents, writeFd)) {
Andrei Homescu2a298012022-06-15 01:08:54 +0000237 int savedErrno = errno;
238 LOG_ALWAYS_FATAL_IF(EPIPE != savedErrno, "mockFileDescriptor write failed: %s",
239 strerror(savedErrno));
240 }
241 }).detach();
242 return readFd;
243}
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000244#endif // __TRUSTY__
Andrei Homescu2a298012022-06-15 01:08:54 +0000245
Frederick Mayleb0221d12022-10-03 23:10:53 +0000246// A threadsafe channel where writes block until the value is read.
247template <typename T>
248class HandoffChannel {
249public:
250 void write(T v) {
251 {
252 RpcMutexUniqueLock lock(mMutex);
253 // Wait for space to send.
254 mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
255 mValue.emplace(std::move(v));
256 }
257 mCvFull.notify_all();
258 RpcMutexUniqueLock lock(mMutex);
259 // Wait for it to be taken.
260 mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
261 }
262
263 T read() {
264 RpcMutexUniqueLock lock(mMutex);
265 if (!mValue.has_value()) {
266 mCvFull.wait(lock, [&]() { return mValue.has_value(); });
267 }
268 T v = std::move(mValue.value());
269 mValue.reset();
270 lock.unlock();
271 mCvEmpty.notify_all();
Tomasz Wasilczyke97f3a82024-04-30 10:37:32 -0700272 return v;
Frederick Mayleb0221d12022-10-03 23:10:53 +0000273 }
274
275private:
276 RpcMutex mMutex;
277 RpcConditionVariable mCvEmpty;
278 RpcConditionVariable mCvFull;
279 std::optional<T> mValue;
280};
281
Andrei Homescu2a298012022-06-15 01:08:54 +0000282using android::binder::Status;
283
284class MyBinderRpcSession : public BnBinderRpcSession {
285public:
286 static std::atomic<int32_t> gNum;
287
288 MyBinderRpcSession(const std::string& name) : mName(name) { gNum++; }
289 Status getName(std::string* name) override {
290 *name = mName;
291 return Status::ok();
292 }
293 ~MyBinderRpcSession() { gNum--; }
294
295private:
296 std::string mName;
297};
298
299class MyBinderRpcCallback : public BnBinderRpcCallback {
300 Status sendCallback(const std::string& value) {
301 RpcMutexUniqueLock _l(mMutex);
302 mValues.push_back(value);
303 _l.unlock();
304 mCv.notify_one();
305 return Status::ok();
306 }
307 Status sendOnewayCallback(const std::string& value) { return sendCallback(value); }
308
309public:
310 RpcMutex mMutex;
311 RpcConditionVariable mCv;
312 std::vector<std::string> mValues;
313};
314
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000315// Base class for all concrete implementations of MyBinderRpcTest.
316// Sub-classes that want to provide a full implementation should derive
317// from this class instead of MyBinderRpcTestDefault below so the compiler
318// checks that all methods are implemented.
319class MyBinderRpcTestBase : public BnBinderRpcTest {
Andrei Homescu2a298012022-06-15 01:08:54 +0000320public:
Andrei Homescu2a298012022-06-15 01:08:54 +0000321 int port = 0;
322
323 Status sendString(const std::string& str) override {
324 (void)str;
325 return Status::ok();
326 }
327 Status doubleString(const std::string& str, std::string* strstr) override {
328 *strstr = str + str;
329 return Status::ok();
330 }
331 Status getClientPort(int* out) override {
332 *out = port;
333 return Status::ok();
334 }
Andrei Homescu2a298012022-06-15 01:08:54 +0000335 Status getNullBinder(sp<IBinder>* out) override {
336 out->clear();
337 return Status::ok();
338 }
339 Status pingMe(const sp<IBinder>& binder, int32_t* out) override {
340 if (binder == nullptr) {
341 std::cout << "Received null binder!" << std::endl;
342 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
343 }
344 *out = binder->pingBinder();
345 return Status::ok();
346 }
347 Status repeatBinder(const sp<IBinder>& binder, sp<IBinder>* out) override {
348 *out = binder;
349 return Status::ok();
350 }
351 static sp<IBinder> mHeldBinder;
352 Status holdBinder(const sp<IBinder>& binder) override {
353 mHeldBinder = binder;
354 return Status::ok();
355 }
356 Status getHeldBinder(sp<IBinder>* held) override {
357 *held = mHeldBinder;
358 return Status::ok();
359 }
360 Status nestMe(const sp<IBinderRpcTest>& binder, int count) override {
361 if (count <= 0) return Status::ok();
362 return binder->nestMe(this, count - 1);
363 }
364 Status alwaysGiveMeTheSameBinder(sp<IBinder>* out) override {
365 static sp<IBinder> binder = new BBinder;
366 *out = binder;
367 return Status::ok();
368 }
369 Status openSession(const std::string& name, sp<IBinderRpcSession>* out) override {
370 *out = new MyBinderRpcSession(name);
371 return Status::ok();
372 }
373 Status getNumOpenSessions(int32_t* out) override {
374 *out = MyBinderRpcSession::gNum;
375 return Status::ok();
376 }
377
378 RpcMutex blockMutex;
379 Status lock() override {
380 blockMutex.lock();
381 return Status::ok();
382 }
383 Status unlockInMsAsync(int32_t ms) override {
384 usleep(ms * 1000);
385 blockMutex.unlock();
386 return Status::ok();
387 }
388 Status lockUnlock() override {
389 RpcMutexLockGuard _l(blockMutex);
390 return Status::ok();
391 }
392
393 Status sleepMs(int32_t ms) override {
394 usleep(ms * 1000);
395 return Status::ok();
396 }
397
398 Status sleepMsAsync(int32_t ms) override {
399 // In-process binder calls are asynchronous, but the call to this method
400 // is synchronous wrt its client. This in/out-process threading model
401 // diffentiation is a classic binder leaky abstraction (for better or
402 // worse) and is preserved here the way binder sockets plugs itself
403 // into BpBinder, as nothing is changed at the higher levels
404 // (IInterface) which result in this behavior.
405 return sleepMs(ms);
406 }
407
408 Status doCallback(const sp<IBinderRpcCallback>& callback, bool oneway, bool delayed,
409 const std::string& value) override {
410 if (callback == nullptr) {
411 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
412 }
413
414 if (delayed) {
Tomasz Wasilczyke9c93a72023-12-04 11:53:26 -0800415 RpcMaybeThread([=, this]() {
Andrei Homescu2a298012022-06-15 01:08:54 +0000416 ALOGE("Executing delayed callback: '%s'", value.c_str());
417 Status status = doCallback(callback, oneway, false, value);
418 ALOGE("Delayed callback status: '%s'", status.toString8().c_str());
419 }).detach();
420 return Status::ok();
421 }
422
423 if (oneway) {
424 return callback->sendOnewayCallback(value);
425 }
426
427 return callback->sendCallback(value);
428 }
429
430 Status doCallbackAsync(const sp<IBinderRpcCallback>& callback, bool oneway, bool delayed,
431 const std::string& value) override {
432 return doCallback(callback, oneway, delayed, value);
433 }
434
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000435protected:
436 // Generic version of countBinders that works with both
437 // RpcServer and RpcServerTrusty
438 template <typename T>
439 Status countBindersImpl(const wp<T>& server, std::vector<int32_t>* out) {
440 sp<T> spServer = server.promote();
441 if (spServer == nullptr) {
Andrei Homescu2a298012022-06-15 01:08:54 +0000442 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
443 }
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000444 out->clear();
445 for (auto session : spServer->listSessions()) {
446 size_t count = session->state()->countBinders();
447 out->push_back(count);
Andrei Homescu2a298012022-06-15 01:08:54 +0000448 }
449 return Status::ok();
450 }
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000451};
Andrei Homescu2a298012022-06-15 01:08:54 +0000452
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000453// Default implementation of MyBinderRpcTest that can be used as-is
454// or derived from by classes that only want to implement a subset of
455// the unimplemented methods
456class MyBinderRpcTestDefault : public MyBinderRpcTestBase {
457public:
458 Status countBinders(std::vector<int32_t>* /*out*/) override {
459 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Andrei Homescu2a298012022-06-15 01:08:54 +0000460 }
461
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000462 Status die(bool /*cleanup*/) override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
463
464 Status scheduleShutdown() override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
465
466 Status useKernelBinderCallingId() override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
467
468 Status echoAsFile(const std::string& /*content*/,
469 android::os::ParcelFileDescriptor* /*out*/) override {
470 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Andrei Homescu2a298012022-06-15 01:08:54 +0000471 }
Frederick Mayleb0221d12022-10-03 23:10:53 +0000472
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000473 Status concatFiles(const std::vector<android::os::ParcelFileDescriptor>& /*files*/,
474 android::os::ParcelFileDescriptor* /*out*/) override {
475 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Frederick Mayleb0221d12022-10-03 23:10:53 +0000476 }
477
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000478 Status blockingSendFdOneway(const android::os::ParcelFileDescriptor& /*fd*/) override {
479 return Status::fromStatusT(UNKNOWN_TRANSACTION);
480 }
481
482 Status blockingRecvFd(android::os::ParcelFileDescriptor* /*fd*/) override {
483 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Frederick Mayleb0221d12022-10-03 23:10:53 +0000484 }
Frederick Mayle96872592023-03-07 14:56:15 -0800485
486 Status blockingSendIntOneway(int /*n*/) override {
487 return Status::fromStatusT(UNKNOWN_TRANSACTION);
488 }
489
490 Status blockingRecvInt(int* /*n*/) override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
Andrei Homescu2a298012022-06-15 01:08:54 +0000491};
492
493} // namespace android