From 7a1ca59839f3ebb8fd73037c7380af958e03ef07 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Sat, 7 Oct 2023 01:09:39 +0000 Subject: [PATCH] libutils: split out libutils_binder Dependencies of libbinder, so we can build a core libbinder library, libbinder_sdk. This is preparing the way to move this part of libbinder together with binder code into a single project. Bug: 302720583 Change-Id: Icff078ac6e36c7f2b91cf815d5b9ed19b2e706e1 --- libutils/Android.bp | 48 +- libutils/TEST_MAPPING | 3 + libutils/binder/Android.bp | 126 +++ libutils/{ => binder}/Errors.cpp | 0 libutils/{ => binder}/Errors_test.cpp | 0 libutils/{ => binder}/FuzzFormatTypes.h | 0 libutils/{ => binder}/RefBase.cpp | 13 +- libutils/{ => binder}/RefBase_fuzz.cpp | 0 libutils/{ => binder}/RefBase_test.cpp | 0 libutils/{ => binder}/SharedBuffer.cpp | 0 libutils/{ => binder}/SharedBuffer.h | 0 libutils/{ => binder}/SharedBuffer_test.cpp | 0 libutils/{ => binder}/String16.cpp | 0 libutils/{ => binder}/String16_fuzz.cpp | 0 libutils/{ => binder}/String16_test.cpp | 0 libutils/{ => binder}/String8.cpp | 0 libutils/{ => binder}/String8_fuzz.cpp | 0 libutils/{ => binder}/String8_test.cpp | 0 libutils/{ => binder}/StrongPointer.cpp | 0 libutils/{ => binder}/StrongPointer_test.cpp | 0 libutils/{ => binder}/Unicode.cpp | 0 libutils/{ => binder}/Unicode_test.cpp | 0 libutils/{ => binder}/VectorImpl.cpp | 0 libutils/{ => binder}/Vector_benchmark.cpp | 0 libutils/{ => binder}/Vector_fuzz.cpp | 0 libutils/{ => binder}/Vector_test.cpp | 0 libutils/binder/include/utils/Errors.h | 77 ++ libutils/binder/include/utils/RefBase.h | 819 +++++++++++++++++ libutils/binder/include/utils/String16.h | 383 ++++++++ libutils/binder/include/utils/String8.h | 354 ++++++++ libutils/binder/include/utils/StrongPointer.h | 361 ++++++++ libutils/binder/include/utils/Unicode.h | 139 +++ libutils/binder/include/utils/Vector.h | 418 +++++++++ libutils/binder/include/utils/VectorImpl.h | 182 ++++ libutils/include/utils/Errors.h | 78 +- libutils/include/utils/RefBase.h | 820 +----------------- libutils/include/utils/String16.h | 384 +------- libutils/include/utils/String8.h | 355 +------- libutils/include/utils/StrongPointer.h | 362 +------- libutils/include/utils/Unicode.h | 140 +-- libutils/include/utils/Vector.h | 419 +-------- libutils/include/utils/VectorImpl.h | 183 +--- 42 files changed, 2878 insertions(+), 2786 deletions(-) create mode 100644 libutils/binder/Android.bp rename libutils/{ => binder}/Errors.cpp (100%) rename libutils/{ => binder}/Errors_test.cpp (100%) rename libutils/{ => binder}/FuzzFormatTypes.h (100%) rename libutils/{ => binder}/RefBase.cpp (99%) rename libutils/{ => binder}/RefBase_fuzz.cpp (100%) rename libutils/{ => binder}/RefBase_test.cpp (100%) rename libutils/{ => binder}/SharedBuffer.cpp (100%) rename libutils/{ => binder}/SharedBuffer.h (100%) rename libutils/{ => binder}/SharedBuffer_test.cpp (100%) rename libutils/{ => binder}/String16.cpp (100%) rename libutils/{ => binder}/String16_fuzz.cpp (100%) rename libutils/{ => binder}/String16_test.cpp (100%) rename libutils/{ => binder}/String8.cpp (100%) rename libutils/{ => binder}/String8_fuzz.cpp (100%) rename libutils/{ => binder}/String8_test.cpp (100%) rename libutils/{ => binder}/StrongPointer.cpp (100%) rename libutils/{ => binder}/StrongPointer_test.cpp (100%) rename libutils/{ => binder}/Unicode.cpp (100%) rename libutils/{ => binder}/Unicode_test.cpp (100%) rename libutils/{ => binder}/VectorImpl.cpp (100%) rename libutils/{ => binder}/Vector_benchmark.cpp (100%) rename libutils/{ => binder}/Vector_fuzz.cpp (100%) rename libutils/{ => binder}/Vector_test.cpp (100%) create mode 100644 libutils/binder/include/utils/Errors.h create mode 100644 libutils/binder/include/utils/RefBase.h create mode 100644 libutils/binder/include/utils/String16.h create mode 100644 libutils/binder/include/utils/String8.h create mode 100644 libutils/binder/include/utils/StrongPointer.h create mode 100644 libutils/binder/include/utils/Unicode.h create mode 100644 libutils/binder/include/utils/Vector.h create mode 100644 libutils/binder/include/utils/VectorImpl.h mode change 100644 => 120000 libutils/include/utils/Errors.h mode change 100644 => 120000 libutils/include/utils/RefBase.h mode change 100644 => 120000 libutils/include/utils/String16.h mode change 100644 => 120000 libutils/include/utils/String8.h mode change 100644 => 120000 libutils/include/utils/StrongPointer.h mode change 100644 => 120000 libutils/include/utils/Unicode.h mode change 100644 => 120000 libutils/include/utils/Vector.h mode change 100644 => 120000 libutils/include/utils/VectorImpl.h diff --git a/libutils/Android.bp b/libutils/Android.bp index 0f63df43d..b3ddda3b3 100644 --- a/libutils/Android.bp +++ b/libutils/Android.bp @@ -132,25 +132,19 @@ cc_defaults { ], native_bridge_supported: true, + whole_static_libs: ["libutils_binder"], + srcs: [ - "Errors.cpp", "FileMap.cpp", "JenkinsHash.cpp", "LightRefBase.cpp", "NativeHandle.cpp", "Printer.cpp", - "RefBase.cpp", - "SharedBuffer.cpp", "StopWatch.cpp", - "String8.cpp", - "String16.cpp", - "StrongPointer.cpp", "SystemClock.cpp", "Threads.cpp", "Timers.cpp", "Tokenizer.cpp", - "Unicode.cpp", - "VectorImpl.cpp", "misc.cpp", ], @@ -273,24 +267,6 @@ cc_fuzz { srcs: ["FileMap_fuzz.cpp"], } -cc_fuzz { - name: "libutils_fuzz_string8", - defaults: ["libutils_fuzz_defaults"], - srcs: ["String8_fuzz.cpp"], -} - -cc_fuzz { - name: "libutils_fuzz_string16", - defaults: ["libutils_fuzz_defaults"], - srcs: ["String16_fuzz.cpp"], -} - -cc_fuzz { - name: "libutils_fuzz_vector", - defaults: ["libutils_fuzz_defaults"], - srcs: ["Vector_fuzz.cpp"], -} - cc_fuzz { name: "libutils_fuzz_printer", defaults: ["libutils_fuzz_defaults"], @@ -315,12 +291,6 @@ cc_fuzz { ], } -cc_fuzz { - name: "libutils_fuzz_refbase", - defaults: ["libutils_fuzz_defaults"], - srcs: ["RefBase_fuzz.cpp"], -} - cc_fuzz { name: "libutils_fuzz_lrucache", defaults: ["libutils_fuzz_defaults"], @@ -340,18 +310,11 @@ cc_test { srcs: [ "BitSet_test.cpp", "CallStack_test.cpp", - "Errors_test.cpp", "FileMap_test.cpp", "LruCache_test.cpp", "Mutex_test.cpp", - "SharedBuffer_test.cpp", "Singleton_test.cpp", - "String16_test.cpp", - "String8_test.cpp", - "StrongPointer_test.cpp", "Timers_test.cpp", - "Unicode_test.cpp", - "Vector_test.cpp", ], target: { @@ -373,7 +336,6 @@ cc_test { linux: { srcs: [ "Looper_test.cpp", - "RefBase_test.cpp", ], }, host: { @@ -427,9 +389,3 @@ cc_test_library { shared_libs: ["libutils_test_singleton1"], header_libs: ["libutils_headers"], } - -cc_benchmark { - name: "libutils_benchmark", - srcs: ["Vector_benchmark.cpp"], - shared_libs: ["libutils"], -} diff --git a/libutils/TEST_MAPPING b/libutils/TEST_MAPPING index c8ef45cc3..472146f13 100644 --- a/libutils/TEST_MAPPING +++ b/libutils/TEST_MAPPING @@ -2,6 +2,9 @@ "presubmit": [ { "name": "libutils_test" + }, + { + "name": "libutils_binder_test" } ] } diff --git a/libutils/binder/Android.bp b/libutils/binder/Android.bp new file mode 100644 index 000000000..e2eddb332 --- /dev/null +++ b/libutils/binder/Android.bp @@ -0,0 +1,126 @@ +package { + default_applicable_licenses: ["system_core_libutils_license"], +} + +cc_defaults { + name: "libutils_binder_impl_defaults", + defaults: [ + "libutils_defaults", + "apex-lowest-min-sdk-version", + ], + native_bridge_supported: true, + + srcs: [ + "Errors.cpp", + "RefBase.cpp", + "SharedBuffer.cpp", + "String16.cpp", + "String8.cpp", + "StrongPointer.cpp", + "Unicode.cpp", + "VectorImpl.cpp", + ], + + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], + + afdo: true, +} + +cc_library { + name: "libutils_binder", + defaults: ["libutils_binder_impl_defaults"], +} + +cc_library { + name: "libutils_binder_test_compile", + defaults: ["libutils_binder_impl_defaults"], + + cflags: [ + "-DDEBUG_REFS=1", + ], + + visibility: [":__subpackages__"], +} + +cc_fuzz { + name: "libutils_fuzz_string8", + defaults: ["libutils_fuzz_defaults"], + srcs: ["String8_fuzz.cpp"], +} + +cc_fuzz { + name: "libutils_fuzz_string16", + defaults: ["libutils_fuzz_defaults"], + srcs: ["String16_fuzz.cpp"], +} + +cc_fuzz { + name: "libutils_fuzz_vector", + defaults: ["libutils_fuzz_defaults"], + srcs: ["Vector_fuzz.cpp"], +} + +cc_fuzz { + name: "libutils_fuzz_refbase", + defaults: ["libutils_fuzz_defaults"], + srcs: ["RefBase_fuzz.cpp"], +} + +cc_test { + name: "libutils_binder_test", + host_supported: true, + + srcs: [ + "Errors_test.cpp", + "SharedBuffer_test.cpp", + "String16_test.cpp", + "String8_test.cpp", + "StrongPointer_test.cpp", + "Unicode_test.cpp", + "Vector_test.cpp", + ], + + target: { + android: { + shared_libs: [ + "libbase", + "libcutils", + "liblog", + "liblzma", + "libutils", // which includes libutils_binder + "libz", + ], + }, + linux: { + srcs: [ + "RefBase_test.cpp", + ], + }, + host: { + static_libs: [ + "libbase", + "liblog", + "liblzma", + "libutils", // which includes libutils_binder + ], + }, + }, + + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + "-Wthread-safety", + ], + + test_suites: ["device-tests"], +} + +cc_benchmark { + name: "libutils_binder_benchmark", + srcs: ["Vector_benchmark.cpp"], + shared_libs: ["libutils"], +} diff --git a/libutils/Errors.cpp b/libutils/binder/Errors.cpp similarity index 100% rename from libutils/Errors.cpp rename to libutils/binder/Errors.cpp diff --git a/libutils/Errors_test.cpp b/libutils/binder/Errors_test.cpp similarity index 100% rename from libutils/Errors_test.cpp rename to libutils/binder/Errors_test.cpp diff --git a/libutils/FuzzFormatTypes.h b/libutils/binder/FuzzFormatTypes.h similarity index 100% rename from libutils/FuzzFormatTypes.h rename to libutils/binder/FuzzFormatTypes.h diff --git a/libutils/RefBase.cpp b/libutils/binder/RefBase.cpp similarity index 99% rename from libutils/RefBase.cpp rename to libutils/binder/RefBase.cpp index e0a2846d4..c7055fb48 100644 --- a/libutils/RefBase.cpp +++ b/libutils/binder/RefBase.cpp @@ -18,6 +18,7 @@ // #define LOG_NDEBUG 0 #include +#include #include @@ -27,8 +28,6 @@ #include #include -#include - #ifndef __unused #define __unused __attribute__((__unused__)) #endif @@ -310,7 +309,7 @@ public: String8 text; { - Mutex::Autolock _l(mMutex); + std::lock_guard _l(mMutex); char buf[128]; snprintf(buf, sizeof(buf), "Strong references on RefBase %p (weakref_type %p):\n", @@ -353,7 +352,7 @@ private: void addRef(ref_entry** refs, const void* id, int32_t mRef) { if (mTrackEnabled) { - AutoMutex _l(mMutex); + std::lock_guard _l(mMutex); ref_entry* ref = new ref_entry; // Reference count at the time of the snapshot, but before the @@ -372,7 +371,7 @@ private: void removeRef(ref_entry** refs, const void* id) { if (mTrackEnabled) { - AutoMutex _l(mMutex); + std::lock_guard _l(mMutex); ref_entry* const head = *refs; ref_entry* ref = head; @@ -406,7 +405,7 @@ private: void renameRefsId(ref_entry* r, const void* old_id, const void* new_id) { if (mTrackEnabled) { - AutoMutex _l(mMutex); + std::lock_guard _l(mMutex); ref_entry* ref = r; while (ref != NULL) { if (ref->id == old_id) { @@ -434,7 +433,7 @@ private: } } - mutable Mutex mMutex; + mutable std::mutex mMutex; ref_entry* mStrongRefs; ref_entry* mWeakRefs; diff --git a/libutils/RefBase_fuzz.cpp b/libutils/binder/RefBase_fuzz.cpp similarity index 100% rename from libutils/RefBase_fuzz.cpp rename to libutils/binder/RefBase_fuzz.cpp diff --git a/libutils/RefBase_test.cpp b/libutils/binder/RefBase_test.cpp similarity index 100% rename from libutils/RefBase_test.cpp rename to libutils/binder/RefBase_test.cpp diff --git a/libutils/SharedBuffer.cpp b/libutils/binder/SharedBuffer.cpp similarity index 100% rename from libutils/SharedBuffer.cpp rename to libutils/binder/SharedBuffer.cpp diff --git a/libutils/SharedBuffer.h b/libutils/binder/SharedBuffer.h similarity index 100% rename from libutils/SharedBuffer.h rename to libutils/binder/SharedBuffer.h diff --git a/libutils/SharedBuffer_test.cpp b/libutils/binder/SharedBuffer_test.cpp similarity index 100% rename from libutils/SharedBuffer_test.cpp rename to libutils/binder/SharedBuffer_test.cpp diff --git a/libutils/String16.cpp b/libutils/binder/String16.cpp similarity index 100% rename from libutils/String16.cpp rename to libutils/binder/String16.cpp diff --git a/libutils/String16_fuzz.cpp b/libutils/binder/String16_fuzz.cpp similarity index 100% rename from libutils/String16_fuzz.cpp rename to libutils/binder/String16_fuzz.cpp diff --git a/libutils/String16_test.cpp b/libutils/binder/String16_test.cpp similarity index 100% rename from libutils/String16_test.cpp rename to libutils/binder/String16_test.cpp diff --git a/libutils/String8.cpp b/libutils/binder/String8.cpp similarity index 100% rename from libutils/String8.cpp rename to libutils/binder/String8.cpp diff --git a/libutils/String8_fuzz.cpp b/libutils/binder/String8_fuzz.cpp similarity index 100% rename from libutils/String8_fuzz.cpp rename to libutils/binder/String8_fuzz.cpp diff --git a/libutils/String8_test.cpp b/libutils/binder/String8_test.cpp similarity index 100% rename from libutils/String8_test.cpp rename to libutils/binder/String8_test.cpp diff --git a/libutils/StrongPointer.cpp b/libutils/binder/StrongPointer.cpp similarity index 100% rename from libutils/StrongPointer.cpp rename to libutils/binder/StrongPointer.cpp diff --git a/libutils/StrongPointer_test.cpp b/libutils/binder/StrongPointer_test.cpp similarity index 100% rename from libutils/StrongPointer_test.cpp rename to libutils/binder/StrongPointer_test.cpp diff --git a/libutils/Unicode.cpp b/libutils/binder/Unicode.cpp similarity index 100% rename from libutils/Unicode.cpp rename to libutils/binder/Unicode.cpp diff --git a/libutils/Unicode_test.cpp b/libutils/binder/Unicode_test.cpp similarity index 100% rename from libutils/Unicode_test.cpp rename to libutils/binder/Unicode_test.cpp diff --git a/libutils/VectorImpl.cpp b/libutils/binder/VectorImpl.cpp similarity index 100% rename from libutils/VectorImpl.cpp rename to libutils/binder/VectorImpl.cpp diff --git a/libutils/Vector_benchmark.cpp b/libutils/binder/Vector_benchmark.cpp similarity index 100% rename from libutils/Vector_benchmark.cpp rename to libutils/binder/Vector_benchmark.cpp diff --git a/libutils/Vector_fuzz.cpp b/libutils/binder/Vector_fuzz.cpp similarity index 100% rename from libutils/Vector_fuzz.cpp rename to libutils/binder/Vector_fuzz.cpp diff --git a/libutils/Vector_test.cpp b/libutils/binder/Vector_test.cpp similarity index 100% rename from libutils/Vector_test.cpp rename to libutils/binder/Vector_test.cpp diff --git a/libutils/binder/include/utils/Errors.h b/libutils/binder/include/utils/Errors.h new file mode 100644 index 000000000..22fb36d25 --- /dev/null +++ b/libutils/binder/include/utils/Errors.h @@ -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 +#include +#include +#include + +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 diff --git a/libutils/binder/include/utils/RefBase.h b/libutils/binder/include/utils/RefBase.h new file mode 100644 index 000000000..5e3fa7d13 --- /dev/null +++ b/libutils/binder/include/utils/RefBase.h @@ -0,0 +1,819 @@ +/* + * 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 . + +// 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) { +// std::lock_guard 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) { +// std::unique_lock lock(mMutex); +// sp 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), 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. + +// 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 myFoo = sp::make(/*args*/); +// +// // if you need a weak pointer, it must be constructed from a strong +// // pointer +// wp 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 thiz = sp::fromExisting(this); +// } +// + +#ifndef ANDROID_REF_BASE_H +#define ANDROID_REF_BASE_H + +#include +#include +#include +#include // for common_type. + +#include +#include +#include +#include + +// LightRefBase used to be declared in this header, so we have to include it +#include + +#include +#include + +// --------------------------------------------------------------------------- +namespace android { + +// --------------------------------------------------------------------------- + +#define COMPARE_WEAK(_op_) \ +template \ +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 class comparator, typename T, typename U> +static inline bool _wp_compare_(T* a, U* b) { + return comparator::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 \ +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 +class wp +{ +public: + typedef typename RefBase::weakref_type weakref_type; + + inline 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 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 + wp(U* other); // NOLINT(implicit) + wp& operator=(T* other); + template + wp& operator=(U* other); +#endif + + wp(const wp& other); + explicit wp(const sp& other); + + template wp(const sp& other); // NOLINT(implicit) + template wp(const wp& other); // NOLINT(implicit) + + ~wp(); + + // Assignment + + wp& operator = (const wp& other); + wp& operator = (const sp& other); + + template wp& operator = (const wp& other); + template wp& operator = (const sp& other); + + void set_object_and_refs(T* other, weakref_type* refs); + + // promotion to sp + + sp 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 + inline bool operator == (const wp& o) const { + return m_refs == o.m_refs; // Implies m_ptr == o.mptr; see invariants below. + } + + template + inline bool operator == (const sp& 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 + inline bool operator != (const sp& o) const { + return !(*this == o); + } + + template + inline bool operator > (const wp& o) const { + if (m_ptr == o.m_ptr) { + return _wp_compare_(m_refs, o.m_refs); + } else { + return _wp_compare_(m_ptr, o.m_ptr); + } + } + + template + inline bool operator < (const wp& o) const { + if (m_ptr == o.m_ptr) { + return _wp_compare_(m_refs, o.m_refs); + } else { + return _wp_compare_(m_ptr, o.m_ptr); + } + } + template inline bool operator != (const wp& o) const { return !operator == (o); } + template inline bool operator <= (const wp& o) const { return !operator > (o); } + template inline bool operator >= (const wp& o) const { return !operator < (o); } + +private: + template friend class sp; + template 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 +wp wp::fromExisting(T* other) { + if (!other) return nullptr; + + auto refs = other->getWeakRefs(); + refs->incWeakRequireWeak(other); + + wp ret; + ret.m_ptr = other; + ret.m_refs = refs; + return ret; +} + +#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION) +template +wp::wp(T* other) + : m_ptr(other) +{ + m_refs = other ? m_refs = other->createWeak(this) : nullptr; +} + +template +template +wp::wp(U* other) : m_ptr(other) { + m_refs = other ? other->createWeak(this) : nullptr; +} + +template +wp& wp::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 +template +wp& wp::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 +wp::wp(const wp& other) + : m_ptr(other.m_ptr), m_refs(other.m_refs) +{ + if (m_ptr) m_refs->incWeak(this); +} + +template +wp::wp(const sp& other) + : m_ptr(other.m_ptr) +{ + m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr; +} + +template template +wp::wp(const wp& other) + : m_ptr(other.m_ptr) +{ + if (m_ptr) { + m_refs = other.m_refs; + m_refs->incWeak(this); + } else { + m_refs = nullptr; + } +} + +template template +wp::wp(const sp& other) + : m_ptr(other.m_ptr) +{ + m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr; +} + +template +wp::~wp() +{ + if (m_ptr) m_refs->decWeak(this); +} + +template +wp& wp::operator = (const wp& 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 +wp& wp::operator = (const sp& 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 template +wp& wp::operator = (const wp& 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 template +wp& wp::operator = (const sp& other) +{ + weakref_type* newRefs = + other != nullptr ? other->createWeak(this) : 0; + U* otherPtr(other.m_ptr); + if (m_ptr) m_refs->decWeak(this); + m_ptr = otherPtr; + m_refs = newRefs; + return *this; +} + +template +void wp::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 +sp wp::promote() const +{ + sp result; + if (m_ptr && m_refs->attemptIncStrong(&result)) { + result.set_pointer(m_ptr); + } + return result; +} + +template +void wp::clear() +{ + if (m_ptr) { + m_refs->decWeak(this); + m_refs = 0; + m_ptr = 0; + } +} + +// --------------------------------------------------------------------------- + +// 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 or wp when TYPE is a descendant of RefBase: + // Using a sp override doesn't work; it's a bit like we wanted + // a template template... + + template static inline + void move_references(sp* dest, sp const* src, size_t n) { + + class Renamer : public ReferenceRenamer { + sp* d_; + sp 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* d, sp const* s) : d_(d), s_(s) { } + virtual ~Renamer() { } + }; + + memmove(dest, src, n*sizeof(sp)); + TYPE::renameRefs(n, Renamer(dest, src)); + } + + + template static inline + void move_references(wp* dest, wp const* src, size_t n) { + + class Renamer : public ReferenceRenamer { + wp* d_; + wp 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* rd, wp const* rs) : d_(rd), s_(rs) { } + virtual ~Renamer() { } + }; + + memmove(dest, src, n*sizeof(wp)); + 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 inline +void move_forward_type(sp* d, sp const* s, size_t n) { + ReferenceMover::move_references(d, s, n); +} + +template inline +void move_backward_type(sp* d, sp const* s, size_t n) { + ReferenceMover::move_references(d, s, n); +} + +template inline +void move_forward_type(wp* d, wp const* s, size_t n) { + ReferenceMover::move_references(d, s, n); +} + +template inline +void move_backward_type(wp* d, wp const* s, size_t n) { + ReferenceMover::move_references(d, s, n); +} + +} // namespace android + +namespace libutilsinternal { +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : 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::make(...)` instead. +// +// Note: We exclude incomplete types because `std::is_base_of` is undefined in +// that case. + +template ::value, bool>::value = true, + typename std::enable_if::value, bool>::value = true> +shared_ptr make_shared(Args...) { // SEE COMMENT ABOVE. + static_assert(!std::is_base_of::value, "Must use RefBase with sp<>"); +} + +template ::value, bool>::value = true, + typename std::enable_if::value, bool>::value = true> +unique_ptr make_unique(Args...) { // SEE COMMENT ABOVE. + static_assert(!std::is_base_of::value, "Must use RefBase with sp<>"); +} + +} // namespace std + +// --------------------------------------------------------------------------- + +#endif // ANDROID_REF_BASE_H diff --git a/libutils/binder/include/utils/String16.h b/libutils/binder/include/utils/String16.h new file mode 100644 index 000000000..c7135766b --- /dev/null +++ b/libutils/binder/include/utils/String16.h @@ -0,0 +1,383 @@ +/* + * 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 +#include + +#include +#include +#include + +#if __has_include() +#include +#define HAS_STRING_VIEW +#endif + +// --------------------------------------------------------------------------- + +namespace android { + +// --------------------------------------------------------------------------- + +template +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; + + 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; + + inline operator const char16_t*() const; + +#ifdef HAS_STRING_VIEW + // 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; +#endif + + // 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 + 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&) = default; + }; + + /* + * Helper function for constructing a StaticData object. + */ + template + static constexpr const StaticData makeStaticData(const char16_t (&s)[N]) { + StaticData 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 + explicit constexpr String16(const StaticData& 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 +class StaticString16 : public String16 { +public: + constexpr StaticString16(const char16_t (&s)[N]) : String16(mData), mData(makeStaticData(s)) {} + + constexpr StaticString16(const StaticString16& other) + : String16(mData), mData(other.mData) {} + + constexpr StaticString16(const StaticString16&&) = 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 mData; +}; + +template +StaticString16(const F&)->StaticString16; + +// --------------------------------------------------------------------------- +// 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; +} + +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; +} + +inline String16::operator const char16_t*() const +{ + return mString; +} + +inline String16::operator std::u16string_view() const +{ + return {mString, length()}; +} + +} // namespace android + +// --------------------------------------------------------------------------- + +#undef HAS_STRING_VIEW + +#endif // ANDROID_STRING16_H diff --git a/libutils/binder/include/utils/String8.h b/libutils/binder/include/utils/String8.h new file mode 100644 index 000000000..6d250723b --- /dev/null +++ b/libutils/binder/include/utils/String8.h @@ -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. + */ + +#ifndef ANDROID_STRING8_H +#define ANDROID_STRING8_H + +#include + +#include +#include +#include + +#include // for strcmp +#include + +#if __has_include() +#include +#define HAS_STRING +#endif + +#if __has_include() +#include +#define HAS_STRING_VIEW +#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(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; + + 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; + + inline operator const char*() const; + +#ifdef HAS_STRING_VIEW + inline explicit operator std::string_view() const; +#endif + + 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; +} + +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; +} + +inline String8::operator const char*() const +{ + return mString; +} + +#ifdef HAS_STRING_VIEW +inline String8::operator std::string_view() const +{ + return {mString, length()}; +} +#endif + +} // namespace android + +// --------------------------------------------------------------------------- + +#undef HAS_STRING +#undef HAS_STRING_VIEW + +#endif // ANDROID_STRING8_H diff --git a/libutils/binder/include/utils/StrongPointer.h b/libutils/binder/include/utils/StrongPointer.h new file mode 100644 index 000000000..54aa691e0 --- /dev/null +++ b/libutils/binder/include/utils/StrongPointer.h @@ -0,0 +1,361 @@ +/* + * 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 +#include // for common_type. + +// --------------------------------------------------------------------------- +namespace android { + +template class wp; + +// --------------------------------------------------------------------------- + +template +class sp { +public: + inline 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 = new Foo(...); // DO NOT DO THIS + // + // Instead, prefer to do this: + // + // sp foo = sp::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; + template + static inline sp 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 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 + sp(U* other); // NOLINT(implicit) + sp& operator=(T* other); + template + sp& operator=(U* other); +#endif + + sp(const sp& other); + sp(sp&& other) noexcept; + + template sp(const sp& other); // NOLINT(implicit) + template sp(sp&& 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 + static inline sp cast(const sp& other); + + ~sp(); + + // Assignment + + sp& operator = (const sp& other); + sp& operator=(sp&& other) noexcept; + + template sp& operator = (const sp& other); + template sp& operator = (sp&& other); + + //! Special optimization for use by ProcessState (and nobody else). + void force_set(T* other); + + // Reset + + void clear(); + + // 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 + inline bool operator == (const wp& o) const { + return o == *this; + } + + template + inline bool operator != (const wp& o) const { + return o != *this; + } + +private: + template friend class sp; + template friend class wp; + void set_pointer(T* ptr); + T* m_ptr; +}; + +#define COMPARE_STRONG(_op_) \ + template \ + static inline bool operator _op_(const sp& t, const sp& u) { \ + return t.get() _op_ u.get(); \ + } \ + template \ + static inline bool operator _op_(const T* t, const sp& u) { \ + return t _op_ u.get(); \ + } \ + template \ + static inline bool operator _op_(const sp& t, const U* u) { \ + return t.get() _op_ u; \ + } \ + template \ + static inline bool operator _op_(const sp& t, std::nullptr_t) { \ + return t.get() _op_ nullptr; \ + } \ + template \ + static inline bool operator _op_(std::nullptr_t, const sp& t) { \ + return nullptr _op_ t.get(); \ + } + +template