summaryrefslogtreecommitdiffstats
path: root/libutils
diff options
context:
space:
mode:
Diffstat (limited to 'libutils')
-rw-r--r--libutils/Android.bp16
-rw-r--r--libutils/BlobCache.cpp379
-rw-r--r--libutils/CallStack.cpp3
-rw-r--r--libutils/LinearTransform.cpp282
-rw-r--r--libutils/Looper.cpp15
-rw-r--r--libutils/NativeHandle.cpp8
-rw-r--r--libutils/Printer.cpp2
-rw-r--r--libutils/ProcessCallStack.cpp11
-rw-r--r--libutils/PropertyMap.cpp4
-rw-r--r--libutils/RefBase.cpp11
-rw-r--r--libutils/SharedBuffer.cpp28
-rw-r--r--libutils/StopWatch.cpp6
-rw-r--r--libutils/String16.cpp4
-rw-r--r--libutils/String8.cpp2
-rw-r--r--libutils/SystemClock.cpp10
-rw-r--r--libutils/Threads.cpp11
-rw-r--r--libutils/Timers.cpp5
-rw-r--r--libutils/Tokenizer.cpp6
-rw-r--r--libutils/Trace.cpp5
-rw-r--r--libutils/Unicode.cpp3
-rw-r--r--libutils/VectorImpl.cpp4
-rw-r--r--libutils/include/utils/BlobCache.h249
-rw-r--r--libutils/include/utils/Flattenable.h4
-rw-r--r--libutils/include/utils/LightRefBase.h72
-rw-r--r--libutils/include/utils/LinearTransform.h64
-rw-r--r--libutils/include/utils/NativeHandle.h4
-rw-r--r--libutils/include/utils/RefBase.h77
-rw-r--r--libutils/include/utils/Singleton.h5
-rw-r--r--libutils/include/utils/SortedVector.h63
-rw-r--r--libutils/include/utils/StrongPointer.h6
-rw-r--r--libutils/include/utils/Trace.h26
-rw-r--r--libutils/include/utils/TypeHelpers.h10
-rw-r--r--libutils/include/utils/Vector.h60
-rw-r--r--libutils/misc.cpp49
-rw-r--r--libutils/tests/Android.bp1
-rw-r--r--libutils/tests/BlobCache_test.cpp425
36 files changed, 281 insertions, 1649 deletions
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 109ac3326..7d293efa7 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -18,12 +18,10 @@ cc_library_headers {
host_supported: true,
header_libs: [
- "liblog_headers",
"libsystem_headers",
"libcutils_headers"
],
export_header_lib_headers: [
- "liblog_headers",
"libsystem_headers",
"libcutils_headers"
],
@@ -52,7 +50,6 @@ cc_library {
"CallStack.cpp",
"FileMap.cpp",
"JenkinsHash.cpp",
- "LinearTransform.cpp",
"NativeHandle.cpp",
"Printer.cpp",
"PropertyMap.cpp",
@@ -74,11 +71,11 @@ cc_library {
cflags: ["-Werror"],
include_dirs: ["external/safe-iop/include"],
- header_libs: ["libutils_headers"],
- export_header_lib_headers: ["libutils_headers"],
-
- shared_libs: [
- "liblog",
+ header_libs: [
+ "libutils_headers",
+ ],
+ export_header_lib_headers: [
+ "libutils_headers",
],
arch: {
@@ -90,7 +87,6 @@ cc_library {
target: {
android: {
srcs: [
- "BlobCache.cpp",
"Looper.cpp",
"ProcessCallStack.cpp",
"Trace.cpp",
@@ -102,6 +98,8 @@ cc_library {
"libbacktrace",
"libcutils",
"libdl",
+ "liblog",
+ "libvndksupport",
],
sanitize: {
diff --git a/libutils/BlobCache.cpp b/libutils/BlobCache.cpp
deleted file mode 100644
index 126995b8c..000000000
--- a/libutils/BlobCache.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- ** Copyright 2011, 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.
- */
-
-#define LOG_TAG "BlobCache"
-//#define LOG_NDEBUG 0
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <utils/BlobCache.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <cutils/properties.h>
-
-namespace android {
-
-// BlobCache::Header::mMagicNumber value
-static const uint32_t blobCacheMagic = ('_' << 24) + ('B' << 16) + ('b' << 8) + '$';
-
-// BlobCache::Header::mBlobCacheVersion value
-static const uint32_t blobCacheVersion = 3;
-
-// BlobCache::Header::mDeviceVersion value
-static const uint32_t blobCacheDeviceVersion = 1;
-
-BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
- mMaxKeySize(maxKeySize),
- mMaxValueSize(maxValueSize),
- mMaxTotalSize(maxTotalSize),
- mTotalSize(0) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-#ifdef _WIN32
- srand(now);
-#else
- mRandState[0] = (now >> 0) & 0xFFFF;
- mRandState[1] = (now >> 16) & 0xFFFF;
- mRandState[2] = (now >> 32) & 0xFFFF;
-#endif
- ALOGV("initializing random seed using %lld", (unsigned long long)now);
-}
-
-void BlobCache::set(const void* key, size_t keySize, const void* value,
- size_t valueSize) {
- if (mMaxKeySize < keySize) {
- ALOGV("set: not caching because the key is too large: %zu (limit: %zu)",
- keySize, mMaxKeySize);
- return;
- }
- if (mMaxValueSize < valueSize) {
- ALOGV("set: not caching because the value is too large: %zu (limit: %zu)",
- valueSize, mMaxValueSize);
- return;
- }
- if (mMaxTotalSize < keySize + valueSize) {
- ALOGV("set: not caching because the combined key/value size is too "
- "large: %zu (limit: %zu)", keySize + valueSize, mMaxTotalSize);
- return;
- }
- if (keySize == 0) {
- ALOGW("set: not caching because keySize is 0");
- return;
- }
- if (valueSize <= 0) {
- ALOGW("set: not caching because valueSize is 0");
- return;
- }
-
- sp<Blob> dummyKey(new Blob(key, keySize, false));
- CacheEntry dummyEntry(dummyKey, NULL);
-
- while (true) {
- ssize_t index = mCacheEntries.indexOf(dummyEntry);
- if (index < 0) {
- // Create a new cache entry.
- sp<Blob> keyBlob(new Blob(key, keySize, true));
- sp<Blob> valueBlob(new Blob(value, valueSize, true));
- size_t newTotalSize = mTotalSize + keySize + valueSize;
- if (mMaxTotalSize < newTotalSize) {
- if (isCleanable()) {
- // Clean the cache and try again.
- clean();
- continue;
- } else {
- ALOGV("set: not caching new key/value pair because the "
- "total cache size limit would be exceeded: %zu "
- "(limit: %zu)",
- keySize + valueSize, mMaxTotalSize);
- break;
- }
- }
- mCacheEntries.add(CacheEntry(keyBlob, valueBlob));
- mTotalSize = newTotalSize;
- ALOGV("set: created new cache entry with %zu byte key and %zu byte value",
- keySize, valueSize);
- } else {
- // Update the existing cache entry.
- sp<Blob> valueBlob(new Blob(value, valueSize, true));
- sp<Blob> oldValueBlob(mCacheEntries[index].getValue());
- size_t newTotalSize = mTotalSize + valueSize - oldValueBlob->getSize();
- if (mMaxTotalSize < newTotalSize) {
- if (isCleanable()) {
- // Clean the cache and try again.
- clean();
- continue;
- } else {
- ALOGV("set: not caching new value because the total cache "
- "size limit would be exceeded: %zu (limit: %zu)",
- keySize + valueSize, mMaxTotalSize);
- break;
- }
- }
- mCacheEntries.editItemAt(index).setValue(valueBlob);
- mTotalSize = newTotalSize;
- ALOGV("set: updated existing cache entry with %zu byte key and %zu byte "
- "value", keySize, valueSize);
- }
- break;
- }
-}
-
-size_t BlobCache::get(const void* key, size_t keySize, void* value,
- size_t valueSize) {
- if (mMaxKeySize < keySize) {
- ALOGV("get: not searching because the key is too large: %zu (limit %zu)",
- keySize, mMaxKeySize);
- return 0;
- }
- sp<Blob> dummyKey(new Blob(key, keySize, false));
- CacheEntry dummyEntry(dummyKey, NULL);
- ssize_t index = mCacheEntries.indexOf(dummyEntry);
- if (index < 0) {
- ALOGV("get: no cache entry found for key of size %zu", keySize);
- return 0;
- }
-
- // The key was found. Return the value if the caller's buffer is large
- // enough.
- sp<Blob> valueBlob(mCacheEntries[index].getValue());
- size_t valueBlobSize = valueBlob->getSize();
- if (valueBlobSize <= valueSize) {
- ALOGV("get: copying %zu bytes to caller's buffer", valueBlobSize);
- memcpy(value, valueBlob->getData(), valueBlobSize);
- } else {
- ALOGV("get: caller's buffer is too small for value: %zu (needs %zu)",
- valueSize, valueBlobSize);
- }
- return valueBlobSize;
-}
-
-static inline size_t align4(size_t size) {
- return (size + 3) & ~3;
-}
-
-size_t BlobCache::getFlattenedSize() const {
- size_t size = align4(sizeof(Header) + PROPERTY_VALUE_MAX);
- for (size_t i = 0; i < mCacheEntries.size(); i++) {
- const CacheEntry& e(mCacheEntries[i]);
- sp<Blob> keyBlob = e.getKey();
- sp<Blob> valueBlob = e.getValue();
- size += align4(sizeof(EntryHeader) + keyBlob->getSize() +
- valueBlob->getSize());
- }
- return size;
-}
-
-status_t BlobCache::flatten(void* buffer, size_t size) const {
- // Write the cache header
- if (size < sizeof(Header)) {
- ALOGE("flatten: not enough room for cache header");
- return BAD_VALUE;
- }
- Header* header = reinterpret_cast<Header*>(buffer);
- header->mMagicNumber = blobCacheMagic;
- header->mBlobCacheVersion = blobCacheVersion;
- header->mDeviceVersion = blobCacheDeviceVersion;
- header->mNumEntries = mCacheEntries.size();
- char buildId[PROPERTY_VALUE_MAX];
- header->mBuildIdLength = property_get("ro.build.id", buildId, "");
- memcpy(header->mBuildId, buildId, header->mBuildIdLength);
-
- // Write cache entries
- uint8_t* byteBuffer = reinterpret_cast<uint8_t*>(buffer);
- off_t byteOffset = align4(sizeof(Header) + header->mBuildIdLength);
- for (size_t i = 0; i < mCacheEntries.size(); i++) {
- const CacheEntry& e(mCacheEntries[i]);
- sp<Blob> keyBlob = e.getKey();
- sp<Blob> valueBlob = e.getValue();
- size_t keySize = keyBlob->getSize();
- size_t valueSize = valueBlob->getSize();
-
- size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
- size_t totalSize = align4(entrySize);
- if (byteOffset + totalSize > size) {
- ALOGE("flatten: not enough room for cache entries");
- return BAD_VALUE;
- }
-
- EntryHeader* eheader = reinterpret_cast<EntryHeader*>(
- &byteBuffer[byteOffset]);
- eheader->mKeySize = keySize;
- eheader->mValueSize = valueSize;
-
- memcpy(eheader->mData, keyBlob->getData(), keySize);
- memcpy(eheader->mData + keySize, valueBlob->getData(), valueSize);
-
- if (totalSize > entrySize) {
- // We have padding bytes. Those will get written to storage, and contribute to the CRC,
- // so make sure we zero-them to have reproducible results.
- memset(eheader->mData + keySize + valueSize, 0, totalSize - entrySize);
- }
-
- byteOffset += totalSize;
- }
-
- return OK;
-}
-
-status_t BlobCache::unflatten(void const* buffer, size_t size) {
- // All errors should result in the BlobCache being in an empty state.
- mCacheEntries.clear();
-
- // Read the cache header
- if (size < sizeof(Header)) {
- ALOGE("unflatten: not enough room for cache header");
- return BAD_VALUE;
- }
- const Header* header = reinterpret_cast<const Header*>(buffer);
- if (header->mMagicNumber != blobCacheMagic) {
- ALOGE("unflatten: bad magic number: %" PRIu32, header->mMagicNumber);
- return BAD_VALUE;
- }
- char buildId[PROPERTY_VALUE_MAX];
- int len = property_get("ro.build.id", buildId, "");
- if (header->mBlobCacheVersion != blobCacheVersion ||
- header->mDeviceVersion != blobCacheDeviceVersion ||
- len != header->mBuildIdLength ||
- strncmp(buildId, header->mBuildId, len)) {
- // We treat version mismatches as an empty cache.
- return OK;
- }
-
- // Read cache entries
- const uint8_t* byteBuffer = reinterpret_cast<const uint8_t*>(buffer);
- off_t byteOffset = align4(sizeof(Header) + header->mBuildIdLength);
- size_t numEntries = header->mNumEntries;
- for (size_t i = 0; i < numEntries; i++) {
- if (byteOffset + sizeof(EntryHeader) > size) {
- mCacheEntries.clear();
- ALOGE("unflatten: not enough room for cache entry headers");
- return BAD_VALUE;
- }
-
- const EntryHeader* eheader = reinterpret_cast<const EntryHeader*>(
- &byteBuffer[byteOffset]);
- size_t keySize = eheader->mKeySize;
- size_t valueSize = eheader->mValueSize;
- size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
-
- size_t totalSize = align4(entrySize);
- if (byteOffset + totalSize > size) {
- mCacheEntries.clear();
- ALOGE("unflatten: not enough room for cache entry headers");
- return BAD_VALUE;
- }
-
- const uint8_t* data = eheader->mData;
- set(data, keySize, data + keySize, valueSize);
-
- byteOffset += totalSize;
- }
-
- return OK;
-}
-
-long int BlobCache::blob_random() {
-#ifdef _WIN32
- return rand();
-#else
- return nrand48(mRandState);
-#endif
-}
-
-void BlobCache::clean() {
- // Remove a random cache entry until the total cache size gets below half
- // the maximum total cache size.
- while (mTotalSize > mMaxTotalSize / 2) {
- size_t i = size_t(blob_random() % (mCacheEntries.size()));
- const CacheEntry& entry(mCacheEntries[i]);
- mTotalSize -= entry.getKey()->getSize() + entry.getValue()->getSize();
- mCacheEntries.removeAt(i);
- }
-}
-
-bool BlobCache::isCleanable() const {
- return mTotalSize > mMaxTotalSize / 2;
-}
-
-BlobCache::Blob::Blob(const void* data, size_t size, bool copyData):
- mData(copyData ? malloc(size) : data),
- mSize(size),
- mOwnsData(copyData) {
- if (data != NULL && copyData) {
- memcpy(const_cast<void*>(mData), data, size);
- }
-}
-
-BlobCache::Blob::~Blob() {
- if (mOwnsData) {
- free(const_cast<void*>(mData));
- }
-}
-
-bool BlobCache::Blob::operator<(const Blob& rhs) const {
- if (mSize == rhs.mSize) {
- return memcmp(mData, rhs.mData, mSize) < 0;
- } else {
- return mSize < rhs.mSize;
- }
-}
-
-const void* BlobCache::Blob::getData() const {
- return mData;
-}
-
-size_t BlobCache::Blob::getSize() const {
- return mSize;
-}
-
-BlobCache::CacheEntry::CacheEntry() {
-}
-
-BlobCache::CacheEntry::CacheEntry(const sp<Blob>& key, const sp<Blob>& value):
- mKey(key),
- mValue(value) {
-}
-
-BlobCache::CacheEntry::CacheEntry(const CacheEntry& ce):
- mKey(ce.mKey),
- mValue(ce.mValue) {
-}
-
-bool BlobCache::CacheEntry::operator<(const CacheEntry& rhs) const {
- return *mKey < *rhs.mKey;
-}
-
-const BlobCache::CacheEntry& BlobCache::CacheEntry::operator=(const CacheEntry& rhs) {
- mKey = rhs.mKey;
- mValue = rhs.mValue;
- return *this;
-}
-
-sp<BlobCache::Blob> BlobCache::CacheEntry::getKey() const {
- return mKey;
-}
-
-sp<BlobCache::Blob> BlobCache::CacheEntry::getValue() const {
- return mValue;
-}
-
-void BlobCache::CacheEntry::setValue(const sp<Blob>& value) {
- mValue = value;
-}
-
-} // namespace android
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index 699da7469..bd6015e79 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -16,9 +16,10 @@
#define LOG_TAG "CallStack"
+#include <utils/CallStack.h>
+
#include <memory>
-#include <utils/CallStack.h>
#include <utils/Printer.h>
#include <utils/Errors.h>
#include <utils/Log.h>
diff --git a/libutils/LinearTransform.cpp b/libutils/LinearTransform.cpp
deleted file mode 100644
index 138ce8be7..000000000
--- a/libutils/LinearTransform.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define __STDC_LIMIT_MACROS
-
-#include <assert.h>
-#include <stdint.h>
-
-#include <utils/LinearTransform.h>
-
-// disable sanitize as these functions may intentionally overflow (see comments below).
-// the ifdef can be removed when host builds use clang.
-#if defined(__clang__)
-#define ATTRIBUTE_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
-#else
-#define ATTRIBUTE_NO_SANITIZE_INTEGER
-#endif
-
-namespace android {
-
-// sanitize failure with T = int32_t and x = 0x80000000
-template<class T>
-ATTRIBUTE_NO_SANITIZE_INTEGER
-static inline T ABS(T x) { return (x < 0) ? -x : x; }
-
-// Static math methods involving linear transformations
-// remote sanitize failure on overflow case.
-ATTRIBUTE_NO_SANITIZE_INTEGER
-static bool scale_u64_to_u64(
- uint64_t val,
- uint32_t N,
- uint32_t D,
- uint64_t* res,
- bool round_up_not_down) {
- uint64_t tmp1, tmp2;
- uint32_t r;
-
- assert(res);
- assert(D);
-
- // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
- // integer X.
- // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
- // integer X.
- // Let X[A, B] with A <= B denote bits A through B of the integer X.
- // Let (A | B) denote the concatination of two 32 bit ints, A and B.
- // IOW X = (A | B) => U32(X) == A && L32(X) == B
- //
- // compute M = val * N (a 96 bit int)
- // ---------------------------------
- // tmp2 = U32(val) * N (a 64 bit int)
- // tmp1 = L32(val) * N (a 64 bit int)
- // which means
- // M = val * N = (tmp2 << 32) + tmp1
- tmp2 = (val >> 32) * N;
- tmp1 = (val & UINT32_MAX) * N;
-
- // compute M[32, 95]
- // tmp2 = tmp2 + U32(tmp1)
- // = (U32(val) * N) + U32(L32(val) * N)
- // = M[32, 95]
- tmp2 += tmp1 >> 32;
-
- // if M[64, 95] >= D, then M/D has bits > 63 set and we have
- // an overflow.
- if ((tmp2 >> 32) >= D) {
- *res = UINT64_MAX;
- return false;
- }
-
- // Divide. Going in we know
- // tmp2 = M[32, 95]
- // U32(tmp2) < D
- r = tmp2 % D;
- tmp2 /= D;
-
- // At this point
- // tmp1 = L32(val) * N
- // tmp2 = M[32, 95] / D
- // = (M / D)[32, 95]
- // r = M[32, 95] % D
- // U32(tmp2) = 0
- //
- // compute tmp1 = (r | M[0, 31])
- tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
-
- // Divide again. Keep the remainder around in order to round properly.
- r = tmp1 % D;
- tmp1 /= D;
-
- // At this point
- // tmp2 = (M / D)[32, 95]
- // tmp1 = (M / D)[ 0, 31]
- // r = M % D
- // U32(tmp1) = 0
- // U32(tmp2) = 0
-
- // Pack the result and deal with the round-up case (As well as the
- // remote possiblility over overflow in such a case).
- *res = (tmp2 << 32) | tmp1;
- if (r && round_up_not_down) {
- ++(*res);
- if (!(*res)) {
- *res = UINT64_MAX;
- return false;
- }
- }
-
- return true;
-}
-
-// at least one known sanitize failure (see comment below)
-ATTRIBUTE_NO_SANITIZE_INTEGER
-static bool linear_transform_s64_to_s64(
- int64_t val,
- int64_t basis1,
- int32_t N,
- uint32_t D,
- bool invert_frac,
- int64_t basis2,
- int64_t* out) {
- uint64_t scaled, res;
- uint64_t abs_val;
- bool is_neg;
-
- if (!out)
- return false;
-
- // Compute abs(val - basis_64). Keep track of whether or not this delta
- // will be negative after the scale opertaion.
- if (val < basis1) {
- is_neg = true;
- abs_val = basis1 - val;
- } else {
- is_neg = false;
- abs_val = val - basis1;
- }
-
- if (N < 0)
- is_neg = !is_neg;
-
- if (!scale_u64_to_u64(abs_val,
- invert_frac ? D : ABS(N),
- invert_frac ? ABS(N) : D,
- &scaled,
- is_neg))
- return false; // overflow/undeflow
-
- // if scaled is >= 0x8000<etc>, then we are going to overflow or
- // underflow unless ABS(basis2) is large enough to pull us back into the
- // non-overflow/underflow region.
- if (scaled & INT64_MIN) {
- if (is_neg && (basis2 < 0))
- return false; // certain underflow
-
- if (!is_neg && (basis2 >= 0))
- return false; // certain overflow
-
- if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
- return false; // not enough
-
- // Looks like we are OK
- *out = (is_neg ? (-scaled) : scaled) + basis2;
- } else {
- // Scaled fits within signed bounds, so we just need to check for
- // over/underflow for two signed integers. Basically, if both scaled
- // and basis2 have the same sign bit, and the result has a different
- // sign bit, then we have under/overflow. An easy way to compute this
- // is
- // (scaled_signbit XNOR basis_signbit) &&
- // (scaled_signbit XOR res_signbit)
- // ==
- // (scaled_signbit XOR basis_signbit XOR 1) &&
- // (scaled_signbit XOR res_signbit)
-
- if (is_neg)
- scaled = -scaled; // known sanitize failure
- res = scaled + basis2;
-
- if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
- return false;
-
- *out = res;
- }
-
- return true;
-}
-
-bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
- if (0 == a_to_b_denom)
- return false;
-
- return linear_transform_s64_to_s64(a_in,
- a_zero,
- a_to_b_numer,
- a_to_b_denom,
- false,
- b_zero,
- b_out);
-}
-
-bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
- if (0 == a_to_b_numer)
- return false;
-
- return linear_transform_s64_to_s64(b_in,
- b_zero,
- a_to_b_numer,
- a_to_b_denom,
- true,
- a_zero,
- a_out);
-}
-
-template <class T> void LinearTransform::reduce(T* N, T* D) {
- T a, b;
- if (!N || !D || !(*D)) {
- assert(false);
- return;
- }
-
- a = *N;
- b = *D;
-
- if (a == 0) {
- *D = 1;
- return;
- }
-
- // This implements Euclid's method to find GCD.
- if (a < b) {
- T tmp = a;
- a = b;
- b = tmp;
- }
-
- while (1) {
- // a is now the greater of the two.
- const T remainder = a % b;
- if (remainder == 0) {
- *N /= b;
- *D /= b;
- return;
- }
- // by swapping remainder and b, we are guaranteeing that a is
- // still the greater of the two upon entrance to the loop.
- a = b;
- b = remainder;
- }
-};
-
-template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
-template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
-
-// sanitize failure if *N = 0x80000000
-ATTRIBUTE_NO_SANITIZE_INTEGER
-void LinearTransform::reduce(int32_t* N, uint32_t* D) {
- if (N && D && *D) {
- if (*N < 0) {
- *N = -(*N);
- reduce(reinterpret_cast<uint32_t*>(N), D);
- *N = -(*N);
- } else {
- reduce(reinterpret_cast<uint32_t*>(N), D);
- }
- }
-}
-
-} // namespace android
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 77e69e4b3..6c57b2e54 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -13,17 +13,8 @@
// Debugs callback registration and invocation.
#define DEBUG_CALLBACKS 0
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <string.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-
-#include <log/log.h>
#include <utils/Looper.h>
-#include <utils/Timers.h>
+#include <sys/eventfd.h>
namespace android {
@@ -83,6 +74,7 @@ Looper::Looper(bool allowNonCallbacks) :
Looper::~Looper() {
close(mWakeEventFd);
+ mWakeEventFd = -1;
if (mEpollFd >= 0) {
close(mEpollFd);
}
@@ -412,7 +404,8 @@ void Looper::wake() {
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
- ALOGW("Could not write wake signal: %s", strerror(errno));
+ LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s",
+ mWakeEventFd, strerror(errno));
}
}
}
diff --git a/libutils/NativeHandle.cpp b/libutils/NativeHandle.cpp
index e4daca7ff..97d06b8bd 100644
--- a/libutils/NativeHandle.cpp
+++ b/libutils/NativeHandle.cpp
@@ -19,14 +19,14 @@
namespace android {
-sp<NativeHandle> NativeHandle::create(
- native_handle_t* handle, bool ownsHandle) {
+sp<NativeHandle> NativeHandle::create(native_handle_t* handle, bool ownsHandle) {
return handle ? new NativeHandle(handle, ownsHandle) : NULL;
}
NativeHandle::NativeHandle(native_handle_t* handle, bool ownsHandle)
-: mHandle(handle), mOwnsHandle(ownsHandle)
-{}
+ : mHandle(handle), mOwnsHandle(ownsHandle) {
+
+}
NativeHandle::~NativeHandle() {
if (mOwnsHandle) {
diff --git a/libutils/Printer.cpp b/libutils/Printer.cpp
index 84af2930b..cbf042eb5 100644
--- a/libutils/Printer.cpp
+++ b/libutils/Printer.cpp
@@ -21,8 +21,6 @@
#include <utils/String8.h>
#include <utils/Log.h>
-#include <string.h>
-#include <stdio.h>
#include <stdlib.h>
namespace android {
diff --git a/libutils/ProcessCallStack.cpp b/libutils/ProcessCallStack.cpp
index 983847c4c..b8fb6dc2a 100644
--- a/libutils/ProcessCallStack.cpp
+++ b/libutils/ProcessCallStack.cpp
@@ -17,20 +17,15 @@
#define LOG_TAG "ProcessCallStack"
// #define LOG_NDEBUG 0
+#include <utils/ProcessCallStack.h>
+
#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
#include <unistd.h>
+
#include <memory>
-#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <utils/ProcessCallStack.h>
#include <utils/Printer.h>
-#include <limits.h>
-
namespace android {
enum {
diff --git a/libutils/PropertyMap.cpp b/libutils/PropertyMap.cpp
index 55207027b..4bcdd0f7f 100644
--- a/libutils/PropertyMap.cpp
+++ b/libutils/PropertyMap.cpp
@@ -16,11 +16,7 @@
#define LOG_TAG "PropertyMap"
-#include <stdlib.h>
-#include <string.h>
-
#include <utils/PropertyMap.h>
-#include <utils/Log.h>
// Enables debug output for the parser.
#define DEBUG_PARSER 0
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 4252ba6b2..24737b985 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -17,18 +17,9 @@
#define LOG_TAG "RefBase"
// #define LOG_NDEBUG 0
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
#include <utils/RefBase.h>
#include <utils/CallStack.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
#ifndef __unused
#define __unused __attribute__((__unused__))
@@ -769,6 +760,4 @@ void RefBase::renameRefId(RefBase* ref,
ref->mRefs->renameWeakRefId(old_id, new_id);
}
-VirtualLightRefBase::~VirtualLightRefBase() {}
-
}; // namespace android
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 957aedb8f..bad98b274 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -16,13 +16,13 @@
#define LOG_TAG "sharedbuffer"
+#include "SharedBuffer.h"
+
#include <stdlib.h>
#include <string.h>
#include <log/log.h>
-#include "SharedBuffer.h"
-
// ---------------------------------------------------------------------------
namespace android {
@@ -113,16 +113,26 @@ void SharedBuffer::acquire() const {
int32_t SharedBuffer::release(uint32_t flags) const
{
- int32_t prev = 1;
- if (onlyOwner()
- || (((prev = mRefs.fetch_sub(1, std::memory_order_release)) == 1)
- && (atomic_thread_fence(std::memory_order_acquire), true))) {
+ const bool useDealloc = ((flags & eKeepStorage) == 0);
+ if (onlyOwner()) {
+ // Since we're the only owner, our reference count goes to zero.
mRefs.store(0, std::memory_order_relaxed);
- if ((flags & eKeepStorage) == 0) {
- free(const_cast<SharedBuffer*>(this));
+ if (useDealloc) {
+ dealloc(this);
+ }
+ // As the only owner, our previous reference count was 1.
+ return 1;
+ }
+ // There's multiple owners, we need to use an atomic decrement.
+ int32_t prevRefCount = mRefs.fetch_sub(1, std::memory_order_release);
+ if (prevRefCount == 1) {
+ // We're the last reference, we need the acquire fence.
+ atomic_thread_fence(std::memory_order_acquire);
+ if (useDealloc) {
+ dealloc(this);
}
}
- return prev;
+ return prevRefCount;
}
diff --git a/libutils/StopWatch.cpp b/libutils/StopWatch.cpp
index 8c7b59645..219c13c67 100644
--- a/libutils/StopWatch.cpp
+++ b/libutils/StopWatch.cpp
@@ -16,9 +16,7 @@
#define LOG_TAG "StopWatch"
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include <utils/StopWatch.h>
/* for PRId64 */
#ifndef __STDC_FORMAT_MACROS
@@ -27,8 +25,6 @@
#include <inttypes.h>
#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <utils/StopWatch.h>
/*****************************************************************************/
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 9f5cfeab4..ad335c399 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -17,11 +17,7 @@
#include <utils/String16.h>
#include <utils/Log.h>
-#include <utils/Unicode.h>
-#include <utils/threads.h>
-#include <memory.h>
-#include <stdio.h>
#include <ctype.h>
#include "SharedBuffer.h"
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index cacaf91b8..ad0e72ec1 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -21,9 +21,7 @@
#include <utils/Compat.h>
#include <utils/Log.h>
-#include <utils/Unicode.h>
#include <utils/String16.h>
-#include <utils/threads.h>
#include <ctype.h>
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index 965e32c0f..28fc35145 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -19,17 +19,17 @@
* System clock functions.
*/
+#define LOG_TAG "SystemClock"
+
+#include <utils/SystemClock.h>
+
#include <sys/time.h>
-#include <limits.h>
-#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <cutils/compiler.h>
-#include <utils/SystemClock.h>
-#include <utils/Timers.h>
-#define LOG_TAG "SystemClock"
+#include <utils/Timers.h>
#include <utils/Log.h>
namespace android {
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index def739f9f..6317c32d4 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -18,16 +18,10 @@
#define LOG_TAG "libutils.threads"
#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include <utils/Thread.h>
+#include <utils/AndroidThreads.h>
#if !defined(_WIN32)
-# include <pthread.h>
-# include <sched.h>
# include <sys/resource.h>
#else
# include <windows.h>
@@ -40,7 +34,6 @@
#include <sys/prctl.h>
#endif
-#include <utils/threads.h>
#include <utils/Log.h>
#include <cutils/sched_policy.h>
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
index 201bc412c..b2df9a58f 100644
--- a/libutils/Timers.cpp
+++ b/libutils/Timers.cpp
@@ -20,7 +20,6 @@
#include <utils/Timers.h>
#include <limits.h>
-#include <sys/time.h>
#include <time.h>
#if defined(__ANDROID__)
@@ -53,7 +52,7 @@ nsecs_t systemTime(int /*clock*/)
int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime)
{
- int timeoutDelayMillis;
+ nsecs_t timeoutDelayMillis;
if (timeoutTime > referenceTime) {
uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
@@ -64,5 +63,5 @@ int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime)
} else {
timeoutDelayMillis = 0;
}
- return timeoutDelayMillis;
+ return (int)timeoutDelayMillis;
}
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index 2d0e83dcd..b68a2cfa3 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -16,14 +16,10 @@
#define LOG_TAG "Tokenizer"
-#include <stdlib.h>
-#include <unistd.h>
+#include <utils/Tokenizer.h>
#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <utils/Log.h>
-#include <utils/Tokenizer.h>
// Enables debug output for the tokenizer.
#define DEBUG_TOKENIZER 0
diff --git a/libutils/Trace.cpp b/libutils/Trace.cpp
index 36fd80214..8530fdca0 100644
--- a/libutils/Trace.cpp
+++ b/libutils/Trace.cpp
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-#include <utils/misc.h>
#include <utils/Trace.h>
+#include <utils/misc.h>
static void traceInit() __attribute__((constructor));
-static void traceInit()
-{
+static void traceInit() {
::android::add_sysprop_change_callback(atrace_update_tags, 0);
}
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index f1a41b96f..5fd915524 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -16,11 +16,10 @@
#define LOG_TAG "unicode"
+#include <utils/Unicode.h>
#include <limits.h>
-#include <stddef.h>
#include <log/log.h>
-#include <utils/Unicode.h>
#if defined(_WIN32)
# undef nhtol
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index f7ca8f4f9..ef3277f42 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -16,13 +16,13 @@
#define LOG_TAG "Vector"
+#include <utils/VectorImpl.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <log/log.h>
-#include <utils/Errors.h>
-#include <utils/VectorImpl.h>
#include <safe_iop.h>
diff --git a/libutils/include/utils/BlobCache.h b/libutils/include/utils/BlobCache.h
deleted file mode 100644
index 65dca9fb4..000000000
--- a/libutils/include/utils/BlobCache.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- ** Copyright 2011, 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_BLOB_CACHE_H
-#define ANDROID_BLOB_CACHE_H
-
-#include <stddef.h>
-
-#include <utils/Flattenable.h>
-#include <utils/RefBase.h>
-#include <utils/SortedVector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-// A BlobCache is an in-memory cache for binary key/value pairs. A BlobCache
-// does NOT provide any thread-safety guarantees.
-//
-// The cache contents can be serialized to an in-memory buffer or mmap'd file
-// and then reloaded in a subsequent execution of the program. This
-// serialization is non-portable and the data should only be used by the device
-// that generated it.
-class BlobCache : public RefBase {
-
-public:
-
- // Create an empty blob cache. The blob cache will cache key/value pairs
- // with key and value sizes less than or equal to maxKeySize and
- // maxValueSize, respectively. The total combined size of ALL cache entries
- // (key sizes plus value sizes) will not exceed maxTotalSize.
- BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
-
- // set inserts a new binary value into the cache and associates it with the
- // given binary key. If the key or value are too large for the cache then
- // the cache remains unchanged. This includes the case where a different
- // value was previously associated with the given key - the old value will
- // remain in the cache. If the given key and value are small enough to be
- // put in the cache (based on the maxKeySize, maxValueSize, and maxTotalSize
- // values specified to the BlobCache constructor), then the key/value pair
- // will be in the cache after set returns. Note, however, that a subsequent
- // call to set may evict old key/value pairs from the cache.
- //
- // Preconditions:
- // key != NULL
- // 0 < keySize
- // value != NULL
- // 0 < valueSize
- void set(const void* key, size_t keySize, const void* value,
- size_t valueSize);
-
- // get retrieves from the cache the binary value associated with a given
- // binary key. If the key is present in the cache then the length of the
- // binary value associated with that key is returned. If the value argument
- // is non-NULL and the size of the cached value is less than valueSize bytes
- // then the cached value is copied into the buffer pointed to by the value
- // argument. If the key is not present in the cache then 0 is returned and
- // the buffer pointed to by the value argument is not modified.
- //
- // Note that when calling get multiple times with the same key, the later
- // calls may fail, returning 0, even if earlier calls succeeded. The return
- // value must be checked for each call.
- //
- // Preconditions:
- // key != NULL
- // 0 < keySize
- // 0 <= valueSize
- size_t get(const void* key, size_t keySize, void* value, size_t valueSize);
-
-
- // getFlattenedSize returns the number of bytes needed to store the entire
- // serialized cache.
- size_t getFlattenedSize() const;
-
- // flatten serializes the current contents of the cache into the memory
- // pointed to by 'buffer'. The serialized cache contents can later be
- // loaded into a BlobCache object using the unflatten method. The contents
- // of the BlobCache object will not be modified.
- //
- // Preconditions:
- // size >= this.getFlattenedSize()
- status_t flatten(void* buffer, size_t size) const;
-
- // unflatten replaces the contents of the cache with the serialized cache
- // contents in the memory pointed to by 'buffer'. The previous contents of
- // the BlobCache will be evicted from the cache. If an error occurs while
- // unflattening the serialized cache contents then the BlobCache will be
- // left in an empty state.
- //
- status_t unflatten(void const* buffer, size_t size);
-
-private:
- // Copying is disallowed.
- BlobCache(const BlobCache&);
- void operator=(const BlobCache&);
-
- // A random function helper to get around MinGW not having nrand48()
- long int blob_random();
-
- // clean evicts a randomly chosen set of entries from the cache such that
- // the total size of all remaining entries is less than mMaxTotalSize/2.
- void clean();
-
- // isCleanable returns true if the cache is full enough for the clean method
- // to have some effect, and false otherwise.
- bool isCleanable() const;
-
- // A Blob is an immutable sized unstructured data blob.
- class Blob : public RefBase {
- public:
- Blob(const void* data, size_t size, bool copyData);
- ~Blob();
-
- bool operator<(const Blob& rhs) const;
-
- const void* getData() const;
- size_t getSize() const;
-
- private:
- // Copying is not allowed.
- Blob(const Blob&);
- void operator=(const Blob&);
-
- // mData points to the buffer containing the blob data.
- const void* mData;
-
- // mSize is the size of the blob data in bytes.
- size_t mSize;
-
- // mOwnsData indicates whether or not this Blob object should free the
- // memory pointed to by mData when the Blob gets destructed.
- bool mOwnsData;
- };
-
- // A CacheEntry is a single key/value pair in the cache.
- class CacheEntry {
- public:
- CacheEntry();
- CacheEntry(const sp<Blob>& key, const sp<Blob>& value);
- CacheEntry(const CacheEntry& ce);
-
- bool operator<(const CacheEntry& rhs) const;
- const CacheEntry& operator=(const CacheEntry&);
-
- sp<Blob> getKey() const;
- sp<Blob> getValue() const;
-
- void setValue(const sp<Blob>& value);
-
- private:
-
- // mKey is the key that identifies the cache entry.
- sp<Blob> mKey;
-
- // mValue is the cached data associated with the key.
- sp<Blob> mValue;
- };
-
- // A Header is the header for the entire BlobCache serialization format. No
- // need to make this portable, so we simply write the struct out.
- struct Header {
- // mMagicNumber is the magic number that identifies the data as
- // serialized BlobCache contents. It must always contain 'Blb$'.
- uint32_t mMagicNumber;
-
- // mBlobCacheVersion is the serialization format version.
- uint32_t mBlobCacheVersion;
-
- // mDeviceVersion is the device-specific version of the cache. This can
- // be used to invalidate the cache.
- uint32_t mDeviceVersion;
-
- // mNumEntries is number of cache entries following the header in the
- // data.
- size_t mNumEntries;
-
- // mBuildId is the build id of the device when the cache was created.
- // When an update to the build happens (via an OTA or other update) this
- // is used to invalidate the cache.
- int mBuildIdLength;
- char mBuildId[];
- };
-
- // An EntryHeader is the header for a serialized cache entry. No need to
- // make this portable, so we simply write the struct out. Each EntryHeader
- // is followed imediately by the key data and then the value data.
- //
- // The beginning of each serialized EntryHeader is 4-byte aligned, so the
- // number of bytes that a serialized cache entry will occupy is:
- //
- // ((sizeof(EntryHeader) + keySize + valueSize) + 3) & ~3
- //
- struct EntryHeader {
- // mKeySize is the size of the entry key in bytes.
- size_t mKeySize;
-
- // mValueSize is the size of the entry value in bytes.
- size_t mValueSize;
-
- // mData contains both the key and value data for the cache entry. The
- // key comes first followed immediately by the value.
- uint8_t mData[];
- };
-
- // mMaxKeySize is the maximum key size that will be cached. Calls to
- // BlobCache::set with a keySize parameter larger than mMaxKeySize will
- // simply not add the key/value pair to the cache.
- const size_t mMaxKeySize;
-
- // mMaxValueSize is the maximum value size that will be cached. Calls to
- // BlobCache::set with a valueSize parameter larger than mMaxValueSize will
- // simply not add the key/value pair to the cache.
- const size_t mMaxValueSize;
-
- // mMaxTotalSize is the maximum size that all cache entries can occupy. This
- // includes space for both keys and values. When a call to BlobCache::set
- // would otherwise cause this limit to be exceeded, either the key/value
- // pair passed to BlobCache::set will not be cached or other cache entries
- // will be evicted from the cache to make room for the new entry.
- const size_t mMaxTotalSize;
-
- // mTotalSize is the total combined size of all keys and values currently in
- // the cache.
- size_t mTotalSize;
-
- // mRandState is the pseudo-random number generator state. It is passed to
- // nrand48 to generate random numbers when needed.
- unsigned short mRandState[3];
-
- // mCacheEntries stores all the cache entries that are resident in memory.
- // Cache entries are added to it by the 'set' method.
- SortedVector<CacheEntry> mCacheEntries;
-};
-
-}
-
-#endif // ANDROID_BLOB_CACHE_H
diff --git a/libutils/include/utils/Flattenable.h b/libutils/include/utils/Flattenable.h
index 22b811a14..070c71026 100644
--- a/libutils/include/utils/Flattenable.h
+++ b/libutils/include/utils/Flattenable.h
@@ -189,11 +189,11 @@ public:
}
inline status_t flatten(void* buffer, size_t size) const {
if (size < sizeof(T)) return NO_MEMORY;
- *reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
+ memcpy(buffer, static_cast<T const*>(this), sizeof(T));
return NO_ERROR;
}
inline status_t unflatten(void const* buffer, size_t) {
- *static_cast<T*>(this) = *reinterpret_cast<T const*>(buffer);
+ memcpy(static_cast<T*>(this), buffer, sizeof(T));
return NO_ERROR;
}
};
diff --git a/libutils/include/utils/LightRefBase.h b/libutils/include/utils/LightRefBase.h
new file mode 100644
index 000000000..65257edb9
--- /dev/null
+++ b/libutils/include/utils/LightRefBase.h
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+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 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);
+ }
+
+ typedef LightRefBase<T> basetype;
+
+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
diff --git a/libutils/include/utils/LinearTransform.h b/libutils/include/utils/LinearTransform.h
deleted file mode 100644
index 04cb355c7..000000000
--- a/libutils/include/utils/LinearTransform.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 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 _LIBS_UTILS_LINEAR_TRANSFORM_H
-#define _LIBS_UTILS_LINEAR_TRANSFORM_H
-
-#include <stdint.h>
-
-namespace android {
-
-// LinearTransform defines a structure which hold the definition of a
-// transformation from single dimensional coordinate system A into coordinate
-// system B (and back again). Values in A and in B are 64 bit, the linear
-// scale factor is expressed as a rational number using two 32 bit values.
-//
-// Specifically, let
-// f(a) = b
-// F(b) = f^-1(b) = a
-// then
-//
-// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
-//
-// and
-//
-// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
-//
-struct LinearTransform {
- int64_t a_zero;
- int64_t b_zero;
- int32_t a_to_b_numer;
- uint32_t a_to_b_denom;
-
- // Transform from A->B
- // Returns true on success, or false in the case of a singularity or an
- // overflow.
- bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
-
- // Transform from B->A
- // Returns true on success, or false in the case of a singularity or an
- // overflow.
- bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
-
- // Helpers which will reduce the fraction N/D using Euclid's method.
- template <class T> static void reduce(T* N, T* D);
- static void reduce(int32_t* N, uint32_t* D);
-};
-
-
-}
-
-#endif // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/libutils/include/utils/NativeHandle.h b/libutils/include/utils/NativeHandle.h
index b82516879..73fe804cc 100644
--- a/libutils/include/utils/NativeHandle.h
+++ b/libutils/include/utils/NativeHandle.h
@@ -24,7 +24,7 @@ typedef struct native_handle native_handle_t;
namespace android {
-class NativeHandle: public LightRefBase<NativeHandle> {
+class NativeHandle : public LightRefBase<NativeHandle> {
public:
// Create a refcounted wrapper around a native_handle_t, and declare
// whether the wrapper owns the handle (so that it should clean up the
@@ -41,7 +41,7 @@ private:
friend class LightRefBase<NativeHandle>;
NativeHandle(native_handle_t* handle, bool ownsHandle);
- virtual ~NativeHandle();
+ ~NativeHandle();
native_handle_t* mHandle;
bool mOwnsHandle;
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 36016cde6..223b6669d 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -177,6 +177,9 @@
#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>
@@ -216,7 +219,7 @@ inline bool operator _op_ (const U* o) const { \
class ReferenceRenamer {
protected:
- // destructor is purposedly not virtual so we avoid code overhead from
+ // 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).
@@ -246,13 +249,13 @@ public:
{
public:
RefBase* refBase() const;
-
+
void incWeak(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.
@@ -268,12 +271,12 @@ public:
// 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
+ // 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;
@@ -345,56 +348,12 @@ private:
// ---------------------------------------------------------------------------
-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 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);
- }
-
- typedef LightRefBase<T> basetype;
-
-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();
-};
-
-// ---------------------------------------------------------------------------
-
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
-
+
inline wp() : m_ptr(0) { }
wp(T* other); // NOLINT(implicit)
@@ -405,31 +364,31 @@ public:
template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~wp();
-
+
// Assignment
wp& operator = (T* other);
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& other);
-
+
template<typename U> wp& operator = (U* 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
diff --git a/libutils/include/utils/Singleton.h b/libutils/include/utils/Singleton.h
index abb72f510..9afedd4a0 100644
--- a/libutils/include/utils/Singleton.h
+++ b/libutils/include/utils/Singleton.h
@@ -18,9 +18,12 @@
#define ANDROID_UTILS_SINGLETON_H
#include <stdint.h>
+
+// some vendor code assumes they have atoi() after including this file.
+#include <stdlib.h>
+
#include <sys/types.h>
#include <utils/Mutex.h>
-#include <utils/threads.h>
#include <cutils/compiler.h>
namespace android {
diff --git a/libutils/include/utils/SortedVector.h b/libutils/include/utils/SortedVector.h
index 86f349645..5b2a23200 100644
--- a/libutils/include/utils/SortedVector.h
+++ b/libutils/include/utils/SortedVector.h
@@ -37,18 +37,18 @@ class SortedVector : private SortedVectorImpl
public:
typedef TYPE value_type;
-
- /*!
+
+ /*!
* Constructors and destructors
*/
-
+
SortedVector();
SortedVector(const SortedVector<TYPE>& rhs);
virtual ~SortedVector();
/*! copy operator */
- const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
- SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
+ const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
+ SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
/*
* empty the vector
@@ -56,7 +56,7 @@ public:
inline void clear() { VectorImpl::clear(); }
- /*!
+ /*!
* vector stats
*/
@@ -69,11 +69,11 @@ public:
//! sets the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
- /*!
+ /*!
* C-style array access
*/
-
- //! read-only C-style access
+
+ //! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access. BE VERY CAREFUL when modifying the array
@@ -82,12 +82,12 @@ public:
//! finds the index of an item
ssize_t indexOf(const TYPE& item) const;
-
+
//! finds where this item should be inserted
size_t orderOf(const TYPE& item) const;
-
-
- /*!
+
+
+ /*!
* accessors
*/
@@ -104,7 +104,7 @@ public:
//! add an item in the right place (and replace the one that is there)
ssize_t add(const TYPE& item);
-
+
//! editItemAt() MUST NOT change the order of this item
TYPE& editItemAt(size_t index) {
return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
@@ -113,7 +113,7 @@ public:
//! merges a vector into this one
ssize_t merge(const Vector<TYPE>& vector);
ssize_t merge(const SortedVector<TYPE>& vector);
-
+
//! removes an item
ssize_t remove(const TYPE&);
@@ -121,7 +121,24 @@ public:
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
-
+
+ /*
+ * these inlines add some level of compatibility with STL.
+ */
+ 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 iterator erase(iterator pos) {
+ ssize_t index = removeItemsAt(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;
@@ -159,13 +176,13 @@ SortedVector<TYPE>::~SortedVector() {
template<class TYPE> inline
SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
SortedVectorImpl::operator = (rhs);
- return *this;
+ return *this;
}
template<class TYPE> inline
const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
SortedVectorImpl::operator = (rhs);
- return *this;
+ return *this;
}
template<class TYPE> inline
@@ -235,7 +252,7 @@ ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
// ---------------------------------------------------------------------------
template<class TYPE>
-void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
+UTILS_VECTOR_NO_CFI void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
construct_type( reinterpret_cast<TYPE*>(storage), num );
}
@@ -245,22 +262,22 @@ void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
}
template<class TYPE>
-void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+UTILS_VECTOR_NO_CFI void SortedVector<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>
-void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+UTILS_VECTOR_NO_CFI void SortedVector<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>
-void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+UTILS_VECTOR_NO_CFI void SortedVector<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>
-void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+UTILS_VECTOR_NO_CFI void SortedVector<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 );
}
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index c2f772222..0c2060791 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -17,12 +17,6 @@
#ifndef ANDROID_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
-#include <cutils/atomic.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <stdlib.h>
-
// ---------------------------------------------------------------------------
namespace android {
diff --git a/libutils/include/utils/Trace.h b/libutils/include/utils/Trace.h
index eeba40d65..5e9229c1e 100644
--- a/libutils/include/utils/Trace.h
+++ b/libutils/include/utils/Trace.h
@@ -19,16 +19,8 @@
#if defined(__ANDROID__)
-#include <fcntl.h>
#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cutils/compiler.h>
-#include <utils/threads.h>
+
#include <cutils/trace.h>
// See <cutils/trace.h> for more ATRACE_* macros.
@@ -37,6 +29,7 @@
#define _PASTE(x, y) x ## y
#define PASTE(x, y) _PASTE(x,y)
#define ATRACE_NAME(name) android::ScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
+
// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
@@ -44,14 +37,13 @@ namespace android {
class ScopedTrace {
public:
-inline ScopedTrace(uint64_t tag, const char* name)
- : mTag(tag) {
- atrace_begin(mTag,name);
-}
-
-inline ~ScopedTrace() {
- atrace_end(mTag);
-}
+ inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) {
+ atrace_begin(mTag, name);
+ }
+
+ inline ~ScopedTrace() {
+ atrace_end(mTag);
+ }
private:
uint64_t mTag;
diff --git a/libutils/include/utils/TypeHelpers.h b/libutils/include/utils/TypeHelpers.h
index 2a2522722..28fbca508 100644
--- a/libutils/include/utils/TypeHelpers.h
+++ b/libutils/include/utils/TypeHelpers.h
@@ -36,7 +36,7 @@ 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 { enum { value = false }; };
template <typename T> struct trait_pointer<T*> { enum { value = true }; };
template <typename TYPE>
@@ -59,13 +59,13 @@ template <typename T, typename U>
struct aggregate_traits {
enum {
is_pointer = false,
- has_trivial_ctor =
+ has_trivial_ctor =
traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
- has_trivial_dtor =
+ has_trivial_dtor =
traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
- has_trivial_copy =
+ has_trivial_copy =
traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
- has_trivial_move =
+ has_trivial_move =
traits<T>::has_trivial_move && traits<U>::has_trivial_move
};
};
diff --git a/libutils/include/utils/Vector.h b/libutils/include/utils/Vector.h
index 9a643f9b0..7e00123f7 100644
--- a/libutils/include/utils/Vector.h
+++ b/libutils/include/utils/Vector.h
@@ -24,6 +24,20 @@
#include <utils/TypeHelpers.h>
#include <utils/VectorImpl.h>
+/*
+ * Used to blacklist some functions from CFI.
+ *
+ */
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(no_sanitize)
+#define UTILS_VECTOR_NO_CFI __attribute__((no_sanitize("cfi")))
+#else
+#define UTILS_VECTOR_NO_CFI
+#endif
+
// ---------------------------------------------------------------------------
namespace android {
@@ -42,11 +56,11 @@ class Vector : private VectorImpl
{
public:
typedef TYPE value_type;
-
- /*!
+
+ /*!
* Constructors and destructors
*/
-
+
Vector();
Vector(const Vector<TYPE>& rhs);
explicit Vector(const SortedVector<TYPE>& rhs);
@@ -54,7 +68,7 @@ public:
/*! copy operator */
const Vector<TYPE>& operator = (const Vector<TYPE>& rhs) const;
- Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
+ Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
const Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
@@ -65,7 +79,7 @@ public:
inline void clear() { VectorImpl::clear(); }
- /*!
+ /*!
* vector stats
*/
@@ -87,13 +101,13 @@ public:
/*!
* C-style array access
*/
-
- //! read-only C-style access
+
+ //! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access
TYPE* editArray();
-
- /*!
+
+ /*!
* accessors
*/
@@ -113,10 +127,10 @@ public:
//! 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);
@@ -130,10 +144,10 @@ public:
//! 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
@@ -147,7 +161,7 @@ public:
//! 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);
+ 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
@@ -165,10 +179,10 @@ public:
/*!
* 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);
@@ -237,7 +251,7 @@ Vector<TYPE>::~Vector() {
template<class TYPE> inline
Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
VectorImpl::operator = (rhs);
- return *this;
+ return *this;
}
template<class TYPE> inline
@@ -255,7 +269,7 @@ Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
template<class TYPE> inline
const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
VectorImpl::operator = (rhs);
- return *this;
+ return *this;
}
template<class TYPE> inline
@@ -380,7 +394,7 @@ status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
// ---------------------------------------------------------------------------
template<class TYPE>
-void Vector<TYPE>::do_construct(void* storage, size_t num) const {
+UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_construct(void* storage, size_t num) const {
construct_type( reinterpret_cast<TYPE*>(storage), num );
}
@@ -390,22 +404,22 @@ void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
}
template<class TYPE>
-void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+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>
-void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+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>
-void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+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>
-void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+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 );
}
diff --git a/libutils/misc.cpp b/libutils/misc.cpp
index 216dc1430..d95fd056b 100644
--- a/libutils/misc.cpp
+++ b/libutils/misc.cpp
@@ -16,21 +16,19 @@
#define LOG_TAG "misc"
-//
-// Miscellaneous utility functions.
-//
#include <utils/misc.h>
-#include <utils/Log.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <stdio.h>
+#include <pthread.h>
-#if !defined(_WIN32)
-# include <pthread.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+
+#if defined(__ANDROID__)
+#include <dlfcn.h>
+#include <vndksupport/linker.h>
#endif
-#include <utils/Vector.h>
+extern "C" void do_report_sysprop_change();
using namespace android;
@@ -70,7 +68,36 @@ void add_sysprop_change_callback(sysprop_change_callback cb, int priority) {
#endif
}
+#if defined(__ANDROID__)
+void (*get_report_sysprop_change_func())() {
+ void (*func)() = nullptr;
+ void* handle = android_load_sphal_library("libutils.so", RTLD_NOW);
+ if (handle != nullptr) {
+ func = reinterpret_cast<decltype(func)>(dlsym(handle, "do_report_sysprop_change"));
+ }
+
+ return func;
+}
+#endif
+
void report_sysprop_change() {
+ do_report_sysprop_change();
+
+#if defined(__ANDROID__)
+ // libutils.so is double loaded; from the default namespace and from the
+ // 'sphal' namespace. Redirect the sysprop change event to the other instance
+ // of libutils.so loaded in the 'sphal' namespace so that listeners attached
+ // to that instance is also notified with this event.
+ static auto func = get_report_sysprop_change_func();
+ if (func != nullptr) {
+ (*func)();
+ }
+#endif
+}
+
+}; // namespace android
+
+void do_report_sysprop_change() {
#if !defined(_WIN32)
pthread_mutex_lock(&gSyspropMutex);
Vector<sysprop_change_callback_info> listeners;
@@ -85,5 +112,3 @@ void report_sysprop_change() {
}
#endif
}
-
-}; // namespace android
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index 7cae13351..08691756a 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -34,7 +34,6 @@ cc_test {
target: {
android: {
srcs: [
- "BlobCache_test.cpp",
"Looper_test.cpp",
"RefBase_test.cpp",
"SystemClock_test.cpp",
diff --git a/libutils/tests/BlobCache_test.cpp b/libutils/tests/BlobCache_test.cpp
deleted file mode 100644
index 1e2ff9828..000000000
--- a/libutils/tests/BlobCache_test.cpp
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- ** Copyright 2011, 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.
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-
-#include <gtest/gtest.h>
-
-#include <utils/BlobCache.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class BlobCacheTest : public ::testing::Test {
-protected:
- enum {
- MAX_KEY_SIZE = 6,
- MAX_VALUE_SIZE = 8,
- MAX_TOTAL_SIZE = 13,
- };
-
- virtual void SetUp() {
- mBC = new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE);
- }
-
- virtual void TearDown() {
- mBC.clear();
- }
-
- sp<BlobCache> mBC;
-};
-
-TEST_F(BlobCacheTest, CacheSingleValueSucceeds) {
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
- ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
- ASSERT_EQ('e', buf[0]);
- ASSERT_EQ('f', buf[1]);
- ASSERT_EQ('g', buf[2]);
- ASSERT_EQ('h', buf[3]);
-}
-
-TEST_F(BlobCacheTest, CacheTwoValuesSucceeds) {
- unsigned char buf[2] = { 0xee, 0xee };
- mBC->set("ab", 2, "cd", 2);
- mBC->set("ef", 2, "gh", 2);
- ASSERT_EQ(size_t(2), mBC->get("ab", 2, buf, 2));
- ASSERT_EQ('c', buf[0]);
- ASSERT_EQ('d', buf[1]);
- ASSERT_EQ(size_t(2), mBC->get("ef", 2, buf, 2));
- ASSERT_EQ('g', buf[0]);
- ASSERT_EQ('h', buf[1]);
-}
-
-TEST_F(BlobCacheTest, GetOnlyWritesInsideBounds) {
- unsigned char buf[6] = { 0xee, 0xee, 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
- ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf+1, 4));
- ASSERT_EQ(0xee, buf[0]);
- ASSERT_EQ('e', buf[1]);
- ASSERT_EQ('f', buf[2]);
- ASSERT_EQ('g', buf[3]);
- ASSERT_EQ('h', buf[4]);
- ASSERT_EQ(0xee, buf[5]);
-}
-
-TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
- unsigned char buf[3] = { 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
- ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 3));
- ASSERT_EQ(0xee, buf[0]);
- ASSERT_EQ(0xee, buf[1]);
- ASSERT_EQ(0xee, buf[2]);
-}
-
-TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) {
- mBC->set("abcd", 4, "efgh", 4);
- ASSERT_EQ(size_t(4), mBC->get("abcd", 4, NULL, 0));
-}
-
-TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) {
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
- mBC->set("abcd", 4, "ijkl", 4);
- ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
- ASSERT_EQ('i', buf[0]);
- ASSERT_EQ('j', buf[1]);
- ASSERT_EQ('k', buf[2]);
- ASSERT_EQ('l', buf[3]);
-}
-
-TEST_F(BlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
- unsigned char buf[MAX_VALUE_SIZE+1] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
- mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
- ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
- ASSERT_EQ('e', buf[0]);
- ASSERT_EQ('f', buf[1]);
- ASSERT_EQ('g', buf[2]);
- ASSERT_EQ('h', buf[3]);
-}
-
-TEST_F(BlobCacheTest, DoesntCacheIfKeyIsTooBig) {
- char key[MAX_KEY_SIZE+1];
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- for (int i = 0; i < MAX_KEY_SIZE+1; i++) {
- key[i] = 'a';
- }
- mBC->set(key, MAX_KEY_SIZE+1, "bbbb", 4);
- ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE+1, buf, 4));
- ASSERT_EQ(0xee, buf[0]);
- ASSERT_EQ(0xee, buf[1]);
- ASSERT_EQ(0xee, buf[2]);
- ASSERT_EQ(0xee, buf[3]);
-}
-
-TEST_F(BlobCacheTest, DoesntCacheIfValueIsTooBig) {
- char buf[MAX_VALUE_SIZE+1];
- for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
- buf[i] = 'b';
- }
- mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
- for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
- buf[i] = 0xee;
- }
- ASSERT_EQ(size_t(0), mBC->get("abcd", 4, buf, MAX_VALUE_SIZE+1));
- for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
- SCOPED_TRACE(i);
- ASSERT_EQ(0xee, buf[i]);
- }
-}
-
-TEST_F(BlobCacheTest, DoesntCacheIfKeyValuePairIsTooBig) {
- // Check a testing assumptions
- ASSERT_TRUE(MAX_TOTAL_SIZE < MAX_KEY_SIZE + MAX_VALUE_SIZE);
- ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
-
- enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE + 1 };
-
- char key[MAX_KEY_SIZE];
- char buf[bufSize];
- for (int i = 0; i < MAX_KEY_SIZE; i++) {
- key[i] = 'a';
- }
- for (int i = 0; i < bufSize; i++) {
- buf[i] = 'b';
- }
-
- mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE);
- ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
-}
-
-TEST_F(BlobCacheTest, CacheMaxKeySizeSucceeds) {
- char key[MAX_KEY_SIZE];
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- for (int i = 0; i < MAX_KEY_SIZE; i++) {
- key[i] = 'a';
- }
- mBC->set(key, MAX_KEY_SIZE, "wxyz", 4);
- ASSERT_EQ(size_t(4), mBC->get(key, MAX_KEY_SIZE, buf, 4));
- ASSERT_EQ('w', buf[0]);
- ASSERT_EQ('x', buf[1]);
- ASSERT_EQ('y', buf[2]);
- ASSERT_EQ('z', buf[3]);
-}
-
-TEST_F(BlobCacheTest, CacheMaxValueSizeSucceeds) {
- char buf[MAX_VALUE_SIZE];
- for (int i = 0; i < MAX_VALUE_SIZE; i++) {
- buf[i] = 'b';
- }
- mBC->set("abcd", 4, buf, MAX_VALUE_SIZE);
- for (int i = 0; i < MAX_VALUE_SIZE; i++) {
- buf[i] = 0xee;
- }
- ASSERT_EQ(size_t(MAX_VALUE_SIZE), mBC->get("abcd", 4, buf,
- MAX_VALUE_SIZE));
- for (int i = 0; i < MAX_VALUE_SIZE; i++) {
- SCOPED_TRACE(i);
- ASSERT_EQ('b', buf[i]);
- }
-}
-
-TEST_F(BlobCacheTest, CacheMaxKeyValuePairSizeSucceeds) {
- // Check a testing assumption
- ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
-
- enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE };
-
- char key[MAX_KEY_SIZE];
- char buf[bufSize];
- for (int i = 0; i < MAX_KEY_SIZE; i++) {
- key[i] = 'a';
- }
- for (int i = 0; i < bufSize; i++) {
- buf[i] = 'b';
- }
-
- mBC->set(key, MAX_KEY_SIZE, buf, bufSize);
- ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
-}
-
-TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
- unsigned char buf[1] = { 0xee };
- mBC->set("x", 1, "y", 1);
- ASSERT_EQ(size_t(1), mBC->get("x", 1, buf, 1));
- ASSERT_EQ('y', buf[0]);
-}
-
-TEST_F(BlobCacheTest, CacheSizeDoesntExceedTotalLimit) {
- for (int i = 0; i < 256; i++) {
- uint8_t k = i;
- mBC->set(&k, 1, "x", 1);
- }
- int numCached = 0;
- for (int i = 0; i < 256; i++) {
- uint8_t k = i;
- if (mBC->get(&k, 1, NULL, 0) == 1) {
- numCached++;
- }
- }
- ASSERT_GE(MAX_TOTAL_SIZE / 2, numCached);
-}
-
-TEST_F(BlobCacheTest, ExceedingTotalLimitHalvesCacheSize) {
- // Fill up the entire cache with 1 char key/value pairs.
- const int maxEntries = MAX_TOTAL_SIZE / 2;
- for (int i = 0; i < maxEntries; i++) {
- uint8_t k = i;
- mBC->set(&k, 1, "x", 1);
- }
- // Insert one more entry, causing a cache overflow.
- {
- uint8_t k = maxEntries;
- mBC->set(&k, 1, "x", 1);
- }
- // Count the number of entries in the cache.
- int numCached = 0;
- for (int i = 0; i < maxEntries+1; i++) {
- uint8_t k = i;
- if (mBC->get(&k, 1, NULL, 0) == 1) {
- numCached++;
- }
- }
- ASSERT_EQ(maxEntries/2 + 1, numCached);
-}
-
-class BlobCacheFlattenTest : public BlobCacheTest {
-protected:
- virtual void SetUp() {
- BlobCacheTest::SetUp();
- mBC2 = new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE);
- }
-
- virtual void TearDown() {
- mBC2.clear();
- BlobCacheTest::TearDown();
- }
-
- void roundTrip() {
- size_t size = mBC->getFlattenedSize();
- uint8_t* flat = new uint8_t[size];
- ASSERT_EQ(OK, mBC->flatten(flat, size));
- ASSERT_EQ(OK, mBC2->unflatten(flat, size));
- delete[] flat;
- }
-
- sp<BlobCache> mBC2;
-};
-
-TEST_F(BlobCacheFlattenTest, FlattenOneValue) {
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
- roundTrip();
- ASSERT_EQ(size_t(4), mBC2->get("abcd", 4, buf, 4));
- ASSERT_EQ('e', buf[0]);
- ASSERT_EQ('f', buf[1]);
- ASSERT_EQ('g', buf[2]);
- ASSERT_EQ('h', buf[3]);
-}
-
-TEST_F(BlobCacheFlattenTest, FlattenFullCache) {
- // Fill up the entire cache with 1 char key/value pairs.
- const int maxEntries = MAX_TOTAL_SIZE / 2;
- for (int i = 0; i < maxEntries; i++) {
- uint8_t k = i;
- mBC->set(&k, 1, &k, 1);
- }
-
- roundTrip();
-
- // Verify the deserialized cache
- for (int i = 0; i < maxEntries; i++) {
- uint8_t k = i;
- uint8_t v = 0xee;
- ASSERT_EQ(size_t(1), mBC2->get(&k, 1, &v, 1));
- ASSERT_EQ(k, v);
- }
-}
-
-TEST_F(BlobCacheFlattenTest, FlattenDoesntChangeCache) {
- // Fill up the entire cache with 1 char key/value pairs.
- const int maxEntries = MAX_TOTAL_SIZE / 2;
- for (int i = 0; i < maxEntries; i++) {
- uint8_t k = i;
- mBC->set(&k, 1, &k, 1);
- }
-
- size_t size = mBC->getFlattenedSize();
- uint8_t* flat = new uint8_t[size];
- ASSERT_EQ(OK, mBC->flatten(flat, size));
- delete[] flat;
-
- // Verify the cache that we just serialized
- for (int i = 0; i < maxEntries; i++) {
- uint8_t k = i;
- uint8_t v = 0xee;
- ASSERT_EQ(size_t(1), mBC->get(&k, 1, &v, 1));
- ASSERT_EQ(k, v);
- }
-}
-
-TEST_F(BlobCacheFlattenTest, FlattenCatchesBufferTooSmall) {
- // Fill up the entire cache with 1 char key/value pairs.
- const int maxEntries = MAX_TOTAL_SIZE / 2;
- for (int i = 0; i < maxEntries; i++) {
- uint8_t k = i;
- mBC->set(&k, 1, &k, 1);
- }
-
- size_t size = mBC->getFlattenedSize() - 1;
- uint8_t* flat = new uint8_t[size];
- // ASSERT_EQ(BAD_VALUE, mBC->flatten(flat, size));
- // TODO: The above fails. I expect this is so because getFlattenedSize()
- // overstimates the size by using PROPERTY_VALUE_MAX.
- delete[] flat;
-}
-
-TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadMagic) {
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
-
- size_t size = mBC->getFlattenedSize();
- uint8_t* flat = new uint8_t[size];
- ASSERT_EQ(OK, mBC->flatten(flat, size));
- flat[1] = ~flat[1];
-
- // Bad magic should cause an error.
- ASSERT_EQ(BAD_VALUE, mBC2->unflatten(flat, size));
- delete[] flat;
-
- // The error should cause the unflatten to result in an empty cache
- ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
-}
-
-TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadBlobCacheVersion) {
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
-
- size_t size = mBC->getFlattenedSize();
- uint8_t* flat = new uint8_t[size];
- ASSERT_EQ(OK, mBC->flatten(flat, size));
- flat[5] = ~flat[5];
-
- // Version mismatches shouldn't cause errors, but should not use the
- // serialized entries
- ASSERT_EQ(OK, mBC2->unflatten(flat, size));
- delete[] flat;
-
- // The version mismatch should cause the unflatten to result in an empty
- // cache
- ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
-}
-
-TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadBlobCacheDeviceVersion) {
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
-
- size_t size = mBC->getFlattenedSize();
- uint8_t* flat = new uint8_t[size];
- ASSERT_EQ(OK, mBC->flatten(flat, size));
- flat[10] = ~flat[10];
-
- // Version mismatches shouldn't cause errors, but should not use the
- // serialized entries
- ASSERT_EQ(OK, mBC2->unflatten(flat, size));
- delete[] flat;
-
- // The version mismatch should cause the unflatten to result in an empty
- // cache
- ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
-}
-
-TEST_F(BlobCacheFlattenTest, UnflattenCatchesBufferTooSmall) {
- unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
- mBC->set("abcd", 4, "efgh", 4);
-
- size_t size = mBC->getFlattenedSize();
- uint8_t* flat = new uint8_t[size];
- ASSERT_EQ(OK, mBC->flatten(flat, size));
-
- // A buffer truncation shouldt cause an error
- // ASSERT_EQ(BAD_VALUE, mBC2->unflatten(flat, size-1));
- // TODO: The above appears to fail because getFlattenedSize() is
- // conservative.
- delete[] flat;
-
- // The error should cause the unflatten to result in an empty cache
- ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
-}
-
-} // namespace android