src: cpp: Pull required headers from AOSP
tag: android-16.0.0_r1 Signed-off-by: Dakkshesh <beakthoven@gmail.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
This project is licensed under the GNU General Public License v3.0
|
||||
(see LICENSE file).
|
||||
|
||||
Third-party components:
|
||||
-----------------------
|
||||
|
||||
1. Portions of this project include code from the Android Open Source Project (AOSP) located in:
|
||||
app/src/main/cpp/external/AOSP/
|
||||
The corresponding Apache License 2.0 is provided in:
|
||||
app/src/main/cpp/external/AOSP/LICENSE
|
||||
|
||||
2. This project includes the LSPlt library as a Git submodule located in:
|
||||
app/src/main/cpp/external/LSPlt/
|
||||
LSPlt is licensed under the GNU Lesser General Public License v3.0 (LGPLv3).
|
||||
The license can be viewed at:
|
||||
https://github.com/LSPosed/LSPlt/blob/master/LICENSE
|
||||
+202
@@ -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")));
|
||||
@@ -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,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
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -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,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,298 @@
|
||||
/*
|
||||
* 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.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
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 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 do not use this as a security identifier! PID is unreliable
|
||||
* as it may be re-used. This should mostly be used for debugging.
|
||||
*
|
||||
* 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,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
|
||||
+1674
File diff suppressed because it is too large
Load Diff
@@ -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,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,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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user