Add stub for AOSP Binder and utility components

The primary function of these stubs is to provide necessary interface definitions and that can be utilized by `binder_interceptor.cpp` during compilation (and runtime).

Crucially, `libTEESimulator.so` (which encapsulates these stubs) is dynamically loaded into the target process via `ptrace` after the system's official libraries, such as `/system/lib64/libbinder.so` and `/system/lib64/libutils.so`, have already been loaded and their symbols resolved by the dynamic linker.

Consequently, the dynamic linker will have already established bindings to the robust, canonical implementations within the system libraries for existing code paths. The dynamic linker does not automatically re-resolve or update these established symbol bindings when a new library with conflicting definitions is loaded later.

The AOSP files are downloaded via links:
1. https://android.googlesource.com/platform/frameworks/native/+/refs/heads/main/libs/binder/include/binder
2. https://android.googlesource.com/platform/system/core/+/refs/heads/main/libutils/binder/include/utils

The link for binder header in Android kernel is:
https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/include/uapi/linux/android/binder.h
This commit is contained in:
JingMatrix
2025-11-25 19:21:05 +01:00
parent ffb27915e2
commit cc52307ca8
59 changed files with 12599 additions and 1 deletions
+10 -1
View File
@@ -10,10 +10,19 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
OPTION(LSPLT_BUILD_SHARED OFF)
add_subdirectory(external/LSPlt/lsplt/src/main/jni)
add_compile_definitions(BINDER_DISABLE_NATIVE_HANDLE)
add_library(utils SHARED stub/stub_utils.cpp)
target_include_directories(utils PUBLIC external/AOSP/include)
add_library(binder SHARED stub/stub_binder.cpp)
target_include_directories(binder PUBLIC external/AOSP/include)
target_link_libraries(binder PRIVATE utils)
add_executable(libinject.so inject/main.cpp inject/utils.cpp)
target_include_directories(libinject.so PUBLIC include)
target_link_libraries(libinject.so PRIVATE lsplt_static)
add_library(${CMAKE_PROJECT_NAME} SHARED binder_interceptor.cpp)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE lsplt_static)
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC external/linux-kernel/include include)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE binder lsplt_static utils)
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,322 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
// DO NOT INCLUDE OTHER LIBBASE HEADERS HERE!
// This file gets used in libbinder, and libbinder is used everywhere.
// Including other headers from libbase frequently results in inclusion of
// android-base/macros.h, which causes macro collisions.
#if defined(__BIONIC__)
#include <android/fdsan.h>
#endif
#if !defined(_WIN32) && !defined(__TRUSTY__)
#include <sys/socket.h>
#endif
namespace android {
namespace base {
// Container for a file descriptor that automatically closes the descriptor as
// it goes out of scope.
//
// unique_fd ufd(open("/some/path", "r"));
// if (ufd.get() == -1) return error;
//
// // Do something useful, possibly including 'return'.
//
// return 0; // Descriptor is closed for you.
//
// See also the Pipe()/Socketpair()/Fdopen()/Fdopendir() functions in this file
// that provide interoperability with the libc functions with the same (but
// lowercase) names.
//
// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
// you find this class if you're searching for one of those names.
//
// unique_fd itself is a specialization of unique_fd_impl with a default closer.
template <typename Closer>
class unique_fd_impl final {
public:
unique_fd_impl() {}
explicit unique_fd_impl(int fd) { reset(fd); }
~unique_fd_impl() { reset(); }
unique_fd_impl(const unique_fd_impl&) = delete;
void operator=(const unique_fd_impl&) = delete;
unique_fd_impl(unique_fd_impl&& other) noexcept { reset(other.release()); }
unique_fd_impl& operator=(unique_fd_impl&& s) noexcept {
int fd = s.fd_;
s.fd_ = -1;
reset(fd, &s);
return *this;
}
[[clang::reinitializes]] void reset(int new_value = -1) { reset(new_value, nullptr); }
int get() const { return fd_; }
#if !defined(ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION)
// unique_fd's operator int is dangerous, but we have way too much code that
// depends on it, so make this opt-in at first.
operator int() const { return get(); } // NOLINT
#endif
bool operator>=(int rhs) const { return get() >= rhs; }
bool operator<(int rhs) const { return get() < rhs; }
bool operator==(int rhs) const { return get() == rhs; }
bool operator!=(int rhs) const { return get() != rhs; }
bool operator==(const unique_fd_impl& rhs) const { return get() == rhs.get(); }
bool operator!=(const unique_fd_impl& rhs) const { return get() != rhs.get(); }
// Catch bogus error checks (i.e.: "!fd" instead of "fd != -1").
bool operator!() const = delete;
bool ok() const { return get() >= 0; }
int release() __attribute__((warn_unused_result)) {
tag(fd_, this, nullptr);
int ret = fd_;
fd_ = -1;
return ret;
}
private:
void reset(int new_value, void* previous_tag) {
int previous_errno = errno;
if (fd_ != -1) {
close(fd_, this);
}
fd_ = new_value;
if (new_value != -1) {
tag(new_value, previous_tag, this);
}
errno = previous_errno;
}
int fd_ = -1;
// Template magic to use Closer::Tag if available, and do nothing if not.
// If Closer::Tag exists, this implementation is preferred, because int is a better match.
// If not, this implementation is SFINAEd away, and the no-op below is the only one that exists.
template <typename T = Closer>
static auto tag(int fd, void* old_tag, void* new_tag)
-> decltype(T::Tag(fd, old_tag, new_tag), void()) {
T::Tag(fd, old_tag, new_tag);
}
template <typename T = Closer>
static void tag(long, void*, void*) {
// No-op.
}
// Same as above, to select between Closer::Close(int) and Closer::Close(int, void*).
template <typename T = Closer>
static auto close(int fd, void* tag_value) -> decltype(T::Close(fd, tag_value), void()) {
T::Close(fd, tag_value);
}
template <typename T = Closer>
static auto close(int fd, void*) -> decltype(T::Close(fd), void()) {
T::Close(fd);
}
};
// The actual details of closing are factored out to support unusual cases.
// Almost everyone will want this DefaultCloser, which handles fdsan on bionic.
struct DefaultCloser {
#if defined(__BIONIC__)
static void Tag(int fd, void* old_addr, void* new_addr) {
if (android_fdsan_exchange_owner_tag) {
uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
reinterpret_cast<uint64_t>(old_addr));
uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
reinterpret_cast<uint64_t>(new_addr));
android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
}
}
static void Close(int fd, void* addr) {
if (android_fdsan_close_with_tag) {
uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
reinterpret_cast<uint64_t>(addr));
android_fdsan_close_with_tag(fd, tag);
} else {
close(fd);
}
}
#else
static void Close(int fd) {
// Even if close(2) fails with EINTR, the fd will have been closed.
// Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
// else's fd.
// http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
::close(fd);
}
#endif
};
using unique_fd = unique_fd_impl<DefaultCloser>;
#if !defined(_WIN32) && !defined(__TRUSTY__)
// Inline functions, so that they can be used header-only.
// See pipe(2).
// This helper hides the details of converting to unique_fd, and also hides the
// fact that macOS doesn't support O_CLOEXEC or O_NONBLOCK directly.
template <typename Closer>
inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write,
int flags = O_CLOEXEC) {
int pipefd[2];
#if defined(__linux__)
if (pipe2(pipefd, flags) != 0) {
return false;
}
#else // defined(__APPLE__)
if (flags & ~(O_CLOEXEC | O_NONBLOCK)) {
return false;
}
if (pipe(pipefd) != 0) {
return false;
}
if (flags & O_CLOEXEC) {
if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
close(pipefd[0]);
close(pipefd[1]);
return false;
}
}
if (flags & O_NONBLOCK) {
if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 || fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) {
close(pipefd[0]);
close(pipefd[1]);
return false;
}
}
#endif
read->reset(pipefd[0]);
write->reset(pipefd[1]);
return true;
}
// See socketpair(2).
// This helper hides the details of converting to unique_fd.
template <typename Closer>
inline bool Socketpair(int domain, int type, int protocol, unique_fd_impl<Closer>* left,
unique_fd_impl<Closer>* right) {
int sockfd[2];
if (socketpair(domain, type, protocol, sockfd) != 0) {
return false;
}
left->reset(sockfd[0]);
right->reset(sockfd[1]);
return true;
}
// See socketpair(2).
// This helper hides the details of converting to unique_fd.
template <typename Closer>
inline bool Socketpair(int type, unique_fd_impl<Closer>* left, unique_fd_impl<Closer>* right) {
return Socketpair(AF_UNIX, type, 0, left, right);
}
// See fdopen(3).
// Using fdopen with unique_fd correctly is more annoying than it should be,
// because fdopen doesn't close the file descriptor received upon failure.
inline FILE* Fdopen(unique_fd&& ufd, const char* mode) {
int fd = ufd.release();
FILE* file = fdopen(fd, mode);
if (!file) {
close(fd);
}
return file;
}
// See fdopendir(3).
// Using fdopendir with unique_fd correctly is more annoying than it should be,
// because fdopen doesn't close the file descriptor received upon failure.
inline DIR* Fdopendir(unique_fd&& ufd) {
int fd = ufd.release();
DIR* dir = fdopendir(fd);
if (dir == nullptr) {
close(fd);
}
return dir;
}
#endif // !defined(_WIN32) && !defined(__TRUSTY__)
// A wrapper type that can be implicitly constructed from either int or
// unique_fd. This supports cases where you don't actually own the file
// descriptor, and can't take ownership, but are temporarily acting as if
// you're the owner.
//
// One example would be a function that needs to also allow
// STDERR_FILENO, not just a newly-opened fd. Another example would be JNI code
// that's using a file descriptor that's actually owned by a
// ParcelFileDescriptor or whatever on the Java side, but where the JNI code
// would like to enforce this weaker sense of "temporary ownership".
//
// If you think of unique_fd as being like std::string in that represents
// ownership, borrowed_fd is like std::string_view (and int is like const
// char*).
struct borrowed_fd {
/* implicit */ borrowed_fd(int fd) : fd_(fd) {} // NOLINT
template <typename T>
/* implicit */ borrowed_fd(const unique_fd_impl<T>& ufd) : fd_(ufd.get()) {} // NOLINT
int get() const { return fd_; }
bool operator>=(int rhs) const { return get() >= rhs; }
bool operator<(int rhs) const { return get() < rhs; }
bool operator==(int rhs) const { return get() == rhs; }
bool operator!=(int rhs) const { return get() != rhs; }
private:
int fd_ = -1;
};
} // namespace base
} // namespace android
template <typename T>
int close(const android::base::unique_fd_impl<T>&)
__attribute__((__unavailable__("close called on unique_fd")));
template <typename T>
FILE* fdopen(const android::base::unique_fd_impl<T>&, const char* mode)
__attribute__((__unavailable__("fdopen takes ownership of the fd passed in; either dup the "
"unique_fd, or use android::base::Fdopen to pass ownership")));
template <typename T>
DIR* fdopendir(const android::base::unique_fd_impl<T>&) __attribute__((
__unavailable__("fdopendir takes ownership of the fd passed in; either dup the "
"unique_fd, or use android::base::Fdopendir to pass ownership")));
+165
View File
@@ -0,0 +1,165 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <atomic>
#include <stdint.h>
#include <binder/Common.h>
#include <binder/IBinder.h>
// ---------------------------------------------------------------------------
namespace android {
namespace internal {
class Stability;
}
class BBinder : public IBinder {
public:
LIBBINDER_EXPORTED BBinder();
LIBBINDER_EXPORTED virtual const String16& getInterfaceDescriptor() const;
LIBBINDER_EXPORTED virtual bool isBinderAlive() const;
LIBBINDER_EXPORTED virtual status_t pingBinder();
LIBBINDER_EXPORTED virtual status_t dump(int fd, const Vector<String16>& args);
// NOLINTNEXTLINE(google-default-arguments)
LIBBINDER_EXPORTED virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0) final;
// NOLINTNEXTLINE(google-default-arguments)
LIBBINDER_EXPORTED virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = nullptr, uint32_t flags = 0);
// NOLINTNEXTLINE(google-default-arguments)
LIBBINDER_EXPORTED virtual status_t unlinkToDeath(const wp<DeathRecipient>& recipient,
void* cookie = nullptr, uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = nullptr);
LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object,
void* cleanupCookie,
object_cleanup_func func) final;
LIBBINDER_EXPORTED virtual void* findObject(const void* objectID) const final;
LIBBINDER_EXPORTED virtual void* detachObject(const void* objectID) final;
LIBBINDER_EXPORTED void withLock(const std::function<void()>& doWithLock);
LIBBINDER_EXPORTED sp<IBinder> lookupOrCreateWeak(const void* objectID,
IBinder::object_make_func make,
const void* makeArgs);
LIBBINDER_EXPORTED virtual BBinder* localBinder();
LIBBINDER_EXPORTED bool isRequestingSid();
// This must be called before the object is sent to another process. Not thread safe.
LIBBINDER_EXPORTED void setRequestingSid(bool requestSid);
LIBBINDER_EXPORTED sp<IBinder> getExtension();
// This must be called before the object is sent to another process. Not thread safe.
LIBBINDER_EXPORTED void setExtension(const sp<IBinder>& extension);
// This must be called before the object is sent to another process. Not thread safe.
//
// This function will abort if improper parameters are set. This is like
// sched_setscheduler. However, it sets the minimum scheduling policy
// only for the duration that this specific binder object is handling the
// call in a threadpool. By default, this API is set to SCHED_NORMAL/0. In
// this case, the scheduling priority will not actually be modified from
// binder defaults. See also IPCThreadState::disableBackgroundScheduling.
//
// Appropriate values are:
// SCHED_NORMAL: -20 <= priority <= 19
// SCHED_RR/SCHED_FIFO: 1 <= priority <= 99
LIBBINDER_EXPORTED void setMinSchedulerPolicy(int policy, int priority);
LIBBINDER_EXPORTED int getMinSchedulerPolicy();
LIBBINDER_EXPORTED int getMinSchedulerPriority();
// Whether realtime scheduling policies are inherited.
LIBBINDER_EXPORTED bool isInheritRt();
// This must be called before the object is sent to another process. Not thread safe.
LIBBINDER_EXPORTED void setInheritRt(bool inheritRt);
LIBBINDER_EXPORTED pid_t getDebugPid();
// Whether this binder has been sent to another process.
LIBBINDER_EXPORTED bool wasParceled();
// Consider this binder as parceled (setup/init-related calls should no
// longer by called. This is automatically set by when this binder is sent
// to another process.
LIBBINDER_EXPORTED void setParceled();
[[nodiscard]] LIBBINDER_EXPORTED status_t setRpcClientDebug(binder::unique_fd clientFd,
const sp<IBinder>& keepAliveBinder);
protected:
LIBBINDER_EXPORTED virtual ~BBinder();
// NOLINTNEXTLINE(google-default-arguments)
LIBBINDER_EXPORTED virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0);
private:
BBinder(const BBinder& o);
BBinder& operator=(const BBinder& o);
class RpcServerLink;
class Extras;
Extras* getOrCreateExtras();
[[nodiscard]] status_t setRpcClientDebug(const Parcel& data);
void removeRpcServerLink(const sp<RpcServerLink>& link);
[[nodiscard]] status_t startRecordingTransactions(const Parcel& data);
[[nodiscard]] status_t stopRecordingTransactions();
std::atomic<Extras*> mExtras;
friend ::android::internal::Stability;
int16_t mStability;
bool mParceled;
bool mRecordingOn;
#ifdef __LP64__
int32_t mReserved1;
#endif
};
// ---------------------------------------------------------------------------
class BpRefBase : public virtual RefBase {
protected:
LIBBINDER_EXPORTED explicit BpRefBase(const sp<IBinder>& o);
LIBBINDER_EXPORTED virtual ~BpRefBase();
LIBBINDER_EXPORTED virtual void onFirstRef();
LIBBINDER_EXPORTED virtual void onLastStrongRef(const void* id);
LIBBINDER_EXPORTED virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
LIBBINDER_EXPORTED inline IBinder* remote() const { return mRemote; }
LIBBINDER_EXPORTED inline sp<IBinder> remoteStrong() const {
return sp<IBinder>::fromExisting(mRemote);
}
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
} // namespace android
// ---------------------------------------------------------------------------
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#include <utils/Errors.h>
#include <utils/String16.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
// WARNING: deprecated - DO NOT USE - prefer to setup service directly.
//
// This class embellishes a class with a few static methods which can be used in
// limited circumstances (when one service needs to be registered and
// published). However, this is an anti-pattern:
// - these methods are aliases of existing methods, and as such, represent an
// incremental amount of information required to understand the system but
// which does not actually save in terms of lines of code. For instance, users
// of this class should be surprised to know that this will start up to 16
// threads in the binder threadpool.
// - the template instantiation costs need to be paid, even though everything
// done here is generic.
// - the getServiceName API here is undocumented and non-local (for instance,
// this unnecessarily assumes a single service type will only be instantiated
// once with no arguments).
//
// So, DO NOT USE.
// ---------------------------------------------------------------------------
namespace android {
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false,
int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
dumpFlags);
}
static void publishAndJoinThreadPool(
bool allowIsolated = false,
int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
publish(allowIsolated, dumpFlags);
joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() { return NO_ERROR; }
private:
static void joinThreadPool() {
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
IPCThreadState::self()->joinThreadPool();
}
};
} // namespace android
// ---------------------------------------------------------------------------
+247
View File
@@ -0,0 +1,247 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IBinder.h>
#include <binder/RpcThreads.h>
#include <binder/unique_fd.h>
#include <map>
#include <optional>
#include <unordered_map>
#include <variant>
// ---------------------------------------------------------------------------
namespace android {
class IPCThreadState;
class RpcSession;
class RpcState;
namespace internal {
class Stability;
}
class ProcessState;
using binder_proxy_limit_callback = std::function<void(int)>;
using binder_proxy_warning_callback = std::function<void(int)>;
class BpBinder : public IBinder {
public:
/**
* Return value:
* true - this is associated with a socket RpcSession
* false - (usual) binder over e.g. /dev/binder
*/
LIBBINDER_EXPORTED bool isRpcBinder() const;
LIBBINDER_EXPORTED virtual const String16& getInterfaceDescriptor() const;
LIBBINDER_EXPORTED virtual bool isBinderAlive() const;
LIBBINDER_EXPORTED virtual status_t pingBinder();
LIBBINDER_EXPORTED virtual status_t dump(int fd, const Vector<String16>& args);
// NOLINTNEXTLINE(google-default-arguments)
LIBBINDER_EXPORTED virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0) final;
// NOLINTNEXTLINE(google-default-arguments)
LIBBINDER_EXPORTED virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = nullptr, uint32_t flags = 0);
// NOLINTNEXTLINE(google-default-arguments)
LIBBINDER_EXPORTED virtual status_t unlinkToDeath(const wp<DeathRecipient>& recipient,
void* cookie = nullptr, uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = nullptr);
[[nodiscard]] status_t addFrozenStateChangeCallback(
const wp<FrozenStateChangeCallback>& recipient);
[[nodiscard]] status_t removeFrozenStateChangeCallback(
const wp<FrozenStateChangeCallback>& recipient);
LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object,
void* cleanupCookie,
object_cleanup_func func) final;
LIBBINDER_EXPORTED virtual void* findObject(const void* objectID) const final;
LIBBINDER_EXPORTED virtual void* detachObject(const void* objectID) final;
LIBBINDER_EXPORTED void withLock(const std::function<void()>& doWithLock);
LIBBINDER_EXPORTED sp<IBinder> lookupOrCreateWeak(const void* objectID,
IBinder::object_make_func make,
const void* makeArgs);
LIBBINDER_EXPORTED virtual BpBinder* remoteBinder();
LIBBINDER_EXPORTED void sendObituary();
LIBBINDER_EXPORTED static uint32_t getBinderProxyCount(uint32_t uid);
LIBBINDER_EXPORTED static void getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts);
LIBBINDER_EXPORTED static void enableCountByUid();
LIBBINDER_EXPORTED static void disableCountByUid();
LIBBINDER_EXPORTED static void setCountByUidEnabled(bool enable);
LIBBINDER_EXPORTED static void setBinderProxyCountEventCallback(
binder_proxy_limit_callback cbl, binder_proxy_warning_callback cbw);
LIBBINDER_EXPORTED static void setBinderProxyCountWatermarks(int high, int low, int warning);
LIBBINDER_EXPORTED static uint32_t getBinderProxyCount();
LIBBINDER_EXPORTED std::optional<int32_t> getDebugBinderHandle() const;
// Start recording transactions to the unique_fd.
// See RecordedTransaction.h for more details.
LIBBINDER_EXPORTED status_t startRecordingBinder(const binder::unique_fd& fd);
// Stop the current recording.
LIBBINDER_EXPORTED status_t stopRecordingBinder();
// Note: This class is not thread safe so protect uses of it when necessary
class ObjectManager {
public:
ObjectManager();
~ObjectManager();
void* attach(const void* objectID, void* object, void* cleanupCookie,
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void* detach(const void* objectID);
sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
const void* makeArgs);
private:
ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
struct entry_t {
void* object = nullptr;
void* cleanupCookie = nullptr;
IBinder::object_cleanup_func func = nullptr;
};
std::map<const void*, entry_t> mObjects;
};
class PrivateAccessor {
private:
friend class BpBinder;
friend class ::android::Parcel;
friend class ::android::ProcessState;
friend class ::android::RpcSession;
friend class ::android::RpcState;
friend class ::android::IPCThreadState;
explicit PrivateAccessor(const BpBinder* binder)
: mBinder(binder), mMutableBinder(nullptr) {}
explicit PrivateAccessor(BpBinder* binder) : mBinder(binder), mMutableBinder(binder) {}
static sp<BpBinder> create(int32_t handle, std::function<void()>* postTask) {
return BpBinder::create(handle, postTask);
}
static sp<BpBinder> create(const sp<RpcSession>& session, uint64_t address) {
return BpBinder::create(session, address);
}
// valid if !isRpcBinder
int32_t binderHandle() const { return mBinder->binderHandle(); }
// valid if isRpcBinder
uint64_t rpcAddress() const { return mBinder->rpcAddress(); }
const sp<RpcSession>& rpcSession() const { return mBinder->rpcSession(); }
void onFrozenStateChanged(bool isFrozen) { mMutableBinder->onFrozenStateChanged(isFrozen); }
const BpBinder* mBinder;
BpBinder* mMutableBinder;
};
LIBBINDER_EXPORTED const PrivateAccessor getPrivateAccessor() const {
return PrivateAccessor(this);
}
PrivateAccessor getPrivateAccessor() { return PrivateAccessor(this); }
private:
friend PrivateAccessor;
friend class sp<BpBinder>;
static sp<BpBinder> create(int32_t handle, std::function<void()>* postTask);
static sp<BpBinder> create(const sp<RpcSession>& session, uint64_t address);
struct BinderHandle {
int32_t handle;
};
struct RpcHandle {
sp<RpcSession> session;
uint64_t address;
};
using Handle = std::variant<BinderHandle, RpcHandle>;
int32_t binderHandle() const;
uint64_t rpcAddress() const;
const sp<RpcSession>& rpcSession() const;
explicit BpBinder(Handle&& handle);
BpBinder(BinderHandle&& handle, int32_t trackedUid);
explicit BpBinder(RpcHandle&& handle);
virtual ~BpBinder();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
friend ::android::internal::Stability;
int32_t mStability;
Handle mHandle;
struct Obituary {
wp<DeathRecipient> recipient;
void* cookie;
uint32_t flags;
};
void onFrozenStateChanged(bool isFrozen);
struct FrozenStateChange {
bool isFrozen = false;
Vector<wp<FrozenStateChangeCallback>> callbacks;
bool initialStateReceived = false;
};
void reportOneDeath(const Obituary& obit);
bool isDescriptorCached() const;
mutable RpcMutex mLock;
volatile int32_t mAlive;
volatile int32_t mObitsSent;
Vector<Obituary>* mObituaries;
std::unique_ptr<FrozenStateChange> mFrozen;
ObjectManager mObjectMgr;
mutable String16 mDescriptorCache;
int32_t mTrackedUid;
static RpcMutex sTrackingLock;
static std::unordered_map<int32_t, uint32_t> sTrackingMap;
static int sNumTrackedUids;
static std::atomic_bool sCountByUidEnabled;
static binder_proxy_limit_callback sLimitCallback;
static uint32_t sBinderProxyCountHighWatermark;
static uint32_t sBinderProxyCountLowWatermark;
static bool sBinderProxyThrottleCreate;
static std::unordered_map<int32_t, uint32_t> sLastLimitCallbackMap;
static std::atomic<uint32_t> sBinderProxyCount;
static std::atomic<uint32_t> sBinderProxyCountWarned;
static binder_proxy_warning_callback sWarningCallback;
static uint32_t sBinderProxyCountWarningWatermark;
};
} // namespace android
// ---------------------------------------------------------------------------
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
// libbinder is built with symbol hidden by default. To add a new symbol to the
// ABI, you must annotate it with this LIBBINDER_EXPORTED macro. When not
// building libbinder (e.g. when another binary includes a libbinder header),
// this macro is a no-op.
//
// Examples:
//
// // Export a function.
// LIBBINDER_EXPORTED void someFunction();
//
// // Export a subset of the symbols for a class.
// class SomeClassA {
// public:
// LIBBINDER_EXPORTED SomeClassA();
//
// LIBBINDER_EXPORTED SomeMethod();
// }
//
// // Export all the symbols for a class, even private symbols.
// class LIBBINDER_EXPORTED SomeClassB {};
//
// For a more detailed explanation of this strategy, see
// https://www.gnu.org/software/gnulib/manual/html_node/Exported-Symbols-of-Shared-Libraries.html
#if BUILDING_LIBBINDER
#define LIBBINDER_EXPORTED __attribute__((__visibility__("default")))
#else
#define LIBBINDER_EXPORTED
#endif
// For stuff that is exported but probably shouldn't be. It behaves the exact
// same way as LIBBINDER_EXPORTED, only exists to help track what we want
// eventually remove.
//
// Needed, at least in part, because the test binaries are using internal
// headers and accessing these symbols directly.
#define LIBBINDER_INTERNAL_EXPORTED LIBBINDER_EXPORTED
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IBinder.h>
#if !defined(__BIONIC__) && defined(BINDER_ENABLE_LIBLOG_ASSERT)
#include <log/log.h>
#define __assert(file, line, message) LOG_ALWAYS_FATAL(file ":" #line ": " message)
#endif
#ifndef __BIONIC__
#ifndef __assert
// defined differently by liblog
#pragma push_macro("LOG_PRI")
#ifdef LOG_PRI
#undef LOG_PRI
#endif
#include <syslog.h>
#pragma pop_macro("LOG_PRI")
#define __assert(a, b, c) \
do { \
syslog(LOG_ERR, a ": " c); \
abort(); \
} while (false)
#endif // __assert
#endif // __BIONIC__
namespace android {
/*
* Used to manage AIDL's *Delegator types.
* This is used to:
* - create a new *Delegator object that delegates to the binder argument.
* - or return an existing *Delegator object that already delegates to the
* binder argument.
* - or return the underlying delegate binder if the binder argument is a
* *Delegator itself.
*
* @param binder - the binder to delegate to or unwrap
*
* @return pointer to the *Delegator object or the unwrapped binder object
*/
template <typename T>
sp<T> delegate(const sp<T>& binder) {
const void* isDelegatorId = &T::descriptor;
const void* hasDelegatorId = &T::descriptor + 1;
// is binder itself a delegator?
if (T::asBinder(binder)->findObject(isDelegatorId)) {
if (T::asBinder(binder)->findObject(hasDelegatorId)) {
__assert(__FILE__, __LINE__,
"This binder has a delegator and is also delegator itself! This is "
"likely an unintended mixing of binders.");
return nullptr;
}
// unwrap the delegator
return static_cast<typename T::DefaultDelegator*>(binder.get())->getImpl();
}
struct MakeArgs {
const sp<T>* binder;
const void* id;
} makeArgs;
makeArgs.binder = &binder;
makeArgs.id = isDelegatorId;
// the binder is not a delegator, so construct one
sp<IBinder> newDelegator = T::asBinder(binder)->lookupOrCreateWeak(
hasDelegatorId,
[](const void* args) -> sp<IBinder> {
auto delegator = sp<typename T::DefaultDelegator>::make(
*static_cast<const MakeArgs*>(args)->binder);
// make sure we know this binder is a delegator by attaching a unique ID
(void)delegator->attachObject(static_cast<const MakeArgs*>(args)->id,
reinterpret_cast<void*>(0x1), nullptr, nullptr);
return delegator;
},
static_cast<const void*>(&makeArgs));
return sp<typename T::DefaultDelegator>::cast(newDelegator);
}
} // namespace android
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <iterator>
#include <type_traits>
namespace android {
namespace internal {
// Never instantiated. Used as a placeholder for template variables.
template <typename T>
struct invalid_type;
// AIDL generates specializations of this for enums.
template <typename EnumType, typename = std::enable_if_t<std::is_enum<EnumType>::value>>
constexpr invalid_type<EnumType> enum_values;
} // namespace internal
// Usage: for (const auto v : enum_range<EnumType>() ) { ... }
template <typename EnumType, typename = std::enable_if_t<std::is_enum<EnumType>::value>>
struct enum_range {
constexpr auto begin() const { return std::begin(internal::enum_values<EnumType>); }
constexpr auto end() const { return std::end(internal::enum_values<EnumType>); }
};
} // namespace android
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <functional>
#include <optional>
namespace android::binder::impl {
template <typename F>
class scope_guard;
template <typename F>
scope_guard<F> make_scope_guard(F f);
template <typename F>
class scope_guard {
public:
inline ~scope_guard() {
if (f_.has_value()) std::move(f_.value())();
}
inline void release() { f_.reset(); }
private:
friend scope_guard<F> android::binder::impl::make_scope_guard<>(F);
inline scope_guard(F&& f) : f_(std::move(f)) {}
std::optional<F> f_;
};
template <typename F>
inline scope_guard<F> make_scope_guard(F f) {
return scope_guard<F>(std::move(f));
}
template <typename F>
constexpr void assert_small_callable() {
// While this buffer (std::function::__func::__buf_) is an implementation detail generally not
// accessible to users, it's a good bet to assume its size to be around 3 pointers.
constexpr size_t kFunctionBufferSize = 3 * sizeof(void*);
static_assert(sizeof(F) <= kFunctionBufferSize,
"Supplied callable is larger than std::function optimization buffer. "
"Try using std::ref, but make sure lambda lives long enough to be called.");
}
template <typename T>
class SmallFunction : public std::function<T> {
public:
template <typename F>
SmallFunction(F&& f) : std::function<T>(f) {
assert_small_callable<F>();
}
};
} // namespace android::binder::impl
+356
View File
@@ -0,0 +1,356 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/unique_fd.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
#include <utils/Vector.h>
#include <functional>
// linux/binder.h defines this, but we don't want to include it here in order to
// avoid exporting the kernel headers
#ifndef B_PACK_CHARS
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#endif // B_PACK_CHARS
// ---------------------------------------------------------------------------
namespace android {
class BBinder;
class BpBinder;
class IInterface;
class Parcel;
class IResultReceiver;
class IShellCallback;
/**
* Base class and low-level protocol for a remotable object.
* You can derive from this class to create an object for which other
* processes can hold references to it. Communication between processes
* (method calls, property get and set) is down through a low-level
* protocol implemented on top of the transact() API.
*/
class [[clang::lto_visibility_public]] LIBBINDER_EXPORTED IBinder : public virtual RefBase {
public:
enum {
FIRST_CALL_TRANSACTION = 0x00000001,
LAST_CALL_TRANSACTION = 0x00ffffff,
PING_TRANSACTION = B_PACK_CHARS('_', 'P', 'N', 'G'),
START_RECORDING_TRANSACTION = B_PACK_CHARS('_', 'S', 'R', 'D'),
STOP_RECORDING_TRANSACTION = B_PACK_CHARS('_', 'E', 'R', 'D'),
DUMP_TRANSACTION = B_PACK_CHARS('_', 'D', 'M', 'P'),
SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_', 'C', 'M', 'D'),
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
SET_RPC_CLIENT_TRANSACTION = B_PACK_CHARS('_', 'R', 'P', 'C'),
// See android.os.IBinder.TWEET_TRANSACTION
// Most importantly, messages can be anything not exceeding 130 UTF-8
// characters, and callees should exclaim "jolly good message old boy!"
TWEET_TRANSACTION = B_PACK_CHARS('_', 'T', 'W', 'T'),
// See android.os.IBinder.LIKE_TRANSACTION
// Improve binder self-esteem.
LIKE_TRANSACTION = B_PACK_CHARS('_', 'L', 'I', 'K'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
FLAG_ONEWAY = 0x00000001,
// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call
// is made
FLAG_CLEAR_BUF = 0x00000020,
// Private userspace flag for transaction which is being requested from
// a vendor context.
FLAG_PRIVATE_VENDOR = 0x10000000,
};
IBinder();
/**
* Check if this IBinder implements the interface named by
* @a descriptor. If it does, the base pointer to it is returned,
* which you can safely static_cast<> to the concrete C++ interface.
*/
virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
/**
* Return the canonical name of the interface provided by this IBinder
* object.
*/
virtual const String16& getInterfaceDescriptor() const = 0;
/**
* Last known alive status, from last call. May be arbitrarily stale.
* May be incorrect if a service returns an incorrect status code.
*/
virtual bool isBinderAlive() const = 0;
virtual status_t pingBinder() = 0;
virtual status_t dump(int fd, const Vector<String16>& args) = 0;
static status_t shellCommand(const sp<IBinder>& target, int in, int out, int err,
Vector<String16>& args, const sp<IShellCallback>& callback,
const sp<IResultReceiver>& resultReceiver);
/**
* This allows someone to add their own additions to an interface without
* having to modify the original interface.
*
* For instance, imagine if we have this interface:
* interface IFoo { void doFoo(); }
*
* If an unrelated owner (perhaps in a downstream codebase) wants to make a
* change to the interface, they have two options:
*
* A). Historical option that has proven to be BAD! Only the original
* author of an interface should change an interface. If someone
* downstream wants additional functionality, they should not ever
* change the interface or use this method.
*
* BAD TO DO: interface IFoo { BAD TO DO
* BAD TO DO: void doFoo(); BAD TO DO
* BAD TO DO: + void doBar(); // adding a method BAD TO DO
* BAD TO DO: } BAD TO DO
*
* B). Option that this method enables!
* Leave the original interface unchanged (do not change IFoo!).
* Instead, create a new interface in a downstream package:
*
* package com.<name>; // new functionality in a new package
* interface IBar { void doBar(); }
*
* When registering the interface, add:
* sp<MyFoo> foo = new MyFoo; // class in AOSP codebase
* sp<MyBar> bar = new MyBar; // custom extension class
* foo->setExtension(bar); // use method in BBinder
*
* Then, clients of IFoo can get this extension:
* sp<IBinder> binder = ...;
* sp<IFoo> foo = interface_cast<IFoo>(binder); // handle if null
* sp<IBinder> barBinder;
* ... handle error ... = binder->getExtension(&barBinder);
* sp<IBar> bar = interface_cast<IBar>(barBinder);
* // if bar is null, then there is no extension or a different
* // type of extension
*/
status_t getExtension(sp<IBinder>* out);
/**
* Dump PID for a binder, for debugging.
*/
status_t getDebugPid(pid_t* outPid);
/**
* Set the RPC client fd to this binder service, for debugging. This is only available on
* debuggable builds.
*
* When this is called on a binder service, the service:
* 1. sets up RPC server
* 2. spawns 1 new thread that calls RpcServer::join()
* - join() spawns some number of threads that accept() connections; see RpcServer
*
* setRpcClientDebug() may be called multiple times. Each call will add a new RpcServer
* and opens up a TCP port.
*
* Note: A thread is spawned for each accept()'ed fd, which may call into functions of the
* interface freely. See RpcServer::join(). To avoid such race conditions, implement the service
* functions with multithreading support.
*
* On death of @a keepAliveBinder, the RpcServer shuts down.
*/
[[nodiscard]] status_t setRpcClientDebug(binder::unique_fd socketFd,
const sp<IBinder>& keepAliveBinder);
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) = 0;
// DeathRecipient is pure abstract, there is no virtual method
// implementation to put in a translation unit in order to silence the
// weak vtables warning.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
class FrozenStateChangeCallback : public virtual RefBase {
public:
enum class State {
FROZEN,
UNFROZEN,
};
virtual void onStateChanged(const wp<IBinder>& who, State state) = 0;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
/**
* Register the @a recipient for a notification if this binder
* goes away. If this binder object unexpectedly goes away
* (typically because its hosting process has been killed),
* then DeathRecipient::binderDied() will be called with a reference
* to this.
*
* The @a cookie is optional -- if non-NULL, it should be a
* memory address that you own (that is, you know it is unique).
*
* @note When all references to the binder being linked to are dropped, the
* recipient is automatically unlinked. So, you must hold onto a binder in
* order to receive death notifications about it.
*
* @note You will only receive death notifications for remote binders,
* as local binders by definition can't die without you dying as well.
* Trying to use this function on a local binder will result in an
* INVALID_OPERATION code being returned and nothing happening.
*
* @note This link always holds a weak reference to its recipient.
*
* @note You will only receive a weak reference to the dead
* binder. You should not try to promote this to a strong reference.
* (Nor should you need to, as there is nothing useful you can
* directly do with it now that it has passed on.)
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = nullptr,
uint32_t flags = 0) = 0;
/**
* Remove a previously registered death notification.
* The @a recipient will no longer be called if this object
* dies. The @a cookie is optional. If non-NULL, you can
* supply a NULL @a recipient, and the recipient previously
* added with that cookie will be unlinked.
*
* If the binder is dead, this will return DEAD_OBJECT. Deleting
* the object will also unlink all death recipients.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = nullptr,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = nullptr) = 0;
/**
* addFrozenStateChangeCallback provides a callback mechanism to notify
* about process frozen/unfrozen events. Upon registration and any
* subsequent state changes, the callback is invoked with the latest process
* frozen state.
*
* If the listener process (the one using this API) is itself frozen, state
* change events might be combined into a single one with the latest state.
* (meaning 'frozen, unfrozen' might just be 'unfrozen'). This single event
* would then be delivered when the listener process becomes unfrozen.
* Similarly, if an event happens before the previous event is consumed,
* they might be combined. This means the callback might not be called for
* every single state change, so don't rely on this API to count how many
* times the state has changed.
*
* @note When all references to the binder are dropped, the callback is
* automatically removed. So, you must hold onto a binder in order to
* receive notifications about it.
*
* @note You will only receive freeze notifications for remote binders, as
* local binders by definition can't be frozen without you being frozen as
* well. Trying to use this function on a local binder will result in an
* INVALID_OPERATION code being returned and nothing happening.
*
* @note This binder always holds a weak reference to the callback.
*
* @note You will only receive a weak reference to the binder object. You
* should not try to promote this to a strong reference. (Nor should you
* need to, as there is nothing useful you can directly do with it now that
* it has passed on.)
*/
[[nodiscard]] status_t addFrozenStateChangeCallback(
const wp<FrozenStateChangeCallback>& callback);
/**
* Remove a previously registered freeze callback.
* The @a callback will no longer be called if this object
* changes its frozen state.
*/
[[nodiscard]] status_t removeFrozenStateChangeCallback(
const wp<FrozenStateChangeCallback>& callback);
virtual bool checkSubclass(const void* subclassID) const;
typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
/**
* This object is attached for the lifetime of this binder object. When
* this binder object is destructed, the cleanup function of all attached
* objects are invoked with their respective objectID, object, and
* cleanupCookie. Access to these APIs can be made from multiple threads,
* but calls from different threads are allowed to be interleaved.
*
* This returns the object which is already attached. If this returns a
* non-null value, it means that attachObject failed (a given objectID can
* only be used once).
*/
[[nodiscard]] virtual void* attachObject(const void* objectID, void* object,
void* cleanupCookie, object_cleanup_func func) = 0;
/**
* Returns object attached with attachObject.
*/
[[nodiscard]] virtual void* findObject(const void* objectID) const = 0;
/**
* Returns object attached with attachObject, and detaches it. This does not
* delete the object.
*/
[[nodiscard]] virtual void* detachObject(const void* objectID) = 0;
/**
* Use the lock that this binder contains internally. For instance, this can
* be used to modify an attached object without needing to add an additional
* lock (though, that attached object must be retrieved before calling this
* method). Calling (most) IBinder methods inside this will deadlock.
*/
void withLock(const std::function<void()>& doWithLock);
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
typedef sp<IBinder> (*object_make_func)(const void* makeArgs);
sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make,
const void* makeArgs);
protected:
virtual ~IBinder();
private:
};
} // namespace android
// ---------------------------------------------------------------------------
@@ -0,0 +1,299 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Binder.h>
#include <binder/Common.h>
#include <assert.h>
namespace android {
// ----------------------------------------------------------------------
class LIBBINDER_EXPORTED IInterface : public virtual RefBase {
public:
IInterface();
static sp<IBinder> asBinder(const IInterface*);
static sp<IBinder> asBinder(const sp<IInterface>&);
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
// ----------------------------------------------------------------------
/**
* If this is a local object and the descriptor matches, this will return the
* actual local object which is implementing the interface. Otherwise, this will
* return a proxy to the interface without checking the interface descriptor.
* This means that subsequent calls may fail with BAD_TYPE.
*/
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
/**
* This is the same as interface_cast, except that it always checks to make sure
* the descriptor matches, and if it doesn't match, it will return nullptr.
*/
template<typename INTERFACE>
inline sp<INTERFACE> checked_interface_cast(const sp<IBinder>& obj)
{
if (obj->getInterfaceDescriptor() != INTERFACE::descriptor) {
return nullptr;
}
return interface_cast<INTERFACE>(obj);
}
// ----------------------------------------------------------------------
template <typename INTERFACE>
class LIBBINDER_EXPORTED BnInterface : public INTERFACE, public BBinder {
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
typedef INTERFACE BaseInterface;
protected:
virtual IBinder* onAsBinder();
};
// ----------------------------------------------------------------------
template <typename INTERFACE>
class LIBBINDER_EXPORTED BpInterface : public INTERFACE, public BpRefBase {
public:
explicit BpInterface(const sp<IBinder>& remote);
typedef INTERFACE BaseInterface;
protected:
virtual IBinder* onAsBinder();
};
// ----------------------------------------------------------------------
#define DECLARE_META_INTERFACE(INTERFACE) \
public: \
static const ::android::String16 descriptor; \
static ::android::sp<I##INTERFACE> asInterface(const ::android::sp<::android::IBinder>& obj); \
virtual const ::android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
static bool setDefaultImpl(::android::sp<I##INTERFACE> impl); \
static const ::android::sp<I##INTERFACE>& getDefaultImpl(); \
\
private: \
static ::android::sp<I##INTERFACE> default_impl; \
\
public:
#define __IINTF_CONCAT(x, y) (x ## y)
#ifndef DO_NOT_CHECK_MANUAL_BINDER_INTERFACES
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
static_assert(internal::allowedManualInterface(NAME), \
"b/64223827: Manually written binder interfaces are " \
"considered error prone and frequently have bugs. " \
"The preferred way to add interfaces is to define " \
"an .aidl file to auto-generate the interface. If " \
"an interface must be manually written, add its " \
"name to the allowlist."); \
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
#else
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
#endif
// Macro to be used by both IMPLEMENT_META_INTERFACE and IMPLEMENT_META_NESTED_INTERFACE
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE) \
const ::android::String16& ITYPE::getInterfaceDescriptor() const { return ITYPE::descriptor; } \
::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj) { \
::android::sp<ITYPE> intr; \
if (obj != nullptr) { \
intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor)); \
if (intr == nullptr) { \
intr = ::android::sp<BPTYPE>::make(obj); \
} \
} \
return intr; \
} \
::android::sp<ITYPE> ITYPE::default_impl; \
bool ITYPE::setDefaultImpl(::android::sp<ITYPE> impl) { \
/* Only one user of this interface can use this function */ \
/* at a time. This is a heuristic to detect if two different */ \
/* users in the same process use this function. */ \
assert(!ITYPE::default_impl); \
if (impl) { \
ITYPE::default_impl = std::move(impl); \
return true; \
} \
return false; \
} \
const ::android::sp<ITYPE>& ITYPE::getDefaultImpl() { return ITYPE::default_impl; } \
ITYPE::INAME() {} \
ITYPE::~INAME() {}
// Macro for an interface type.
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const ::android::StaticString16 I##INTERFACE##_descriptor_static_str16( \
__IINTF_CONCAT(u, NAME)); \
const ::android::String16 I##INTERFACE::descriptor(I##INTERFACE##_descriptor_static_str16); \
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(I##INTERFACE, I##INTERFACE, Bp##INTERFACE)
// Macro for "nested" interface type.
// For example,
// class Parent .. { class INested .. { }; };
// DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(Parent, Nested, "Parent.INested")
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(PARENT, INTERFACE, NAME) \
const ::android::String16 PARENT::I##INTERFACE::descriptor(NAME); \
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(PARENT::I##INTERFACE, I##INTERFACE, \
PARENT::Bp##INTERFACE)
#define CHECK_INTERFACE(interface, data, reply) \
do { \
if (!(data).checkInterface(this)) { return PERMISSION_DENIED; } \
} while (false) \
// ----------------------------------------------------------------------
// No user-serviceable parts after this...
template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return sp<IInterface>::fromExisting(this);
return nullptr;
}
template<typename INTERFACE>
inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
{
return INTERFACE::getInterfaceDescriptor();
}
template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
return this;
}
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
template<typename INTERFACE>
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
return remote();
}
// ----------------------------------------------------------------------
namespace internal {
constexpr const char* const kManualInterfaces[] = {
"android.app.IActivityManager",
"android.app.IUidObserver",
"android.gfx.tests.ICallback",
"android.gfx.tests.IIPCTest",
"android.gfx.tests.ISafeInterfaceTest",
"android.graphicsenv.IGpuService",
"android.gui.IConsumerListener",
"android.gui.IGraphicBufferConsumer",
"android.gui.ITransactionComposerListener",
"android.gui.SensorEventConnection",
"android.gui.SensorServer",
"android.hardware.ICamera",
"android.hardware.ICameraClient",
"android.hardware.ICameraRecordingProxy",
"android.hardware.ICameraRecordingProxyListener",
"android.hardware.IOMXObserver",
"android.hardware.IStreamListener",
"android.hardware.IStreamSource",
"android.media.IAudioService",
"android.media.IDataSource",
"android.media.IMediaCodecList",
"android.media.IMediaExtractor",
"android.media.IMediaHTTPConnection",
"android.media.IMediaHTTPService",
"android.media.IMediaLogService",
"android.media.IMediaMetadataRetriever",
"android.media.IMediaPlayer",
"android.media.IMediaPlayerClient",
"android.media.IMediaPlayerService",
"android.media.IMediaRecorder",
"android.media.IMediaRecorderClient",
"android.media.IMediaResourceMonitor",
"android.media.IMediaSource",
"android.media.IRemoteDisplay",
"android.media.IRemoteDisplayClient",
"android.os.IPermissionController",
"android.os.IProcessInfoService",
"android.os.ISchedulingPolicyService",
"android.os.storage.IObbActionListener",
"android.os.storage.IStorageEventListener",
"android.os.storage.IStorageManager",
"android.os.storage.IStorageShutdownObserver",
"android.ui.ISurfaceComposer",
"android.utils.IMemory",
"android.utils.IMemoryHeap",
"com.android.car.procfsinspector.IProcfsInspector",
"com.android.internal.app.IAppOpsCallback",
"com.android.internal.app.IAppOpsService",
"com.android.internal.app.IBatteryStats",
"com.android.internal.os.IResultReceiver",
"com.android.internal.os.IShellCallback",
"drm.IDrmManagerService",
"drm.IDrmServiceListener",
nullptr,
};
constexpr const char* const kDownstreamManualInterfaces[] = {
// Add downstream interfaces here.
nullptr,
};
constexpr bool equals(const char* a, const char* b) {
if (*a != *b) return false;
if (*a == '\0') return true;
return equals(a + 1, b + 1);
}
constexpr bool inList(const char* a, const char* const* allowlist) {
if (*allowlist == nullptr) return false;
if (equals(a, *allowlist)) return true;
return inList(a, allowlist + 1);
}
constexpr bool allowedManualInterface(const char* name) {
return inList(name, kManualInterfaces) ||
inList(name, kDownstreamManualInterfaces);
}
} // namespace internal
} // namespace android
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <utils/RefBase.h>
#include <utils/Errors.h>
#include <binder/Common.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------------
class LIBBINDER_EXPORTED IMemoryHeap : public IInterface {
public:
DECLARE_META_INTERFACE(MemoryHeap)
// flags returned by getFlags()
enum {
READ_ONLY = 0x00000001
};
virtual int getHeapID() const = 0;
virtual void* getBase() const = 0;
virtual size_t getSize() const = 0;
virtual uint32_t getFlags() const = 0;
virtual off_t getOffset() const = 0;
// these are there just for backward source compatibility
int32_t heapID() const { return getHeapID(); }
void* base() const { return getBase(); }
size_t virtualSize() const { return getSize(); }
};
class LIBBINDER_EXPORTED BnMemoryHeap : public BnInterface<IMemoryHeap> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
BnMemoryHeap();
protected:
virtual ~BnMemoryHeap();
};
// ----------------------------------------------------------------------------
class LIBBINDER_EXPORTED IMemory : public IInterface {
public:
DECLARE_META_INTERFACE(Memory)
// NOLINTNEXTLINE(google-default-arguments)
virtual sp<IMemoryHeap> getMemory(ssize_t* offset=nullptr, size_t* size=nullptr) const = 0;
// helpers
// Accessing the underlying pointer must be done with caution, as there are
// some inherent security risks associated with it. When receiving an
// IMemory from an untrusted process, there is currently no way to guarantee
// that this process would't change the content after the fact. This may
// lead to TOC/TOU class of security bugs. In most cases, when performance
// is not an issue, the recommended practice is to immediately copy the
// buffer upon reception, then work with the copy, e.g.:
//
// std::string private_copy(mem.size(), '\0');
// memcpy(private_copy.data(), mem.unsecurePointer(), mem.size());
//
// In cases where performance is an issue, this matter must be addressed on
// an ad-hoc basis.
void* unsecurePointer() const;
size_t size() const;
ssize_t offset() const;
private:
// These are now deprecated and are left here for backward-compatibility
// with prebuilts that may reference these symbol at runtime.
// Instead, new code should use unsecurePointer()/unsecureFastPointer(),
// which do the same thing, but make it more obvious that there are some
// security-related pitfalls associated with them.
void* pointer() const;
void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const;
};
class LIBBINDER_EXPORTED BnMemory : public BnInterface<IMemory> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
BnMemory();
protected:
virtual ~BnMemory();
};
// ----------------------------------------------------------------------------
} // namespace android
@@ -0,0 +1,261 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
#if defined(_WIN32)
typedef int uid_t;
#endif
// ---------------------------------------------------------------------------
namespace android {
/**
* Kernel binder thread state. All operations here refer to kernel binder. This
* object is allocated per-thread.
*/
class IPCThreadState {
public:
using CallRestriction = ProcessState::CallRestriction;
LIBBINDER_EXPORTED static IPCThreadState* self();
LIBBINDER_EXPORTED static IPCThreadState* selfOrNull(); // self(), but won't instantiate
// Freeze or unfreeze the binder interface to a specific process. When freezing, this method
// will block up to timeout_ms to process pending transactions directed to pid. Unfreeze
// is immediate. Transactions to processes frozen via this method won't be delivered and the
// driver will return BR_FROZEN_REPLY to the client sending them. After unfreeze,
// transactions will be delivered normally.
//
// pid: id for the process for which the binder interface is to be frozen
// enable: freeze (true) or unfreeze (false)
// timeout_ms: maximum time this function is allowed to block the caller waiting for pending
// binder transactions to be processed.
//
// returns: 0 in case of success, a value < 0 in case of error
LIBBINDER_EXPORTED static status_t freeze(pid_t pid, bool enabled, uint32_t timeout_ms);
// Provide information about the state of a frozen process
LIBBINDER_EXPORTED static status_t getProcessFreezeInfo(pid_t pid, uint32_t* sync_received,
uint32_t* async_received);
LIBBINDER_EXPORTED status_t clearLastError();
/**
* Returns the PID of the process which has made the current binder
* call. If not in a binder call, this will return getpid.
*
* Warning: oneway transactions do not receive PID. Even if you expect
* a transaction to be synchronous, a misbehaving client could send it
* as an asynchronous call and result in a 0 PID here. Additionally, if
* there is a race and the calling process dies, the PID may still be
* 0 for a synchronous call.
*/
[[nodiscard]] LIBBINDER_EXPORTED pid_t getCallingPid() const;
/**
* Returns the SELinux security identifier of the process which has
* made the current binder call. If not in a binder call this will
* return nullptr. If this isn't requested with
* Binder::setRequestingSid, it will also return nullptr.
*
* This can't be restored once it's cleared, and it does not return the
* context of the current process when not in a binder call.
*/
[[nodiscard]] LIBBINDER_EXPORTED const char* getCallingSid() const;
/**
* Returns the UID of the process which has made the current binder
* call. If not in a binder call, this will return 0.
*/
[[nodiscard]] LIBBINDER_EXPORTED uid_t getCallingUid() const;
/**
* Make it an abort to rely on getCalling* for a section of
* execution.
*
* Usage:
* IPCThreadState::SpGuard guard {
* .address = __builtin_frame_address(0),
* .context = "...",
* };
* const auto* orig = pushGetCallingSpGuard(&guard);
* {
* // will abort if you call getCalling*, unless you are
* // serving a nested binder transaction
* }
* restoreCallingSpGuard(orig);
*/
struct SpGuard {
const void* address;
const char* context;
};
LIBBINDER_EXPORTED const SpGuard* pushGetCallingSpGuard(const SpGuard* guard);
LIBBINDER_EXPORTED void restoreGetCallingSpGuard(const SpGuard* guard);
/**
* Used internally by getCalling*. Can also be used to assert that
* you are in a binder context (getCalling* is valid). This is
* intentionally not exposed as a boolean API since code should be
* written to know its environment.
*/
LIBBINDER_EXPORTED void checkContextIsBinderForUse(const char* use) const;
LIBBINDER_EXPORTED void setStrictModePolicy(int32_t policy);
LIBBINDER_EXPORTED int32_t getStrictModePolicy() const;
// See Binder#setCallingWorkSourceUid in Binder.java.
LIBBINDER_EXPORTED int64_t setCallingWorkSourceUid(uid_t uid);
// Internal only. Use setCallingWorkSourceUid(uid) instead.
LIBBINDER_EXPORTED int64_t setCallingWorkSourceUidWithoutPropagation(uid_t uid);
// See Binder#getCallingWorkSourceUid in Binder.java.
LIBBINDER_EXPORTED uid_t getCallingWorkSourceUid() const;
// See Binder#clearCallingWorkSource in Binder.java.
LIBBINDER_EXPORTED int64_t clearCallingWorkSource();
// See Binder#restoreCallingWorkSource in Binder.java.
LIBBINDER_EXPORTED void restoreCallingWorkSource(int64_t token);
LIBBINDER_EXPORTED void clearPropagateWorkSource();
LIBBINDER_EXPORTED bool shouldPropagateWorkSource() const;
LIBBINDER_EXPORTED void setLastTransactionBinderFlags(int32_t flags);
LIBBINDER_EXPORTED int32_t getLastTransactionBinderFlags() const;
LIBBINDER_EXPORTED void setCallRestriction(CallRestriction restriction);
LIBBINDER_EXPORTED CallRestriction getCallRestriction() const;
LIBBINDER_EXPORTED int64_t clearCallingIdentity();
// Restores PID/UID (not SID)
LIBBINDER_EXPORTED void restoreCallingIdentity(int64_t token);
LIBBINDER_EXPORTED bool hasExplicitIdentity();
// For main functions - dangerous for libraries to use
LIBBINDER_EXPORTED status_t setupPolling(int* fd);
LIBBINDER_EXPORTED status_t handlePolledCommands();
LIBBINDER_EXPORTED void flushCommands();
LIBBINDER_EXPORTED bool flushIfNeeded();
// Adds the current thread into the binder threadpool.
//
// This is in addition to any threads which are started
// with startThreadPool. Libraries should not call this
// function, as they may be loaded into processes which
// try to configure the threadpool differently.
LIBBINDER_EXPORTED void joinThreadPool(bool isMain = true);
// Stop the local process.
LIBBINDER_EXPORTED void stopProcess(bool immediate = true);
LIBBINDER_EXPORTED status_t transact(int32_t handle, uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
LIBBINDER_EXPORTED void incStrongHandle(int32_t handle, BpBinder* proxy);
LIBBINDER_EXPORTED void decStrongHandle(int32_t handle);
LIBBINDER_EXPORTED void incWeakHandle(int32_t handle, BpBinder* proxy);
LIBBINDER_EXPORTED void decWeakHandle(int32_t handle);
LIBBINDER_EXPORTED status_t attemptIncStrongHandle(int32_t handle);
LIBBINDER_EXPORTED static void expungeHandle(int32_t handle, IBinder* binder);
LIBBINDER_EXPORTED status_t requestDeathNotification(int32_t handle, BpBinder* proxy);
LIBBINDER_EXPORTED status_t clearDeathNotification(int32_t handle, BpBinder* proxy);
[[nodiscard]] status_t addFrozenStateChangeCallback(int32_t handle, BpBinder* proxy);
[[nodiscard]] status_t removeFrozenStateChangeCallback(int32_t handle, BpBinder* proxy);
LIBBINDER_EXPORTED static void shutdown();
// Call this to disable switching threads to background scheduling when
// receiving incoming IPC calls. This is specifically here for the
// Android system process, since it expects to have background apps calling
// in to it but doesn't want to acquire locks in its services while in
// the background.
LIBBINDER_EXPORTED static void disableBackgroundScheduling(bool disable);
LIBBINDER_EXPORTED bool backgroundSchedulingDisabled();
// Call blocks until the number of executing binder threads is less than
// the maximum number of binder threads threads allowed for this process.
LIBBINDER_EXPORTED void blockUntilThreadAvailable();
// Service manager registration
LIBBINDER_EXPORTED void setTheContextObject(const sp<BBinder>& obj);
// WARNING: DO NOT USE THIS API
//
// Returns a pointer to the stack from the last time a transaction
// was initiated by the kernel. Used to compare when making nested
// calls between multiple different transports.
LIBBINDER_EXPORTED const void* getServingStackPointer() const;
// The work source represents the UID of the process we should attribute the transaction
// to. We use -1 to specify that the work source was not set using #setWorkSource.
//
// This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java
// side.
LIBBINDER_EXPORTED static const int32_t kUnsetWorkSource = -1;
private:
IPCThreadState();
~IPCThreadState();
[[nodiscard]] status_t sendReply(const Parcel& reply, uint32_t flags);
[[nodiscard]] status_t waitForResponse(Parcel* reply, status_t* acquireResult = nullptr);
[[nodiscard]] status_t talkWithDriver(bool doReceive = true);
[[nodiscard]] status_t writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle,
uint32_t code, const Parcel& data,
status_t* statusBuffer);
[[nodiscard]] status_t getAndExecuteCommand();
[[nodiscard]] status_t executeCommand(int32_t command);
void processPendingDerefs();
void processPostWriteDerefs();
void clearCaller();
static void threadDestructor(void *st);
static void freeBuffer(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
size_t objectsSize);
static void logExtendedError();
const sp<ProcessState> mProcess;
Vector<BBinder*> mPendingStrongDerefs;
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
Vector<RefBase*> mPostWriteStrongDerefs;
Vector<RefBase::weakref_type*> mPostWriteWeakDerefs;
Parcel mIn;
Parcel mOut;
status_t mLastError;
const void* mServingStackPointer;
const SpGuard* mServingStackPointerGuard;
pid_t mCallingPid;
const char* mCallingSid;
uid_t mCallingUid;
// The UID of the process who is responsible for this transaction.
// This is used for resource attribution.
int32_t mWorkSource;
// Whether the work source should be propagated.
bool mPropagateWorkSource;
bool mIsLooper;
bool mIsFlushing;
bool mHasExplicitIdentity;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
CallRestriction mCallRestriction;
};
} // namespace android
// ---------------------------------------------------------------------------
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifndef __ANDROID_VNDK__
#include <binder/Common.h>
#include <binder/IInterface.h>
#include <stdlib.h>
namespace android {
// ----------------------------------------------------------------------
class LIBBINDER_EXPORTED IPermissionController : public IInterface {
public:
DECLARE_META_INTERFACE(PermissionController)
virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid) = 0;
virtual int32_t noteOp(const String16& op, int32_t uid, const String16& packageName) = 0;
virtual void getPackagesForUid(const uid_t uid, Vector<String16> &packages) = 0;
virtual bool isRuntimePermission(const String16& permission) = 0;
virtual int getPackageUid(const String16& package, int flags) = 0;
enum {
CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
NOTE_OP_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2,
IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 3,
GET_PACKAGE_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 4
};
};
// ----------------------------------------------------------------------
class LIBBINDER_EXPORTED BnPermissionController : public BnInterface<IPermissionController> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
#endif // __ANDROID_VNDK__
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class LIBBINDER_EXPORTED IResultReceiver : public IInterface {
public:
DECLARE_META_INTERFACE(ResultReceiver)
virtual void send(int32_t resultCode) = 0;
enum {
OP_SEND = IBinder::FIRST_CALL_TRANSACTION
};
};
// ----------------------------------------------------------------------
class LIBBINDER_EXPORTED BnResultReceiver : public BnInterface<IResultReceiver> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
} // namespace android
@@ -0,0 +1,354 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IInterface.h>
// Trusty has its own definition of socket APIs from trusty_ipc.h
#ifndef __TRUSTY__
#include <sys/socket.h>
#endif // __TRUSTY__
#include <utils/String16.h>
#include <utils/Vector.h>
#include <optional>
#include <set>
namespace android {
/**
* Service manager for C++ services.
*
* IInterface is only for legacy ABI compatibility
*/
class LIBBINDER_EXPORTED IServiceManager : public IInterface {
public:
// for ABI compatibility
virtual const String16& getInterfaceDescriptor() const;
IServiceManager();
virtual ~IServiceManager();
/**
* Must match values in IServiceManager.aidl
*/
/* Allows services to dump sections according to priorities. */
static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
static const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
static const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
/**
* Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the
* same priority as NORMAL priority but the services are not called with dump priority
* arguments.
*/
static const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3;
static const int DUMP_FLAG_PRIORITY_ALL = DUMP_FLAG_PRIORITY_CRITICAL |
DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
static const int DUMP_FLAG_PROTO = 1 << 4;
/**
* Retrieve an existing service, blocking for a few seconds if it doesn't yet exist. This
* does polling. A more efficient way to make sure you unblock as soon as the service is
* available is to use waitForService or to use service notifications.
*
* Warning: when using this API, typically, you should call it in a loop. It's dangerous to
* assume that nullptr could mean that the service is not available. The service could just
* be starting. Generally, whether a service exists, this information should be declared
* externally (for instance, an Android feature might imply the existence of a service,
* a system property, or in the case of services in the VINTF manifest, it can be checked
* with isDeclared).
*/
[[deprecated("this polls for 5s, prefer waitForService or checkService")]]
virtual sp<IBinder> getService(const String16& name) const = 0;
/**
* Retrieve an existing service, non-blocking.
*/
virtual sp<IBinder> checkService( const String16& name) const = 0;
/**
* Register a service.
*
* Note:
* This status_t return value may be an exception code from an underlying
* Status type that doesn't have a representive error code in
* utils/Errors.h.
* One example of this is a return value of -7
* (Status::Exception::EX_UNSUPPORTED_OPERATION) when the service manager
* process is not installed on the device when addService is called.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated = false,
int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;
/**
* Return list of all existing services.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
/**
* Efficiently wait for a service.
*
* Returns nullptr only for permission problem or fatal error.
*/
virtual sp<IBinder> waitForService(const String16& name) = 0;
/**
* Check if a service is declared (e.g. VINTF manifest).
*
* If this returns true, waitForService should always be able to return the
* service.
*/
virtual bool isDeclared(const String16& name) = 0;
/**
* Get all instances of a service as declared in the VINTF manifest
*/
virtual Vector<String16> getDeclaredInstances(const String16& interface) = 0;
/**
* If this instance is updatable via an APEX, returns the APEX with which
* this can be updated.
*/
virtual std::optional<String16> updatableViaApex(const String16& name) = 0;
/**
* Returns all instances which are updatable via the APEX. Instance names are fully qualified
* like `pack.age.IFoo/default`.
*/
virtual Vector<String16> getUpdatableNames(const String16& apexName) = 0;
/**
* If this instance has declared remote connection information, returns
* the ConnectionInfo.
*/
struct ConnectionInfo {
std::string ipAddress;
unsigned int port;
};
virtual std::optional<ConnectionInfo> getConnectionInfo(const String16& name) = 0;
struct LocalRegistrationCallback : public virtual RefBase {
virtual void onServiceRegistration(const String16& instance, const sp<IBinder>& binder) = 0;
virtual ~LocalRegistrationCallback() {}
};
virtual status_t registerForNotifications(const String16& name,
const sp<LocalRegistrationCallback>& callback) = 0;
virtual status_t unregisterForNotifications(const String16& name,
const sp<LocalRegistrationCallback>& callback) = 0;
struct ServiceDebugInfo {
std::string name;
int pid;
};
virtual std::vector<ServiceDebugInfo> getServiceDebugInfo() = 0;
/**
* Directly enable or disable caching binder during addService calls.
* Only used for testing. This is enabled by default.
*/
virtual void enableAddServiceCache(bool value) = 0;
};
LIBBINDER_EXPORTED sp<IServiceManager> defaultServiceManager();
/**
* Directly set the default service manager. Only used for testing.
* Note that the caller is responsible for caling this method
* *before* any call to defaultServiceManager(); if the latter is
* called first, setDefaultServiceManager() will abort.
*/
LIBBINDER_EXPORTED void setDefaultServiceManager(const sp<IServiceManager>& sm);
template<typename INTERFACE>
sp<INTERFACE> waitForService(const String16& name) {
const sp<IServiceManager> sm = defaultServiceManager();
return interface_cast<INTERFACE>(sm->waitForService(name));
}
template<typename INTERFACE>
sp<INTERFACE> waitForDeclaredService(const String16& name) {
const sp<IServiceManager> sm = defaultServiceManager();
if (!sm->isDeclared(name)) return nullptr;
return interface_cast<INTERFACE>(sm->waitForService(name));
}
template <typename INTERFACE>
sp<INTERFACE> checkDeclaredService(const String16& name) {
const sp<IServiceManager> sm = defaultServiceManager();
if (!sm->isDeclared(name)) return nullptr;
return interface_cast<INTERFACE>(sm->checkService(name));
}
template<typename INTERFACE>
sp<INTERFACE> waitForVintfService(
const String16& instance = String16("default")) {
return waitForDeclaredService<INTERFACE>(
INTERFACE::descriptor + String16("/") + instance);
}
template<typename INTERFACE>
sp<INTERFACE> checkVintfService(
const String16& instance = String16("default")) {
return checkDeclaredService<INTERFACE>(
INTERFACE::descriptor + String16("/") + instance);
}
template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
const sp<IServiceManager> sm = defaultServiceManager();
if (sm != nullptr) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
*outService = interface_cast<INTERFACE>(sm->getService(name));
#pragma clang diagnostic pop // getService deprecation
if ((*outService) != nullptr) return NO_ERROR;
}
return NAME_NOT_FOUND;
}
LIBBINDER_EXPORTED void* openDeclaredPassthroughHal(const String16& interface,
const String16& instance, int flag);
LIBBINDER_EXPORTED bool checkCallingPermission(const String16& permission);
LIBBINDER_EXPORTED bool checkCallingPermission(const String16& permission, int32_t* outPid,
int32_t* outUid);
LIBBINDER_EXPORTED bool checkPermission(const String16& permission, pid_t pid, uid_t uid,
bool logPermissionFailure = true);
// ----------------------------------------------------------------------
// Trusty's definition of the socket APIs does not include sockaddr types
#ifndef __TRUSTY__
typedef std::function<status_t(const String16& name, sockaddr* outAddr, socklen_t addrSize)>
RpcSocketAddressProvider;
/**
* This callback provides a way for clients to get access to remote services by
* providing an Accessor object from libbinder that can connect to the remote
* service over sockets.
*
* \param instance name of the service that the callback will provide an
* Accessor for. The provided accessor will be used to set up a client
* RPC connection in libbinder in order to return a binder for the
* associated remote service.
*
* \return IBinder of the Accessor object that libbinder implements.
* nullptr if the provider callback doesn't know how to reach the
* service or doesn't want to provide access for any other reason.
*/
typedef std::function<sp<IBinder>(const String16& instance)> RpcAccessorProvider;
class AccessorProvider;
/**
* Register a RpcAccessorProvider for the service manager APIs.
*
* \param instances that the RpcAccessorProvider knows about and can provide an
* Accessor for.
* \param provider callback that generates Accessors.
*
* \return A pointer used as a recept for the successful addition of the
* AccessorProvider. This is needed to unregister it later.
*/
[[nodiscard]] LIBBINDER_EXPORTED std::weak_ptr<AccessorProvider> addAccessorProvider(
std::set<std::string>&& instances, RpcAccessorProvider&& providerCallback);
/**
* Remove an accessor provider using the pointer provided by addAccessorProvider
* along with the cookie pointer that was used.
*
* \param provider cookie that was returned by addAccessorProvider to keep track
* of this instance.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t
removeAccessorProvider(std::weak_ptr<AccessorProvider> provider);
/**
* Create an Accessor associated with a service that can create a socket connection based
* on the connection info from the supplied RpcSocketAddressProvider.
*
* \param instance name of the service that this Accessor is associated with
* \param connectionInfoProvider a callback that returns connection info for
* connecting to the service.
* \return the binder of the IAccessor implementation from libbinder
*/
LIBBINDER_EXPORTED sp<IBinder> createAccessor(const String16& instance,
RpcSocketAddressProvider&& connectionInfoProvider);
/**
* Check to make sure this binder is the expected binder that is an IAccessor
* associated with a specific instance.
*
* This helper function exists to avoid adding the IAccessor type to
* libbinder_ndk.
*
* \param instance name of the service that this Accessor should be associated with
* \param binder to validate
*
* \return OK if the binder is an IAccessor for `instance`
*/
LIBBINDER_EXPORTED status_t validateAccessor(const String16& instance, const sp<IBinder>& binder);
/**
* Have libbinder wrap this IAccessor binder in an IAccessorDelegator and return
* it.
*
* This is required only in very specific situations when the process that has
* permissions to connect the to RPC service's socket and create the FD for it
* is in a separate process from this process that wants to service the Accessor
* binder and the communication between these two processes is binder RPC. This
* is needed because the binder passed over the binder RPC connection can not be
* used as a kernel binder, and needs to be wrapped by a kernel binder that can
* then be registered with service manager.
*
* \param instance name of the Accessor.
* \param binder to wrap in a Delegator and register with service manager.
* \param outDelegator the wrapped kernel binder for IAccessorDelegator
*
* \return OK if the binder is an IAccessor for `instance` and the delegator was
* successfully created.
*/
LIBBINDER_EXPORTED status_t delegateAccessor(const String16& name, const sp<IBinder>& accessor,
sp<IBinder>* delegator);
#endif // __TRUSTY__
#ifndef __ANDROID__
// Create an IServiceManager that delegates the service manager on the device via adb.
// This is can be set as the default service manager at program start, so that
// defaultServiceManager() returns it:
// int main() {
// setDefaultServiceManager(createRpcDelegateServiceManager());
// auto sm = defaultServiceManager();
// // ...
// }
// Resources are cleaned up when the object is destroyed.
//
// For each returned binder object, at most |maxOutgoingConnections| outgoing connections are
// instantiated, depending on how many the service on the device is configured with.
// Hence, only |maxOutgoingConnections| calls can be made simultaneously.
// See also RpcSession::setMaxOutgoingConnections.
struct RpcDelegateServiceManagerOptions {
std::optional<size_t> maxOutgoingConnections;
};
LIBBINDER_EXPORTED sp<IServiceManager> createRpcDelegateServiceManager(
const RpcDelegateServiceManagerOptions& options);
#endif
} // namespace android
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <android/os/IServiceManager.h>
namespace android::impl {
LIBBINDER_EXPORTED sp<android::os::IServiceManager>
getJavaServicemanagerImplPrivateDoNotUseExceptInTheOnePlaceItIsUsed();
} // namespace android::impl
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <android/os/IServiceManager.h>
#include "IServiceManager.h"
namespace android {
/**
* Encapsulate an AidlServiceManager in a CppBackendShim. Only used for testing.
*/
LIBBINDER_EXPORTED sp<IServiceManager> getServiceManagerShimFromAidlServiceManagerForTests(
const sp<os::IServiceManager>& sm);
} // namespace android
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class LIBBINDER_EXPORTED IShellCallback : public IInterface {
public:
DECLARE_META_INTERFACE(ShellCallback)
virtual int openFile(const String16& path, const String16& seLinuxContext,
const String16& mode) = 0;
enum {
OP_OPEN_OUTPUT_FILE = IBinder::FIRST_CALL_TRANSACTION
};
};
// ----------------------------------------------------------------------
class LIBBINDER_EXPORTED BnShellCallback : public BnInterface<IShellCallback> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
} // namespace android
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <functional>
#include <binder/Common.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <utils/StrongPointer.h>
namespace android {
namespace binder {
namespace internal {
class ClientCounterCallback;
} // namespace internal
/**
* Exits when all services registered through this object have 0 clients
*
* In order to use this class, it's expected that your service:
* - registers all services in the process with this API
* - configures services as oneshot in init .rc files
* - configures services as disabled in init.rc files, unless a client is
* guaranteed early in boot, in which case, forcePersist should also be used
* to avoid races.
* - uses 'interface' declarations in init .rc files
*
* For more information on init .rc configuration, see system/core/init/README.md
**/
class LazyServiceRegistrar {
public:
LIBBINDER_EXPORTED static LazyServiceRegistrar& getInstance();
LIBBINDER_EXPORTED status_t
registerService(const sp<IBinder>& service, const std::string& name = "default",
bool allowIsolated = false,
int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
/**
* Force the service to persist, even when it has 0 clients.
* If setting this flag from the server side, make sure to do so before calling
* registerService, or there may be a race with the default dynamic shutdown.
*
* This should only be used if it is every eventually set to false. If a
* service needs to persist but doesn't need to dynamically shut down,
* prefer to control it with another mechanism such as ctl.start.
*/
LIBBINDER_EXPORTED void forcePersist(bool persist);
/**
* Set a callback that is invoked when the active service count (i.e. services with clients)
* registered with this process drops to zero (or becomes nonzero).
* The callback takes a boolean argument, which is 'true' if there is
* at least one service with clients.
*
* Callback return value:
* - false: Default behavior for lazy services (shut down the process if there
* are no clients).
* - true: Don't shut down the process even if there are no clients.
*
* This callback gives a chance to:
* 1 - Perform some additional operations before exiting;
* 2 - Prevent the process from exiting by returning "true" from the
* callback.
*
* This method should be called before 'registerService' to avoid races.
*/
LIBBINDER_EXPORTED void setActiveServicesCallback(
const std::function<bool(bool)>& activeServicesCallback);
/**
* Try to unregister all services previously registered with 'registerService'.
* Returns 'true' if successful. This should only be called within the callback registered by
* setActiveServicesCallback.
*/
LIBBINDER_EXPORTED bool tryUnregister();
/**
* Re-register services that were unregistered by 'tryUnregister'.
* This method should be called in the case 'tryUnregister' fails
* (and should be called on the same thread).
*/
LIBBINDER_EXPORTED void reRegister();
/**
* Create a second instance of lazy service registrar.
*
* WARNING: dangerous! DO NOT USE THIS - LazyServiceRegistrar
* should be single-instanced, so that the service will only
* shut down when all services are unused. A separate instance
* is only used to test race conditions.
*/
LIBBINDER_EXPORTED static LazyServiceRegistrar createExtraTestInstance();
private:
std::shared_ptr<internal::ClientCounterCallback> mClientCC;
LazyServiceRegistrar();
};
} // namespace binder
} // namespace android
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include <binder/Common.h>
#include <binder/IMemory.h>
namespace android {
// ---------------------------------------------------------------------------
class LIBBINDER_EXPORTED MemoryBase : public BnMemory {
public:
MemoryBase(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
virtual ~MemoryBase();
virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
protected:
size_t getSize() const { return mSize; }
ssize_t getOffset() const { return mOffset; }
const sp<IMemoryHeap>& getHeap() const { return mHeap; }
private:
size_t mSize;
ssize_t mOffset;
sp<IMemoryHeap> mHeap;
};
// ---------------------------------------------------------------------------
} // namespace android
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#include <sys/types.h>
#include <binder/Common.h>
#include <binder/IMemory.h>
#include <binder/MemoryHeapBase.h>
namespace android {
// ----------------------------------------------------------------------------
class SimpleBestFitAllocator;
// ----------------------------------------------------------------------------
class MemoryDealer : public RefBase {
public:
LIBBINDER_EXPORTED explicit MemoryDealer(
size_t size, const char* name = nullptr,
uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */);
LIBBINDER_EXPORTED virtual sp<IMemory> allocate(size_t size);
LIBBINDER_EXPORTED virtual void dump(const char* what) const;
// allocations are aligned to some value. return that value so clients can account for it.
LIBBINDER_EXPORTED static size_t getAllocationAlignment();
sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
protected:
LIBBINDER_EXPORTED virtual ~MemoryDealer();
private:
friend class Allocation;
virtual void deallocate(size_t offset);
LIBBINDER_EXPORTED const sp<IMemoryHeap>& heap() const;
SimpleBestFitAllocator* allocator() const;
sp<IMemoryHeap> mHeap;
SimpleBestFitAllocator* mAllocator;
};
// ----------------------------------------------------------------------------
} // namespace android
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include <binder/Common.h>
#include <binder/IMemory.h>
namespace android {
// ---------------------------------------------------------------------------
class MemoryHeapBase : public BnMemoryHeap {
public:
static constexpr auto MEMFD_ALLOW_SEALING_FLAG = 0x00000800;
enum {
READ_ONLY = IMemoryHeap::READ_ONLY,
// memory won't be mapped locally, but will be mapped in the remote
// process.
DONT_MAP_LOCALLY = 0x00000100,
NO_CACHING = 0x00000200,
// Bypass ashmem-libcutils to create a memfd shared region.
// Ashmem-libcutils will eventually migrate to memfd.
// Memfd has security benefits and supports file sealing.
// Calling process will need to modify selinux permissions to
// open access to tmpfs files. See audioserver for examples.
// This is only valid for size constructor.
// For host compilation targets, memfd is stubbed in favor of /tmp
// files so sealing is not enforced.
FORCE_MEMFD = 0x00000400,
// Default opt-out of sealing behavior in memfd to avoid potential DOS.
// Clients of shared files can seal at anytime via syscall, leading to
// TOC/TOU issues if additional seals prevent access from the creating
// process. Alternatively, seccomp fcntl().
MEMFD_ALLOW_SEALING = FORCE_MEMFD | MEMFD_ALLOW_SEALING_FLAG
};
/*
* maps the memory referenced by fd. but DOESN'T take ownership
* of the filedescriptor (it makes a copy with dup()
*/
LIBBINDER_EXPORTED MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, off_t offset = 0);
/*
* maps memory from the given device
*/
LIBBINDER_EXPORTED explicit MemoryHeapBase(const char* device, size_t size = 0,
uint32_t flags = 0);
/*
* maps memory from ashmem, with the given name for debugging
* if the READ_ONLY flag is set, the memory will be writeable by the calling process,
* but not by others. this is NOT the case with the other ctors.
*/
LIBBINDER_EXPORTED explicit MemoryHeapBase(size_t size, uint32_t flags = 0,
char const* name = nullptr);
LIBBINDER_EXPORTED virtual ~MemoryHeapBase();
/* implement IMemoryHeap interface */
LIBBINDER_EXPORTED int getHeapID() const override;
/* virtual address of the heap. returns MAP_FAILED in case of error */
LIBBINDER_EXPORTED void* getBase() const override;
LIBBINDER_EXPORTED size_t getSize() const override;
LIBBINDER_EXPORTED uint32_t getFlags() const override;
LIBBINDER_EXPORTED off_t getOffset() const override;
LIBBINDER_EXPORTED const char* getDevice() const;
/* this closes this heap -- use carefully */
LIBBINDER_EXPORTED void dispose();
protected:
LIBBINDER_EXPORTED MemoryHeapBase();
// init() takes ownership of fd
LIBBINDER_EXPORTED status_t init(int fd, void* base, size_t size, int flags = 0,
const char* device = nullptr);
private:
status_t mapfd(int fd, bool writeableByCaller, size_t size, off_t offset = 0);
int mFD;
size_t mSize;
void* mBase;
uint32_t mFlags;
const char* mDevice;
bool mNeedUnmap;
off_t mOffset;
};
// ---------------------------------------------------------------------------
} // namespace android
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <binder/unique_fd.h>
namespace android {
namespace os {
/*
* C++ implementation of the Java class android.os.ParcelFileDescriptor
*/
class LIBBINDER_EXPORTED ParcelFileDescriptor : public android::Parcelable {
public:
ParcelFileDescriptor();
explicit ParcelFileDescriptor(binder::unique_fd fd);
ParcelFileDescriptor(ParcelFileDescriptor&& other) noexcept : mFd(std::move(other.mFd)) { }
ParcelFileDescriptor& operator=(ParcelFileDescriptor&& other) noexcept = default;
~ParcelFileDescriptor() override;
int get() const { return mFd.get(); }
binder::unique_fd release() { return std::move(mFd); }
void reset(binder::unique_fd fd = binder::unique_fd()) { mFd = std::move(fd); }
// android::Parcelable override:
android::status_t writeToParcel(android::Parcel* parcel) const override;
android::status_t readFromParcel(const android::Parcel* parcel) override;
inline std::string toString() const { return "ParcelFileDescriptor:" + std::to_string(get()); }
inline bool operator!=(const ParcelFileDescriptor& rhs) const {
return mFd.get() != rhs.mFd.get();
}
inline bool operator<(const ParcelFileDescriptor& rhs) const {
return mFd.get() < rhs.mFd.get();
}
inline bool operator<=(const ParcelFileDescriptor& rhs) const {
return mFd.get() <= rhs.mFd.get();
}
inline bool operator==(const ParcelFileDescriptor& rhs) const {
return mFd.get() == rhs.mFd.get();
}
inline bool operator>(const ParcelFileDescriptor& rhs) const {
return mFd.get() > rhs.mFd.get();
}
inline bool operator>=(const ParcelFileDescriptor& rhs) const {
return mFd.get() >= rhs.mFd.get();
}
private:
binder::unique_fd mFd;
};
} // namespace os
} // namespace android
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <vector>
#include <utils/Errors.h>
#include <utils/String16.h>
#include <binder/Common.h>
namespace android {
class Parcel;
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
// Abstract interface of all parcelables.
class LIBBINDER_EXPORTED Parcelable {
public:
virtual ~Parcelable() = default;
Parcelable() = default;
Parcelable(const Parcelable&) = default;
// Write |this| parcelable to the given |parcel|. Keep in mind that
// implementations of writeToParcel must be manually kept in sync
// with readFromParcel and the Java equivalent versions of these methods.
//
// Returns android::OK on success and an appropriate error otherwise.
virtual status_t writeToParcel(Parcel* parcel) const = 0;
// Read data from the given |parcel| into |this|. After readFromParcel
// completes, |this| should have equivalent state to the object that
// wrote itself to the parcel.
//
// Returns android::OK on success and an appropriate error otherwise.
virtual status_t readFromParcel(const Parcel* parcel) = 0;
// WARNING: for use by auto-generated code only (AIDL). Should not be used
// manually, or there is a risk of breaking CTS, GTS, VTS, or CTS-on-GSI
// tests.
enum class Stability : int32_t {
STABILITY_LOCAL,
STABILITY_VINTF, // corresponds to @VintfStability
};
// 'Stable' means this parcelable is guaranteed to be stable for multiple
// years.
// It must be guaranteed by setting stability field in aidl_interface.
// WARNING: getStability() is only expected to be overridden by auto-generated
// code. Returns true if this parcelable is stable.
virtual Stability getStability() const { return Stability::STABILITY_LOCAL; }
}; // class Parcelable
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace android
@@ -0,0 +1,146 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <utils/String16.h>
#include <mutex>
#include <optional>
#include <tuple>
namespace android {
namespace os {
/*
* C++ implementation of the Java class android.os.ParcelableHolder
*/
class LIBBINDER_EXPORTED ParcelableHolder : public android::Parcelable {
public:
ParcelableHolder() = delete;
explicit ParcelableHolder(Stability stability) : mStability(stability){}
virtual ~ParcelableHolder() = default;
ParcelableHolder(const ParcelableHolder& other) {
mParcelable = other.mParcelable;
mParcelableName = other.mParcelableName;
if (other.mParcelPtr) {
mParcelPtr = std::make_unique<Parcel>();
mParcelPtr->appendFrom(other.mParcelPtr.get(), 0, other.mParcelPtr->dataSize());
}
mStability = other.mStability;
}
ParcelableHolder(ParcelableHolder&& other) = default;
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
void reset() {
this->mParcelable = nullptr;
this->mParcelableName = std::nullopt;
this->mParcelPtr = nullptr;
}
template <typename T>
status_t setParcelable(T&& p) {
using Tt = typename std::decay<T>::type;
return setParcelable<Tt>(std::make_shared<Tt>(std::forward<T>(p)));
}
template <typename T>
status_t setParcelable(std::shared_ptr<T> p) {
static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable");
if (p && this->getStability() > p->getStability()) {
return android::BAD_VALUE;
}
this->mParcelable = p;
this->mParcelableName = T::getParcelableDescriptor();
this->mParcelPtr = nullptr;
return android::OK;
}
template <typename T>
status_t getParcelable(std::shared_ptr<T>* ret) const {
static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable");
const String16& parcelableDesc = T::getParcelableDescriptor();
if (!this->mParcelPtr) {
if (!this->mParcelable || !this->mParcelableName) {
ALOGD("empty ParcelableHolder");
*ret = nullptr;
return android::OK;
} else if (parcelableDesc != *mParcelableName) {
ALOGD("extension class name mismatch expected:%s actual:%s",
String8(*mParcelableName).c_str(), String8(parcelableDesc).c_str());
*ret = nullptr;
return android::BAD_VALUE;
}
*ret = std::static_pointer_cast<T>(mParcelable);
return android::OK;
}
this->mParcelPtr->setDataPosition(0);
status_t status = this->mParcelPtr->readString16(&this->mParcelableName);
if (status != android::OK || parcelableDesc != this->mParcelableName) {
this->mParcelableName = std::nullopt;
*ret = nullptr;
return status;
}
this->mParcelable = std::make_shared<T>();
status = mParcelable.get()->readFromParcel(this->mParcelPtr.get());
if (status != android::OK) {
this->mParcelableName = std::nullopt;
this->mParcelable = nullptr;
*ret = nullptr;
return status;
}
this->mParcelPtr = nullptr;
*ret = std::static_pointer_cast<T>(mParcelable);
return android::OK;
}
Stability getStability() const override { return mStability; }
inline std::string toString() const {
return "ParcelableHolder:" +
(mParcelableName ? std::string(String8(mParcelableName.value()).c_str())
: "<parceled>");
}
inline bool operator!=(const ParcelableHolder& rhs) const {
return this != &rhs;
}
inline bool operator<(const ParcelableHolder& rhs) const {
return this < &rhs;
}
inline bool operator<=(const ParcelableHolder& rhs) const {
return this <= &rhs;
}
inline bool operator==(const ParcelableHolder& rhs) const {
return this == &rhs;
}
inline bool operator>(const ParcelableHolder& rhs) const {
return this > &rhs;
}
inline bool operator>=(const ParcelableHolder& rhs) const {
return this >= &rhs;
}
private:
mutable std::shared_ptr<Parcelable> mParcelable;
mutable std::optional<String16> mParcelableName;
mutable std::unique_ptr<Parcel> mParcelPtr;
Stability mStability;
};
} // namespace os
} // namespace android
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifndef __ANDROID_VNDK__
#include <stdint.h>
#include <unistd.h>
#include <utils/String16.h>
#include <utils/Singleton.h>
#include <utils/SortedVector.h>
#include <binder/Common.h>
namespace android {
// ---------------------------------------------------------------------------
/*
* PermissionCache caches permission checks for a given uid.
*
* Currently the cache is not updated when there is a permission change,
* for instance when an application is uninstalled.
*
* IMPORTANT: for the reason stated above, only system permissions are safe
* to cache. This restriction may be lifted at a later time.
*
*/
class PermissionCache : Singleton<PermissionCache> {
struct Entry {
String16 name;
uid_t uid;
bool granted;
inline bool operator < (const Entry& e) const {
return (uid == e.uid) ? (name < e.name) : (uid < e.uid);
}
};
mutable Mutex mLock;
// we pool all the permission names we see, as many permissions checks
// will have identical names
SortedVector< String16 > mPermissionNamesPool;
// this is our cache per say. it stores pooled names.
SortedVector< Entry > mCache;
// free the whole cache, but keep the permission name pool
void purge();
status_t check(bool* granted,
const String16& permission, uid_t uid) const;
void cache(const String16& permission, uid_t uid, bool granted);
public:
LIBBINDER_EXPORTED PermissionCache();
LIBBINDER_EXPORTED static bool checkCallingPermission(const String16& permission);
LIBBINDER_EXPORTED static bool checkCallingPermission(const String16& permission,
int32_t* outPid, int32_t* outUid);
LIBBINDER_EXPORTED static bool checkPermission(const String16& permission, pid_t pid,
uid_t uid);
LIBBINDER_EXPORTED static void purgeCache();
};
// ---------------------------------------------------------------------------
} // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
#endif // __ANDROID_VNDK__
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifndef __ANDROID_VNDK__
#include <binder/Common.h>
#include <binder/IPermissionController.h>
#include <utils/Mutex.h>
// ---------------------------------------------------------------------------
namespace android {
class PermissionController {
public:
enum {
MATCH_SYSTEM_ONLY = 1<<16,
MATCH_UNINSTALLED_PACKAGES = 1<<13,
MATCH_FACTORY_ONLY = 1<<21,
MATCH_INSTANT = 1<<23
};
enum {
MODE_ALLOWED = 0,
MODE_IGNORED = 1,
MODE_ERRORED = 2,
MODE_DEFAULT = 3,
};
LIBBINDER_EXPORTED PermissionController();
LIBBINDER_EXPORTED bool checkPermission(const String16& permission, int32_t pid, int32_t uid);
LIBBINDER_EXPORTED int32_t noteOp(const String16& op, int32_t uid, const String16& packageName);
LIBBINDER_EXPORTED void getPackagesForUid(const uid_t uid, Vector<String16>& packages);
LIBBINDER_EXPORTED bool isRuntimePermission(const String16& permission);
LIBBINDER_EXPORTED int getPackageUid(const String16& package, int flags);
private:
Mutex mLock;
sp<IPermissionController> mService;
sp<IPermissionController> getService();
};
} // namespace android
// ---------------------------------------------------------------------------
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
#endif // __ANDROID_VNDK__
@@ -0,0 +1,130 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <map>
#include <set>
#include <vector>
#include <binder/Common.h>
#include <binder/Parcelable.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
namespace android {
namespace os {
/*
* C++ implementation of PersistableBundle, a mapping from String values to
* various types that can be saved to persistent and later restored.
*/
class LIBBINDER_EXPORTED PersistableBundle : public Parcelable {
public:
PersistableBundle() = default;
virtual ~PersistableBundle() = default;
PersistableBundle(const PersistableBundle& bundle) = default;
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
bool empty() const;
size_t size() const;
size_t erase(const String16& key);
/*
* Setters for PersistableBundle. Adds a a key-value pair instantiated with
* |key| and |value| into the member map appropriate for the type of |value|.
* If there is already an existing value for |key|, |value| will replace it.
*/
void putBoolean(const String16& key, bool value);
void putInt(const String16& key, int32_t value);
void putLong(const String16& key, int64_t value);
void putDouble(const String16& key, double value);
void putString(const String16& key, const String16& value);
void putBooleanVector(const String16& key, const std::vector<bool>& value);
void putIntVector(const String16& key, const std::vector<int32_t>& value);
void putLongVector(const String16& key, const std::vector<int64_t>& value);
void putDoubleVector(const String16& key, const std::vector<double>& value);
void putStringVector(const String16& key, const std::vector<String16>& value);
void putPersistableBundle(const String16& key, const PersistableBundle& value);
/*
* Getters for PersistableBundle. If |key| exists, these methods write the
* value associated with |key| into |out|, and return true. Otherwise, these
* methods return false.
*/
bool getBoolean(const String16& key, bool* out) const;
bool getInt(const String16& key, int32_t* out) const;
bool getLong(const String16& key, int64_t* out) const;
bool getDouble(const String16& key, double* out) const;
bool getString(const String16& key, String16* out) const;
bool getBooleanVector(const String16& key, std::vector<bool>* out) const;
bool getIntVector(const String16& key, std::vector<int32_t>* out) const;
bool getLongVector(const String16& key, std::vector<int64_t>* out) const;
bool getDoubleVector(const String16& key, std::vector<double>* out) const;
bool getStringVector(const String16& key, std::vector<String16>* out) const;
bool getPersistableBundle(const String16& key, PersistableBundle* out) const;
/* Getters for all keys for each value type */
std::set<String16> getBooleanKeys() const;
std::set<String16> getIntKeys() const;
std::set<String16> getLongKeys() const;
std::set<String16> getDoubleKeys() const;
std::set<String16> getStringKeys() const;
std::set<String16> getBooleanVectorKeys() const;
std::set<String16> getIntVectorKeys() const;
std::set<String16> getLongVectorKeys() const;
std::set<String16> getDoubleVectorKeys() const;
std::set<String16> getStringVectorKeys() const;
std::set<String16> getPersistableBundleKeys() const;
friend bool operator==(const PersistableBundle& lhs, const PersistableBundle& rhs) {
return (lhs.mBoolMap == rhs.mBoolMap && lhs.mIntMap == rhs.mIntMap &&
lhs.mLongMap == rhs.mLongMap && lhs.mDoubleMap == rhs.mDoubleMap &&
lhs.mStringMap == rhs.mStringMap && lhs.mBoolVectorMap == rhs.mBoolVectorMap &&
lhs.mIntVectorMap == rhs.mIntVectorMap &&
lhs.mLongVectorMap == rhs.mLongVectorMap &&
lhs.mDoubleVectorMap == rhs.mDoubleVectorMap &&
lhs.mStringVectorMap == rhs.mStringVectorMap &&
lhs.mPersistableBundleMap == rhs.mPersistableBundleMap);
}
friend bool operator!=(const PersistableBundle& lhs, const PersistableBundle& rhs) {
return !(lhs == rhs);
}
private:
status_t writeToParcelInner(Parcel* parcel) const;
status_t readFromParcelInner(const Parcel* parcel, size_t length);
std::map<String16, bool> mBoolMap;
std::map<String16, int32_t> mIntMap;
std::map<String16, int64_t> mLongMap;
std::map<String16, double> mDoubleMap;
std::map<String16, String16> mStringMap;
std::map<String16, std::vector<bool>> mBoolVectorMap;
std::map<String16, std::vector<int32_t>> mIntVectorMap;
std::map<String16, std::vector<int64_t>> mLongVectorMap;
std::map<String16, std::vector<double>> mDoubleVectorMap;
std::map<String16, std::vector<String16>> mStringVectorMap;
std::map<String16, PersistableBundle> mPersistableBundleMap;
};
} // namespace os
} // namespace android
@@ -0,0 +1,202 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IBinder.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <pthread.h>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
// ---------------------------------------------------------------------------
namespace android {
class IPCThreadState;
/**
* Kernel binder process state. All operations here refer to kernel binder. This
* object is allocated per process.
*/
class ProcessState : public virtual RefBase {
public:
LIBBINDER_EXPORTED static sp<ProcessState> self();
LIBBINDER_EXPORTED static sp<ProcessState> selfOrNull();
LIBBINDER_EXPORTED static bool isVndservicemanagerEnabled();
/* initWithDriver() can be used to configure libbinder to use
* a different binder driver dev node. It must be called *before*
* any call to ProcessState::self(). The default is /dev/vndbinder
* for processes built with the VNDK and /dev/binder for those
* which are not.
*
* If this is called with nullptr, the behavior is the same as selfOrNull.
*/
LIBBINDER_EXPORTED static sp<ProcessState> initWithDriver(const char* driver);
LIBBINDER_EXPORTED sp<IBinder> getContextObject(const sp<IBinder>& caller);
// This should be called before startThreadPool at the beginning
// of a program, and libraries should never call it because programs
// should configure their own threadpools. The threadpool size can
// never be decreased.
//
// The 'maxThreads' value refers to the total number of threads
// that will be started by the kernel. This is in addition to any
// threads started by 'startThreadPool' or 'joinRpcThreadpool'.
LIBBINDER_EXPORTED status_t setThreadPoolMaxThreadCount(size_t maxThreads);
// Libraries should not call this, as processes should configure
// threadpools themselves. Should be called in the main function
// directly before any code executes or joins the threadpool.
//
// Starts one thread, PLUS those requested in setThreadPoolMaxThreadCount,
// PLUS those manually requested in joinThreadPool.
//
// For instance, if setThreadPoolMaxCount(3) is called and
// startThreadpPool (+1 thread) and joinThreadPool (+1 thread)
// are all called, then up to 5 threads can be started.
LIBBINDER_EXPORTED void startThreadPool();
[[nodiscard]] LIBBINDER_EXPORTED bool becomeContextManager();
LIBBINDER_EXPORTED sp<IBinder> getStrongProxyForHandle(int32_t handle);
LIBBINDER_EXPORTED void expungeHandle(int32_t handle, IBinder* binder);
// TODO: deprecate.
LIBBINDER_EXPORTED void spawnPooledThread(bool isMain);
LIBBINDER_EXPORTED status_t enableOnewaySpamDetection(bool enable);
// Set the name of the current thread to look like a threadpool
// thread. Typically this is called before joinThreadPool.
//
// TODO: remove this API, and automatically set it intelligently.
LIBBINDER_EXPORTED void giveThreadPoolName();
LIBBINDER_EXPORTED String8 getDriverName();
LIBBINDER_EXPORTED ssize_t getKernelReferences(size_t count, uintptr_t* buf);
// Only usable by the context manager.
// This refcount includes:
// 1. Strong references to the node by this and other processes
// 2. Temporary strong references held by the kernel during a
// transaction on the node.
// It does NOT include local strong references to the node
LIBBINDER_EXPORTED ssize_t getStrongRefCountForNode(const sp<BpBinder>& binder);
enum class CallRestriction {
// all calls okay
NONE,
// log when calls are blocking
ERROR_IF_NOT_ONEWAY,
// abort process on blocking calls
FATAL_IF_NOT_ONEWAY,
};
// Sets calling restrictions for all transactions in this process. This must be called
// before any threads are spawned.
LIBBINDER_EXPORTED void setCallRestriction(CallRestriction restriction);
/**
* Get the max number of threads that have joined the thread pool.
* This includes kernel started threads, user joined threads and polling
* threads if used.
*/
LIBBINDER_EXPORTED size_t getThreadPoolMaxTotalThreadCount() const;
/**
* Check to see if the thread pool has started.
*/
LIBBINDER_EXPORTED bool isThreadPoolStarted() const;
enum class DriverFeature {
ONEWAY_SPAM_DETECTION,
EXTENDED_ERROR,
FREEZE_NOTIFICATION,
};
// Determine whether a feature is supported by the binder driver.
LIBBINDER_EXPORTED static bool isDriverFeatureEnabled(const DriverFeature feature);
private:
static sp<ProcessState> init(const char* defaultDriver, bool requireDefault);
void checkExpectingThreadPoolStart() const;
static void onFork();
static void parentPostFork();
static void childPostFork();
friend class IPCThreadState;
friend class sp<ProcessState>;
explicit ProcessState(const char* driver);
~ProcessState();
ProcessState(const ProcessState& o);
ProcessState& operator=(const ProcessState& o);
String8 makeBinderThreadName();
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
handle_entry* lookupHandleLocked(int32_t handle);
String8 mDriverName;
int mDriverFD;
void* mVMStart;
mutable std::mutex mOnThreadAvailableLock;
std::condition_variable mOnThreadAvailableCondVar;
// Number of threads waiting on `mOnThreadAvailableCondVar`.
std::atomic_int64_t mOnThreadAvailableWaiting = 0;
// Number of binder threads current executing a command.
std::atomic_size_t mExecutingThreadsCount;
// Maximum number of lazy threads to be started in the threadpool by the kernel.
std::atomic_size_t mMaxThreads;
// Current number of threads inside the thread pool.
std::atomic_size_t mCurrentThreads;
// Current number of pooled threads inside the thread pool.
std::atomic_size_t mKernelStartedThreads;
// Time when thread pool was emptied
std::atomic<std::chrono::steady_clock::time_point> mStarvationStartTime;
static constexpr auto never = &std::chrono::steady_clock::time_point::min;
mutable std::mutex mLock; // protects everything below.
Vector<handle_entry> mHandleToObject;
bool mForked;
std::atomic_bool mThreadPoolStarted;
std::atomic_int32_t mThreadPoolSeq;
CallRestriction mCallRestriction;
};
} // namespace android
// ---------------------------------------------------------------------------
@@ -0,0 +1,89 @@
/*
* Copyright (C) 2022, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/unique_fd.h>
#include <mutex>
namespace android {
namespace binder::debug {
// Warning: Transactions are sequentially recorded to the file descriptor in a
// non-stable format. A detailed description of the recording format can be found in
// RecordedTransaction.cpp.
class RecordedTransaction {
public:
// Filled with the first transaction from fd.
LIBBINDER_EXPORTED static std::optional<RecordedTransaction> fromFile(
const binder::unique_fd& fd);
// Filled with the arguments.
LIBBINDER_EXPORTED static std::optional<RecordedTransaction> fromDetails(
const String16& interfaceName, uint32_t code, uint32_t flags, timespec timestamp,
const Parcel& data, const Parcel& reply, status_t err);
LIBBINDER_EXPORTED RecordedTransaction(RecordedTransaction&& t) noexcept;
[[nodiscard]] LIBBINDER_EXPORTED status_t dumpToFile(const binder::unique_fd& fd) const;
LIBBINDER_EXPORTED const std::string& getInterfaceName() const;
LIBBINDER_EXPORTED uint32_t getCode() const;
LIBBINDER_EXPORTED uint32_t getFlags() const;
LIBBINDER_EXPORTED int32_t getReturnedStatus() const;
LIBBINDER_EXPORTED timespec getTimestamp() const;
LIBBINDER_EXPORTED uint32_t getVersion() const;
LIBBINDER_EXPORTED const Parcel& getDataParcel() const;
LIBBINDER_EXPORTED const Parcel& getReplyParcel() const;
LIBBINDER_EXPORTED const std::vector<uint64_t>& getObjectOffsets() const;
private:
RecordedTransaction() = default;
android::status_t writeChunk(const binder::borrowed_fd, uint32_t chunkType, size_t byteCount,
const uint8_t* data) const;
#pragma clang diagnostic push
#pragma clang diagnostic error "-Wpadded"
struct TransactionHeader {
uint32_t code = 0;
uint32_t flags = 0;
int32_t statusReturned = 0;
uint32_t version = 0; // !0 iff Rpc
int64_t timestampSeconds = 0;
int32_t timestampNanoseconds = 0;
int32_t reserved = 0;
};
#pragma clang diagnostic pop
static_assert(sizeof(TransactionHeader) == 32);
static_assert(sizeof(TransactionHeader) % 8 == 0);
struct MovableData { // movable
TransactionHeader mHeader;
std::string mInterfaceName;
std::vector<uint64_t> mSentObjectData; /* Object Offsets */
};
MovableData mData;
Parcel mSentDataOnly;
Parcel mReplyDataOnly;
};
} // namespace binder::debug
} // namespace android
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Formats for serializing TLS certificate.
#pragma once
#include <string>
namespace android {
enum class RpcCertificateFormat {
PEM,
DER,
};
static inline std::string PrintToString(RpcCertificateFormat format) {
switch (format) {
case RpcCertificateFormat::PEM:
return "PEM";
case RpcCertificateFormat::DER:
return "DER";
default:
return "<unknown>";
}
}
} // namespace android
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Formats for serializing TLS private keys.
#pragma once
#include <string>
namespace android {
enum class RpcKeyFormat {
PEM,
DER,
};
static inline std::string PrintToString(RpcKeyFormat format) {
switch (format) {
case RpcKeyFormat::PEM:
return "PEM";
case RpcKeyFormat::DER:
return "DER";
default:
return "<unknown>";
}
}
} // namespace android
@@ -0,0 +1,297 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IBinder.h>
#include <binder/RpcSession.h>
#include <binder/RpcThreads.h>
#include <binder/RpcTransport.h>
#include <binder/unique_fd.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <bitset>
#include <mutex>
#include <thread>
namespace android {
class FdTrigger;
class RpcServerTrusty;
class RpcSocketAddress;
/**
* This represents a server of an interface, which may be connected to by any
* number of clients over sockets.
*
* Usage:
* auto server = RpcServer::make();
* // only supports one now
* if (!server->setup*Server(...)) {
* :(
* }
* server->join();
*/
class RpcServer final : public virtual RefBase, private RpcSession::EventListener {
public:
LIBBINDER_EXPORTED static sp<RpcServer> make(
std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr);
/**
* Creates an RPC server that bootstraps sessions using an existing
* Unix domain socket pair.
*
* Callers should create a pair of SOCK_STREAM Unix domain sockets, pass
* one to RpcServer::setupUnixDomainSocketBootstrapServer and the other
* to RpcSession::setupUnixDomainSocketBootstrapClient. Multiple client
* session can be created from the client end of the pair.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t
setupUnixDomainSocketBootstrapServer(binder::unique_fd serverFd);
/**
* This represents a session for responses, e.g.:
*
* process A serves binder a
* process B opens a session to process A
* process B makes binder b and sends it to A
* A uses this 'back session' to send things back to B
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupUnixDomainServer(const char* path);
/**
* Sets up an RPC server with a raw socket file descriptor.
* The socket should be created and bound to a socket address already, e.g.
* the socket can be created in init.rc.
*
* This method is used in the libbinder_rpc_unstable API
* RunInitUnixDomainRpcServer().
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupRawSocketServer(binder::unique_fd socket_fd);
/**
* Creates an RPC server binding to the given CID at the given port.
*
* Set |port| to VMADDR_PORT_ANY to pick an ephemeral port. In this case, |assignedPort|
* will be set to the picked port number, if it is not null.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned bindCid, unsigned port,
unsigned* assignedPort = nullptr);
/**
* Creates an RPC server at the current port using IPv4.
*
* TODO(b/182914638): IPv6 support
*
* Set |port| to 0 to pick an ephemeral port; see discussion of
* /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
* will be set to the picked port number, if it is not null.
*
* Set the IPv4 address for the socket to be listening on.
* "127.0.0.1" allows for local connections from the same device.
* "0.0.0.0" allows for connections on any IP address that the device may
* have
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupInetServer(const char* address,
unsigned int port,
unsigned int* assignedPort = nullptr);
/**
* If setup*Server has been successful, return true. Otherwise return false.
*/
[[nodiscard]] LIBBINDER_EXPORTED bool hasServer();
/**
* If hasServer(), return the server FD. Otherwise return invalid FD.
*/
[[nodiscard]] LIBBINDER_EXPORTED binder::unique_fd releaseServer();
/**
* Set up server using an external FD previously set up by releaseServer().
* Return false if there's already a server.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupExternalServer(binder::unique_fd serverFd);
/**
* This must be called before adding a client session. This corresponds
* to the number of incoming connections to RpcSession objects in the
* server, which will correspond to the number of outgoing connections
* in client RpcSession objects.
*
* If this is not specified, this will be a single-threaded server.
*
* TODO(b/167966510): these are currently created per client, but these
* should be shared.
*/
LIBBINDER_EXPORTED void setMaxThreads(size_t threads);
LIBBINDER_EXPORTED size_t getMaxThreads();
/**
* By default, the latest protocol version which is supported by a client is
* used. However, this can be used in order to prevent newer protocol
* versions from ever being used. This is expected to be useful for testing.
*/
[[nodiscard]] LIBBINDER_EXPORTED bool setProtocolVersion(uint32_t version);
/**
* Set the supported transports for sending and receiving file descriptors.
*
* Clients will propose a mode when connecting. If the mode is not in the
* provided list, the connection will be rejected.
*/
LIBBINDER_EXPORTED void setSupportedFileDescriptorTransportModes(
const std::vector<RpcSession::FileDescriptorTransportMode>& modes);
/**
* The root object can be retrieved by any client, without any
* authentication. TODO(b/183988761)
*
* Holds a strong reference to the root object.
*/
LIBBINDER_EXPORTED void setRootObject(const sp<IBinder>& binder);
/**
* Holds a weak reference to the root object.
*/
LIBBINDER_EXPORTED void setRootObjectWeak(const wp<IBinder>& binder);
/**
* Allows a root object to be created for each session.
*
* Takes one argument: a callable that is invoked once per new session.
* The callable takes three arguments:
* - a weak pointer to the session. If you want to hold onto this in the root object, then
* you should keep a weak pointer, and promote it when needed. For instance, if you refer
* to this from the root object, then you could get ahold of transport-specific information.
* - a type-erased pointer to an OS- and transport-specific address structure, e.g.,
* sockaddr_vm for vsock
* - an integer representing the size in bytes of that structure. The callable should
* validate the size, then cast the type-erased pointer to a pointer to the actual type of the
* address, e.g., const void* to const sockaddr_vm*.
*/
LIBBINDER_EXPORTED void setPerSessionRootObject(
std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& object);
LIBBINDER_EXPORTED sp<IBinder> getRootObject();
/**
* Set optional filter of incoming connections based on the peer's address.
*
* Takes one argument: a callable that is invoked on each accept()-ed
* connection and returns false if the connection should be dropped.
* See the description of setPerSessionRootObject() for details about
* the callable's arguments.
*/
LIBBINDER_EXPORTED void setConnectionFilter(std::function<bool(const void*, size_t)>&& filter);
/**
* Set optional modifier of each newly created server socket.
*
* The only argument is a successfully created file descriptor, not bound to an address yet.
*/
LIBBINDER_EXPORTED void setServerSocketModifier(
std::function<void(binder::borrowed_fd)>&& modifier);
/**
* See RpcTransportCtx::getCertificate
*/
LIBBINDER_EXPORTED std::vector<uint8_t> getCertificate(RpcCertificateFormat);
/**
* Runs join() in a background thread. Immediately returns.
*/
LIBBINDER_EXPORTED void start();
/**
* You must have at least one client session before calling this.
*
* If a client needs to actively terminate join, call shutdown() in a separate thread.
*
* At any given point, there can only be one thread calling join().
*
* Warning: if shutdown is called, this will return while the shutdown is
* still occurring. To ensure that the service is fully shutdown, you might
* want to call shutdown after 'join' returns.
*/
LIBBINDER_EXPORTED void join();
/**
* Shut down any existing join(). Return true if successfully shut down, false otherwise
* (e.g. no join() is running). Will wait for the server to be fully
* shutdown.
*
* Warning: this will hang if it is called from its own thread.
*/
[[nodiscard]] LIBBINDER_EXPORTED bool shutdown();
/**
* For debugging!
*/
LIBBINDER_EXPORTED std::vector<sp<RpcSession>> listSessions();
LIBBINDER_EXPORTED size_t numUninitializedSessions();
/**
* Whether any requests are currently being processed.
*/
LIBBINDER_EXPORTED bool hasActiveRequests();
LIBBINDER_EXPORTED ~RpcServer();
private:
friend RpcServerTrusty;
friend sp<RpcServer>;
explicit RpcServer(std::unique_ptr<RpcTransportCtx> ctx);
void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
void onSessionIncomingThreadEnded() override;
status_t setupExternalServer(
binder::unique_fd serverFd,
std::function<status_t(const RpcServer&, RpcTransportFd*)>&& acceptFn);
static constexpr size_t kRpcAddressSize = 128;
static void establishConnection(
sp<RpcServer>&& server, RpcTransportFd clientFd,
std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen,
std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn);
static status_t acceptSocketConnection(const RpcServer& server, RpcTransportFd* out);
static status_t recvmsgSocketConnection(const RpcServer& server, RpcTransportFd* out);
[[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
const std::unique_ptr<RpcTransportCtx> mCtx;
size_t mMaxThreads = 1;
std::optional<uint32_t> mProtocolVersion;
// A mode is supported if the N'th bit is on, where N is the mode enum's value.
std::bitset<8> mSupportedFileDescriptorTransportModes = std::bitset<8>().set(
static_cast<size_t>(RpcSession::FileDescriptorTransportMode::NONE));
RpcTransportFd mServer; // socket we are accepting sessions on
RpcMutex mLock; // for below
std::unique_ptr<RpcMaybeThread> mJoinThread;
bool mJoinThreadRunning = false;
std::map<RpcMaybeThread::id, RpcMaybeThread> mConnectingThreads;
sp<IBinder> mRootObject;
wp<IBinder> mRootObjectWeak;
std::function<sp<IBinder>(wp<RpcSession>, const void*, size_t)> mRootObjectFactory;
std::function<bool(const void*, size_t)> mConnectionFilter;
std::function<void(binder::borrowed_fd)> mServerSocketModifier;
std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
std::unique_ptr<FdTrigger> mShutdownTrigger;
RpcConditionVariable mShutdownCv;
std::function<status_t(const RpcServer& server, RpcTransportFd* out)> mAcceptFn;
};
} // namespace android
@@ -0,0 +1,413 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IBinder.h>
#include <binder/RpcThreads.h>
#include <binder/RpcTransport.h>
#include <binder/unique_fd.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <map>
#include <optional>
#include <type_traits>
#include <vector>
namespace android {
class Parcel;
class RpcServer;
class RpcServerTrusty;
class RpcSocketAddress;
class RpcState;
class RpcTransport;
class FdTrigger;
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 2;
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000;
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 1;
// Starting with this version:
//
// * RpcWireReply is larger (4 bytes -> 20).
// * RpcWireTransaction and RpcWireReplyV1 include the parcel data size.
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE = 1;
/**
* This represents a session (group of connections) between a client
* and a server. Multiple connections are needed for multiple parallel "binder"
* calls which may also have nested calls.
*
* Once a binder exists in the session, if all references to all binders are dropped,
* the session shuts down.
*/
class RpcSession final : public virtual RefBase {
public:
// Create an RpcSession with default configuration (raw sockets).
LIBBINDER_EXPORTED static sp<RpcSession> make();
// Create an RpcSession with the given configuration. |serverRpcCertificateFormat| and
// |serverCertificate| must have values or be nullopt simultaneously. If they have values, set
// server certificate.
LIBBINDER_EXPORTED static sp<RpcSession> make(
std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory);
/**
* Set the maximum number of incoming threads allowed to be made (for things like callbacks).
* By default, this is 0. This must be called before setting up this connection as a client.
* Server sessions will inherits this value from RpcServer. Each thread will serve a
* connection to the remote RpcSession.
*
* If this is called, 'shutdown' on this session must also be called.
* Otherwise, a threadpool will leak.
*
* TODO(b/189955605): start these lazily - currently all are started
*/
LIBBINDER_EXPORTED void setMaxIncomingThreads(size_t threads);
LIBBINDER_EXPORTED size_t getMaxIncomingThreads();
/**
* Set the maximum number of outgoing connections allowed to be made.
* By default, this is |kDefaultMaxOutgoingConnections|. This must be called before setting up
* this connection as a client.
*
* For an RpcSession client, if you are connecting to a server which starts N threads,
* then this must be set to >= N. If you set the maximum number of outgoing connections
* to 1, but the server requests 10, then it would be considered an error. If you set a
* maximum number of connections to 10, and the server requests 1, then only 1 will be
* created. This API is used to limit the amount of resources a server can request you
* create.
*/
LIBBINDER_EXPORTED void setMaxOutgoingConnections(size_t connections);
LIBBINDER_EXPORTED size_t getMaxOutgoingThreads();
/**
* By default, the minimum of the supported versions of the client and the
* server will be used. Usually, this API should only be used for debugging.
*/
[[nodiscard]] LIBBINDER_EXPORTED bool setProtocolVersion(uint32_t version);
LIBBINDER_EXPORTED std::optional<uint32_t> getProtocolVersion();
enum class FileDescriptorTransportMode : uint8_t {
NONE = 0,
// Send file descriptors via unix domain socket ancillary data.
UNIX = 1,
// Send file descriptors as Trusty IPC handles.
TRUSTY = 2,
};
/**
* Set the transport for sending and receiving file descriptors.
*/
LIBBINDER_EXPORTED void setFileDescriptorTransportMode(FileDescriptorTransportMode mode);
LIBBINDER_EXPORTED FileDescriptorTransportMode getFileDescriptorTransportMode();
/**
* This should be called once per thread, matching 'join' in the remote
* process.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupUnixDomainClient(const char* path);
/**
* Connects to an RPC server over a nameless Unix domain socket pair.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t
setupUnixDomainSocketBootstrapClient(binder::unique_fd bootstrap);
/**
* Connects to an RPC server at the CID & port.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockClient(unsigned int cid, unsigned int port);
/**
* Connects to an RPC server at the given address and port.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t setupInetClient(const char* addr, unsigned int port);
/**
* Starts talking to an RPC server which has already been connected to. This
* is expected to be used when another process has permission to connect to
* a binder RPC service, but this process only has permission to talk to
* that service.
*
* For convenience, if 'fd' is -1, 'request' will be called.
*
* For future compatibility, 'request' should not reference any stack data.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t
setupPreconnectedClient(binder::unique_fd fd, std::function<binder::unique_fd()>&& request);
/**
* For debugging!
*
* Sets up an empty connection. All queries to this connection which require a
* response will never be satisfied. All data sent here will be
* unceremoniously cast down the bottomless pit, /dev/null.
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t addNullDebuggingClient();
/**
* Query the other side of the session for the root object hosted by that
* process's RpcServer (if one exists)
*/
LIBBINDER_EXPORTED sp<IBinder> getRootObject();
/**
* Query the other side of the session for the maximum number of threads
* it supports (maximum number of concurrent non-nested synchronous transactions)
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t getRemoteMaxThreads(size_t* maxThreads);
/**
* See RpcTransportCtx::getCertificate
*/
LIBBINDER_EXPORTED std::vector<uint8_t> getCertificate(RpcCertificateFormat);
/**
* Shuts down the service.
*
* For client sessions, wait can be true or false. For server sessions,
* waiting is not currently supported (will abort).
*
* Warning: this is currently not active/nice (the server isn't told we're
* shutting down). Being nicer to the server could potentially make it
* reclaim resources faster.
*
* If this is called w/ 'wait' true, then this will wait for shutdown to
* complete before returning. This will hang if it is called from the
* session threadpool (when processing received calls).
*/
[[nodiscard]] LIBBINDER_EXPORTED bool shutdownAndWait(bool wait);
[[nodiscard]] LIBBINDER_EXPORTED status_t transact(const sp<IBinder>& binder, uint32_t code,
const Parcel& data, Parcel* reply,
uint32_t flags);
/**
* Generally, you should not call this, unless you are testing error
* conditions, as this is called automatically by BpBinders when they are
* deleted (this is also why a raw pointer is used here)
*/
[[nodiscard]] LIBBINDER_EXPORTED status_t sendDecStrong(const BpBinder* binder);
/**
* Whether any requests are currently being processed.
*/
LIBBINDER_EXPORTED bool hasActiveRequests();
LIBBINDER_EXPORTED ~RpcSession();
/**
* Server if this session is created as part of a server (symmetrical to
* client servers). Otherwise, nullptr.
*/
LIBBINDER_EXPORTED sp<RpcServer> server();
// internal only
LIBBINDER_EXPORTED const std::unique_ptr<RpcState>& state() { return mRpcBinderState; }
/**
* Sets the session-specific root object. This is the object that will be used to attach
* the IAccessor binder to the RpcSession when a binder is set up via accessor.
*/
LIBBINDER_EXPORTED void setSessionSpecificRoot(const sp<IBinder>& sessionSpecificRoot);
private:
friend sp<RpcSession>;
friend RpcServer;
friend RpcServerTrusty;
friend RpcState;
explicit RpcSession(std::unique_ptr<RpcTransportCtx> ctx);
static constexpr size_t kDefaultMaxOutgoingConnections = 10;
// internal version of setProtocolVersion that
// optionally skips the mStartedSetup check
[[nodiscard]] bool setProtocolVersionInternal(uint32_t version, bool checkStarted);
// for 'target', see RpcState::sendDecStrongToTarget
[[nodiscard]] status_t sendDecStrongToTarget(uint64_t address, size_t target);
class EventListener : public virtual RefBase {
public:
virtual void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) = 0;
virtual void onSessionIncomingThreadEnded() = 0;
};
class WaitForShutdownListener : public EventListener {
public:
void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
void onSessionIncomingThreadEnded() override;
void waitForShutdown(RpcMutexUniqueLock& lock, const sp<RpcSession>& session);
private:
RpcConditionVariable mCv;
std::atomic<size_t> mShutdownCount = 0;
};
friend WaitForShutdownListener;
struct RpcConnection : public RefBase {
std::unique_ptr<RpcTransport> rpcTransport;
// whether this or another thread is currently using this fd to make
// or receive transactions.
std::optional<uint64_t> exclusiveTid;
bool allowNested = false;
};
[[nodiscard]] status_t readId();
// A thread joining a server must always call these functions in order, and
// cleanup is only programmed once into join. These are in separate
// functions in order to allow for different locks to be taken during
// different parts of setup.
//
// transfer ownership of thread (usually done while a lock is taken on the
// structure which originally owns the thread)
void preJoinThreadOwnership(RpcMaybeThread thread);
// pass FD to thread and read initial connection information
struct PreJoinSetupResult {
// Server connection object associated with this
sp<RpcConnection> connection;
// Status of setup
status_t status;
};
PreJoinSetupResult preJoinSetup(std::unique_ptr<RpcTransport> rpcTransport);
// join on thread passed to preJoinThreadOwnership
static void join(sp<RpcSession>&& session, PreJoinSetupResult&& result);
// This is a workaround to support move-only functors.
// TODO: use std::move_only_function when it becomes available.
template <typename Fn,
// Fn must be a callable type taking (const std::vector<uint8_t>&, bool) and returning
// status_t
typename = std::enable_if_t<
std::is_invocable_r_v<status_t, Fn, const std::vector<uint8_t>&, bool>>>
[[nodiscard]] status_t setupClient(Fn&& connectAndInit);
[[nodiscard]] status_t setupSocketClient(const RpcSocketAddress& address);
[[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address,
const std::vector<uint8_t>& sessionId,
bool incoming);
[[nodiscard]] status_t initAndAddConnection(RpcTransportFd fd,
const std::vector<uint8_t>& sessionId,
bool incoming);
[[nodiscard]] status_t addIncomingConnection(std::unique_ptr<RpcTransport> rpcTransport);
[[nodiscard]] status_t addOutgoingConnection(std::unique_ptr<RpcTransport> rpcTransport,
bool init);
[[nodiscard]] bool setForServer(const wp<RpcServer>& server,
const wp<RpcSession::EventListener>& eventListener,
const std::vector<uint8_t>& sessionId,
const sp<IBinder>& sessionSpecificRoot);
sp<RpcConnection> assignIncomingConnectionToThisThread(
std::unique_ptr<RpcTransport> rpcTransport);
[[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection);
void clearConnectionTid(const sp<RpcConnection>& connection);
[[nodiscard]] status_t initShutdownTrigger();
/**
* Checks whether any connection is active (Not polling on fd)
*/
bool hasActiveConnection(const std::vector<sp<RpcConnection>>& connections);
enum class ConnectionUse {
CLIENT,
CLIENT_ASYNC,
CLIENT_REFCOUNT,
};
// Object representing exclusive access to a connection.
class ExclusiveConnection {
public:
[[nodiscard]] static status_t find(const sp<RpcSession>& session, ConnectionUse use,
ExclusiveConnection* connection);
~ExclusiveConnection();
const sp<RpcConnection>& get() { return mConnection; }
private:
static void findConnection(uint64_t tid, sp<RpcConnection>* exclusive,
sp<RpcConnection>* available,
std::vector<sp<RpcConnection>>& sockets,
size_t socketsIndexHint);
sp<RpcSession> mSession; // avoid deallocation
sp<RpcConnection> mConnection;
// whether this is being used for a nested transaction (being on the same
// thread guarantees we won't write in the middle of a message, the way
// the wire protocol is constructed guarantees this is safe).
bool mReentrant = false;
};
const std::unique_ptr<RpcTransportCtx> mCtx;
// On the other side of a session, for each of mOutgoing here, there should
// be one of mIncoming on the other side (and vice versa).
//
// For the simplest session, a single server with one client, you would
// have:
// - the server has a single 'mIncoming' and a thread listening on this
// - the client has a single 'mOutgoing' and makes calls to this
// - here, when the client makes a call, the server can call back into it
// (nested calls), but outside of this, the client will only ever read
// calls from the server when it makes a call itself.
//
// For a more complicated case, the client might itself open up a thread to
// serve calls to the server at all times (e.g. if it hosts a callback)
wp<RpcServer> mForServer; // maybe null, for client sessions
sp<WaitForShutdownListener> mShutdownListener; // used for client sessions
wp<EventListener> mEventListener; // mForServer if server, mShutdownListener if client
// session-specific root object (if a different root is used for each
// session)
sp<IBinder> mSessionSpecificRootObject;
std::vector<uint8_t> mId;
std::unique_ptr<FdTrigger> mShutdownTrigger;
std::unique_ptr<RpcState> mRpcBinderState;
RpcMutex mMutex; // for all below
bool mStartedSetup = false;
size_t mMaxIncomingThreads = 0;
size_t mMaxOutgoingConnections = kDefaultMaxOutgoingConnections;
std::optional<uint32_t> mProtocolVersion;
FileDescriptorTransportMode mFileDescriptorTransportMode = FileDescriptorTransportMode::NONE;
RpcConditionVariable mAvailableConnectionCv; // for mWaitingThreads
std::unique_ptr<RpcTransport> mBootstrapTransport;
struct ThreadState {
size_t mWaitingThreads = 0;
// hint index into clients, ++ when sending an async transaction
size_t mOutgoingOffset = 0;
std::vector<sp<RpcConnection>> mOutgoing;
// max size of mIncoming. Once any thread starts down, no more can be started.
size_t mMaxIncoming = 0;
std::vector<sp<RpcConnection>> mIncoming;
std::map<RpcMaybeThread::id, RpcMaybeThread> mThreads;
} mConnections;
};
} // namespace android
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <pthread.h>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <binder/Common.h>
namespace android {
#ifdef BINDER_RPC_SINGLE_THREADED
class LIBBINDER_EXPORTED RpcMutex {
public:
void lock() {}
void unlock() {}
};
class LIBBINDER_EXPORTED RpcMutexUniqueLock {
public:
RpcMutexUniqueLock(RpcMutex&) {}
void unlock() {}
};
class LIBBINDER_EXPORTED RpcMutexLockGuard {
public:
RpcMutexLockGuard(RpcMutex&) {}
};
class LIBBINDER_EXPORTED RpcConditionVariable {
public:
void notify_one() {}
void notify_all() {}
void wait(RpcMutexUniqueLock&) {}
template <typename Predicate>
void wait(RpcMutexUniqueLock&, Predicate stop_waiting) {
LOG_ALWAYS_FATAL_IF(!stop_waiting(), "RpcConditionVariable::wait condition not met");
}
template <typename Duration>
std::cv_status wait_for(RpcMutexUniqueLock&, const Duration&) {
return std::cv_status::no_timeout;
}
template <typename Duration, typename Predicate>
bool wait_for(RpcMutexUniqueLock&, const Duration&, Predicate stop_waiting) {
return stop_waiting();
}
};
class LIBBINDER_EXPORTED RpcMaybeThread {
public:
RpcMaybeThread() = default;
template <typename Function, typename... Args>
RpcMaybeThread(Function&& f, Args&&... args) {
// std::function requires a copy-constructible closure,
// so we need to wrap both the function and its arguments
// in a shared pointer that std::function can copy internally
struct Vars {
std::decay_t<Function> f;
std::tuple<std::decay_t<Args>...> args;
explicit Vars(Function&& f, Args&&... args)
: f(std::move(f)), args(std::move(args)...) {}
};
auto vars = std::make_shared<Vars>(std::forward<Function>(f), std::forward<Args>(args)...);
mFunc = [vars]() { std::apply(std::move(vars->f), std::move(vars->args)); };
}
void join() {
if (mFunc) {
// Move mFunc into a temporary so we can clear mFunc before
// executing the callback. This avoids infinite recursion if
// the callee then calls join() again directly or indirectly.
decltype(mFunc) func = nullptr;
mFunc.swap(func);
func();
}
}
void detach() { join(); }
class id {
public:
bool operator==(const id&) const { return true; }
bool operator!=(const id&) const { return false; }
bool operator<(const id&) const { return false; }
bool operator<=(const id&) const { return true; }
bool operator>(const id&) const { return false; }
bool operator>=(const id&) const { return true; }
};
id get_id() const { return id(); }
private:
std::function<void(void)> mFunc;
};
namespace rpc_this_thread {
static inline RpcMaybeThread::id get_id() {
return RpcMaybeThread::id();
}
} // namespace rpc_this_thread
static inline void rpcJoinIfSingleThreaded(RpcMaybeThread& t) {
t.join();
}
#else // BINDER_RPC_SINGLE_THREADED
using RpcMutex = std::mutex;
using RpcMutexUniqueLock = std::unique_lock<std::mutex>;
using RpcMutexLockGuard = std::lock_guard<std::mutex>;
using RpcConditionVariable = std::condition_variable;
using RpcMaybeThread = std::thread;
namespace rpc_this_thread = std::this_thread;
static inline void rpcJoinIfSingleThreaded(RpcMaybeThread&) {}
#endif // BINDER_RPC_SINGLE_THREADED
} // namespace android
@@ -0,0 +1,207 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Wraps the transport layer of RPC. Implementation may use plain sockets or TLS.
#pragma once
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <variant>
#include <vector>
#include <utils/Errors.h>
#include <binder/Common.h>
#include <binder/Functional.h>
#include <binder/RpcCertificateFormat.h>
#include <binder/RpcThreads.h>
#include <binder/unique_fd.h>
#include <sys/uio.h>
namespace android {
class FdTrigger;
struct RpcTransportFd;
// for 'friend'
class RpcTransportRaw;
class RpcTransportTls;
class RpcTransportTipcAndroid;
class RpcTransportTipcTrusty;
class RpcTransportCtxRaw;
class RpcTransportCtxTls;
class RpcTransportCtxTipcAndroid;
class RpcTransportCtxTipcTrusty;
// Represents a socket connection.
// No thread-safety is guaranteed for these APIs.
class LIBBINDER_EXPORTED RpcTransport {
public:
virtual ~RpcTransport() = default;
/**
* Poll the transport to check whether there is any data ready to read.
*
* Return:
* OK - There is data available on this transport
* WOULDBLOCK - No data is available
* error - any other error
*/
[[nodiscard]] virtual status_t pollRead(void) = 0;
/**
* Read (or write), but allow to be interrupted by a trigger.
*
* iovs - array of iovecs to perform the operation on. The elements
* of the array may be modified by this method.
*
* altPoll - function to be called instead of polling, when needing to wait
* to read/write data. If this returns an error, that error is returned from
* this function.
*
* ancillaryFds - FDs to be sent via UNIX domain dockets or Trusty IPC. When
* reading, if `ancillaryFds` is null, any received FDs will be silently
* dropped and closed (by the OS). Appended values will always be unique_fd,
* the variant type is used to avoid extra copies elsewhere.
*
* Return:
* OK - succeeded in completely processing 'size'
* error - interrupted (failure or trigger)
*/
[[nodiscard]] virtual status_t interruptableWriteFully(
FdTrigger* fdTrigger, iovec* iovs, int niovs,
const std::optional<binder::impl::SmallFunction<status_t()>>& altPoll,
const std::vector<std::variant<binder::unique_fd, binder::borrowed_fd>>*
ancillaryFds) = 0;
[[nodiscard]] virtual status_t interruptableReadFully(
FdTrigger* fdTrigger, iovec* iovs, int niovs,
const std::optional<binder::impl::SmallFunction<status_t()>>& altPoll,
std::vector<std::variant<binder::unique_fd, binder::borrowed_fd>>* ancillaryFds) = 0;
/**
* Check whether any threads are blocked while polling the transport
* for read operations
* Return:
* True - Specifies that there is active polling on transport.
* False - No active polling on transport
*/
[[nodiscard]] virtual bool isWaiting() = 0;
private:
// limit the classes which can implement RpcTransport. Being able to change this
// interface is important to allow development of RPC binder. In the past, we
// changed this interface to use iovec for efficiency, and we added FDs to the
// interface. If another transport is needed, it should be added directly here.
// non-socket FDs likely also need changes in RpcSession in order to get
// connected, and similarly to how addrinfo was type-erased from RPC binder
// interfaces when RpcTransportTipc* was added, other changes may be needed
// to add more transports.
friend class ::android::RpcTransportRaw;
friend class ::android::RpcTransportTls;
friend class ::android::RpcTransportTipcAndroid;
friend class ::android::RpcTransportTipcTrusty;
RpcTransport() = default;
};
// Represents the context that generates the socket connection.
// All APIs are thread-safe. See RpcTransportCtxRaw and RpcTransportCtxTls for details.
class LIBBINDER_EXPORTED RpcTransportCtx {
public:
virtual ~RpcTransportCtx() = default;
// Create a new RpcTransport object.
//
// Implementation details: for TLS, this function may incur I/O. |fdTrigger| may be used
// to interrupt I/O. This function blocks until handshake is finished.
[[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport(
android::RpcTransportFd fd, FdTrigger *fdTrigger) const = 0;
// Return the preconfigured certificate of this context.
//
// Implementation details:
// - For raw sockets, this always returns empty string.
// - For TLS, this returns the certificate. See RpcTransportTls for details.
[[nodiscard]] virtual std::vector<uint8_t> getCertificate(
RpcCertificateFormat format) const = 0;
private:
// see comment on RpcTransport
friend class ::android::RpcTransportCtxRaw;
friend class ::android::RpcTransportCtxTls;
friend class ::android::RpcTransportCtxTipcAndroid;
friend class ::android::RpcTransportCtxTipcTrusty;
RpcTransportCtx() = default;
};
// A factory class that generates RpcTransportCtx.
// All APIs are thread-safe.
class LIBBINDER_EXPORTED RpcTransportCtxFactory {
public:
virtual ~RpcTransportCtxFactory() = default;
// Creates server context.
[[nodiscard]] virtual std::unique_ptr<RpcTransportCtx> newServerCtx() const = 0;
// Creates client context.
[[nodiscard]] virtual std::unique_ptr<RpcTransportCtx> newClientCtx() const = 0;
// Return a short description of this transport (e.g. "raw"). For logging / debugging / testing
// only.
[[nodiscard]] virtual const char *toCString() const = 0;
protected:
RpcTransportCtxFactory() = default;
};
struct LIBBINDER_EXPORTED RpcTransportFd final {
private:
mutable bool isPolling{false};
void setPollingState(bool state) const { isPolling = state; }
public:
binder::unique_fd fd;
RpcTransportFd() = default;
explicit RpcTransportFd(binder::unique_fd&& descriptor)
: isPolling(false), fd(std::move(descriptor)) {}
RpcTransportFd(RpcTransportFd &&transportFd) noexcept
: isPolling(transportFd.isPolling), fd(std::move(transportFd.fd)) {}
RpcTransportFd &operator=(RpcTransportFd &&transportFd) noexcept {
fd = std::move(transportFd.fd);
isPolling = transportFd.isPolling;
return *this;
}
RpcTransportFd& operator=(binder::unique_fd&& descriptor) noexcept {
fd = std::move(descriptor);
isPolling = false;
return *this;
}
bool isInPollingState() const { return isPolling; }
friend class FdTrigger;
};
} // namespace android
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Wraps the transport layer of RPC. Implementation uses plain sockets.
// Note: don't use directly. You probably want newServerRpcTransportCtx / newClientRpcTransportCtx.
#pragma once
#include <memory>
#include <binder/Common.h>
#include <binder/RpcTransport.h>
namespace android {
// RpcTransportCtxFactory with TLS disabled.
class RpcTransportCtxFactoryRaw : public RpcTransportCtxFactory {
public:
LIBBINDER_EXPORTED static std::unique_ptr<RpcTransportCtxFactory> make();
LIBBINDER_EXPORTED std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
LIBBINDER_EXPORTED std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
LIBBINDER_EXPORTED const char* toCString() const override;
private:
RpcTransportCtxFactoryRaw() = default;
};
} // namespace android
@@ -0,0 +1,726 @@
/*
* Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
// Set to 1 to enable CallStacks when logging errors
#define SI_DUMP_CALLSTACKS 0
#if SI_DUMP_CALLSTACKS
#include <utils/CallStack.h>
#endif
#include <utils/NativeHandle.h>
#include <functional>
#include <type_traits>
namespace android {
namespace SafeInterface {
/**
* WARNING: Prefer to use AIDL-generated interfaces. Using SafeInterface to generate interfaces
* does not support tracing, and many other AIDL features out of the box. The general direction
* we should go is to migrate safe interface users to AIDL and then remove this so that there
* is only one thing to learn/use/test/integrate, not this as well.
*/
// ParcelHandler is responsible for writing/reading various types to/from a Parcel in a generic way
class LIBBINDER_EXPORTED ParcelHandler {
public:
explicit ParcelHandler(const char* logTag) : mLogTag(logTag) {}
// Specializations for types with dedicated handling in Parcel
status_t read(const Parcel& parcel, bool* b) const {
return callParcel("readBool", [&]() { return parcel.readBool(b); });
}
status_t write(Parcel* parcel, bool b) const {
return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
}
template <typename E>
typename std::enable_if<std::is_enum<E>::value, status_t>::type read(const Parcel& parcel,
E* e) const {
typename std::underlying_type<E>::type u{};
status_t result = read(parcel, &u);
*e = static_cast<E>(u);
return result;
}
template <typename E>
typename std::enable_if<std::is_enum<E>::value, status_t>::type write(Parcel* parcel,
E e) const {
return write(parcel, static_cast<typename std::underlying_type<E>::type>(e));
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("read(Flattenable)", [&]() { return parcel.read(*t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
Parcel* parcel, const T& t) const {
return callParcel("write(Flattenable)", [&]() { return parcel->write(t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, sp<T>* t) const {
*t = new T{};
return callParcel("read(sp<Flattenable>)", [&]() { return parcel.read(*(t->get())); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& t) const {
return callParcel("write(sp<Flattenable>)", [&]() { return parcel->write(*(t.get())); });
}
template <typename T>
typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type write(
Parcel* parcel, const T& t) const {
return callParcel("write(LightFlattenable)", [&]() { return parcel->write(t); });
}
template <typename NH>
typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type read(
const Parcel& parcel, NH* nh) {
*nh = NativeHandle::create(parcel.readNativeHandle(), true);
return NO_ERROR;
}
template <typename NH>
typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type write(
Parcel* parcel, const NH& nh) {
return callParcel("write(sp<NativeHandle>)",
[&]() { return parcel->writeNativeHandle(nh->handle()); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("readParcelable", [&]() { return parcel.readParcelable(t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
Parcel* parcel, const T& t) const {
return callParcel("writeParcelable", [&]() { return parcel->writeParcelable(t); });
}
status_t read(const Parcel& parcel, String8* str) const {
return callParcel("readString8", [&]() { return parcel.readString8(str); });
}
status_t write(Parcel* parcel, const String8& str) const {
return callParcel("writeString8", [&]() { return parcel->writeString8(str); });
}
template <typename T>
typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type read(
const Parcel& parcel, sp<T>* pointer) const {
return callParcel("readNullableStrongBinder",
[&]() { return parcel.readNullableStrongBinder(pointer); });
}
template <typename T>
typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& pointer) const {
return callParcel("writeStrongBinder",
[&]() { return parcel->writeStrongBinder(pointer); });
}
template <typename T>
typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type read(
const Parcel& parcel, sp<T>* pointer) const {
return callParcel("readNullableStrongBinder[IInterface]",
[&]() { return parcel.readNullableStrongBinder(pointer); });
}
template <typename T>
typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& interface) const {
return write(parcel, IInterface::asBinder(interface));
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
const Parcel& parcel, std::vector<T>* v) const {
return callParcel("readParcelableVector", [&]() { return parcel.readParcelableVector(v); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
Parcel* parcel, const std::vector<T>& v) const {
return callParcel("writeParcelableVector",
[&]() { return parcel->writeParcelableVector(v); });
}
status_t read(const Parcel& parcel, std::vector<bool>* v) const {
return callParcel("readBoolVector", [&]() { return parcel.readBoolVector(v); });
}
status_t write(Parcel* parcel, const std::vector<bool>& v) const {
return callParcel("writeBoolVector", [&]() { return parcel->writeBoolVector(v); });
}
status_t read(const Parcel& parcel, float* f) const {
return callParcel("readFloat", [&]() { return parcel.readFloat(f); });
}
status_t write(Parcel* parcel, float f) const {
return callParcel("writeFloat", [&]() { return parcel->writeFloat(f); });
}
// Templates to handle integral types. We use a struct template to require that the called
// function exactly matches the signedness and size of the argument (e.g., the argument isn't
// silently widened).
template <bool isSigned, size_t size, typename I>
struct HandleInt;
template <typename I>
struct HandleInt<true, 4, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readInt32", [&]() { return parcel.readInt32(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeInt32", [&]() { return parcel->writeInt32(i); });
}
};
template <typename I>
struct HandleInt<false, 4, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readUint32", [&]() { return parcel.readUint32(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeUint32", [&]() { return parcel->writeUint32(i); });
}
};
template <typename I>
struct HandleInt<true, 8, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readInt64", [&]() { return parcel.readInt64(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeInt64", [&]() { return parcel->writeInt64(i); });
}
};
template <typename I>
struct HandleInt<false, 8, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readUint64", [&]() { return parcel.readUint64(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeUint64", [&]() { return parcel->writeUint64(i); });
}
};
template <typename I>
typename std::enable_if<std::is_integral<I>::value, status_t>::type read(const Parcel& parcel,
I* i) const {
return HandleInt<std::is_signed<I>::value, sizeof(I), I>::read(*this, parcel, i);
}
template <typename I>
typename std::enable_if<std::is_integral<I>::value, status_t>::type write(Parcel* parcel,
I i) const {
return HandleInt<std::is_signed<I>::value, sizeof(I), I>::write(*this, parcel, i);
}
private:
const char* const mLogTag;
// Helper to encapsulate error handling while calling the various Parcel methods
template <typename Function>
status_t callParcel(const char* name, Function f) const {
status_t error = f();
if (error != NO_ERROR) [[unlikely]] {
ALOG(LOG_ERROR, mLogTag, "Failed to %s, (%d: %s)", name, error, strerror(-error));
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
}
return error;
}
};
// Utility struct template which allows us to retrieve the types of the parameters of a member
// function pointer
template <typename T>
struct ParamExtractor;
template <typename Class, typename Return, typename... Params>
struct ParamExtractor<Return (Class::*)(Params...)> {
using ParamTuple = std::tuple<Params...>;
};
template <typename Class, typename Return, typename... Params>
struct ParamExtractor<Return (Class::*)(Params...) const> {
using ParamTuple = std::tuple<Params...>;
};
} // namespace SafeInterface
template <typename Interface>
class LIBBINDER_EXPORTED SafeBpInterface : public BpInterface<Interface> {
protected:
SafeBpInterface(const sp<IBinder>& impl, const char* logTag)
: BpInterface<Interface>(impl), mLogTag(logTag) {}
~SafeBpInterface() override = default;
// callRemote is used to invoke a synchronous procedure call over Binder
template <typename Method, typename TagType, typename... Args>
status_t callRemote(TagType tag, Args&&... args) const {
static_assert(sizeof(TagType) <= sizeof(uint32_t), "Tag must fit inside uint32_t");
// Verify that the arguments are compatible with the parameters
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
static_assert(ArgsMatchParams<std::tuple<Args...>, ParamTuple>::value,
"Invalid argument type");
// Write the input arguments to the data Parcel
Parcel data;
data.writeInterfaceToken(this->getInterfaceDescriptor());
status_t error = writeInputs(&data, std::forward<Args>(args)...);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by writeInputs
return error;
}
// Send the data Parcel to the remote and retrieve the reply parcel
Parcel reply;
error = this->remote()->transact(static_cast<uint32_t>(tag), data, &reply);
if (error != NO_ERROR) [[unlikely]] {
ALOG(LOG_ERROR, mLogTag, "Failed to transact (%d)", error);
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
return error;
}
// Read the outputs from the reply Parcel into the output arguments
error = readOutputs(reply, std::forward<Args>(args)...);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by readOutputs
return error;
}
// Retrieve the result code from the reply Parcel
status_t result = NO_ERROR;
error = reply.readInt32(&result);
if (error != NO_ERROR) [[unlikely]] {
ALOG(LOG_ERROR, mLogTag, "Failed to obtain result");
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
return error;
}
return result;
}
// callRemoteAsync is used to invoke an asynchronous procedure call over Binder
template <typename Method, typename TagType, typename... Args>
void callRemoteAsync(TagType tag, Args&&... args) const {
static_assert(sizeof(TagType) <= sizeof(uint32_t), "Tag must fit inside uint32_t");
// Verify that the arguments are compatible with the parameters
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
static_assert(ArgsMatchParams<std::tuple<Args...>, ParamTuple>::value,
"Invalid argument type");
// Write the input arguments to the data Parcel
Parcel data;
data.writeInterfaceToken(this->getInterfaceDescriptor());
status_t error = writeInputs(&data, std::forward<Args>(args)...);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by writeInputs
return;
}
// There will be no data in the reply Parcel since the call is one-way
Parcel reply;
error = this->remote()->transact(static_cast<uint32_t>(tag), data, &reply,
IBinder::FLAG_ONEWAY);
if (error != NO_ERROR) [[unlikely]] {
ALOG(LOG_ERROR, mLogTag, "Failed to transact (%d)", error);
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
}
}
private:
const char* const mLogTag;
// This struct provides information on whether the decayed types of the elements at Index in the
// tuple types T and U (that is, the types after stripping cv-qualifiers, removing references,
// and a few other less common operations) are the same
template <size_t Index, typename T, typename U>
struct DecayedElementsMatch {
private:
using FirstT = typename std::tuple_element<Index, T>::type;
using DecayedT = typename std::decay<FirstT>::type;
using FirstU = typename std::tuple_element<Index, U>::type;
using DecayedU = typename std::decay<FirstU>::type;
public:
static constexpr bool value = std::is_same<DecayedT, DecayedU>::value;
};
// When comparing whether the argument types match the parameter types, we first decay them (see
// DecayedElementsMatch) to avoid falsely flagging, say, T&& against T even though they are
// equivalent enough for our purposes
template <typename T, typename U>
struct ArgsMatchParams {};
template <typename... Args, typename... Params>
struct ArgsMatchParams<std::tuple<Args...>, std::tuple<Params...>> {
static_assert(sizeof...(Args) <= sizeof...(Params), "Too many arguments");
static_assert(sizeof...(Args) >= sizeof...(Params), "Not enough arguments");
private:
template <size_t Index>
static constexpr typename std::enable_if<(Index < sizeof...(Args)), bool>::type
elementsMatch() {
if (!DecayedElementsMatch<Index, std::tuple<Args...>, std::tuple<Params...>>::value) {
return false;
}
return elementsMatch<Index + 1>();
}
template <size_t Index>
static constexpr typename std::enable_if<(Index >= sizeof...(Args)), bool>::type
elementsMatch() {
return true;
}
public:
static constexpr bool value = elementsMatch<0>();
};
// Since we assume that pointer arguments are outputs, we can use this template struct to
// determine whether or not a given argument is fundamentally a pointer type and thus an output
template <typename T>
struct IsPointerIfDecayed {
private:
using Decayed = typename std::decay<T>::type;
public:
static constexpr bool value = std::is_pointer<Decayed>::value;
};
template <typename T>
typename std::enable_if<!IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
Parcel* data, T&& t) const {
return SafeInterface::ParcelHandler{mLogTag}.write(data, std::forward<T>(t));
}
template <typename T>
typename std::enable_if<IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
Parcel* /*data*/, T&& /*t*/) const {
return NO_ERROR;
}
// This method iterates through all of the arguments, writing them to the data Parcel if they
// are an input (i.e., if they are not a pointer type)
template <typename T, typename... Remaining>
status_t writeInputs(Parcel* data, T&& t, Remaining&&... remaining) const {
status_t error = writeIfInput(data, std::forward<T>(t));
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by writeIfInput
return error;
}
return writeInputs(data, std::forward<Remaining>(remaining)...);
}
static status_t writeInputs(Parcel* /*data*/) { return NO_ERROR; }
template <typename T>
typename std::enable_if<IsPointerIfDecayed<T>::value, status_t>::type readIfOutput(
const Parcel& reply, T&& t) const {
return SafeInterface::ParcelHandler{mLogTag}.read(reply, std::forward<T>(t));
}
template <typename T>
static typename std::enable_if<!IsPointerIfDecayed<T>::value, status_t>::type readIfOutput(
const Parcel& /*reply*/, T&& /*t*/) {
return NO_ERROR;
}
// Similar to writeInputs except that it reads output arguments from the reply Parcel
template <typename T, typename... Remaining>
status_t readOutputs(const Parcel& reply, T&& t, Remaining&&... remaining) const {
status_t error = readIfOutput(reply, std::forward<T>(t));
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by readIfOutput
return error;
}
return readOutputs(reply, std::forward<Remaining>(remaining)...);
}
static status_t readOutputs(const Parcel& /*data*/) { return NO_ERROR; }
};
template <typename Interface>
class LIBBINDER_EXPORTED SafeBnInterface : public BnInterface<Interface> {
public:
explicit SafeBnInterface(const char* logTag) : mLogTag(logTag) {}
protected:
template <typename Method>
status_t callLocal(const Parcel& data, Parcel* reply, Method method) {
CHECK_INTERFACE(this, data, reply);
// Since we need to both pass inputs into the call as well as retrieve outputs, we create a
// "raw" tuple, where the inputs are interleaved with actual, non-pointer versions of the
// outputs. When we ultimately call into the method, we will pass the addresses of the
// output arguments instead of their tuple members directly, but the storage will live in
// the tuple.
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
typename RawConverter<std::tuple<>, ParamTuple>::type rawArgs{};
// Read the inputs from the data Parcel into the argument tuple
status_t error = InputReader<ParamTuple>{mLogTag}.readInputs(data, &rawArgs);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by read
return error;
}
// Call the local method
status_t result = MethodCaller<ParamTuple>::call(this, method, &rawArgs);
// Extract the outputs from the argument tuple and write them into the reply Parcel
error = OutputWriter<ParamTuple>{mLogTag}.writeOutputs(reply, &rawArgs);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by write
return error;
}
// Return the result code in the reply Parcel
error = reply->writeInt32(result);
if (error != NO_ERROR) [[unlikely]] {
ALOG(LOG_ERROR, mLogTag, "Failed to write result");
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
return error;
}
return NO_ERROR;
}
template <typename Method>
status_t callLocalAsync(const Parcel& data, Parcel* /*reply*/, Method method) {
// reply is not actually used by CHECK_INTERFACE
CHECK_INTERFACE(this, data, reply);
// Since we need to both pass inputs into the call as well as retrieve outputs, we create a
// "raw" tuple, where the inputs are interleaved with actual, non-pointer versions of the
// outputs. When we ultimately call into the method, we will pass the addresses of the
// output arguments instead of their tuple members directly, but the storage will live in
// the tuple.
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
typename RawConverter<std::tuple<>, ParamTuple>::type rawArgs{};
// Read the inputs from the data Parcel into the argument tuple
status_t error = InputReader<ParamTuple>{mLogTag}.readInputs(data, &rawArgs);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged by read
return error;
}
// Call the local method
MethodCaller<ParamTuple>::callVoid(this, method, &rawArgs);
// After calling, there is nothing more to do since asynchronous calls do not return a value
// to the caller
return NO_ERROR;
}
private:
const char* const mLogTag;
// RemoveFirst strips the first element from a tuple.
// For example, given T = std::tuple<A, B, C>, RemoveFirst<T>::type = std::tuple<B, C>
template <typename T, typename... Args>
struct RemoveFirst;
template <typename T, typename... Args>
struct RemoveFirst<std::tuple<T, Args...>> {
using type = std::tuple<Args...>;
};
// RawConverter strips a tuple down to its fundamental types, discarding both pointers and
// references. This allows us to allocate storage for both input (non-pointer) arguments and
// output (pointer) arguments in one tuple.
// For example, given T = std::tuple<const A&, B*>, RawConverter<T>::type = std::tuple<A, B>
template <typename Unconverted, typename... Converted>
struct RawConverter;
template <typename Unconverted, typename... Converted>
struct RawConverter<std::tuple<Converted...>, Unconverted> {
private:
using ElementType = typename std::tuple_element<0, Unconverted>::type;
using Decayed = typename std::decay<ElementType>::type;
using WithoutPointer = typename std::remove_pointer<Decayed>::type;
public:
using type = typename RawConverter<std::tuple<Converted..., WithoutPointer>,
typename RemoveFirst<Unconverted>::type>::type;
};
template <typename... Converted>
struct RawConverter<std::tuple<Converted...>, std::tuple<>> {
using type = std::tuple<Converted...>;
};
// This provides a simple way to determine whether the indexed element of Args... is a pointer
template <size_t I, typename... Args>
struct ElementIsPointer {
private:
using ElementType = typename std::tuple_element<I, std::tuple<Args...>>::type;
public:
static constexpr bool value = std::is_pointer<ElementType>::value;
};
// This class iterates over the parameter types, and if a given parameter is an input
// (i.e., is not a pointer), reads the corresponding argument tuple element from the data Parcel
template <typename... Params>
class InputReader;
template <typename... Params>
class InputReader<std::tuple<Params...>> {
public:
explicit InputReader(const char* logTag) : mLogTag(logTag) {}
// Note that in this case (as opposed to in SafeBpInterface), we iterate using an explicit
// index (starting with 0 here) instead of using recursion and stripping the first element.
// This is because in SafeBpInterface we aren't actually operating on a real tuple, but are
// instead just using a tuple as a convenient container for variadic types, whereas here we
// can't modify the argument tuple without causing unnecessary copies or moves of the data
// contained therein.
template <typename RawTuple>
status_t readInputs(const Parcel& data, RawTuple* args) {
return dispatchArg<0>(data, args);
}
private:
const char* const mLogTag;
template <std::size_t I, typename RawTuple>
typename std::enable_if<!ElementIsPointer<I, Params...>::value, status_t>::type readIfInput(
const Parcel& data, RawTuple* args) {
return SafeInterface::ParcelHandler{mLogTag}.read(data, &std::get<I>(*args));
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<ElementIsPointer<I, Params...>::value, status_t>::type readIfInput(
const Parcel& /*data*/, RawTuple* /*args*/) {
return NO_ERROR;
}
// Recursively iterate through the arguments
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I < sizeof...(Params)), status_t>::type dispatchArg(
const Parcel& data, RawTuple* args) {
status_t error = readIfInput<I>(data, args);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged in read
return error;
}
return dispatchArg<I + 1>(data, args);
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I >= sizeof...(Params)), status_t>::type dispatchArg(
const Parcel& /*data*/, RawTuple* /*args*/) {
return NO_ERROR;
}
};
// getForCall uses the types of the parameters to determine whether a given element of the
// argument tuple is an input, which should be passed directly into the call, or an output, for
// which its address should be passed into the call
template <size_t I, typename RawTuple, typename... Params>
static typename std::enable_if<
ElementIsPointer<I, Params...>::value,
typename std::tuple_element<I, std::tuple<Params...>>::type>::type
getForCall(RawTuple* args) {
return &std::get<I>(*args);
}
template <size_t I, typename RawTuple, typename... Params>
static typename std::enable_if<
!ElementIsPointer<I, Params...>::value,
typename std::tuple_element<I, std::tuple<Params...>>::type>::type&
getForCall(RawTuple* args) {
return std::get<I>(*args);
}
// This template class uses std::index_sequence and parameter pack expansion to call the given
// method using the elements of the argument tuple (after those arguments are passed through
// getForCall to get addresses instead of values for output arguments)
template <typename... Params>
struct MethodCaller;
template <typename... Params>
struct MethodCaller<std::tuple<Params...>> {
public:
// The calls through these to the helper methods are necessary to generate the
// std::index_sequences used to unpack the argument tuple into the method call
template <typename Class, typename MemberFunction, typename RawTuple>
static status_t call(Class* instance, MemberFunction function, RawTuple* args) {
return callHelper(instance, function, args, std::index_sequence_for<Params...>{});
}
template <typename Class, typename MemberFunction, typename RawTuple>
static void callVoid(Class* instance, MemberFunction function, RawTuple* args) {
callVoidHelper(instance, function, args, std::index_sequence_for<Params...>{});
}
private:
template <typename Class, typename MemberFunction, typename RawTuple, std::size_t... I>
static status_t callHelper(Class* instance, MemberFunction function, RawTuple* args,
std::index_sequence<I...> /*unused*/) {
return (instance->*function)(getForCall<I, RawTuple, Params...>(args)...);
}
template <typename Class, typename MemberFunction, typename RawTuple, std::size_t... I>
static void callVoidHelper(Class* instance, MemberFunction function, RawTuple* args,
std::index_sequence<I...> /*unused*/) {
(instance->*function)(getForCall<I, RawTuple, Params...>(args)...);
}
};
// This class iterates over the parameter types, and if a given parameter is an output
// (i.e., is a pointer), writes the corresponding argument tuple element into the reply Parcel
template <typename... Params>
struct OutputWriter;
template <typename... Params>
struct OutputWriter<std::tuple<Params...>> {
public:
explicit OutputWriter(const char* logTag) : mLogTag(logTag) {}
// See the note on InputReader::readInputs for why this differs from the arguably simpler
// RemoveFirst approach in SafeBpInterface
template <typename RawTuple>
status_t writeOutputs(Parcel* reply, RawTuple* args) {
return dispatchArg<0>(reply, args);
}
private:
const char* const mLogTag;
template <std::size_t I, typename RawTuple>
typename std::enable_if<ElementIsPointer<I, Params...>::value, status_t>::type
writeIfOutput(Parcel* reply, RawTuple* args) {
return SafeInterface::ParcelHandler{mLogTag}.write(reply, std::get<I>(*args));
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<!ElementIsPointer<I, Params...>::value, status_t>::type
writeIfOutput(Parcel* /*reply*/, RawTuple* /*args*/) {
return NO_ERROR;
}
// Recursively iterate through the arguments
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I < sizeof...(Params)), status_t>::type dispatchArg(
Parcel* reply, RawTuple* args) {
status_t error = writeIfOutput<I>(reply, args);
if (error != NO_ERROR) [[unlikely]] {
// A message will have been logged in read
return error;
}
return dispatchArg<I + 1>(reply, args);
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I >= sizeof...(Params)), status_t>::type dispatchArg(
Parcel* /*reply*/, RawTuple* /*args*/) {
return NO_ERROR;
}
};
};
} // namespace android
@@ -0,0 +1,176 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <binder/IBinder.h>
#include <string>
class BinderStabilityIntegrationTest_ExpectedStabilityForItsPartition_Test;
namespace android {
class BpBinder;
class ProcessState;
namespace internal {
// Stability encodes how a binder changes over time. There are two levels of
// stability:
// 1). the interface stability - this is how a particular set of API calls (a
// particular ordering of things like writeInt32/readInt32) are changed over
// time. If one release, we have 'writeInt32' and the next release, we have
// 'writeInt64', then this interface doesn't have a very stable
// Stability::Level. Usually this ordering is controlled by a .aidl file.
// 2). the wire format stability - this is how these API calls map to actual
// bytes that are written to the wire (literally, this is how they are written
// to the kernel inside of IBinder::transact, but it may be expanded to other
// wires in the future). For instance, writeInt32 in binder translates to
// writing a 4-byte little-endian integer in two's complement. You can imagine
// in the future, we change writeInt32/readInt32 to instead write 8-bytes with
// that integer and some check bits. In this case, the wire format changes,
// but as long as a client libbinder knows to keep on writing a 4-byte value
// to old servers, and new servers know how to interpret the 8-byte result,
// they can still communicate.
//
// This class is specifically about (1). (2) is not currently tracked by
// libbinder for regular binder calls, and everything on the system uses the
// same copy of libbinder.
class Stability final {
public:
// Given a binder interface at a certain stability, there may be some
// requirements associated with that higher stability level. For instance, a
// VINTF stability binder is required to be in the VINTF manifest. This API
// can be called to use that same interface within the local partition.
LIBBINDER_EXPORTED static void forceDowngradeToLocalStability(const sp<IBinder>& binder);
// WARNING: Below APIs are only ever expected to be called by auto-generated code.
// Instead of calling them, you should set the stability of a .aidl interface
// WARNING: The only client of
// - forceDowngradeToSystemStability() and;
// - korceDowngradeToVendorStability()
// should be AIBinder_forceDowngradeToLocalStability().
//
// getLocalLevel() in libbinder returns Level::SYSTEM when called
// from libbinder_ndk (even on vendor partition). So we explicitly provide
// these methods for use by the NDK API:
// AIBinder_forceDowngradeToLocalStability().
//
// This allows correctly downgrading the binder's stability to either system/vendor,
// depending on the partition.
// Given a binder interface at a certain stability, there may be some
// requirements associated with that higher stability level. For instance, a
// VINTF stability binder is required to be in the VINTF manifest. This API
// can be called to use that same interface within the vendor partition.
LIBBINDER_EXPORTED static void forceDowngradeToVendorStability(const sp<IBinder>& binder);
// Given a binder interface at a certain stability, there may be some
// requirements associated with that higher stability level. For instance, a
// VINTF stability binder is required to be in the VINTF manifest. This API
// can be called to use that same interface within the system partition.
LIBBINDER_EXPORTED static void forceDowngradeToSystemStability(const sp<IBinder>& binder);
// WARNING: This is only ever expected to be called by auto-generated code. You likely want to
// change or modify the stability class of the interface you are using.
// This must be called as soon as the binder in question is constructed. No thread safety
// is provided.
// E.g. stability is according to libbinder compilation unit
LIBBINDER_EXPORTED static void markCompilationUnit(IBinder* binder);
// WARNING: This is only ever expected to be called by auto-generated code. You likely want to
// change or modify the stability class of the interface you are using.
// This must be called as soon as the binder in question is constructed. No thread safety
// is provided.
// E.g. stability is according to libbinder_ndk or Java SDK AND the interface
// expressed here is guaranteed to be stable for multiple years (Stable AIDL)
LIBBINDER_EXPORTED static void markVintf(IBinder* binder);
// WARNING: for debugging only
LIBBINDER_EXPORTED static std::string debugToString(const sp<IBinder>& binder);
// WARNING: This is only ever expected to be called by auto-generated code or tests.
// You likely want to change or modify the stability of the interface you are using.
// This must be called as soon as the binder in question is constructed. No thread safety
// is provided.
// E.g. stability is according to libbinder_ndk or Java SDK AND the interface
// expressed here is guaranteed to be stable for multiple years (Stable AIDL)
// If this is called when __ANDROID_VNDK__ is not defined, then it is UB and will likely
// break the device during GSI or other tests.
LIBBINDER_EXPORTED static void markVndk(IBinder* binder);
// Returns true if the binder needs to be declared in the VINTF manifest or
// else false if the binder is local to the current partition.
LIBBINDER_EXPORTED static bool requiresVintfDeclaration(const sp<IBinder>& binder);
private:
// Parcel needs to read/write stability level in an unstable format.
friend ::android::Parcel;
// only expose internal APIs inside of libbinder, for checking stability
friend ::android::BpBinder;
// so that it can mark the context object (only the root object doesn't go
// through Parcel)
friend ::android::ProcessState;
friend ::BinderStabilityIntegrationTest_ExpectedStabilityForItsPartition_Test;
static void tryMarkCompilationUnit(IBinder* binder);
// Currently, we use int16_t for Level so that it can fit in BBinder.
// However, on the wire, we have 4 bytes reserved for stability, so whenever
// we ingest a Level, we always accept an int32_t.
enum Level : int16_t {
UNDECLARED = 0,
VENDOR = 0b000011,
SYSTEM = 0b001100,
VINTF = 0b111111,
};
// returns the stability according to how this was built
static Level getLocalLevel();
// Downgrades binder stability to the specified level.
static void forceDowngradeToStability(const sp<IBinder>& binder, Level level);
enum {
REPR_NONE = 0,
REPR_LOG = 1,
REPR_ALLOW_DOWNGRADE = 2,
};
// applies stability to binder if stability level is known
__attribute__((warn_unused_result)) static status_t setRepr(IBinder* binder, int32_t setting,
uint32_t flags);
// get stability information as encoded on the wire
LIBBINDER_EXPORTED static int16_t getRepr(IBinder* binder);
// whether a transaction on binder is allowed, if the transaction
// is done from a context with a specific stability level
LIBBINDER_EXPORTED static bool check(int16_t provided, Level required);
static bool isDeclaredLevel(int32_t level);
static std::string levelString(int32_t level);
Stability();
};
} // namespace internal
} // namespace android
+177
View File
@@ -0,0 +1,177 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_BINDER_STATUS_H
#define ANDROID_BINDER_STATUS_H
#include <cstdint>
#include <sstream> // historical
#include <ostream>
#include <binder/Common.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <string>
namespace android {
namespace binder {
// An object similar in function to a status_t except that it understands
// how exceptions are encoded in the prefix of a Parcel. Used like:
//
// Parcel data;
// Parcel reply;
// status_t status;
// binder::Status remote_exception;
// if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
// (status = data.writeInt32(function_input)) != OK) {
// // We failed to write into the memory of our local parcel?
// }
// if ((status = remote()->transact(transaction, data, &reply)) != OK) {
// // Something has gone wrong in the binder driver or libbinder.
// }
// if ((status = remote_exception.readFromParcel(reply)) != OK) {
// // The remote didn't correctly write the exception header to the
// // reply.
// }
// if (!remote_exception.isOk()) {
// // The transaction went through correctly, but the remote reported an
// // exception during handling.
// }
//
class LIBBINDER_EXPORTED Status final {
public:
// Keep the exception codes in sync with android/os/Parcel.java.
enum Exception {
EX_NONE = 0,
EX_SECURITY = -1,
EX_BAD_PARCELABLE = -2,
EX_ILLEGAL_ARGUMENT = -3,
EX_NULL_POINTER = -4,
EX_ILLEGAL_STATE = -5,
EX_NETWORK_MAIN_THREAD = -6,
EX_UNSUPPORTED_OPERATION = -7,
EX_SERVICE_SPECIFIC = -8,
EX_PARCELABLE = -9,
// See android/os/Parcel.java. We need to handle this in native code.
EX_HAS_NOTED_APPOPS_REPLY_HEADER = -127,
// This is special and Java specific; see Parcel.java.
EX_HAS_REPLY_HEADER = -128,
// This is special, and indicates to C++ binder proxies that the
// transaction has failed at a low level.
EX_TRANSACTION_FAILED = -129,
};
// A more readable alias for the default constructor.
static Status ok();
// Authors should explicitly pick whether their integer is:
// - an exception code (EX_* above)
// - service specific error code
// - status_t
//
// Prefer a generic exception code when possible, then a service specific
// code, and finally a status_t for low level failures or legacy support.
// Exception codes and service specific errors map to nicer exceptions for
// Java clients.
static Status fromExceptionCode(int32_t exceptionCode);
static Status fromExceptionCode(int32_t exceptionCode,
const String8& message);
static Status fromExceptionCode(int32_t exceptionCode,
const char* message);
// warning: this is still considered an error if it is constructed with a
// zero value error code. Please use Status::ok() instead and avoid zero
// error codes
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const String8& message);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const char* message);
static Status fromStatusT(status_t status);
static std::string exceptionToString(status_t exceptionCode);
Status() = default;
~Status() = default;
// Status objects are copyable and contain just simple data.
Status(const Status& status) = default;
Status(Status&& status) = default;
Status& operator=(const Status& status) = default;
// Bear in mind that if the client or service is a Java endpoint, this
// is not the logic which will provide/interpret the data here.
status_t readFromParcel(const Parcel& parcel);
status_t writeToParcel(Parcel* parcel) const;
// Convenience API to replace a Parcel with a status value, w/o requiring
// calling multiple APIs (makes generated code smaller).
status_t writeOverParcel(Parcel* parcel) const;
// Set one of the pre-defined exception types defined above.
void setException(int32_t ex, const String8& message);
// Set a service specific exception with error code.
void setServiceSpecificError(int32_t errorCode, const String8& message);
// Setting a |status| != OK causes generated code to return |status|
// from Binder transactions, rather than writing an exception into the
// reply Parcel. This is the least preferable way of reporting errors.
void setFromStatusT(status_t status);
// Get information about an exception.
int32_t exceptionCode() const { return mException; }
const String8& exceptionMessage() const { return mMessage; }
status_t transactionError() const {
return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
}
int32_t serviceSpecificErrorCode() const {
return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0;
}
bool isOk() const { return mException == EX_NONE; }
// For logging.
String8 toString8() const;
private:
Status(int32_t exceptionCode, int32_t errorCode);
Status(int32_t exceptionCode, int32_t errorCode, const String8& message);
status_t skipUnusedHeader(const Parcel& parcel);
// If |mException| == EX_TRANSACTION_FAILED, generated code will return
// |mErrorCode| as the result of the transaction rather than write an
// exception to the reply parcel.
//
// Otherwise, we always write |mException| to the parcel.
// If |mException| != EX_NONE, we write |mMessage| as well.
// If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well.
int32_t mException = EX_NONE;
int32_t mErrorCode = 0;
String8 mMessage;
}; // class Status
static inline std::ostream& operator<< (std::ostream& o, const Status& s) {
return o << s.toString8();
}
} // namespace binder
} // namespace android
#endif // ANDROID_BINDER_STATUS_H
@@ -0,0 +1,205 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <stdint.h>
#include <string.h>
#include <sstream>
// ---------------------------------------------------------------------------
namespace android {
class LIBBINDER_EXPORTED TextOutput {
public:
TextOutput();
virtual ~TextOutput();
virtual status_t print(const char* txt, size_t len) = 0;
virtual void moveIndent(int delta) = 0;
class Bundle {
public:
inline explicit Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
inline ~Bundle() { mTO.popBundle(); }
private:
TextOutput& mTO;
};
virtual void pushBundle() = 0;
virtual void popBundle() = 0;
};
// ---------------------------------------------------------------------------
// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
// be allocated.
// Text output stream for printing to the log (via utils/Log.h).
extern LIBBINDER_EXPORTED TextOutput& alog;
// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
// be allocated.
// Text output stream for printing to stdout.
extern LIBBINDER_EXPORTED TextOutput& aout;
// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
// be allocated.
// Text output stream for printing to stderr.
extern LIBBINDER_EXPORTED TextOutput& aerr;
typedef TextOutput& (*TextOutputManipFunc)(TextOutput&);
TextOutput& endl(TextOutput& to);
TextOutput& indent(TextOutput& to);
TextOutput& dedent(TextOutput& to);
template<typename T>
TextOutput& operator<<(TextOutput& to, const T& val)
{
std::stringstream strbuf;
strbuf << val;
std::string str = strbuf.str();
to.print(str.c_str(), str.size());
return to;
}
LIBBINDER_EXPORTED TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func);
class LIBBINDER_EXPORTED TypeCode {
public:
inline explicit TypeCode(uint32_t code);
inline ~TypeCode();
inline uint32_t typeCode() const;
private:
uint32_t mCode;
};
LIBBINDER_EXPORTED std::ostream& operator<<(std::ostream& to, const TypeCode& val);
class LIBBINDER_EXPORTED HexDump {
public:
HexDump(const void *buf, size_t size, size_t bytesPerLine=16);
inline ~HexDump();
inline HexDump& setBytesPerLine(size_t bytesPerLine);
inline HexDump& setSingleLineCutoff(int32_t bytes);
inline HexDump& setAlignment(size_t alignment);
inline HexDump& setCArrayStyle(bool enabled);
inline const void* buffer() const;
inline size_t size() const;
inline size_t bytesPerLine() const;
inline int32_t singleLineCutoff() const;
inline size_t alignment() const;
inline bool carrayStyle() const;
private:
const void* mBuffer;
size_t mSize;
size_t mBytesPerLine;
int32_t mSingleLineCutoff;
size_t mAlignment;
bool mCArrayStyle;
};
LIBBINDER_EXPORTED std::ostream& operator<<(std::ostream& to, const HexDump& val);
inline TextOutput& operator<<(TextOutput& to,
decltype(std::endl<char,
std::char_traits<char>>)
/*val*/) {
endl(to);
return to;
}
inline TextOutput& operator<<(TextOutput& to, const char &c)
{
to.print(&c, 1);
return to;
}
inline TextOutput& operator<<(TextOutput& to, const bool &val)
{
if (val) to.print("true", 4);
else to.print("false", 5);
return to;
}
inline TextOutput& operator<<(TextOutput& to, const String16& val)
{
to << String8(val).c_str();
return to;
}
// ---------------------------------------------------------------------------
// No user servicable parts below.
inline TextOutput& endl(TextOutput& to)
{
to.print("\n", 1);
return to;
}
inline TextOutput& indent(TextOutput& to)
{
to.moveIndent(1);
return to;
}
inline TextOutput& dedent(TextOutput& to)
{
to.moveIndent(-1);
return to;
}
inline TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func)
{
return (*func)(to);
}
inline TypeCode::TypeCode(uint32_t code) : mCode(code) { }
inline TypeCode::~TypeCode() { }
inline uint32_t TypeCode::typeCode() const { return mCode; }
inline HexDump::~HexDump() { }
inline HexDump& HexDump::setBytesPerLine(size_t bytesPerLine) {
mBytesPerLine = bytesPerLine; return *this;
}
inline HexDump& HexDump::setSingleLineCutoff(int32_t bytes) {
mSingleLineCutoff = bytes; return *this;
}
inline HexDump& HexDump::setAlignment(size_t alignment) {
mAlignment = alignment; return *this;
}
inline HexDump& HexDump::setCArrayStyle(bool enabled) {
mCArrayStyle = enabled; return *this;
}
inline const void* HexDump::buffer() const { return mBuffer; }
inline size_t HexDump::size() const { return mSize; }
inline size_t HexDump::bytesPerLine() const { return mBytesPerLine; }
inline int32_t HexDump::singleLineCutoff() const { return mSingleLineCutoff; }
inline size_t HexDump::alignment() const { return mAlignment; }
inline bool HexDump::carrayStyle() const { return mCArrayStyle; }
// ---------------------------------------------------------------------------
} // namespace android
+59
View File
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#if __has_include(<cutils/trace.h>)
#include <cutils/trace.h>
#endif
#include <binder/Common.h>
#ifdef ATRACE_TAG_AIDL
#if ATRACE_TAG_AIDL != (1 << 24)
#error "Mismatched ATRACE_TAG_AIDL definitions"
#endif
#else
#define ATRACE_TAG_AIDL (1 << 24)
#endif
namespace android {
namespace binder {
// Forward declarations from internal OS.h
namespace os {
// Trampoline functions allowing generated aidls to trace binder transactions without depending on
// libcutils/libutils
void trace_begin(uint64_t tag, const char* name);
void trace_end(uint64_t tag);
void trace_int(uint64_t tag, const char* name, int32_t value);
uint64_t get_trace_enabled_tags();
} // namespace os
class LIBBINDER_EXPORTED ScopedTrace {
public:
inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) { os::trace_begin(mTag, name); }
inline ~ScopedTrace() { os::trace_end(mTag); }
private:
uint64_t mTag;
};
} // namespace binder
} // namespace android
@@ -0,0 +1,116 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <binder/Common.h>
#ifndef BINDER_NO_LIBBASE
#include <android-base/unique_fd.h>
namespace android::binder {
using android::base::borrowed_fd;
using android::base::unique_fd;
} // namespace android::binder
#else // BINDER_NO_LIBBASE
#include <errno.h>
#include <fcntl.h> // not needed for unique_fd, but a lot of users depend on open(3)
#include <unistd.h>
namespace android::binder {
// Container for a file descriptor that automatically closes the descriptor as
// it goes out of scope.
//
// unique_fd ufd(open("/some/path", "r"));
// if (!ufd.ok()) return error;
//
// // Do something useful with ufd.get(), possibly including early 'return'.
//
// return 0; // Descriptor is closed for you.
//
class LIBBINDER_EXPORTED unique_fd final {
public:
unique_fd() {}
explicit unique_fd(int fd) { reset(fd); }
~unique_fd() { reset(); }
unique_fd(const unique_fd&) = delete;
void operator=(const unique_fd&) = delete;
unique_fd(unique_fd&& other) noexcept { reset(other.release()); }
unique_fd& operator=(unique_fd&& s) noexcept {
int fd = s.fd_;
s.fd_ = -1;
reset(fd);
return *this;
}
[[clang::reinitializes]] void reset(int new_value = -1) {
int previous_errno = errno;
if (fd_ != -1) {
::close(fd_);
}
fd_ = new_value;
errno = previous_errno;
}
int get() const { return fd_; }
bool ok() const { return get() >= 0; }
[[nodiscard]] int release() {
int ret = fd_;
fd_ = -1;
return ret;
}
private:
int fd_ = -1;
};
// A wrapper type that can be implicitly constructed from either int or
// unique_fd. This supports cases where you don't actually own the file
// descriptor, and can't take ownership, but are temporarily acting as if
// you're the owner.
//
// One example would be a function that needs to also allow
// STDERR_FILENO, not just a newly-opened fd. Another example would be JNI code
// that's using a file descriptor that's actually owned by a
// ParcelFileDescriptor or whatever on the Java side, but where the JNI code
// would like to enforce this weaker sense of "temporary ownership".
//
// If you think of unique_fd as being like std::string in that represents
// ownership, borrowed_fd is like std::string_view (and int is like const
// char*).
struct LIBBINDER_EXPORTED borrowed_fd {
/* implicit */ borrowed_fd(int fd) : fd_(fd) {} // NOLINT
/* implicit */ borrowed_fd(const unique_fd& ufd) : fd_(ufd.get()) {} // NOLINT
int get() const { return fd_; }
private:
int fd_ = -1;
};
} // namespace android::binder
#endif // BINDER_NO_LIBBASE
+77
View File
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <string>
namespace android {
/**
* The type used to return success/failure from frameworks APIs.
* See the anonymous enum below for valid values.
*/
typedef int32_t status_t;
/*
* Error codes.
* All error codes are negative values.
*/
enum {
OK = 0, // Preferred constant for checking success.
#ifndef NO_ERROR
// Win32 #defines NO_ERROR as well. It has the same value, so there's no
// real conflict, though it's a bit awkward.
NO_ERROR = OK, // Deprecated synonym for `OK`. Prefer `OK` because it doesn't conflict with Windows.
#endif
UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
NO_MEMORY = -ENOMEM,
INVALID_OPERATION = -ENOSYS,
BAD_VALUE = -EINVAL,
BAD_TYPE = (UNKNOWN_ERROR + 1),
NAME_NOT_FOUND = -ENOENT,
PERMISSION_DENIED = -EPERM,
NO_INIT = -ENODEV,
ALREADY_EXISTS = -EEXIST,
DEAD_OBJECT = -EPIPE,
FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),
#if !defined(_WIN32)
BAD_INDEX = -EOVERFLOW,
NOT_ENOUGH_DATA = -ENODATA,
WOULD_BLOCK = -EWOULDBLOCK,
TIMED_OUT = -ETIMEDOUT,
UNKNOWN_TRANSACTION = -EBADMSG,
#else
BAD_INDEX = -E2BIG,
NOT_ENOUGH_DATA = (UNKNOWN_ERROR + 3),
WOULD_BLOCK = (UNKNOWN_ERROR + 4),
TIMED_OUT = (UNKNOWN_ERROR + 5),
UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
#endif
FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7),
UNEXPECTED_NULL = (UNKNOWN_ERROR + 8),
};
// Human readable name of error
std::string statusToString(status_t status);
} // namespace android
@@ -0,0 +1,76 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
/*
* See documentation in RefBase.h
*/
#include <atomic>
#include <sys/types.h>
namespace android {
class ReferenceRenamer;
void LightRefBase_reportIncStrongRequireStrongFailed(const void* thiz);
template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
mCount.fetch_add(1, std::memory_order_relaxed);
}
inline void incStrongRequireStrong(__attribute__((unused)) const void* id) const {
if (0 == mCount.fetch_add(1, std::memory_order_relaxed)) {
LightRefBase_reportIncStrongRequireStrongFailed(this);
}
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
delete static_cast<const T*>(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount.load(std::memory_order_relaxed);
}
protected:
inline ~LightRefBase() { }
private:
friend class ReferenceMover;
inline static void renameRefs(size_t /*n*/, const ReferenceRenamer& /*renamer*/) { }
inline static void renameRefId(T* /*ref*/, const void* /*old_id*/ , const void* /*new_id*/) { }
private:
mutable std::atomic<int32_t> mCount;
};
// This is a wrapper around LightRefBase that simply enforces a virtual
// destructor to eliminate the template requirement of LightRefBase
class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
public:
virtual ~VirtualLightRefBase() = default;
};
} // namespace android
+818
View File
@@ -0,0 +1,818 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// SOME COMMENTS ABOUT USAGE:
// This provides primarily wp<> weak pointer types and RefBase, which work
// together with sp<> from <StrongPointer.h>.
// sp<> (and wp<>) are a type of smart pointer that use a well defined protocol
// to operate. As long as the object they are templated with implements that
// protocol, these smart pointers work. In several places the platform
// instantiates sp<> with non-RefBase objects; the two are not tied to each
// other.
// RefBase is such an implementation and it supports strong pointers, weak
// pointers and some magic features for the binder.
// So, when using RefBase objects, you have the ability to use strong and weak
// pointers through sp<> and wp<>.
// Normally, when the last strong pointer goes away, the object is destroyed,
// i.e. it's destructor is called. HOWEVER, parts of its associated memory is not
// freed until the last weak pointer is released.
// Weak pointers are essentially "safe" pointers. They are always safe to
// access through promote(). They may return nullptr if the object was
// destroyed because it ran out of strong pointers. This makes them good candidates
// for keys in a cache for instance.
// Weak pointers remain valid for comparison purposes even after the underlying
// object has been destroyed. Even if object A is destroyed and its memory reused
// for B, A remaining weak pointer to A will not compare equal to one to B.
// This again makes them attractive for use as keys.
// How is this supposed / intended to be used?
// Our recommendation is to use strong references (sp<>) when there is an
// ownership relation. e.g. when an object "owns" another one, use a strong
// ref. And of course use strong refs as arguments of functions (it's extremely
// rare that a function will take a wp<>).
// Typically a newly allocated object will immediately be used to initialize
// a strong pointer, which may then be used to construct or assign to other
// strong and weak pointers.
// Use weak references when there are no ownership relation. e.g. the keys in a
// cache (you cannot use plain pointers because there is no safe way to acquire
// a strong reference from a vanilla pointer).
// This implies that two objects should never (or very rarely) have sp<> on
// each other, because they can't both own each other.
// Caveats with reference counting
// Obviously, circular strong references are a big problem; this creates leaks
// and it's hard to debug -- except it's in fact really easy because RefBase has
// tons of debugging code for that. It can basically tell you exactly where the
// leak is.
// Another problem has to do with destructors with side effects. You must
// assume that the destructor of reference counted objects can be called AT ANY
// TIME. For instance code as simple as this:
// void setStuff(const sp<Stuff>& stuff) {
// std::lock_guard<std::mutex> lock(mMutex);
// mStuff = stuff;
// }
// is very dangerous. This code WILL deadlock one day or another.
// What isn't obvious is that ~Stuff() can be called as a result of the
// assignment. And it gets called with the lock held. First of all, the lock is
// protecting mStuff, not ~Stuff(). Secondly, if ~Stuff() uses its own internal
// mutex, now you have mutex ordering issues. Even worse, if ~Stuff() is
// virtual, now you're calling into "user" code (potentially), by that, I mean,
// code you didn't even write.
// A correct way to write this code is something like:
// void setStuff(const sp<Stuff>& stuff) {
// std::unique_lock<std::mutex> lock(mMutex);
// sp<Stuff> hold = mStuff;
// mStuff = stuff;
// lock.unlock();
// }
// More importantly, reference counted objects should do as little work as
// possible in their destructor, or at least be mindful that their destructor
// could be called from very weird and unintended places.
// Other more specific restrictions for wp<> and sp<>:
// Do not construct a strong pointer to "this" in an object's constructor.
// The onFirstRef() callback would be made on an incompletely constructed
// object.
// Construction of a weak pointer to "this" in an object's constructor is also
// discouraged. But the implementation was recently changed so that, in the
// absence of extendObjectLifetime() calls, weak pointers no longer impact
// object lifetime, and hence this no longer risks premature deallocation,
// and hence usually works correctly.
// Such strong or weak pointers can be safely created in the RefBase onFirstRef()
// callback.
// Use of wp::unsafe_get() for any purpose other than debugging is almost
// always wrong. Unless you somehow know that there is a longer-lived sp<> to
// the same object, it may well return a pointer to a deallocated object that
// has since been reallocated for a different purpose. (And if you know there
// is a longer-lived sp<>, why not use an sp<> directly?) A wp<> should only be
// dereferenced by using promote().
// Any object inheriting from RefBase should always be destroyed as the result
// of a reference count decrement, not via any other means. Such objects
// should never be stack allocated, or appear directly as data members in other
// objects. Objects inheriting from RefBase should have their strong reference
// count incremented as soon as possible after construction. Usually this
// will be done via construction of an sp<> to the object, but may instead
// involve other means of calling RefBase::incStrong().
// Explicitly deleting or otherwise destroying a RefBase object with outstanding
// wp<> or sp<> pointers to it will result in an abort or heap corruption.
// It is particularly important not to mix sp<> and direct storage management
// since the sp from raw pointer constructor is implicit. Thus if a RefBase-
// -derived object of type T is managed without ever incrementing its strong
// count, and accidentally passed to f(sp<T>), a strong pointer to the object
// will be temporarily constructed and destroyed, prematurely deallocating the
// object, and resulting in heap corruption. None of this would be easily
// visible in the source. See below on
// ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION for a compile time
// option which helps avoid this case.
// Extra Features:
// RefBase::extendObjectLifetime() can be used to prevent destruction of the
// object while there are still weak references. This is really special purpose
// functionality to support Binder.
// Wp::promote(), implemented via the attemptIncStrong() member function, is
// used to try to convert a weak pointer back to a strong pointer. It's the
// normal way to try to access the fields of an object referenced only through
// a wp<>. Binder code also sometimes uses attemptIncStrong() directly.
// RefBase provides a number of additional callbacks for certain reference count
// events, as well as some debugging facilities.
// Debugging support can be enabled by turning on DEBUG_REFS in RefBase.cpp.
// Otherwise little checking is provided.
// Thread safety:
// Like std::shared_ptr, sp<> and wp<> allow concurrent accesses to DIFFERENT
// sp<> and wp<> instances that happen to refer to the same underlying object.
// They do NOT support concurrent access (where at least one access is a write)
// to THE SAME sp<> or wp<>. In effect, their thread-safety properties are
// exactly like those of T*, NOT atomic<T*>.
// Safety option: ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION
//
// This flag makes the semantics for using a RefBase object with wp<> and sp<>
// much stricter by disabling implicit conversion from raw pointers to these
// objects. In order to use this, apply this flag in Android.bp like so:
//
// cflags: [
// "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
// ],
//
// REGARDLESS of whether this flag is on, best usage of sp<> is shown below. If
// this flag is on, no other usage is possible (directly calling RefBase methods
// is possible, but seeing code using 'incStrong' instead of 'sp<>', for
// instance, should already set off big alarm bells. With carefully constructed
// data structures, it should NEVER be necessary to directly use RefBase
// methods). Proper RefBase usage:
//
// class Foo : virtual public RefBase { ... };
//
// // always construct an sp object with sp::make
// sp<Foo> myFoo = sp<Foo>::make(/*args*/);
//
// // if you need a weak pointer, it must be constructed from a strong
// // pointer
// wp<Foo> weakFoo = myFoo; // NOT myFoo.get()
//
// // If you are inside of a method of Foo and need access to a strong
// // explicitly call this function. This documents your intention to code
// // readers, and it will give a runtime error for what otherwise would
// // be potential double ownership
// .... Foo::someMethod(...) {
// // asserts if there is a memory issue
// sp<Foo> thiz = sp<Foo>::fromExisting(this);
// }
//
#ifndef ANDROID_REF_BASE_H
#define ANDROID_REF_BASE_H
#include <atomic>
#include <functional>
#include <memory>
#include <type_traits> // for common_type.
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
// LightRefBase used to be declared in this header, so we have to include it
#include <utils/LightRefBase.h>
#include <utils/StrongPointer.h>
#include <utils/TypeHelpers.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
#define COMPARE_WEAK(_op_) \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
} \
/* Needed to handle type inference for nullptr: */ \
inline bool operator _op_ (const T* o) const { \
return m_ptr _op_ o; \
}
template<template<typename C> class comparator, typename T, typename U>
static inline bool _wp_compare_(T* a, U* b) {
return comparator<typename std::common_type<T*, U*>::type>()(a, b);
}
// Use std::less and friends to avoid undefined behavior when ordering pointers
// to different objects.
#define COMPARE_WEAK_FUNCTIONAL(_op_, _compare_) \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return _wp_compare_<_compare_>(m_ptr, o); \
}
// ---------------------------------------------------------------------------
// RefererenceRenamer is pure abstract, there is no virtual method
// implementation to put in a translation unit in order to silence the
// weak vtables warning.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class ReferenceRenamer {
protected:
// destructor is purposely not virtual so we avoid code overhead from
// subclasses; we have to make it protected to guarantee that it
// cannot be called from this base class (and to make strict compilers
// happy).
~ReferenceRenamer() { }
public:
virtual void operator()(size_t i) const = 0;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
// ---------------------------------------------------------------------------
class RefBase
{
public:
void incStrong(const void* id) const;
void incStrongRequireStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void incWeakRequireWeak(const void* id);
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
protected:
// When constructing these objects, prefer using sp::make<>. Using a RefBase
// object on the stack or with other refcount mechanisms (e.g.
// std::shared_ptr) is inherently wrong. RefBase types have an implicit
// ownership model and cannot be safely used with other ownership models.
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
// Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
// Invoked when either the last strong reference goes away, or we need to undo
// the effect of an unnecessary onIncStrongAttempted.
virtual void onLastStrongRef(const void* id);
// Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to
// strong reference. May have side effects if it returns true.
// The first flags argument is always FIRST_INC_STRONG.
// TODO: Remove initial flag argument.
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
// Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
// kind goes away. Unused.
// TODO: Remove.
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
private:
friend class ReferenceMover;
static void renameRefs(size_t n, const ReferenceRenamer& renamer);
static void renameRefId(weakref_type* ref,
const void* old_id, const void* new_id);
static void renameRefId(RefBase* ref,
const void* old_id, const void* new_id);
weakref_impl* const mRefs;
};
// ---------------------------------------------------------------------------
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline constexpr wp() : m_ptr(nullptr), m_refs(nullptr) { }
// if nullptr, returns nullptr
//
// if a weak pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline wp<T> fromExisting(T* other);
// for more information about this flag, see above
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
wp(std::nullptr_t) : wp() {}
#else
wp(T* other); // NOLINT(implicit)
template <typename U>
wp(U* other); // NOLINT(implicit)
wp& operator=(T* other);
template <typename U>
wp& operator=(U* other);
#endif
wp(const wp<T>& other);
explicit wp(const sp<T>& other);
template<typename U> wp(const sp<U>& other); // NOLINT(implicit)
template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~wp();
// Assignment
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& other);
template<typename U> wp& operator = (const wp<U>& other);
template<typename U> wp& operator = (const sp<U>& other);
void set_object_and_refs(T* other, weakref_type* refs);
// promotion to sp
sp<T> promote() const;
// Reset
void clear();
// Accessors
inline weakref_type* get_refs() const { return m_refs; }
inline T* unsafe_get() const { return m_ptr; }
// Operators
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
COMPARE_WEAK_FUNCTIONAL(>, std::greater)
COMPARE_WEAK_FUNCTIONAL(<, std::less)
COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
template<typename U>
inline bool operator == (const wp<U>& o) const {
return m_refs == o.m_refs; // Implies m_ptr == o.mptr; see invariants below.
}
template<typename U>
inline bool operator == (const sp<U>& o) const {
// Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
// object at the same address.
if (o == nullptr) {
return m_ptr == nullptr;
} else {
return m_refs == o->getWeakRefs(); // Implies m_ptr == o.mptr.
}
}
template<typename U>
inline bool operator != (const sp<U>& o) const {
return !(*this == o);
}
template<typename U>
inline bool operator > (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::greater>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
}
}
template<typename U>
inline bool operator < (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::less>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::less>(m_ptr, o.m_ptr);
}
}
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
T* m_ptr;
weakref_type* m_refs;
};
#undef COMPARE_WEAK
#undef COMPARE_WEAK_FUNCTIONAL
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
// Implementation invariants:
// Either
// 1) m_ptr and m_refs are both null, or
// 2) m_refs == m_ptr->mRefs, or
// 3) *m_ptr is no longer live, and m_refs points to the weakref_type object that corresponded
// to m_ptr while it was live. *m_refs remains live while a wp<> refers to it.
//
// The m_refs field in a RefBase object is allocated on construction, unique to that RefBase
// object, and never changes. Thus if two wp's have identical m_refs fields, they are either both
// null or point to the same object. If two wp's have identical m_ptr fields, they either both
// point to the same live object and thus have the same m_ref fields, or at least one of the
// objects is no longer live.
//
// Note that the above comparison operations go out of their way to provide an ordering consistent
// with ordinary pointer comparison; otherwise they could ignore m_ptr, and just compare m_refs.
template <typename T>
wp<T> wp<T>::fromExisting(T* other) {
if (!other) return nullptr;
auto refs = other->getWeakRefs();
refs->incWeakRequireWeak(other);
wp<T> ret;
ret.m_ptr = other;
ret.m_refs = refs;
return ret;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
m_refs = other ? other->createWeak(this) : nullptr;
}
template <typename T>
template <typename U>
wp<T>::wp(U* other) : m_ptr(other) {
m_refs = other ? other->createWeak(this) : nullptr;
}
template <typename T>
wp<T>& wp<T>::operator=(T* other) {
weakref_type* newRefs = other ? other->createWeak(this) : nullptr;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
template <typename T>
template <typename U>
wp<T>& wp<T>::operator=(U* other) {
weakref_type* newRefs = other ? other->createWeak(this) : 0;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
#endif
template<typename T>
wp<T>::wp(const wp<T>& other)
: m_ptr(other.m_ptr), m_refs(other.m_refs)
{
if (m_ptr) m_refs->incWeak(this);
}
template<typename T>
wp<T>::wp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T> template<typename U>
wp<T>::wp(const wp<U>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) {
m_refs = other.m_refs;
m_refs->incWeak(this);
} else {
m_refs = nullptr;
}
}
template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
wp<T>& wp<T>::operator = (const wp<T>& other)
{
weakref_type* otherRefs(other.m_refs);
T* otherPtr(other.m_ptr);
if (otherPtr) otherRefs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = otherRefs;
return *this;
}
template<typename T>
wp<T>& wp<T>::operator = (const sp<T>& other)
{
weakref_type* newRefs =
other != nullptr ? other->createWeak(this) : nullptr;
T* otherPtr(other.m_ptr);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = newRefs;
return *this;
}
template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const wp<U>& other)
{
weakref_type* otherRefs(other.m_refs);
U* otherPtr(other.m_ptr);
if (otherPtr) otherRefs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = otherRefs;
return *this;
}
template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const sp<U>& other)
{
weakref_type* newRefs = other != nullptr ? other->createWeak(this) : nullptr;
U* otherPtr(other.m_ptr);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = newRefs;
return *this;
}
template<typename T>
void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
{
if (other) refs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = refs;
}
template<typename T>
sp<T> wp<T>::promote() const
{
sp<T> result;
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result;
}
template<typename T>
void wp<T>::clear()
{
if (m_ptr) {
m_refs->decWeak(this);
m_refs = nullptr;
m_ptr = nullptr;
}
}
// ---------------------------------------------------------------------------
// this class just serves as a namespace so TYPE::moveReferences can stay
// private.
class ReferenceMover {
public:
// it would be nice if we could make sure no extra code is generated
// for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
// Using a sp<RefBase> override doesn't work; it's a bit like we wanted
// a template<typename TYPE inherits RefBase> template...
template<typename TYPE> static inline
void move_references(sp<TYPE>* dest, sp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
sp<TYPE>* d_;
sp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the sp<>'s this pointer
TYPE::renameRefId(d_[i].get(), &s_[i], &d_[i]);
}
public:
Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d_(d), s_(s) { }
virtual ~Renamer() { }
};
memmove(dest, src, n*sizeof(sp<TYPE>));
TYPE::renameRefs(n, Renamer(dest, src));
}
template<typename TYPE> static inline
void move_references(wp<TYPE>* dest, wp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
wp<TYPE>* d_;
wp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the wp<>'s this pointer
TYPE::renameRefId(d_[i].get_refs(), &s_[i], &d_[i]);
}
public:
Renamer(wp<TYPE>* rd, wp<TYPE> const* rs) : d_(rd), s_(rs) { }
virtual ~Renamer() { }
};
memmove(dest, src, n*sizeof(wp<TYPE>));
TYPE::renameRefs(n, Renamer(dest, src));
}
};
// specialization for moving sp<> and wp<> types.
// these are used by the [Sorted|Keyed]Vector<> implementations
// sp<> and wp<> need to be handled specially, because they do not
// have trivial copy operation in the general case (see RefBase.cpp
// when DEBUG ops are enabled), but can be implemented very
// efficiently in most cases.
template<typename TYPE> inline
void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
} // namespace android
namespace libutilsinternal {
template <typename T, typename = void>
struct is_complete_type : std::false_type {};
template <typename T>
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
} // namespace libutilsinternal
namespace std {
// Define `RefBase` specific versions of `std::make_shared` and
// `std::make_unique` to block people from using them. Using them to allocate
// `RefBase` objects results in double ownership. Use
// `sp<T>::make(...)` instead.
//
// Note: We exclude incomplete types because `std::is_base_of` is undefined in
// that case.
template <typename T, typename... Args,
typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
shared_ptr<T> make_shared(Args...) { // SEE COMMENT ABOVE.
static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
}
template <typename T, typename... Args,
typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
unique_ptr<T> make_unique(Args...) { // SEE COMMENT ABOVE.
static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
}
} // namespace std
// ---------------------------------------------------------------------------
#endif // ANDROID_REF_BASE_H
+411
View File
@@ -0,0 +1,411 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_STRING16_H
#define ANDROID_STRING16_H
#include <iostream>
#include <string>
#include <string_view>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <utils/TypeHelpers.h>
#if __cplusplus >= 202002L
#include <compare>
#endif
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
template <size_t N>
class StaticString16;
// DO NOT USE: please use std::u16string
//! This is a string holding UTF-16 characters.
class String16
{
public:
String16();
String16(const String16& o);
String16(String16&& o) noexcept;
String16(const String16& o,
size_t len,
size_t begin=0);
explicit String16(const char16_t* o);
explicit String16(const char16_t* o, size_t len);
explicit String16(const String8& o);
explicit String16(const char* o);
explicit String16(const char* o, size_t len);
~String16();
inline const char16_t* c_str() const;
size_t size() const;
inline bool empty() const;
inline size_t length() const;
void setTo(const String16& other);
status_t setTo(const char16_t* other);
status_t setTo(const char16_t* other, size_t len);
status_t setTo(const String16& other,
size_t len,
size_t begin=0);
status_t append(const String16& other);
status_t append(const char16_t* other, size_t len);
inline String16& operator=(const String16& other);
String16& operator=(String16&& other) noexcept;
inline String16& operator+=(const String16& other);
inline String16 operator+(const String16& other) const;
status_t insert(size_t pos, const char16_t* chrs);
status_t insert(size_t pos,
const char16_t* chrs, size_t len);
ssize_t findFirst(char16_t c) const;
ssize_t findLast(char16_t c) const;
bool startsWith(const String16& prefix) const;
bool startsWith(const char16_t* prefix) const;
bool contains(const char16_t* chrs) const;
inline bool contains(const String16& other) const;
status_t replaceAll(char16_t replaceThis,
char16_t withThis);
inline int compare(const String16& other) const;
inline bool operator<(const String16& other) const;
inline bool operator<=(const String16& other) const;
inline bool operator==(const String16& other) const;
inline bool operator!=(const String16& other) const;
inline bool operator>=(const String16& other) const;
inline bool operator>(const String16& other) const;
#if __cplusplus >= 202002L
inline std::strong_ordering operator<=>(const String16& other) const;
#endif
inline bool operator<(const char16_t* other) const;
inline bool operator<=(const char16_t* other) const;
inline bool operator==(const char16_t* other) const;
inline bool operator!=(const char16_t* other) const;
inline bool operator>=(const char16_t* other) const;
inline bool operator>(const char16_t* other) const;
#if __cplusplus >= 202002L
inline std::strong_ordering operator<=>(const char16_t* other) const;
#endif
inline operator const char16_t*() const;
// Implicit cast to std::u16string is not implemented on purpose - u16string_view is much
// lighter and if one needs, they can still create u16string from u16string_view.
inline operator std::u16string_view() const;
// Static and non-static String16 behave the same for the users, so
// this method isn't of much use for the users. It is public for testing.
bool isStaticString() const;
private:
/*
* A flag indicating the type of underlying buffer.
*/
static constexpr uint32_t kIsSharedBufferAllocated = 0x80000000;
/*
* alloc() returns void* so that SharedBuffer class is not exposed.
*/
static void* alloc(size_t size);
static char16_t* allocFromUTF8(const char* u8str, size_t u8len);
static char16_t* allocFromUTF16(const char16_t* u16str, size_t u16len);
/*
* edit() and editResize() return void* so that SharedBuffer class
* is not exposed.
*/
void* edit();
void* editResize(size_t new_size);
void acquire();
void release();
size_t staticStringSize() const;
const char16_t* mString;
protected:
/*
* Data structure used to allocate static storage for static String16.
*
* Note that this data structure and SharedBuffer are used interchangably
* as the underlying data structure for a String16. Therefore, the layout
* of this data structure must match the part in SharedBuffer that is
* visible to String16.
*/
template <size_t N>
struct StaticData {
// The high bit of 'size' is used as a flag.
static_assert(N - 1 < kIsSharedBufferAllocated, "StaticString16 too long!");
constexpr StaticData() : size(N - 1), data{0} {}
const uint32_t size;
char16_t data[N];
constexpr StaticData(const StaticData<N>&) = default;
};
/*
* Helper function for constructing a StaticData object.
*/
template <size_t N>
static constexpr const StaticData<N> makeStaticData(const char16_t (&s)[N]) {
StaticData<N> r;
// The 'size' field is at the same location where mClientMetadata would
// be for a SharedBuffer. We do NOT set kIsSharedBufferAllocated flag
// here.
for (size_t i = 0; i < N - 1; ++i) r.data[i] = s[i];
return r;
}
template <size_t N>
explicit constexpr String16(const StaticData<N>& s) : mString(s.data) {}
// These symbols are for potential backward compatibility with prebuilts. To be removed.
#ifdef ENABLE_STRING16_OBSOLETE_METHODS
public:
#else
private:
#endif
inline const char16_t* string() const;
};
// String16 can be trivially moved using memcpy() because moving does not
// require any change to the underlying SharedBuffer contents or reference count.
ANDROID_TRIVIAL_MOVE_TRAIT(String16)
static inline std::ostream& operator<<(std::ostream& os, const String16& str) {
os << String8(str);
return os;
}
// ---------------------------------------------------------------------------
/*
* A StaticString16 object is a specialized String16 object. Instead of holding
* the string data in a ref counted SharedBuffer object, it holds data in a
* buffer within StaticString16 itself. Note that this buffer is NOT ref
* counted and is assumed to be available for as long as there is at least a
* String16 object using it. Therefore, one must be extra careful to NEVER
* assign a StaticString16 to a String16 that outlives the StaticString16
* object.
*
* THE SAFEST APPROACH IS TO USE StaticString16 ONLY AS GLOBAL VARIABLES.
*
* A StaticString16 SHOULD NEVER APPEAR IN APIs. USE String16 INSTEAD.
*/
template <size_t N>
class StaticString16 : public String16 {
public:
constexpr StaticString16(const char16_t (&s)[N]) : String16(mData), mData(makeStaticData(s)) {}
constexpr StaticString16(const StaticString16<N>& other)
: String16(mData), mData(other.mData) {}
constexpr StaticString16(const StaticString16<N>&&) = delete;
// There is no reason why one would want to 'new' a StaticString16. Delete
// it to discourage misuse.
static void* operator new(std::size_t) = delete;
private:
const StaticData<N> mData;
};
template <typename F>
StaticString16(const F&)->StaticString16<sizeof(F) / sizeof(char16_t)>;
// ---------------------------------------------------------------------------
// No user servicable parts below.
inline int compare_type(const String16& lhs, const String16& rhs)
{
return lhs.compare(rhs);
}
inline int strictly_order_type(const String16& lhs, const String16& rhs)
{
return compare_type(lhs, rhs) < 0;
}
inline const char16_t* String16::c_str() const
{
return mString;
}
inline const char16_t* String16::string() const
{
return mString;
}
inline bool String16::empty() const
{
return length() == 0;
}
inline size_t String16::length() const
{
return size();
}
inline bool String16::contains(const String16& other) const
{
return contains(other.c_str());
}
inline String16& String16::operator=(const String16& other)
{
setTo(other);
return *this;
}
inline String16& String16::operator+=(const String16& other)
{
append(other);
return *this;
}
inline String16 String16::operator+(const String16& other) const
{
String16 tmp(*this);
tmp += other;
return tmp;
}
inline int String16::compare(const String16& other) const
{
return strzcmp16(mString, size(), other.mString, other.size());
}
inline bool String16::operator<(const String16& other) const
{
return strzcmp16(mString, size(), other.mString, other.size()) < 0;
}
inline bool String16::operator<=(const String16& other) const
{
return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
}
inline bool String16::operator==(const String16& other) const
{
return strzcmp16(mString, size(), other.mString, other.size()) == 0;
}
inline bool String16::operator!=(const String16& other) const
{
return strzcmp16(mString, size(), other.mString, other.size()) != 0;
}
inline bool String16::operator>=(const String16& other) const
{
return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
}
inline bool String16::operator>(const String16& other) const
{
return strzcmp16(mString, size(), other.mString, other.size()) > 0;
}
#if __cplusplus >= 202002L
inline std::strong_ordering String16::operator<=>(const String16& other) const {
int result = strzcmp16(mString, size(), other.mString, other.size());
if (result == 0) {
return std::strong_ordering::equal;
} else if (result < 0) {
return std::strong_ordering::less;
} else {
return std::strong_ordering::greater;
}
}
#endif
inline bool String16::operator<(const char16_t* other) const
{
return strcmp16(mString, other) < 0;
}
inline bool String16::operator<=(const char16_t* other) const
{
return strcmp16(mString, other) <= 0;
}
inline bool String16::operator==(const char16_t* other) const
{
return strcmp16(mString, other) == 0;
}
inline bool String16::operator!=(const char16_t* other) const
{
return strcmp16(mString, other) != 0;
}
inline bool String16::operator>=(const char16_t* other) const
{
return strcmp16(mString, other) >= 0;
}
inline bool String16::operator>(const char16_t* other) const
{
return strcmp16(mString, other) > 0;
}
#if __cplusplus >= 202002L
inline std::strong_ordering String16::operator<=>(const char16_t* other) const {
int result = strcmp16(mString, other);
if (result == 0) {
return std::strong_ordering::equal;
} else if (result < 0) {
return std::strong_ordering::less;
} else {
return std::strong_ordering::greater;
}
}
#endif
inline String16::operator const char16_t*() const
{
return mString;
}
inline String16::operator std::u16string_view() const
{
return {mString, length()};
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_STRING16_H
+378
View File
@@ -0,0 +1,378 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_STRING8_H
#define ANDROID_STRING8_H
#include <iostream>
#include <string>
#include <string_view>
#include <utils/Errors.h>
#include <utils/Unicode.h>
#include <utils/TypeHelpers.h>
#include <string.h> // for strcmp
#include <stdarg.h>
#if __cplusplus >= 202002L
#include <compare>
#endif
// ---------------------------------------------------------------------------
namespace android {
class String16;
// DO NOT USE: please use std::string
//! This is a string holding UTF-8 characters. Does not allow the value more
// than 0x10FFFF, which is not valid unicode codepoint.
class String8
{
public:
String8();
String8(const String8& o);
explicit String8(const char* o);
explicit String8(const char* o, size_t numChars);
explicit String8(std::string_view o);
explicit String8(const String16& o);
explicit String8(const char16_t* o);
explicit String8(const char16_t* o, size_t numChars);
explicit String8(const char32_t* o);
explicit String8(const char32_t* o, size_t numChars);
~String8();
static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
static String8 formatV(const char* fmt, va_list args);
inline const char* c_str() const;
inline size_t size() const;
inline size_t bytes() const;
inline bool empty() const;
size_t length() const;
void clear();
void setTo(const String8& other);
status_t setTo(const char* other);
status_t setTo(const char* other, size_t numChars);
status_t setTo(const char16_t* other, size_t numChars);
status_t setTo(const char32_t* other,
size_t length);
status_t append(const String8& other);
status_t append(const char* other);
status_t append(const char* other, size_t numChars);
status_t appendFormat(const char* fmt, ...)
__attribute__((format (printf, 2, 3)));
status_t appendFormatV(const char* fmt, va_list args);
inline String8& operator=(const String8& other);
inline String8& operator=(const char* other);
inline String8& operator+=(const String8& other);
inline String8 operator+(const String8& other) const;
inline String8& operator+=(const char* other);
inline String8 operator+(const char* other) const;
inline int compare(const String8& other) const;
inline bool operator<(const String8& other) const;
inline bool operator<=(const String8& other) const;
inline bool operator==(const String8& other) const;
inline bool operator!=(const String8& other) const;
inline bool operator>=(const String8& other) const;
inline bool operator>(const String8& other) const;
#if __cplusplus >= 202002L
inline std::strong_ordering operator<=>(const String8& other) const;
#endif
inline bool operator<(const char* other) const;
inline bool operator<=(const char* other) const;
inline bool operator==(const char* other) const;
inline bool operator!=(const char* other) const;
inline bool operator>=(const char* other) const;
inline bool operator>(const char* other) const;
#if __cplusplus >= 202002L
inline std::strong_ordering operator<=>(const char* other) const;
#endif
inline operator const char*() const;
inline explicit operator std::string_view() const;
char* lockBuffer(size_t size);
void unlockBuffer();
status_t unlockBuffer(size_t size);
// return the index of the first byte of other in this at or after
// start, or -1 if not found
ssize_t find(const char* other, size_t start = 0) const;
inline ssize_t find(const String8& other, size_t start = 0) const;
// return true if this string contains the specified substring
inline bool contains(const char* other) const;
inline bool contains(const String8& other) const;
// removes all occurrence of the specified substring
// returns true if any were found and removed
bool removeAll(const char* other);
inline bool removeAll(const String8& other);
void toLower();
private:
String8 getPathDir(void) const;
String8 getPathExtension(void) const;
status_t real_append(const char* other, size_t numChars);
const char* mString;
// These symbols are for potential backward compatibility with prebuilts. To be removed.
#ifdef ENABLE_STRING8_OBSOLETE_METHODS
public:
#else
private:
#endif
inline const char* string() const;
inline bool isEmpty() const;
};
// String8 can be trivially moved using memcpy() because moving does not
// require any change to the underlying SharedBuffer contents or reference count.
ANDROID_TRIVIAL_MOVE_TRAIT(String8)
static inline std::ostream& operator<<(std::ostream& os, const String8& str) {
os << str.c_str();
return os;
}
// ---------------------------------------------------------------------------
// No user servicable parts below.
inline int compare_type(const String8& lhs, const String8& rhs)
{
return lhs.compare(rhs);
}
inline int strictly_order_type(const String8& lhs, const String8& rhs)
{
return compare_type(lhs, rhs) < 0;
}
inline const char* String8::c_str() const
{
return mString;
}
inline const char* String8::string() const
{
return mString;
}
inline size_t String8::size() const
{
return length();
}
inline bool String8::empty() const
{
return length() == 0;
}
inline bool String8::isEmpty() const
{
return length() == 0;
}
inline size_t String8::bytes() const
{
return length();
}
inline ssize_t String8::find(const String8& other, size_t start) const
{
return find(other.c_str(), start);
}
inline bool String8::contains(const char* other) const
{
return find(other) >= 0;
}
inline bool String8::contains(const String8& other) const
{
return contains(other.c_str());
}
inline bool String8::removeAll(const String8& other)
{
return removeAll(other.c_str());
}
inline String8& String8::operator=(const String8& other)
{
setTo(other);
return *this;
}
inline String8& String8::operator=(const char* other)
{
setTo(other);
return *this;
}
inline String8& String8::operator+=(const String8& other)
{
append(other);
return *this;
}
inline String8 String8::operator+(const String8& other) const
{
String8 tmp(*this);
tmp += other;
return tmp;
}
inline String8& String8::operator+=(const char* other)
{
append(other);
return *this;
}
inline String8 String8::operator+(const char* other) const
{
String8 tmp(*this);
tmp += other;
return tmp;
}
inline int String8::compare(const String8& other) const
{
return strcmp(mString, other.mString);
}
inline bool String8::operator<(const String8& other) const
{
return strcmp(mString, other.mString) < 0;
}
inline bool String8::operator<=(const String8& other) const
{
return strcmp(mString, other.mString) <= 0;
}
inline bool String8::operator==(const String8& other) const
{
return strcmp(mString, other.mString) == 0;
}
inline bool String8::operator!=(const String8& other) const
{
return strcmp(mString, other.mString) != 0;
}
inline bool String8::operator>=(const String8& other) const
{
return strcmp(mString, other.mString) >= 0;
}
inline bool String8::operator>(const String8& other) const
{
return strcmp(mString, other.mString) > 0;
}
#if __cplusplus >= 202002L
inline std::strong_ordering String8::operator<=>(const String8& other) const {
int result = strcmp(mString, other.mString);
if (result == 0) {
return std::strong_ordering::equal;
} else if (result < 0) {
return std::strong_ordering::less;
} else {
return std::strong_ordering::greater;
}
}
#endif
inline bool String8::operator<(const char* other) const
{
return strcmp(mString, other) < 0;
}
inline bool String8::operator<=(const char* other) const
{
return strcmp(mString, other) <= 0;
}
inline bool String8::operator==(const char* other) const
{
return strcmp(mString, other) == 0;
}
inline bool String8::operator!=(const char* other) const
{
return strcmp(mString, other) != 0;
}
inline bool String8::operator>=(const char* other) const
{
return strcmp(mString, other) >= 0;
}
inline bool String8::operator>(const char* other) const
{
return strcmp(mString, other) > 0;
}
#if __cplusplus >= 202002L
inline std::strong_ordering String8::operator<=>(const char* other) const {
int result = strcmp(mString, other);
if (result == 0) {
return std::strong_ordering::equal;
} else if (result < 0) {
return std::strong_ordering::less;
} else {
return std::strong_ordering::greater;
}
}
#endif
inline String8::operator const char*() const
{
return mString;
}
inline String8::String8(std::string_view o) : String8(o.data(), o.length()) { }
inline String8::operator std::string_view() const
{
return {mString, length()};
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_STRING8_H
@@ -0,0 +1,370 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
#include <functional>
#include <type_traits> // for common_type.
// ---------------------------------------------------------------------------
namespace android {
template<typename T> class wp;
// ---------------------------------------------------------------------------
template<typename T>
class sp {
public:
inline constexpr sp() : m_ptr(nullptr) { }
// The old way of using sp<> was like this. This is bad because it relies
// on implicit conversion to sp<>, which we would like to remove (if an
// object is being managed some other way, this is double-ownership). We
// want to move away from this:
//
// sp<Foo> foo = new Foo(...); // DO NOT DO THIS
//
// Instead, prefer to do this:
//
// sp<Foo> foo = sp<Foo>::make(...); // DO THIS
//
// Sometimes, in order to use this, when a constructor is marked as private,
// you may need to add this to your class:
//
// friend class sp<Foo>;
template <typename... Args>
static inline sp<T> make(Args&&... args);
// if nullptr, returns nullptr
//
// if a strong pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline sp<T> fromExisting(T* other);
// for more information about this macro and correct RefBase usage, see
// the comment at the top of utils/RefBase.h
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
sp(std::nullptr_t) : sp() {}
#else
sp(T* other); // NOLINT(implicit)
template <typename U>
sp(U* other); // NOLINT(implicit)
sp& operator=(T* other);
template <typename U>
sp& operator=(U* other);
#endif
sp(const sp<T>& other);
sp(sp<T>&& other) noexcept;
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
// Cast a strong pointer directly from one type to another. Constructors
// allow changing types, but only if they are pointer-compatible. This does
// a static_cast internally.
template <typename U>
static inline sp<T> cast(const sp<U>& other);
~sp();
// Assignment
sp& operator = (const sp<T>& other);
sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<U>&& other);
//! Special optimization for use by ProcessState (and nobody else).
void force_set(T* other);
// Reset
void clear();
// Releases the ownership of the object managed by this instance of sp, if any.
// The caller is now responsible for managing it. That is, the caller must ensure
// decStrong() is called when the pointer is no longer used.
[[nodiscard]] inline T* release() noexcept {
auto ret = m_ptr;
m_ptr = nullptr;
return ret;
}
// Accessors
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
inline explicit operator bool () const { return m_ptr != nullptr; }
// Punt these to the wp<> implementation.
template<typename U>
inline bool operator == (const wp<U>& o) const {
return o == *this;
}
template<typename U>
inline bool operator != (const wp<U>& o) const {
return o != *this;
}
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr;
};
#define COMPARE_STRONG(_op_) \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
return t.get() _op_ u.get(); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const T* t, const sp<U>& u) { \
return t _op_ u.get(); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const U* u) { \
return t.get() _op_ u; \
} \
template <typename T> \
static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
return t.get() _op_ nullptr; \
} \
template <typename T> \
static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
return nullptr _op_ t.get(); \
}
template <template <typename C> class comparator, typename T, typename U>
static inline bool _sp_compare_(T* a, U* b) {
return comparator<typename std::common_type<T*, U*>::type>()(a, b);
}
#define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_) \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
return _sp_compare_<_compare_>(t.get(), u.get()); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const T* t, const sp<U>& u) { \
return _sp_compare_<_compare_>(t, u.get()); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const U* u) { \
return _sp_compare_<_compare_>(t.get(), u); \
} \
template <typename T> \
static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
return _sp_compare_<_compare_>(t.get(), nullptr); \
} \
template <typename T> \
static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
return _sp_compare_<_compare_>(nullptr, t.get()); \
}
COMPARE_STRONG(==)
COMPARE_STRONG(!=)
COMPARE_STRONG_FUNCTIONAL(>, std::greater)
COMPARE_STRONG_FUNCTIONAL(<, std::less)
COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
#undef COMPARE_STRONG
#undef COMPARE_STRONG_FUNCTIONAL
// For code size reasons, we do not want these inlined or templated.
void sp_report_race();
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
// TODO: Ideally we should find a way to increment the reference count before running the
// constructor, so that generating an sp<> to this in the constructor is no longer dangerous.
template <typename T>
template <typename... Args>
sp<T> sp<T>::make(Args&&... args) {
T* t = new T(std::forward<Args>(args)...);
sp<T> result;
result.m_ptr = t;
t->incStrong(t);
return result;
}
template <typename T>
sp<T> sp<T>::fromExisting(T* other) {
if (other) {
other->incStrongRequireStrong(other);
sp<T> result;
result.m_ptr = other;
return result;
}
return nullptr;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other) {
other->incStrong(this);
}
}
template <typename T>
template <typename U>
sp<T>::sp(U* other) : m_ptr(other) {
if (other) {
(static_cast<T*>(other))->incStrong(this);
}
}
template <typename T>
sp<T>& sp<T>::operator=(T* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) {
other->incStrong(this);
}
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
#endif
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template <typename T>
sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(sp<U>&& other)
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template <typename T>
template <typename U>
sp<T> sp<T>::cast(const sp<U>& other) {
return sp<T>::fromExisting(static_cast<T*>(other.get()));
}
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
template<typename T>
sp<T>& sp<T>::operator =(const sp<T>& other) {
// Force m_ptr to be read twice, to heuristically check for data races.
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template <typename T>
sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(const sp<U>& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(sp<U>&& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (m_ptr) m_ptr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(U* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) (static_cast<T*>(other))->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
#endif
template<typename T>
void sp<T>::force_set(T* other) {
other->forceIncStrong(this);
m_ptr = other;
}
template<typename T>
void sp<T>::clear() {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) {
oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = nullptr;
}
}
template<typename T>
void sp<T>::set_pointer(T* ptr) {
m_ptr = ptr;
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_STRONG_POINTER_H
@@ -0,0 +1,341 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_TYPE_HELPERS_H
#define ANDROID_TYPE_HELPERS_H
#include <new>
#include <type_traits>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
// ---------------------------------------------------------------------------
namespace android {
/*
* Types traits
*/
template <typename T> struct trait_trivial_ctor { enum { value = false }; };
template <typename T> struct trait_trivial_dtor { enum { value = false }; };
template <typename T> struct trait_trivial_copy { enum { value = false }; };
template <typename T> struct trait_trivial_move { enum { value = false }; };
template <typename T> struct trait_pointer { enum { value = false }; };
template <typename T> struct trait_pointer<T*> { enum { value = true }; };
template <typename TYPE>
struct traits {
enum {
// whether this type is a pointer
is_pointer = trait_pointer<TYPE>::value,
// whether this type's constructor is a no-op
has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value,
// whether this type's destructor is a no-op
has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value,
// whether this type type can be copy-constructed with memcpy
has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value,
// whether this type can be moved with memmove
has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value
};
};
template <typename T, typename U>
struct aggregate_traits {
enum {
is_pointer = false,
has_trivial_ctor =
traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
has_trivial_dtor =
traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
has_trivial_copy =
traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
has_trivial_move =
traits<T>::has_trivial_move && traits<U>::has_trivial_move
};
};
#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
template<> struct trait_trivial_ctor< T > { enum { value = true }; };
#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
template<> struct trait_trivial_dtor< T > { enum { value = true }; };
#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \
template<> struct trait_trivial_copy< T > { enum { value = true }; };
#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \
template<> struct trait_trivial_move< T > { enum { value = true }; };
#define ANDROID_BASIC_TYPES_TRAITS( T ) \
ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
ANDROID_TRIVIAL_COPY_TRAIT( T ) \
ANDROID_TRIVIAL_MOVE_TRAIT( T )
// ---------------------------------------------------------------------------
/*
* basic types traits
*/
ANDROID_BASIC_TYPES_TRAITS( void )
ANDROID_BASIC_TYPES_TRAITS( bool )
ANDROID_BASIC_TYPES_TRAITS( char )
ANDROID_BASIC_TYPES_TRAITS( unsigned char )
ANDROID_BASIC_TYPES_TRAITS( short )
ANDROID_BASIC_TYPES_TRAITS( unsigned short )
ANDROID_BASIC_TYPES_TRAITS( int )
ANDROID_BASIC_TYPES_TRAITS( unsigned int )
ANDROID_BASIC_TYPES_TRAITS( long )
ANDROID_BASIC_TYPES_TRAITS( unsigned long )
ANDROID_BASIC_TYPES_TRAITS( long long )
ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
ANDROID_BASIC_TYPES_TRAITS( float )
ANDROID_BASIC_TYPES_TRAITS( double )
template<typename T> struct trait_trivial_ctor<T*> { enum { value = true }; };
template<typename T> struct trait_trivial_dtor<T*> { enum { value = true }; };
template<typename T> struct trait_trivial_copy<T*> { enum { value = true }; };
template<typename T> struct trait_trivial_move<T*> { enum { value = true }; };
// ---------------------------------------------------------------------------
/*
* compare and order types
*/
template<typename TYPE> inline
int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
return (lhs < rhs) ? 1 : 0;
}
template<typename TYPE> inline
int compare_type(const TYPE& lhs, const TYPE& rhs) {
return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
}
/*
* create, destroy, copy and move types...
*/
template<typename TYPE> inline
void construct_type(TYPE* p, size_t n) {
if (!traits<TYPE>::has_trivial_ctor) {
while (n > 0) {
n--;
new(p++) TYPE;
}
}
}
template<typename TYPE> inline
void destroy_type(TYPE* p, size_t n) {
if (!traits<TYPE>::has_trivial_dtor) {
while (n > 0) {
n--;
p->~TYPE();
p++;
}
}
}
template<typename TYPE>
typename std::enable_if<traits<TYPE>::has_trivial_copy>::type
inline
copy_type(TYPE* d, const TYPE* s, size_t n) {
memcpy(d,s,n*sizeof(TYPE));
}
template<typename TYPE>
typename std::enable_if<!traits<TYPE>::has_trivial_copy>::type
inline
copy_type(TYPE* d, const TYPE* s, size_t n) {
while (n > 0) {
n--;
new(d) TYPE(*s);
d++, s++;
}
}
template<typename TYPE> inline
void splat_type(TYPE* where, const TYPE* what, size_t n) {
if (!traits<TYPE>::has_trivial_copy) {
while (n > 0) {
n--;
new(where) TYPE(*what);
where++;
}
} else {
while (n > 0) {
n--;
*where++ = *what;
}
}
}
template<typename TYPE>
struct use_trivial_move : public std::integral_constant<bool,
(traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
|| traits<TYPE>::has_trivial_move
> {};
template<typename TYPE>
typename std::enable_if<use_trivial_move<TYPE>::value>::type
inline
move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
memmove(reinterpret_cast<void*>(d), s, n * sizeof(TYPE));
}
template<typename TYPE>
typename std::enable_if<!use_trivial_move<TYPE>::value>::type
inline
move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
d += n;
s += n;
while (n > 0) {
n--;
--d, --s;
if (!traits<TYPE>::has_trivial_copy) {
new(d) TYPE(*s);
} else {
*d = *s;
}
if (!traits<TYPE>::has_trivial_dtor) {
s->~TYPE();
}
}
}
template<typename TYPE>
typename std::enable_if<use_trivial_move<TYPE>::value>::type
inline
move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
memmove(reinterpret_cast<void*>(d), s, n * sizeof(TYPE));
}
template<typename TYPE>
typename std::enable_if<!use_trivial_move<TYPE>::value>::type
inline
move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
while (n > 0) {
n--;
if (!traits<TYPE>::has_trivial_copy) {
new(d) TYPE(*s);
} else {
*d = *s;
}
if (!traits<TYPE>::has_trivial_dtor) {
s->~TYPE();
}
d++, s++;
}
}
// ---------------------------------------------------------------------------
/*
* a key/value pair
*/
template <typename KEY, typename VALUE>
struct key_value_pair_t {
typedef KEY key_t;
typedef VALUE value_t;
KEY key;
VALUE value;
key_value_pair_t() { }
key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
key_value_pair_t& operator=(const key_value_pair_t& o) {
key = o.key;
value = o.value;
return *this;
}
key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
explicit key_value_pair_t(const KEY& k) : key(k) { }
inline bool operator < (const key_value_pair_t& o) const {
return strictly_order_type(key, o.key);
}
inline const KEY& getKey() const {
return key;
}
inline const VALUE& getValue() const {
return value;
}
};
template <typename K, typename V>
struct trait_trivial_ctor< key_value_pair_t<K, V> >
{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
template <typename K, typename V>
struct trait_trivial_dtor< key_value_pair_t<K, V> >
{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
template <typename K, typename V>
struct trait_trivial_copy< key_value_pair_t<K, V> >
{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
template <typename K, typename V>
struct trait_trivial_move< key_value_pair_t<K, V> >
{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
// ---------------------------------------------------------------------------
/*
* Hash codes.
*/
typedef uint32_t hash_t;
template <typename TKey>
hash_t hash_type(const TKey& key);
/* Built-in hash code specializations */
#define ANDROID_INT32_HASH(T) \
template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
#define ANDROID_INT64_HASH(T) \
template <> inline hash_t hash_type(const T& value) { \
return hash_t((value >> 32) ^ value); }
#define ANDROID_REINTERPRET_HASH(T, R) \
template <> inline hash_t hash_type(const T& value) { \
R newValue; \
static_assert(sizeof(newValue) == sizeof(value), "size mismatch"); \
memcpy(&newValue, &value, sizeof(newValue)); \
return hash_type(newValue); \
}
ANDROID_INT32_HASH(bool)
ANDROID_INT32_HASH(int8_t)
ANDROID_INT32_HASH(uint8_t)
ANDROID_INT32_HASH(int16_t)
ANDROID_INT32_HASH(uint16_t)
ANDROID_INT32_HASH(int32_t)
ANDROID_INT32_HASH(uint32_t)
ANDROID_INT64_HASH(int64_t)
ANDROID_INT64_HASH(uint64_t)
ANDROID_REINTERPRET_HASH(float, uint32_t)
ANDROID_REINTERPRET_HASH(double, uint64_t)
template <typename T> inline hash_t hash_type(T* const & value) {
return hash_type(uintptr_t(value));
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_TYPE_HELPERS_H
+139
View File
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_UNICODE_H
#define ANDROID_UNICODE_H
#include <sys/types.h>
#include <stdint.h>
extern "C" {
// Standard string functions on char16_t strings.
int strcmp16(const char16_t *, const char16_t *);
int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
size_t strlen16(const char16_t *);
size_t strnlen16(const char16_t *, size_t);
char16_t *strstr16(const char16_t*, const char16_t*);
// Version of comparison that supports embedded NULs.
// This is different than strncmp() because we don't stop
// at a nul character and consider the strings to be different
// if the lengths are different (thus we need to supply the
// lengths of both strings). This can also be used when
// your string is not nul-terminated as it will have the
// equivalent result as strcmp16 (unlike strncmp16).
int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
/**
* Measure the length of a UTF-32 string in UTF-8. If the string is invalid
* such as containing a surrogate character, -1 will be returned.
*/
ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
/**
* Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
* large enough to store the string, the part of the "src" string is stored
* into "dst" as much as possible. See the examples for more detail.
* Returns the size actually used for storing the string.
* dst" is not nul-terminated when dst_len is fully used (like strncpy).
*
* \code
* Example 1
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" >= 7
* ->
* Returned value == 6
* "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
* (note that "dst" is nul-terminated)
*
* Example 2
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" == 5
* ->
* Returned value == 3
* "dst" becomes \xE3\x81\x82\0
* (note that "dst" is nul-terminated, but \u3044 is not stored in "dst"
* since "dst" does not have enough size to store the character)
*
* Example 3
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" == 6
* ->
* Returned value == 6
* "dst" becomes \xE3\x81\x82\xE3\x81\x84
* (note that "dst" is NOT nul-terminated, like strncpy)
* \endcode
*/
void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len);
/**
* Returns the unicode value at "index".
* Returns -1 when the index is invalid (equals to or more than "src_len").
* If returned value is positive, it is able to be converted to char32_t, which
* is unsigned. Then, if "next_index" is not NULL, the next index to be used is
* stored in "next_index". "next_index" can be NULL.
*/
int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
/**
* Returns the UTF-8 length of UTF-16 string "src".
*/
ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
/**
* Converts a UTF-16 string to UTF-8. The destination buffer must be large
* enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
* NUL terminator.
*/
void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len);
/**
* Returns the UTF-16 length of UTF-8 string "src". Returns -1 in case
* it's invalid utf8. No buffer over-read occurs because of bound checks. Using overreadIsFatal you
* can ask to log a message and fail in case the invalid utf8 could have caused an override if no
* bound checks were used (otherwise -1 is returned).
*/
ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen, bool overreadIsFatal = false);
/**
* Convert UTF-8 to UTF-16 including surrogate pairs.
* Returns a pointer to the end of the string (where a NUL terminator might go
* if you wanted to add one). At most dstLen characters are written; it won't emit half a surrogate
* pair. If dstLen == 0 nothing is written and dst is returned. If dstLen > SSIZE_MAX it aborts
* (this being probably a negative number returned as an error and casted to unsigned).
*/
char16_t* utf8_to_utf16_no_null_terminator(
const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
/**
* Convert UTF-8 to UTF-16 including surrogate pairs. At most dstLen - 1
* characters are written; it won't emit half a surrogate pair; and a NUL terminator is appended
* after. dstLen - 1 can be measured beforehand using utf8_to_utf16_length. Aborts if dstLen == 0
* (at least one character is needed for the NUL terminator) or dstLen > SSIZE_MAX (the latter
* case being likely a negative number returned as an error and casted to unsigned) . Returns a
* pointer to the NUL terminator.
*/
char16_t *utf8_to_utf16(
const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
}
#endif
+418
View File
@@ -0,0 +1,418 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_VECTOR_H
#define ANDROID_VECTOR_H
#include <stdint.h>
#include <sys/types.h>
// #include <log/log.h>
#include <utils/TypeHelpers.h>
#include <utils/VectorImpl.h>
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
/*
* Used to exclude some functions from CFI.
*/
#if __has_attribute(no_sanitize)
#define UTILS_VECTOR_NO_CFI __attribute__((no_sanitize("cfi")))
#else
#define UTILS_VECTOR_NO_CFI
#endif
// ---------------------------------------------------------------------------
namespace android {
template <typename TYPE>
class SortedVector;
/*!
* The main templated vector class ensuring type safety
* while making use of VectorImpl.
* This is the class users want to use.
*
* DO NOT USE: please use std::vector
*/
template <class TYPE>
class Vector : private VectorImpl
{
public:
typedef TYPE value_type;
/*!
* Constructors and destructors
*/
Vector();
Vector(const Vector<TYPE>& rhs);
explicit Vector(const SortedVector<TYPE>& rhs);
virtual ~Vector();
/*! copy operator */
Vector<TYPE>& operator=(const Vector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
Vector<TYPE>& operator=(const SortedVector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
/*
* empty the vector
*/
inline void clear() { VectorImpl::clear(); }
/*!
* vector stats
*/
//! returns number of items in the vector
inline size_t size() const { return VectorImpl::size(); }
//! returns whether or not the vector is empty
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
//! returns how many items can be stored without reallocating the backing store
inline size_t capacity() const { return VectorImpl::capacity(); }
//! sets the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
/*!
* set the size of the vector. items are appended with the default
* constructor, or removed from the end as needed.
*/
inline ssize_t resize(size_t size) { return VectorImpl::resize(size); }
/*!
* C-style array access
*/
//! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access
TYPE* editArray();
/*!
* accessors
*/
//! read-only access to an item at a given index
inline const TYPE& operator [] (size_t index) const;
//! alternate name for operator []
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
/*!
* modifying the array
*/
//! copy-on write support, grants write access to an item
TYPE& editItemAt(size_t index);
//! grants right access to the top of the stack (last element)
TYPE& editTop();
/*!
* append/insert another vector
*/
//! insert another vector at a given index
ssize_t insertVectorAt(const Vector<TYPE>& vector, size_t index);
//! append another vector at the end of this one
ssize_t appendVector(const Vector<TYPE>& vector);
//! insert an array at a given index
ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
//! append an array at the end of this vector
ssize_t appendArray(const TYPE* array, size_t length);
/*!
* add/insert/replace items
*/
//! insert one or several items initialized with their default constructor
inline ssize_t insertAt(size_t index, size_t numItems = 1);
//! insert one or several items initialized from a prototype item
ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
//! pop the top of the stack (removes the last element). No-op if the stack's empty
inline void pop();
//! pushes an item initialized with its default constructor
inline void push();
//! pushes an item on the top of the stack
void push(const TYPE& item);
//! same as push() but returns the index the item was added at (or an error)
inline ssize_t add();
//! same as push() but returns the index the item was added at (or an error)
ssize_t add(const TYPE& item);
//! replace an item with a new one initialized with its default constructor
inline ssize_t replaceAt(size_t index);
//! replace an item with a new one
ssize_t replaceAt(const TYPE& item, size_t index);
/*!
* remove items
*/
//! remove several items
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
/*!
* sort (stable) the array
*/
typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
inline status_t sort(compar_t cmp);
inline status_t sort(compar_r_t cmp, void* state);
// for debugging only
inline size_t getItemSize() const { return itemSize(); }
/*
* these inlines add some level of compatibility with STL. eventually
* we should probably turn things around.
*/
typedef TYPE* iterator;
typedef TYPE const* const_iterator;
inline iterator begin() { return editArray(); }
inline iterator end() { return editArray() + size(); }
inline const_iterator begin() const { return array(); }
inline const_iterator end() const { return array() + size(); }
inline void reserve(size_t n) { setCapacity(n); }
inline bool empty() const{ return isEmpty(); }
inline void push_back(const TYPE& item) { insertAt(item, size(), 1); }
inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
inline iterator erase(iterator pos) {
ssize_t index = removeItemsAt(static_cast<size_t>(pos-array()));
return begin() + index;
}
protected:
virtual void do_construct(void* storage, size_t num) const;
virtual void do_destroy(void* storage, size_t num) const;
virtual void do_copy(void* dest, const void* from, size_t num) const;
virtual void do_splat(void* dest, const void* item, size_t num) const;
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
};
// ---------------------------------------------------------------------------
// No user serviceable parts from here...
// ---------------------------------------------------------------------------
template<class TYPE> inline
Vector<TYPE>::Vector()
: VectorImpl(sizeof(TYPE),
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
)
{
}
template<class TYPE> inline
Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
: VectorImpl(rhs) {
}
template<class TYPE> inline
Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
: VectorImpl(static_cast<const VectorImpl&>(rhs)) {
}
template<class TYPE> inline
Vector<TYPE>::~Vector() {
finish_vector();
}
template <class TYPE>
inline Vector<TYPE>& Vector<TYPE>::operator=(const Vector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
{
VectorImpl::operator=(rhs);
return *this;
}
template <class TYPE>
inline Vector<TYPE>& Vector<TYPE>::operator=(
const SortedVector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
{
VectorImpl::operator=(static_cast<const VectorImpl&>(rhs));
return *this;
}
template<class TYPE> inline
const TYPE* Vector<TYPE>::array() const {
return static_cast<const TYPE *>(arrayImpl());
}
template<class TYPE> inline
TYPE* Vector<TYPE>::editArray() {
return static_cast<TYPE *>(editArrayImpl());
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::operator[](size_t index) const {
LOG_FATAL_IF(index>=size(),
"%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
int(index), int(size()));
return *(array() + index);
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::itemAt(size_t index) const {
return operator[](index);
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::top() const {
return *(array() + size() - 1);
}
template<class TYPE> inline
TYPE& Vector<TYPE>::editItemAt(size_t index) {
return *( static_cast<TYPE *>(editItemLocation(index)) );
}
template<class TYPE> inline
TYPE& Vector<TYPE>::editTop() {
return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
return VectorImpl::insertArrayAt(array, index, length);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
return VectorImpl::appendArray(array, length);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
return VectorImpl::insertAt(&item, index, numItems);
}
template<class TYPE> inline
void Vector<TYPE>::push(const TYPE& item) {
return VectorImpl::push(&item);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::add(const TYPE& item) {
return VectorImpl::add(&item);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
return VectorImpl::replaceAt(&item, index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
return VectorImpl::insertAt(index, numItems);
}
template<class TYPE> inline
void Vector<TYPE>::pop() {
VectorImpl::pop();
}
template<class TYPE> inline
void Vector<TYPE>::push() {
VectorImpl::push();
}
template<class TYPE> inline
ssize_t Vector<TYPE>::add() {
return VectorImpl::add();
}
template<class TYPE> inline
ssize_t Vector<TYPE>::replaceAt(size_t index) {
return VectorImpl::replaceAt(index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
return VectorImpl::removeItemsAt(index, count);
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_t>(cmp));
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_r_t>(cmp), state);
}
// ---------------------------------------------------------------------------
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_construct(void* storage, size_t num) const {
construct_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
destroy_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_VECTOR_H
@@ -0,0 +1,182 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_VECTOR_IMPL_H
#define ANDROID_VECTOR_IMPL_H
#include <assert.h>
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
// ---------------------------------------------------------------------------
// No user serviceable parts in here...
// ---------------------------------------------------------------------------
namespace android {
/*!
* Implementation of the guts of the vector<> class
* this ensures backward binary compatibility and
* reduces code size.
* For performance reasons, we expose mStorage and mCount
* so these fields are set in stone.
*
*/
class VectorImpl
{
public:
enum { // flags passed to the ctor
HAS_TRIVIAL_CTOR = 0x00000001,
HAS_TRIVIAL_DTOR = 0x00000002,
HAS_TRIVIAL_COPY = 0x00000004,
};
VectorImpl(size_t itemSize, uint32_t flags);
VectorImpl(const VectorImpl& rhs);
virtual ~VectorImpl();
/*! must be called from subclasses destructor */
void finish_vector();
VectorImpl& operator = (const VectorImpl& rhs);
/*! C-style array access */
inline const void* arrayImpl() const { return mStorage; }
void* editArrayImpl();
/*! vector stats */
inline size_t size() const { return mCount; }
inline bool isEmpty() const { return mCount == 0; }
size_t capacity() const;
ssize_t setCapacity(size_t size);
ssize_t resize(size_t size);
/*! append/insert another vector or array */
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
/*! add/insert/replace items */
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
void pop();
void push();
void push(const void* item);
ssize_t add();
ssize_t add(const void* item);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
/*! remove items */
ssize_t removeItemsAt(size_t index, size_t count = 1);
void clear();
const void* itemLocation(size_t index) const;
void* editItemLocation(size_t index);
typedef int (*compar_t)(const void* lhs, const void* rhs);
typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
status_t sort(compar_t cmp);
status_t sort(compar_r_t cmp, void* state);
protected:
size_t itemSize() const;
void release_storage();
virtual void do_construct(void* storage, size_t num) const = 0;
virtual void do_destroy(void* storage, size_t num) const = 0;
virtual void do_copy(void* dest, const void* from, size_t num) const = 0;
virtual void do_splat(void* dest, const void* item, size_t num) const = 0;
virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0;
virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0;
private:
void* _grow(size_t where, size_t amount);
void _shrink(size_t where, size_t amount);
inline void _do_construct(void* storage, size_t num) const;
inline void _do_destroy(void* storage, size_t num) const;
inline void _do_copy(void* dest, const void* from, size_t num) const;
inline void _do_splat(void* dest, const void* item, size_t num) const;
inline void _do_move_forward(void* dest, const void* from, size_t num) const;
inline void _do_move_backward(void* dest, const void* from, size_t num) const;
// These 2 fields are exposed in the inlines below,
// so they're set in stone.
void * mStorage; // base address of the vector
size_t mCount; // number of items
const uint32_t mFlags;
const size_t mItemSize;
};
class SortedVectorImpl : public VectorImpl
{
public:
SortedVectorImpl(size_t itemSize, uint32_t flags);
explicit SortedVectorImpl(const VectorImpl& rhs);
virtual ~SortedVectorImpl();
SortedVectorImpl& operator = (const SortedVectorImpl& rhs);
//! finds the index of an item
ssize_t indexOf(const void* item) const;
//! finds where this item should be inserted
size_t orderOf(const void* item) const;
//! add an item in the right place (or replaces it if there is one)
ssize_t add(const void* item);
//! merges a vector into this one
ssize_t merge(const VectorImpl& vector);
ssize_t merge(const SortedVectorImpl& vector);
//! removes an item
ssize_t remove(const void* item);
protected:
virtual int do_compare(const void* lhs, const void* rhs) const = 0;
private:
ssize_t _indexOrderOf(const void* item, size_t* order = nullptr) const;
// these are made private, because they can't be used on a SortedVector
// (they don't have an implementation either)
ssize_t add();
void pop();
void push();
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
};
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_VECTOR_IMPL_H
@@ -0,0 +1,639 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright (C) 2008 Google, Inc.
*
* Based on, but no longer compatible with, the original
* OpenBinder.org binder driver interface, which is:
*
* Copyright (c) 2005 Palmsource, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _UAPI_LINUX_BINDER_H
#define _UAPI_LINUX_BINDER_H
#include <linux/types.h>
#include <linux/ioctl.h>
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#define B_TYPE_LARGE 0x85
enum {
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE),
BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
};
/**
* enum flat_binder_object_shifts: shift values for flat_binder_object_flags
* @FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT: shift for getting scheduler policy.
*
*/
enum flat_binder_object_shifts {
FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT = 9,
};
/**
* enum flat_binder_object_flags - flags for use in flat_binder_object.flags
*/
enum flat_binder_object_flags {
/**
* @FLAT_BINDER_FLAG_PRIORITY_MASK: bit-mask for min scheduler priority
*
* These bits can be used to set the minimum scheduler priority
* at which transactions into this node should run. Valid values
* in these bits depend on the scheduler policy encoded in
* @FLAT_BINDER_FLAG_SCHED_POLICY_MASK.
*
* For SCHED_NORMAL/SCHED_BATCH, the valid range is between [-20..19]
* For SCHED_FIFO/SCHED_RR, the value can run between [1..99]
*/
FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
/**
* @FLAT_BINDER_FLAG_ACCEPTS_FDS: whether the node accepts fds.
*/
FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
/**
* @FLAT_BINDER_FLAG_SCHED_POLICY_MASK: bit-mask for scheduling policy
*
* These two bits can be used to set the min scheduling policy at which
* transactions on this node should run. These match the UAPI
* scheduler policy values, eg:
* 00b: SCHED_NORMAL
* 01b: SCHED_FIFO
* 10b: SCHED_RR
* 11b: SCHED_BATCH
*/
FLAT_BINDER_FLAG_SCHED_POLICY_MASK =
3U << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT,
/**
* @FLAT_BINDER_FLAG_INHERIT_RT: whether the node inherits RT policy
*
* Only when set, calls into this node will inherit a real-time
* scheduling policy from the caller (for synchronous transactions).
*/
FLAT_BINDER_FLAG_INHERIT_RT = 0x800,
/**
* @FLAT_BINDER_FLAG_TXN_SECURITY_CTX: request security contexts
*
* Only when set, causes senders to include their security
* context
*/
FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
};
#ifdef BINDER_IPC_32BIT
typedef __u32 binder_size_t;
typedef __u32 binder_uintptr_t;
#else
typedef __u64 binder_size_t;
typedef __u64 binder_uintptr_t;
#endif
/**
* struct binder_object_header - header shared by all binder metadata objects.
* @type: type of the object
*/
struct binder_object_header {
__u32 type;
};
/*
* This is the flattened representation of a Binder object for transfer
* between processes. The 'offsets' supplied as part of a binder transaction
* contains offsets into the data where these structures occur. The Binder
* driver takes care of re-writing the structure type and data as it moves
* between processes.
*/
struct flat_binder_object {
struct binder_object_header hdr;
__u32 flags;
/* 8 bytes of data. */
union {
binder_uintptr_t binder; /* local object */
__u32 handle; /* remote object */
};
/* extra data associated with local object */
binder_uintptr_t cookie;
};
/**
* struct binder_fd_object - describes a filedescriptor to be fixed up.
* @hdr: common header structure
* @pad_flags: padding to remain compatible with old userspace code
* @pad_binder: padding to remain compatible with old userspace code
* @fd: file descriptor
* @cookie: opaque data, used by user-space
*/
struct binder_fd_object {
struct binder_object_header hdr;
__u32 pad_flags;
union {
binder_uintptr_t pad_binder;
__u32 fd;
};
binder_uintptr_t cookie;
};
/* struct binder_buffer_object - object describing a userspace buffer
* @hdr: common header structure
* @flags: one or more BINDER_BUFFER_* flags
* @buffer: address of the buffer
* @length: length of the buffer
* @parent: index in offset array pointing to parent buffer
* @parent_offset: offset in @parent pointing to this buffer
*
* A binder_buffer object represents an object that the
* binder kernel driver can copy verbatim to the target
* address space. A buffer itself may be pointed to from
* within another buffer, meaning that the pointer inside
* that other buffer needs to be fixed up as well. This
* can be done by setting the BINDER_BUFFER_FLAG_HAS_PARENT
* flag in @flags, by setting @parent buffer to the index
* in the offset array pointing to the parent binder_buffer_object,
* and by setting @parent_offset to the offset in the parent buffer
* at which the pointer to this buffer is located.
*/
struct binder_buffer_object {
struct binder_object_header hdr;
__u32 flags;
binder_uintptr_t buffer;
binder_size_t length;
binder_size_t parent;
binder_size_t parent_offset;
};
enum {
BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
};
/* struct binder_fd_array_object - object describing an array of fds in a buffer
* @hdr: common header structure
* @pad: padding to ensure correct alignment
* @num_fds: number of file descriptors in the buffer
* @parent: index in offset array to buffer holding the fd array
* @parent_offset: start offset of fd array in the buffer
*
* A binder_fd_array object represents an array of file
* descriptors embedded in a binder_buffer_object. It is
* different from a regular binder_buffer_object because it
* describes a list of file descriptors to fix up, not an opaque
* blob of memory, and hence the kernel needs to treat it differently.
*
* An example of how this would be used is with Android's
* native_handle_t object, which is a struct with a list of integers
* and a list of file descriptors. The native_handle_t struct itself
* will be represented by a struct binder_buffer_objct, whereas the
* embedded list of file descriptors is represented by a
* struct binder_fd_array_object with that binder_buffer_object as
* a parent.
*/
struct binder_fd_array_object {
struct binder_object_header hdr;
__u32 pad;
binder_size_t num_fds;
binder_size_t parent;
binder_size_t parent_offset;
};
/*
* On 64-bit platforms where user code may run in 32-bits the driver must
* translate the buffer (and local binder) addresses appropriately.
*/
struct binder_write_read {
binder_size_t write_size; /* bytes to write */
binder_size_t write_consumed; /* bytes consumed by driver */
binder_uintptr_t write_buffer;
binder_size_t read_size; /* bytes to read */
binder_size_t read_consumed; /* bytes consumed by driver */
binder_uintptr_t read_buffer;
};
/* Use with BINDER_VERSION, driver fills in fields. */
struct binder_version {
/* driver protocol version -- increment with incompatible change */
__s32 protocol_version;
};
/* This is the current protocol version. */
#ifdef BINDER_IPC_32BIT
#define BINDER_CURRENT_PROTOCOL_VERSION 7
#else
#define BINDER_CURRENT_PROTOCOL_VERSION 8
#endif
/*
* Use with BINDER_GET_NODE_DEBUG_INFO, driver reads ptr, writes to all fields.
* Set ptr to NULL for the first call to get the info for the first node, and
* then repeat the call passing the previously returned value to get the next
* nodes. ptr will be 0 when there are no more nodes.
*/
struct binder_node_debug_info {
binder_uintptr_t ptr;
binder_uintptr_t cookie;
__u32 has_strong_ref;
__u32 has_weak_ref;
};
struct binder_node_info_for_ref {
__u32 handle;
__u32 strong_count;
__u32 weak_count;
__u32 reserved1;
__u32 reserved2;
__u32 reserved3;
};
struct binder_freeze_info {
__u32 pid;
__u32 enable;
__u32 timeout_ms;
};
struct binder_frozen_status_info {
__u32 pid;
/* process received sync transactions since last frozen
* bit 0: received sync transaction after being frozen
* bit 1: new pending sync transaction during freezing
*/
__u32 sync_recv;
/* process received async transactions since last frozen */
__u32 async_recv;
};
struct binder_frozen_state_info {
binder_uintptr_t cookie;
__u32 is_frozen;
__u32 reserved;
};
/* struct binder_extened_error - extended error information
* @id: identifier for the failed operation
* @command: command as defined by binder_driver_return_protocol
* @param: parameter holding a negative errno value
*
* Used with BINDER_GET_EXTENDED_ERROR. This extends the error information
* returned by the driver upon a failed operation. Userspace can pull this
* data to properly handle specific error scenarios.
*/
struct binder_extended_error {
__u32 id;
__u32 command;
__s32 param;
};
enum {
BINDER_WRITE_READ = _IOWR('b', 1, struct binder_write_read),
BINDER_SET_IDLE_TIMEOUT = _IOW('b', 3, __s64),
BINDER_SET_MAX_THREADS = _IOW('b', 5, __u32),
BINDER_SET_IDLE_PRIORITY = _IOW('b', 6, __s32),
BINDER_SET_CONTEXT_MGR = _IOW('b', 7, __s32),
BINDER_THREAD_EXIT = _IOW('b', 8, __s32),
BINDER_VERSION = _IOWR('b', 9, struct binder_version),
BINDER_GET_NODE_DEBUG_INFO = _IOWR('b', 11, struct binder_node_debug_info),
BINDER_GET_NODE_INFO_FOR_REF = _IOWR('b', 12, struct binder_node_info_for_ref),
BINDER_SET_CONTEXT_MGR_EXT = _IOW('b', 13, struct flat_binder_object),
BINDER_FREEZE = _IOW('b', 14, struct binder_freeze_info),
BINDER_GET_FROZEN_INFO = _IOWR('b', 15, struct binder_frozen_status_info),
BINDER_ENABLE_ONEWAY_SPAM_DETECTION = _IOW('b', 16, __u32),
BINDER_GET_EXTENDED_ERROR = _IOWR('b', 17, struct binder_extended_error),
};
/*
* NOTE: Two special error codes you should check for when calling
* in to the driver are:
*
* EINTR -- The operation has been interupted. This should be
* handled by retrying the ioctl() until a different error code
* is returned.
*
* ECONNREFUSED -- The driver is no longer accepting operations
* from your process. That is, the process is being destroyed.
* You should handle this by exiting from your process. Note
* that once this error code is returned, all further calls to
* the driver from any thread will return this same code.
*/
enum transaction_flags {
TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */
TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */
TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
TF_UPDATE_TXN = 0x40, /* update the outdated pending async txn */
};
struct binder_transaction_data {
/* The first two are only used for bcTRANSACTION and brTRANSACTION,
* identifying the target and contents of the transaction.
*/
union {
/* target descriptor of command transaction */
__u32 handle;
/* target descriptor of return transaction */
binder_uintptr_t ptr;
} target;
binder_uintptr_t cookie; /* target object cookie */
__u32 code; /* transaction command */
/* General information about the transaction. */
__u32 flags;
__kernel_pid_t sender_pid;
__kernel_uid32_t sender_euid;
binder_size_t data_size; /* number of bytes of data */
binder_size_t offsets_size; /* number of bytes of offsets */
/* If this transaction is inline, the data immediately
* follows here; otherwise, it ends with a pointer to
* the data buffer.
*/
union {
struct {
/* transaction data */
binder_uintptr_t buffer;
/* offsets from buffer to flat_binder_object structs */
binder_uintptr_t offsets;
} ptr;
__u8 buf[8];
} data;
};
struct binder_transaction_data_secctx {
struct binder_transaction_data transaction_data;
binder_uintptr_t secctx;
};
struct binder_transaction_data_sg {
struct binder_transaction_data transaction_data;
binder_size_t buffers_size;
};
struct binder_ptr_cookie {
binder_uintptr_t ptr;
binder_uintptr_t cookie;
};
struct binder_handle_cookie {
__u32 handle;
binder_uintptr_t cookie;
} __packed;
struct binder_pri_desc {
__s32 priority;
__u32 desc;
};
struct binder_pri_ptr_cookie {
__s32 priority;
binder_uintptr_t ptr;
binder_uintptr_t cookie;
};
enum binder_driver_return_protocol {
BR_ERROR = _IOR('r', 0, __s32),
/*
* int: error code
*/
BR_OK = _IO('r', 1),
/* No parameters! */
BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
struct binder_transaction_data_secctx),
/*
* binder_transaction_data_secctx: the received command.
*/
BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
/*
* binder_transaction_data: the received command.
*/
BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
/*
* not currently supported
* int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
* Else the remote object has acquired a primary reference.
*/
BR_DEAD_REPLY = _IO('r', 5),
/*
* The target of the last transaction (either a bcTRANSACTION or
* a bcATTEMPT_ACQUIRE) is no longer with us. No parameters.
*/
BR_TRANSACTION_COMPLETE = _IO('r', 6),
/*
* No parameters... always refers to the last transaction requested
* (including replies). Note that this will be sent even for
* asynchronous transactions.
*/
BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
/*
* void *: ptr to binder
* void *: cookie for binder
*/
BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
/*
* not currently supported
* int: priority
* void *: ptr to binder
* void *: cookie for binder
*/
BR_NOOP = _IO('r', 12),
/*
* No parameters. Do nothing and examine the next command. It exists
* primarily so that we can replace it with a BR_SPAWN_LOOPER command.
*/
BR_SPAWN_LOOPER = _IO('r', 13),
/*
* No parameters. The driver has determined that a process has no
* threads waiting to service incoming transactions. When a process
* receives this command, it must spawn a new service thread and
* register it via bcENTER_LOOPER.
*/
BR_FINISHED = _IO('r', 14),
/*
* not currently supported
* stop threadpool thread
*/
BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
/*
* void *: cookie
*/
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
/*
* void *: cookie
*/
BR_FAILED_REPLY = _IO('r', 17),
/*
* The last transaction (either a bcTRANSACTION or
* a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters.
*/
BR_FROZEN_REPLY = _IO('r', 18),
/*
* The target of the last sync transaction (either a bcTRANSACTION or
* a bcATTEMPT_ACQUIRE) is frozen. No parameters.
*/
BR_ONEWAY_SPAM_SUSPECT = _IO('r', 19),
/*
* Current process sent too many oneway calls to target, and the last
* asynchronous transaction makes the allocated async buffer size exceed
* detection threshold. No parameters.
*/
BR_TRANSACTION_PENDING_FROZEN = _IO('r', 20),
/*
* The target of the last async transaction is frozen. No parameters.
*/
BR_FROZEN_BINDER = _IOR('r', 21, struct binder_frozen_state_info),
/*
* The cookie and a boolean (is_frozen) that indicates whether the process
* transitioned into a frozen or an unfrozen state.
*/
BR_CLEAR_FREEZE_NOTIFICATION_DONE = _IOR('r', 22, binder_uintptr_t),
/*
* void *: cookie
*/
};
enum binder_driver_command_protocol {
BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
/*
* binder_transaction_data: the sent command.
*/
BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
/*
* not currently supported
* int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful.
* Else you have acquired a primary reference on the object.
*/
BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
/*
* void *: ptr to transaction data received on a read
*/
BC_INCREFS = _IOW('c', 4, __u32),
BC_ACQUIRE = _IOW('c', 5, __u32),
BC_RELEASE = _IOW('c', 6, __u32),
BC_DECREFS = _IOW('c', 7, __u32),
/*
* int: descriptor
*/
BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
/*
* void *: ptr to binder
* void *: cookie for binder
*/
BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
/*
* not currently supported
* int: priority
* int: descriptor
*/
BC_REGISTER_LOOPER = _IO('c', 11),
/*
* No parameters.
* Register a spawned looper thread with the device.
*/
BC_ENTER_LOOPER = _IO('c', 12),
BC_EXIT_LOOPER = _IO('c', 13),
/*
* No parameters.
* These two commands are sent as an application-level thread
* enters and exits the binder loop, respectively. They are
* used so the binder can have an accurate count of the number
* of looping threads it has available.
*/
BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14,
struct binder_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15,
struct binder_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
/*
* void *: cookie
*/
BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
/*
* binder_transaction_data_sg: the sent command.
*/
BC_REQUEST_FREEZE_NOTIFICATION =
_IOW('c', 19, struct binder_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_CLEAR_FREEZE_NOTIFICATION = _IOW('c', 20,
struct binder_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_FREEZE_NOTIFICATION_DONE = _IOW('c', 21, binder_uintptr_t),
/*
* void *: cookie
*/
};
#endif /* _UAPI_LINUX_BINDER_H */
+270
View File
@@ -0,0 +1,270 @@
#include "binder/Binder.h"
#include "binder/BpBinder.h"
#include "binder/IInterface.h"
#include "binder/IPCThreadState.h"
#include "binder/IServiceManager.h"
#include "binder/RpcSession.h"
#include "binder/Status.h"
namespace android {
IInterface::IInterface() {}
IInterface::~IInterface() {}
IBinder::IBinder() {}
IBinder::~IBinder() {}
sp<IInterface> IBinder::queryLocalInterface(const String16 &) {
return nullptr;
}
BBinder *IBinder::localBinder() {
return nullptr;
}
BpBinder *IBinder::remoteBinder() {
return nullptr;
}
bool IBinder::checkSubclass(const void *) const {
return false;
}
void IBinder::withLock(const std::function<void()> &) {}
#ifdef __LP64__
static_assert(sizeof(IBinder) == 24);
static_assert(sizeof(BBinder) == 40);
#else
static_assert(sizeof(IBinder) == 12);
static_assert(sizeof(BBinder) == 20);
#endif
BBinder::BBinder() {}
BBinder::~BBinder() {}
const String16 &BBinder::getInterfaceDescriptor() const {
__builtin_unreachable();
}
bool BBinder::isBinderAlive() const {
return false;
}
status_t BBinder::pingBinder() {
return 0;
}
status_t BBinder::dump(int, const Vector<String16> &) {
return 0;
}
status_t BBinder::transact(uint32_t, const Parcel &, Parcel *, uint32_t) {
return 0;
}
status_t BBinder::linkToDeath(const sp<DeathRecipient> &, void *, uint32_t) {
return 0;
}
status_t BBinder::unlinkToDeath(const wp<DeathRecipient> &, void *, uint32_t, wp<DeathRecipient> *) {
return 0;
}
void *BBinder::attachObject(const void *, void *, void *, object_cleanup_func) {
return nullptr;
}
void *BBinder::findObject(const void *) const {
return nullptr;
}
void *BBinder::detachObject(const void *) {
return nullptr;
}
void BBinder::withLock(const std::function<void()> &) {}
BBinder *BBinder::localBinder() {
return nullptr;
}
status_t BBinder::onTransact(uint32_t, const Parcel &, Parcel *, uint32_t) {
return 0;
}
IPCThreadState *IPCThreadState::self() {
return nullptr;
}
IPCThreadState *IPCThreadState::selfOrNull() {
return nullptr;
}
pid_t IPCThreadState::getCallingPid() const {
return 0;
}
const char *IPCThreadState::getCallingSid() const {
return nullptr;
}
uid_t IPCThreadState::getCallingUid() const {
return 0;
}
#ifdef __LP64__
static_assert(sizeof(Parcel) == 120);
#else
static_assert(sizeof(Parcel) == 60);
#endif
Parcel::Parcel() {}
Parcel::~Parcel() {}
const uint8_t *Parcel::data() const {
return nullptr;
}
size_t Parcel::dataSize() const {
return 0;
}
size_t Parcel::dataAvail() const {
return 0;
}
size_t Parcel::dataPosition() const {
return 0;
}
size_t Parcel::dataCapacity() const {
return 0;
}
size_t Parcel::dataBufferSize() const {
return 0;
}
status_t Parcel::setDataSize(size_t) {
return 0;
}
void Parcel::setDataPosition(size_t) const {}
status_t Parcel::setDataCapacity(size_t) {
return 0;
}
status_t Parcel::setData(const uint8_t *, size_t) {
return 0;
}
status_t Parcel::appendFrom(const Parcel *, size_t, size_t) {
return 0;
}
binder::Status Parcel::enforceNoDataAvail() const {
return {};
}
void Parcel::setEnforceNoDataAvail(bool) {}
void Parcel::freeData() {}
status_t Parcel::write(const void *, size_t) {
return 0;
}
void *Parcel::writeInplace(size_t) {
return nullptr;
}
status_t Parcel::writeInt32(int32_t) {
return 0;
}
status_t Parcel::writeUint32(uint32_t) {
return 0;
}
status_t Parcel::writeInt64(int64_t) {
return 0;
}
status_t Parcel::writeUint64(uint64_t) {
return 0;
}
status_t Parcel::writeFloat(float) {
return 0;
}
status_t Parcel::writeDouble(double) {
return 0;
}
status_t Parcel::writeCString(const char *) {
return 0;
}
status_t Parcel::writeString8(const char *, size_t) {
return 0;
}
status_t Parcel::writeStrongBinder(const sp<IBinder> &) {
return 0;
}
status_t Parcel::writeBool(bool) {
return 0;
}
status_t Parcel::writeChar(char16_t) {
return 0;
}
status_t Parcel::writeByte(int8_t) {
return 0;
}
status_t Parcel::writeNoException() {
return 0;
}
status_t Parcel::read(void *, size_t) const {
return 0;
}
const void *Parcel::readInplace(size_t) const {
return nullptr;
}
int32_t Parcel::readInt32() const {
return 0;
}
status_t Parcel::readInt32(int32_t *) const {
return 0;
}
uint32_t Parcel::readUint32() const {
return 0;
}
status_t Parcel::readUint32(uint32_t *) const {
return 0;
}
int64_t Parcel::readInt64() const {
return 0;
}
status_t Parcel::readInt64(int64_t *) const {
return 0;
}
uint64_t Parcel::readUint64() const {
return 0;
}
status_t Parcel::readUint64(uint64_t *) const {
return 0;
}
float Parcel::readFloat() const {
return 0;
}
status_t Parcel::readFloat(float *) const {
return 0;
}
double Parcel::readDouble() const {
return 0;
}
status_t Parcel::readDouble(double *) const {
return 0;
}
bool Parcel::readBool() const {
return 0;
}
status_t Parcel::readBool(bool *) const {
return 0;
}
char16_t Parcel::readChar() const {
return 0;
}
status_t Parcel::readChar(char16_t *) const {
return 0;
}
int8_t Parcel::readByte() const {
return 0;
}
status_t Parcel::readByte(int8_t *) const {
return 0;
}
sp<IBinder> Parcel::readStrongBinder() const {
return nullptr;
}
status_t Parcel::readStrongBinder(sp<IBinder> *) const {
return 0;
}
status_t Parcel::readNullableStrongBinder(sp<IBinder> *) const {
return 0;
}
int32_t Parcel::readExceptionCode() const {
return 0;
}
int Parcel::readFileDescriptor() const {
return 0;
}
IServiceManager::IServiceManager() {}
IServiceManager::~IServiceManager() {}
const String16 &IServiceManager::getInterfaceDescriptor() const {
__builtin_unreachable();
}
sp<IServiceManager> defaultServiceManager() {
return nullptr;
}
void setDefaultServiceManager(const sp<IServiceManager> &) {}
} // namespace android
+62
View File
@@ -0,0 +1,62 @@
#include "utils/RefBase.h"
#include "utils/String16.h"
#include "utils/String8.h"
#include "utils/StrongPointer.h"
namespace android {
void RefBase::incStrong(const void *id) const {}
void RefBase::incStrongRequireStrong(const void *id) const {}
void RefBase::decStrong(const void *id) const {}
void RefBase::forceIncStrong(const void *id) const {}
RefBase::weakref_type *RefBase::createWeak(const void *id) const {
return nullptr;
}
RefBase::weakref_type *RefBase::getWeakRefs() const {
return nullptr;
}
RefBase::RefBase() : mRefs(nullptr) {}
RefBase::~RefBase() {}
void RefBase::onFirstRef() {}
void RefBase::onLastStrongRef(const void *id) {}
bool RefBase::onIncStrongAttempted(uint32_t flags, const void *id) {
return false;
}
void RefBase::onLastWeakRef(const void *id) {}
RefBase *RefBase::weakref_type::refBase() const {
return nullptr;
}
void RefBase::weakref_type::incWeak(const void *id) {}
void RefBase::weakref_type::incWeakRequireWeak(const void *id) {}
void RefBase::weakref_type::decWeak(const void *id) {}
bool RefBase::weakref_type::attemptIncStrong(const void *id) {
return false;
}
bool RefBase::weakref_type::attemptIncWeak(const void *id) {
return false;
}
void sp_report_race() {}
String8::String8() {}
String16::String16() {}
String16::String16(const String16 &o) {}
String16::String16(String16 &&o) noexcept {}
String16::String16(const char *o) {}
String16::~String16() {}
} // namespace android