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
diff --git a/libutils/binder/Android.bp b/libutils/binder/Android.bp
new file mode 100644
index 0000000..e2eddb3
--- /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/binder/Errors.cpp b/libutils/binder/Errors.cpp
new file mode 100644
index 0000000..dfb4d9b
--- /dev/null
+++ b/libutils/binder/Errors.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <utils/Errors.h>
+
+#include <string.h>
+
+namespace android {
+
+std::string statusToString(status_t s) {
+#define STATUS_CASE(STATUS) \
+    case STATUS:            \
+        return #STATUS
+
+    switch (s) {
+        STATUS_CASE(OK);
+        STATUS_CASE(UNKNOWN_ERROR);
+        STATUS_CASE(NO_MEMORY);
+        STATUS_CASE(INVALID_OPERATION);
+        STATUS_CASE(BAD_VALUE);
+        STATUS_CASE(BAD_TYPE);
+        STATUS_CASE(NAME_NOT_FOUND);
+        STATUS_CASE(PERMISSION_DENIED);
+        STATUS_CASE(NO_INIT);
+        STATUS_CASE(ALREADY_EXISTS);
+        STATUS_CASE(DEAD_OBJECT);
+        STATUS_CASE(FAILED_TRANSACTION);
+        STATUS_CASE(BAD_INDEX);
+        STATUS_CASE(NOT_ENOUGH_DATA);
+        STATUS_CASE(WOULD_BLOCK);
+        STATUS_CASE(TIMED_OUT);
+        STATUS_CASE(UNKNOWN_TRANSACTION);
+        STATUS_CASE(FDS_NOT_ALLOWED);
+        STATUS_CASE(UNEXPECTED_NULL);
+#undef STATUS_CASE
+    }
+
+    return std::to_string(s) + " (" + strerror(-s) + ")";
+}
+
+}  // namespace android
diff --git a/libutils/binder/Errors_test.cpp b/libutils/binder/Errors_test.cpp
new file mode 100644
index 0000000..0d13bb0
--- /dev/null
+++ b/libutils/binder/Errors_test.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/ErrorsMacros.h"
+
+#include <android-base/result.h>
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+using android::base::Error;
+using android::base::Result;
+
+status_t success_or_fail(bool success) {
+    if (success)
+        return OK;
+    else
+        return PERMISSION_DENIED;
+}
+
+TEST(errors, unwrap_or_return) {
+    auto f = [](bool success, int* val) -> status_t {
+        OR_RETURN(success_or_fail(success));
+        *val = 10;
+        return OK;
+    };
+
+    int val;
+    status_t s = f(true, &val);
+    EXPECT_EQ(OK, s);
+    EXPECT_EQ(10, val);
+
+    val = 0;  // reset
+    status_t q = f(false, &val);
+    EXPECT_EQ(PERMISSION_DENIED, q);
+    EXPECT_EQ(0, val);
+}
+
+TEST(errors, unwrap_or_return_result) {
+    auto f = [](bool success) -> Result<std::string, StatusT> {
+        OR_RETURN(success_or_fail(success));
+        return "hello";
+    };
+
+    auto r = f(true);
+    EXPECT_TRUE(r.ok());
+    EXPECT_EQ("hello", *r);
+
+    auto s = f(false);
+    EXPECT_FALSE(s.ok());
+    EXPECT_EQ(PERMISSION_DENIED, s.error().code());
+    EXPECT_EQ("PERMISSION_DENIED", s.error().message());
+}
+
+TEST(errors, unwrap_or_return_result_int) {
+    auto f = [](bool success) -> Result<int, StatusT> {
+        OR_RETURN(success_or_fail(success));
+        return 10;
+    };
+
+    auto r = f(true);
+    EXPECT_TRUE(r.ok());
+    EXPECT_EQ(10, *r);
+
+    auto s = f(false);
+    EXPECT_FALSE(s.ok());
+    EXPECT_EQ(PERMISSION_DENIED, s.error().code());
+    EXPECT_EQ("PERMISSION_DENIED", s.error().message());
+}
+
+TEST(errors, unwrap_or_fatal) {
+    OR_FATAL(success_or_fail(true));
+
+    EXPECT_DEATH(OR_FATAL(success_or_fail(false)), "PERMISSION_DENIED");
+}
+
+TEST(errors, result_in_status) {
+    auto f = [](bool success) -> Result<std::string, StatusT> {
+        if (success)
+            return "OK";
+        else
+            return Error<StatusT>(PERMISSION_DENIED) << "custom error message";
+    };
+
+    auto g = [&](bool success) -> status_t {
+        std::string val = OR_RETURN(f(success));
+        EXPECT_EQ("OK", val);
+        return OK;
+    };
+
+    status_t a = g(true);
+    EXPECT_EQ(OK, a);
+
+    status_t b = g(false);
+    EXPECT_EQ(PERMISSION_DENIED, b);
+}
+
+TEST(errors, conversion_promotion) {
+    constexpr size_t successVal = 10ull;
+    auto f = [&](bool success) -> Result<size_t, StatusT> {
+        OR_RETURN(success_or_fail(success));
+        return successVal;
+    };
+    auto s = f(true);
+    ASSERT_TRUE(s.ok());
+    EXPECT_EQ(s.value(), successVal);
+    auto r = f(false);
+    EXPECT_TRUE(!r.ok());
+    EXPECT_EQ(PERMISSION_DENIED, r.error().code());
+}
+
+TEST(errors, conversion_promotion_bool) {
+    constexpr size_t successVal = true;
+    auto f = [&](bool success) -> Result<bool, StatusT> {
+        OR_RETURN(success_or_fail(success));
+        return successVal;
+    };
+    auto s = f(true);
+    ASSERT_TRUE(s.ok());
+    EXPECT_EQ(s.value(), successVal);
+    auto r = f(false);
+    EXPECT_TRUE(!r.ok());
+    EXPECT_EQ(PERMISSION_DENIED, r.error().code());
+}
+
+TEST(errors, conversion_promotion_char) {
+    constexpr char successVal = 'a';
+    auto f = [&](bool success) -> Result<unsigned char, StatusT> {
+        OR_RETURN(success_or_fail(success));
+        return successVal;
+    };
+    auto s = f(true);
+    ASSERT_TRUE(s.ok());
+    EXPECT_EQ(s.value(), successVal);
+    auto r = f(false);
+    EXPECT_TRUE(!r.ok());
+    EXPECT_EQ(PERMISSION_DENIED, r.error().code());
+}
+
+struct IntContainer {
+  // Implicit conversion from int is desired
+  IntContainer(int val) : val_(val) {}
+  int val_;
+};
+
+TEST(errors, conversion_construct) {
+    constexpr int successVal = 10;
+    auto f = [&](bool success) -> Result<IntContainer, StatusT> {
+        OR_RETURN(success_or_fail(success));
+        return successVal;
+    };
+    auto s = f(true);
+    ASSERT_TRUE(s.ok());
+    EXPECT_EQ(s.value().val_, successVal);
+    auto r = f(false);
+    EXPECT_TRUE(!r.ok());
+    EXPECT_EQ(PERMISSION_DENIED, r.error().code());
+}
diff --git a/libutils/binder/FuzzFormatTypes.h b/libutils/binder/FuzzFormatTypes.h
new file mode 100644
index 0000000..aa9e503
--- /dev/null
+++ b/libutils/binder/FuzzFormatTypes.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <string>
+
+static const std::string kFormatChars = std::string("duoxXfFeEgGaAcsp");
+static constexpr int32_t kMaxFormatFlagValue = INT16_MAX;
+enum FormatChar : uint8_t {
+    SIGNED_DECIMAL = 0,
+    UNSIGNED_DECIMAL = 1,
+    UNSIGNED_OCTAL = 2,
+    UNSIGNED_HEX_LOWER = 3,
+    UNSIGNED_HEX_UPPER = 4,
+    // Uppercase/lowercase floating point impacts 'inf', 'infinity', and 'nan'
+    FLOAT_LOWER = 5,
+    FLOAT_UPPER = 6,
+    // Upper/lower impacts the "e" in exponents.
+    EXPONENT_LOWER = 7,
+    EXPONENT_UPPER = 8,
+    // %g will use %e or %f, whichever is shortest
+    SHORT_EXP_LOWER = 9,
+    // %G will use %E or %F, whichever is shortest
+    SHORT_EXP_UPPER = 10,
+    HEX_FLOAT_LOWER = 11,
+    HEX_FLOAT_UPPER = 12,
+    CHAR = 13,
+    STRING = 14,
+    POINTER = 15,
+    // Used by libfuzzer
+    kMaxValue = POINTER
+};
+
+bool canApplyFlag(FormatChar formatChar, char modifier) {
+    if (modifier == '#') {
+        return formatChar == UNSIGNED_OCTAL || formatChar == UNSIGNED_HEX_LOWER ||
+               formatChar == UNSIGNED_HEX_UPPER || formatChar == FLOAT_LOWER ||
+               formatChar == FLOAT_UPPER || formatChar == SHORT_EXP_LOWER ||
+               formatChar == SHORT_EXP_UPPER;
+    } else if (modifier == '.') {
+        return formatChar == SIGNED_DECIMAL || formatChar == UNSIGNED_DECIMAL ||
+               formatChar == UNSIGNED_OCTAL || formatChar == UNSIGNED_HEX_LOWER ||
+               formatChar == UNSIGNED_HEX_UPPER || formatChar == FLOAT_LOWER ||
+               formatChar == FLOAT_UPPER || formatChar == SHORT_EXP_LOWER ||
+               formatChar == SHORT_EXP_UPPER || formatChar == STRING;
+    }
+    return true;
+}
diff --git a/libutils/binder/RefBase.cpp b/libutils/binder/RefBase.cpp
new file mode 100644
index 0000000..c7055fb
--- /dev/null
+++ b/libutils/binder/RefBase.cpp
@@ -0,0 +1,856 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RefBase"
+// #define LOG_NDEBUG 0
+
+#include <memory>
+#include <mutex>
+
+#include <android-base/macros.h>
+
+#include <fcntl.h>
+#include <log/log.h>
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+// Compile with refcounting debugging enabled.
+#ifndef DEBUG_REFS
+#define DEBUG_REFS 0
+#endif
+
+// The following three are ignored unless DEBUG_REFS is set.
+
+// whether ref-tracking is enabled by default, if not, trackMe(true, false)
+// needs to be called explicitly
+#define DEBUG_REFS_ENABLED_BY_DEFAULT 0
+
+// whether callstack are collected (significantly slows things down)
+#define DEBUG_REFS_CALLSTACK_ENABLED 1
+
+// folder where stack traces are saved when DEBUG_REFS is enabled
+// this folder needs to exist and be writable
+#ifdef __ANDROID__
+#define DEBUG_REFS_CALLSTACK_PATH "/data/debug"
+#else
+#define DEBUG_REFS_CALLSTACK_PATH "."
+#endif
+
+// log all reference counting operations
+#define PRINT_REFS 0
+
+#if defined(__linux__)
+// CallStack is only supported on linux type platforms.
+#define CALLSTACK_ENABLED 1
+#else
+#define CALLSTACK_ENABLED 0
+#endif
+
+#if CALLSTACK_ENABLED
+#include <utils/CallStack.h>
+#endif
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// Observations, invariants, etc:
+
+// By default, obects are destroyed when the last strong reference disappears
+// or, if the object never had a strong reference, when the last weak reference
+// disappears.
+//
+// OBJECT_LIFETIME_WEAK changes this behavior to retain the object
+// unconditionally until the last reference of either kind disappears.  The
+// client ensures that the extendObjectLifetime call happens before the dec
+// call that would otherwise have deallocated the object, or before an
+// attemptIncStrong call that might rely on it.  We do not worry about
+// concurrent changes to the object lifetime.
+//
+// AttemptIncStrong will succeed if the object has a strong reference, or if it
+// has a weak reference and has never had a strong reference.
+// AttemptIncWeak really does succeed only if there is already a WEAK
+// reference, and thus may fail when attemptIncStrong would succeed.
+//
+// mStrong is the strong reference count.  mWeak is the weak reference count.
+// Between calls, and ignoring memory ordering effects, mWeak includes strong
+// references, and is thus >= mStrong.
+//
+// A weakref_impl holds all the information, including both reference counts,
+// required to perform wp<> operations.  Thus these can continue to be performed
+// after the RefBase object has been destroyed.
+//
+// A weakref_impl is allocated as the value of mRefs in a RefBase object on
+// construction.
+// In the OBJECT_LIFETIME_STRONG case, it is normally deallocated in decWeak,
+// and hence lives as long as the last weak reference. (It can also be
+// deallocated in the RefBase destructor iff the strong reference count was
+// never incremented and the weak count is zero, e.g.  if the RefBase object is
+// explicitly destroyed without decrementing the strong count.  This should be
+// avoided.) In this case, the RefBase destructor should be invoked from
+// decStrong.
+// In the OBJECT_LIFETIME_WEAK case, the weakref_impl is always deallocated in
+// the RefBase destructor, which is always invoked by decWeak. DecStrong
+// explicitly avoids the deletion in this case.
+//
+// Memory ordering:
+// The client must ensure that every inc() call, together with all other
+// accesses to the object, happens before the corresponding dec() call.
+//
+// We try to keep memory ordering constraints on atomics as weak as possible,
+// since memory fences or ordered memory accesses are likely to be a major
+// performance cost for this code. All accesses to mStrong, mWeak, and mFlags
+// explicitly relax memory ordering in some way.
+//
+// The only operations that are not memory_order_relaxed are reference count
+// decrements. All reference count decrements are release operations.  In
+// addition, the final decrement leading the deallocation is followed by an
+// acquire fence, which we can view informally as also turning it into an
+// acquire operation.  (See 29.8p4 [atomics.fences] for details. We could
+// alternatively use acq_rel operations for all decrements. This is probably
+// slower on most current (2016) hardware, especially on ARMv7, but that may
+// not be true indefinitely.)
+//
+// This convention ensures that the second-to-last decrement synchronizes with
+// (in the language of 1.10 in the C++ standard) the final decrement of a
+// reference count. Since reference counts are only updated using atomic
+// read-modify-write operations, this also extends to any earlier decrements.
+// (See "release sequence" in 1.10.)
+//
+// Since all operations on an object happen before the corresponding reference
+// count decrement, and all reference count decrements happen before the final
+// one, we are guaranteed that all other object accesses happen before the
+// object is destroyed.
+
+
+#define INITIAL_STRONG_VALUE (1<<28)
+
+#define MAX_COUNT 0xfffff
+
+// Test whether the argument is a clearly invalid strong reference count.
+// Used only for error checking on the value before an atomic decrement.
+// Intended to be very cheap.
+// Note that we cannot just check for excess decrements by comparing to zero
+// since the object would be deallocated before that.
+#define BAD_STRONG(c) \
+        ((c) == 0 || ((c) & (~(MAX_COUNT | INITIAL_STRONG_VALUE))) != 0)
+
+// Same for weak counts.
+#define BAD_WEAK(c) ((c) == 0 || ((c) & (~MAX_COUNT)) != 0)
+
+// name kept because prebuilts used to use it from inlining sp<> code
+void sp_report_stack_pointer() { LOG_ALWAYS_FATAL("RefBase used with stack pointer argument"); }
+
+// Check whether address is definitely on the calling stack.  We actually check whether it is on
+// the same 4K page as the frame pointer.
+//
+// Assumptions:
+// - Pages are never smaller than 4K (MIN_PAGE_SIZE)
+// - Malloced memory never shares a page with a stack.
+//
+// It does not appear safe to broaden this check to include adjacent pages; apparently this code
+// is used in environments where there may not be a guard page below (at higher addresses than)
+// the bottom of the stack.
+static void check_not_on_stack(const void* ptr) {
+    static constexpr int MIN_PAGE_SIZE = 0x1000;  // 4K. Safer than including sys/user.h.
+    static constexpr uintptr_t MIN_PAGE_MASK = ~static_cast<uintptr_t>(MIN_PAGE_SIZE - 1);
+    uintptr_t my_frame_address =
+            reinterpret_cast<uintptr_t>(__builtin_frame_address(0 /* this frame */));
+    if (((reinterpret_cast<uintptr_t>(ptr) ^ my_frame_address) & MIN_PAGE_MASK) == 0) {
+        sp_report_stack_pointer();
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+class RefBase::weakref_impl : public RefBase::weakref_type
+{
+public:
+    std::atomic<int32_t>    mStrong;
+    std::atomic<int32_t>    mWeak;
+    RefBase* const          mBase;
+    std::atomic<int32_t>    mFlags;
+
+#if !DEBUG_REFS
+
+    explicit weakref_impl(RefBase* base)
+        : mStrong(INITIAL_STRONG_VALUE)
+        , mWeak(0)
+        , mBase(base)
+        , mFlags(OBJECT_LIFETIME_STRONG)
+    {
+    }
+
+    void addStrongRef(const void* /*id*/) { }
+    void removeStrongRef(const void* /*id*/) { }
+    void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+    void addWeakRef(const void* /*id*/) { }
+    void removeWeakRef(const void* /*id*/) { }
+    void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+    void printRefs() const { }
+    void trackMe(bool, bool) { }
+
+#else
+
+    weakref_impl(RefBase* base)
+        : mStrong(INITIAL_STRONG_VALUE)
+        , mWeak(0)
+        , mBase(base)
+        , mFlags(OBJECT_LIFETIME_STRONG)
+        , mStrongRefs(NULL)
+        , mWeakRefs(NULL)
+        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
+        , mRetain(false)
+    {
+    }
+
+    ~weakref_impl()
+    {
+        bool dumpStack = false;
+        if (!mRetain && mStrongRefs != NULL) {
+            dumpStack = true;
+            ALOGE("Strong references remain:");
+            ref_entry* refs = mStrongRefs;
+            while (refs) {
+                char inc = refs->ref >= 0 ? '+' : '-';
+                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
+                CallStack::logStack(LOG_TAG, refs->stack.get());
+#endif
+                refs = refs->next;
+            }
+        }
+
+        if (!mRetain && mWeakRefs != NULL) {
+            dumpStack = true;
+            ALOGE("Weak references remain!");
+            ref_entry* refs = mWeakRefs;
+            while (refs) {
+                char inc = refs->ref >= 0 ? '+' : '-';
+                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
+                CallStack::logStack(LOG_TAG, refs->stack.get());
+#endif
+                refs = refs->next;
+            }
+        }
+        if (dumpStack) {
+            ALOGE("above errors at:");
+#if CALLSTACK_ENABLED
+            CallStack::logStack(LOG_TAG);
+#endif
+        }
+    }
+
+    void addStrongRef(const void* id) {
+        //ALOGD_IF(mTrackEnabled,
+        //        "addStrongRef: RefBase=%p, id=%p", mBase, id);
+        addRef(&mStrongRefs, id, mStrong.load(std::memory_order_relaxed));
+    }
+
+    void removeStrongRef(const void* id) {
+        //ALOGD_IF(mTrackEnabled,
+        //        "removeStrongRef: RefBase=%p, id=%p", mBase, id);
+        if (!mRetain) {
+            removeRef(&mStrongRefs, id);
+        } else {
+            addRef(&mStrongRefs, id, -mStrong.load(std::memory_order_relaxed));
+        }
+    }
+
+    void renameStrongRefId(const void* old_id, const void* new_id) {
+        //ALOGD_IF(mTrackEnabled,
+        //        "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
+        //        mBase, old_id, new_id);
+        renameRefsId(mStrongRefs, old_id, new_id);
+    }
+
+    void addWeakRef(const void* id) {
+        addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
+    }
+
+    void removeWeakRef(const void* id) {
+        if (!mRetain) {
+            removeRef(&mWeakRefs, id);
+        } else {
+            addRef(&mWeakRefs, id, -mWeak.load(std::memory_order_relaxed));
+        }
+    }
+
+    void renameWeakRefId(const void* old_id, const void* new_id) {
+        renameRefsId(mWeakRefs, old_id, new_id);
+    }
+
+    void trackMe(bool track, bool retain) {
+        mTrackEnabled = track;
+        mRetain = retain;
+    }
+
+    void printRefs() const
+    {
+        String8 text;
+
+        {
+            std::lock_guard<std::mutex> _l(mMutex);
+            char buf[128];
+            snprintf(buf, sizeof(buf),
+                     "Strong references on RefBase %p (weakref_type %p):\n",
+                     mBase, this);
+            text.append(buf);
+            printRefsLocked(&text, mStrongRefs);
+            snprintf(buf, sizeof(buf),
+                     "Weak references on RefBase %p (weakref_type %p):\n",
+                     mBase, this);
+            text.append(buf);
+            printRefsLocked(&text, mWeakRefs);
+        }
+
+        {
+            char name[100];
+            snprintf(name, sizeof(name), DEBUG_REFS_CALLSTACK_PATH "/%p.stack",
+                     this);
+            int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 0644);
+            if (rc >= 0) {
+                (void)write(rc, text.c_str(), text.length());
+                close(rc);
+                ALOGI("STACK TRACE for %p saved in %s", this, name);
+            }
+            else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
+                      name, strerror(errno));
+        }
+    }
+
+private:
+    struct ref_entry
+    {
+        ref_entry* next;
+        const void* id;
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
+        CallStack::CallStackUPtr stack;
+#endif
+        int32_t ref;
+    };
+
+    void addRef(ref_entry** refs, const void* id, int32_t mRef)
+    {
+        if (mTrackEnabled) {
+            std::lock_guard<std::mutex> _l(mMutex);
+
+            ref_entry* ref = new ref_entry;
+            // Reference count at the time of the snapshot, but before the
+            // update.  Positive value means we increment, negative--we
+            // decrement the reference count.
+            ref->ref = mRef;
+            ref->id = id;
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
+            ref->stack = CallStack::getCurrent(2);
+#endif
+            ref->next = *refs;
+            *refs = ref;
+        }
+    }
+
+    void removeRef(ref_entry** refs, const void* id)
+    {
+        if (mTrackEnabled) {
+            std::lock_guard<std::mutex> _l(mMutex);
+
+            ref_entry* const head = *refs;
+            ref_entry* ref = head;
+            while (ref != NULL) {
+                if (ref->id == id) {
+                    *refs = ref->next;
+                    delete ref;
+                    return;
+                }
+                refs = &ref->next;
+                ref = *refs;
+            }
+
+            ALOGE("RefBase: removing id %p on RefBase %p"
+                    "(weakref_type %p) that doesn't exist!",
+                    id, mBase, this);
+
+            ref = head;
+            while (ref) {
+                char inc = ref->ref >= 0 ? '+' : '-';
+                ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
+                ref = ref->next;
+            }
+
+#if CALLSTACK_ENABLED
+            CallStack::logStack(LOG_TAG);
+#endif
+        }
+    }
+
+    void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
+    {
+        if (mTrackEnabled) {
+            std::lock_guard<std::mutex> _l(mMutex);
+            ref_entry* ref = r;
+            while (ref != NULL) {
+                if (ref->id == old_id) {
+                    ref->id = new_id;
+                }
+                ref = ref->next;
+            }
+        }
+    }
+
+    void printRefsLocked(String8* out, const ref_entry* refs) const
+    {
+        char buf[128];
+        while (refs) {
+            char inc = refs->ref >= 0 ? '+' : '-';
+            snprintf(buf, sizeof(buf), "\t%c ID %p (ref %d):\n",
+                     inc, refs->id, refs->ref);
+            out->append(buf);
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
+            out->append(CallStack::stackToString("\t\t", refs->stack.get()));
+#else
+            out->append("\t\t(call stacks disabled)");
+#endif
+            refs = refs->next;
+        }
+    }
+
+    mutable std::mutex mMutex;
+    ref_entry* mStrongRefs;
+    ref_entry* mWeakRefs;
+
+    bool mTrackEnabled;
+    // Collect stack traces on addref and removeref, instead of deleting the stack references
+    // on removeref that match the address ones.
+    bool mRetain;
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+void RefBase::incStrong(const void* id) const
+{
+    weakref_impl* const refs = mRefs;
+    refs->incWeak(id);
+
+    refs->addStrongRef(id);
+    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
+    ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
+#if PRINT_REFS
+    ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+    if (c != INITIAL_STRONG_VALUE)  {
+        return;
+    }
+
+    check_not_on_stack(this);
+
+    int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed);
+    // A decStrong() must still happen after us.
+    ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
+    refs->mBase->onFirstRef();
+}
+
+void RefBase::incStrongRequireStrong(const void* id) const {
+    weakref_impl* const refs = mRefs;
+    refs->incWeak(id);
+
+    refs->addStrongRef(id);
+    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
+
+    LOG_ALWAYS_FATAL_IF(c <= 0 || c == INITIAL_STRONG_VALUE,
+                        "incStrongRequireStrong() called on %p which isn't already owned", refs);
+#if PRINT_REFS
+    ALOGD("incStrong (requiring strong) of %p from %p: cnt=%d\n", this, id, c);
+#endif
+}
+
+void RefBase::decStrong(const void* id) const
+{
+    weakref_impl* const refs = mRefs;
+    refs->removeStrongRef(id);
+    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
+#if PRINT_REFS
+    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+    LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
+            refs);
+    if (c == 1) {
+        std::atomic_thread_fence(std::memory_order_acquire);
+        refs->mBase->onLastStrongRef(id);
+        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
+        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
+            delete this;
+            // The destructor does not delete refs in this case.
+        }
+    }
+    // Note that even with only strong reference operations, the thread
+    // deallocating this may not be the same as the thread deallocating refs.
+    // That's OK: all accesses to this happen before its deletion here,
+    // and all accesses to refs happen before its deletion in the final decWeak.
+    // The destructor can safely access mRefs because either it's deleting
+    // mRefs itself, or it's running entirely before the final mWeak decrement.
+    //
+    // Since we're doing atomic loads of `flags`, the static analyzer assumes
+    // they can change between `delete this;` and `refs->decWeak(id);`. This is
+    // not the case. The analyzer may become more okay with this patten when
+    // https://bugs.llvm.org/show_bug.cgi?id=34365 gets resolved. NOLINTNEXTLINE
+    refs->decWeak(id);
+}
+
+void RefBase::forceIncStrong(const void* id) const
+{
+    // Allows initial mStrong of 0 in addition to INITIAL_STRONG_VALUE.
+    // TODO: Better document assumptions.
+    weakref_impl* const refs = mRefs;
+    refs->incWeak(id);
+
+    refs->addStrongRef(id);
+    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
+    ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
+               refs);
+#if PRINT_REFS
+    ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+
+    switch (c) {
+    case INITIAL_STRONG_VALUE:
+        refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
+                std::memory_order_relaxed);
+        FALLTHROUGH_INTENDED;
+    case 0:
+        refs->mBase->onFirstRef();
+    }
+}
+
+int32_t RefBase::getStrongCount() const
+{
+    // Debugging only; No memory ordering guarantees.
+    return mRefs->mStrong.load(std::memory_order_relaxed);
+}
+
+RefBase* RefBase::weakref_type::refBase() const
+{
+    return static_cast<const weakref_impl*>(this)->mBase;
+}
+
+void RefBase::weakref_type::incWeak(const void* id)
+{
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+    impl->addWeakRef(id);
+    const int32_t c __unused = impl->mWeak.fetch_add(1,
+            std::memory_order_relaxed);
+    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
+}
+
+void RefBase::weakref_type::incWeakRequireWeak(const void* id)
+{
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+    impl->addWeakRef(id);
+    const int32_t c __unused = impl->mWeak.fetch_add(1,
+            std::memory_order_relaxed);
+    LOG_ALWAYS_FATAL_IF(c <= 0, "incWeakRequireWeak called on %p which has no weak refs", this);
+}
+
+void RefBase::weakref_type::decWeak(const void* id)
+{
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+    impl->removeWeakRef(id);
+    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
+    LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
+            this);
+    if (c != 1) return;
+    atomic_thread_fence(std::memory_order_acquire);
+
+    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
+    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
+        // This is the regular lifetime case. The object is destroyed
+        // when the last strong reference goes away. Since weakref_impl
+        // outlives the object, it is not destroyed in the dtor, and
+        // we'll have to do it here.
+        if (impl->mStrong.load(std::memory_order_relaxed)
+                == INITIAL_STRONG_VALUE) {
+            // Decrementing a weak count to zero when object never had a strong
+            // reference.  We assume it acquired a weak reference early, e.g.
+            // in the constructor, and will eventually be properly destroyed,
+            // usually via incrementing and decrementing the strong count.
+            // Thus we no longer do anything here.  We log this case, since it
+            // seems to be extremely rare, and should not normally occur. We
+            // used to deallocate mBase here, so this may now indicate a leak.
+            ALOGW("RefBase: Object at %p lost last weak reference "
+                    "before it had a strong reference", impl->mBase);
+        } else {
+            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
+            delete impl;
+        }
+    } else {
+        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
+        // is gone, we can destroy the object.
+        impl->mBase->onLastWeakRef(id);
+        delete impl->mBase;
+    }
+}
+
+bool RefBase::weakref_type::attemptIncStrong(const void* id)
+{
+    incWeak(id);
+
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+    int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
+
+    ALOG_ASSERT(curCount >= 0,
+            "attemptIncStrong called on %p after underflow", this);
+
+    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
+        // we're in the easy/common case of promoting a weak-reference
+        // from an existing strong reference.
+        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
+                std::memory_order_relaxed)) {
+            break;
+        }
+        // the strong count has changed on us, we need to re-assert our
+        // situation. curCount was updated by compare_exchange_weak.
+    }
+
+    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
+        // we're now in the harder case of either:
+        // - there never was a strong reference on us
+        // - or, all strong references have been released
+        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
+        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
+            // this object has a "normal" life-time, i.e.: it gets destroyed
+            // when the last strong reference goes away
+            if (curCount <= 0) {
+                // the last strong-reference got released, the object cannot
+                // be revived.
+                decWeak(id);
+                return false;
+            }
+
+            // here, curCount == INITIAL_STRONG_VALUE, which means
+            // there never was a strong-reference, so we can try to
+            // promote this object; we need to do that atomically.
+            while (curCount > 0) {
+                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
+                        std::memory_order_relaxed)) {
+                    break;
+                }
+                // the strong count has changed on us, we need to re-assert our
+                // situation (e.g.: another thread has inc/decStrong'ed us)
+                // curCount has been updated.
+            }
+
+            if (curCount <= 0) {
+                // promote() failed, some other thread destroyed us in the
+                // meantime (i.e.: strong count reached zero).
+                decWeak(id);
+                return false;
+            }
+        } else {
+            // this object has an "extended" life-time, i.e.: it can be
+            // revived from a weak-reference only.
+            // Ask the object's implementation if it agrees to be revived
+            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
+                // it didn't so give-up.
+                decWeak(id);
+                return false;
+            }
+            // grab a strong-reference, which is always safe due to the
+            // extended life-time.
+            curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
+            // If the strong reference count has already been incremented by
+            // someone else, the implementor of onIncStrongAttempted() is holding
+            // an unneeded reference.  So call onLastStrongRef() here to remove it.
+            // (No, this is not pretty.)  Note that we MUST NOT do this if we
+            // are in fact acquiring the first reference.
+            if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
+                impl->mBase->onLastStrongRef(id);
+            }
+        }
+    }
+
+    impl->addStrongRef(id);
+
+#if PRINT_REFS
+    ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
+#endif
+
+    // curCount is the value of mStrong before we incremented it.
+    // Now we need to fix-up the count if it was INITIAL_STRONG_VALUE.
+    // This must be done safely, i.e.: handle the case where several threads
+    // were here in attemptIncStrong().
+    // curCount > INITIAL_STRONG_VALUE is OK, and can happen if we're doing
+    // this in the middle of another incStrong.  The subtraction is handled
+    // by the thread that started with INITIAL_STRONG_VALUE.
+    if (curCount == INITIAL_STRONG_VALUE) {
+        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
+                std::memory_order_relaxed);
+    }
+
+    return true;
+}
+
+bool RefBase::weakref_type::attemptIncWeak(const void* id)
+{
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+
+    int32_t curCount = impl->mWeak.load(std::memory_order_relaxed);
+    ALOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
+               this);
+    while (curCount > 0) {
+        if (impl->mWeak.compare_exchange_weak(curCount, curCount+1,
+                std::memory_order_relaxed)) {
+            break;
+        }
+        // curCount has been updated.
+    }
+
+    if (curCount > 0) {
+        impl->addWeakRef(id);
+    }
+
+    return curCount > 0;
+}
+
+int32_t RefBase::weakref_type::getWeakCount() const
+{
+    // Debug only!
+    return static_cast<const weakref_impl*>(this)->mWeak
+            .load(std::memory_order_relaxed);
+}
+
+void RefBase::weakref_type::printRefs() const
+{
+    static_cast<const weakref_impl*>(this)->printRefs();
+}
+
+void RefBase::weakref_type::trackMe(bool enable, bool retain)
+{
+    static_cast<weakref_impl*>(this)->trackMe(enable, retain);
+}
+
+RefBase::weakref_type* RefBase::createWeak(const void* id) const
+{
+    mRefs->incWeak(id);
+    return mRefs;
+}
+
+RefBase::weakref_type* RefBase::getWeakRefs() const
+{
+    return mRefs;
+}
+
+RefBase::RefBase()
+    : mRefs(new weakref_impl(this))
+{
+}
+
+RefBase::~RefBase()
+{
+    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
+    // Life-time of this object is extended to WEAK, in
+    // which case weakref_impl doesn't out-live the object and we
+    // can free it now.
+    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
+        // It's possible that the weak count is not 0 if the object
+        // re-acquired a weak reference in its destructor
+        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
+            delete mRefs;
+        }
+    } else {
+        int32_t strongs = mRefs->mStrong.load(std::memory_order_relaxed);
+
+        if (strongs == INITIAL_STRONG_VALUE) {
+            // We never acquired a strong reference on this object.
+
+            // It would be nice to make this fatal, but many places use RefBase on the stack.
+            // However, this is dangerous because it's also common for code to use the
+            // sp<T>(T*) constructor, assuming that if the object is around, it is already
+            // owned by an sp<>.
+            ALOGW("RefBase: Explicit destruction, weak count = %d (in %p). Use sp<> to manage this "
+                  "object.",
+                  mRefs->mWeak.load(), this);
+
+#if CALLSTACK_ENABLED
+            CallStack::logStack(LOG_TAG);
+#endif
+        } else if (strongs != 0) {
+            LOG_ALWAYS_FATAL("RefBase: object %p with strong count %d deleted. Double owned?", this,
+                             strongs);
+        }
+    }
+    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
+    const_cast<weakref_impl*&>(mRefs) = nullptr;
+}
+
+void RefBase::extendObjectLifetime(int32_t mode)
+{
+    check_not_on_stack(this);
+
+    // Must be happens-before ordered with respect to construction or any
+    // operation that could destroy the object.
+    mRefs->mFlags.fetch_or(mode, std::memory_order_relaxed);
+}
+
+void RefBase::onFirstRef()
+{
+}
+
+void RefBase::onLastStrongRef(const void* /*id*/)
+{
+}
+
+bool RefBase::onIncStrongAttempted(uint32_t flags, const void* /*id*/)
+{
+    return (flags&FIRST_INC_STRONG) ? true : false;
+}
+
+void RefBase::onLastWeakRef(const void* /*id*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+#if DEBUG_REFS
+void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) {
+    for (size_t i=0 ; i<n ; i++) {
+        renamer(i);
+    }
+}
+#else
+void RefBase::renameRefs(size_t /*n*/, const ReferenceRenamer& /*renamer*/) { }
+#endif
+
+void RefBase::renameRefId(weakref_type* ref,
+        const void* old_id, const void* new_id) {
+    weakref_impl* const impl = static_cast<weakref_impl*>(ref);
+    impl->renameStrongRefId(old_id, new_id);
+    impl->renameWeakRefId(old_id, new_id);
+}
+
+void RefBase::renameRefId(RefBase* ref,
+        const void* old_id, const void* new_id) {
+    ref->mRefs->renameStrongRefId(old_id, new_id);
+    ref->mRefs->renameWeakRefId(old_id, new_id);
+}
+
+}; // namespace android
diff --git a/libutils/binder/RefBase_fuzz.cpp b/libutils/binder/RefBase_fuzz.cpp
new file mode 100644
index 0000000..05f47a0
--- /dev/null
+++ b/libutils/binder/RefBase_fuzz.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "RefBaseFuzz"
+
+#include <thread>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "log/log.h"
+#include "utils/RWLock.h"
+#include "utils/RefBase.h"
+#include "utils/StrongPointer.h"
+
+using android::RefBase;
+using android::RWLock;
+using android::sp;
+using android::wp;
+
+static constexpr int kMaxOperations = 100;
+static constexpr int kMaxThreads = 10;
+struct RefBaseSubclass : public RefBase {
+  public:
+    RefBaseSubclass(bool* deletedCheck, RWLock& deletedMtx)
+        : mDeleted(deletedCheck), mRwLock(deletedMtx) {
+        RWLock::AutoWLock lock(mRwLock);
+        *mDeleted = false;
+        extendObjectLifetime(OBJECT_LIFETIME_WEAK);
+    }
+
+    virtual ~RefBaseSubclass() {
+        RWLock::AutoWLock lock(mRwLock);
+        *mDeleted = true;
+    }
+
+  private:
+    bool* mDeleted;
+    android::RWLock& mRwLock;
+};
+
+// A thread-specific state object for ref
+struct RefThreadState {
+    size_t strongCount = 0;
+    size_t weakCount = 0;
+};
+
+RWLock gRefDeletedLock;
+bool gRefDeleted = false;
+bool gHasModifiedRefs = false;
+RefBaseSubclass* ref;
+RefBase::weakref_type* weakRefs;
+
+// These operations don't need locks as they explicitly check per-thread counts before running
+// they also have the potential to write to gRefDeleted, so must not be locked.
+const std::vector<std::function<void(RefThreadState*)>> kUnlockedOperations = {
+        [](RefThreadState* refState) -> void {
+            if (refState->strongCount > 0) {
+                ref->decStrong(nullptr);
+                gHasModifiedRefs = true;
+                refState->strongCount--;
+            }
+        },
+        [](RefThreadState* refState) -> void {
+            if (refState->weakCount > 0) {
+                weakRefs->decWeak(nullptr);
+                gHasModifiedRefs = true;
+                refState->weakCount--;
+            }
+        },
+};
+
+const std::vector<std::function<void(RefThreadState*)>> kMaybeLockedOperations = {
+        // Read-only operations
+        [](RefThreadState*) -> void { ref->getStrongCount(); },
+        [](RefThreadState*) -> void { weakRefs->getWeakCount(); },
+        [](RefThreadState*) -> void { ref->printRefs(); },
+
+        // Read/write operations
+        [](RefThreadState* refState) -> void {
+            ref->incStrong(nullptr);
+            gHasModifiedRefs = true;
+            refState->strongCount++;
+        },
+        [](RefThreadState* refState) -> void {
+            ref->forceIncStrong(nullptr);
+            gHasModifiedRefs = true;
+            refState->strongCount++;
+        },
+        [](RefThreadState* refState) -> void {
+            ref->createWeak(nullptr);
+            gHasModifiedRefs = true;
+            refState->weakCount++;
+        },
+        [](RefThreadState* refState) -> void {
+            // This will increment weak internally, then attempt to
+            // promote it to strong. If it fails, it decrements weak.
+            // If it succeeds, the weak is converted to strong.
+            // Both cases net no weak reference change.
+            if (weakRefs->attemptIncStrong(nullptr)) {
+                refState->strongCount++;
+                gHasModifiedRefs = true;
+            }
+        },
+        [](RefThreadState* refState) -> void {
+            if (weakRefs->attemptIncWeak(nullptr)) {
+                refState->weakCount++;
+                gHasModifiedRefs = true;
+            }
+        },
+        [](RefThreadState* refState) -> void {
+            weakRefs->incWeak(nullptr);
+            gHasModifiedRefs = true;
+            refState->weakCount++;
+        },
+};
+
+void loop(const std::vector<uint8_t>& fuzzOps) {
+    RefThreadState state;
+    uint8_t lockedOpSize = kMaybeLockedOperations.size();
+    uint8_t totalOperationTypes = lockedOpSize + kUnlockedOperations.size();
+    for (auto op : fuzzOps) {
+        auto opVal = op % totalOperationTypes;
+        if (opVal >= lockedOpSize) {
+            kUnlockedOperations[opVal % lockedOpSize](&state);
+        } else {
+            // We only need to lock if we have no strong or weak count
+            bool shouldLock = state.strongCount == 0 && state.weakCount == 0;
+            if (shouldLock) {
+                gRefDeletedLock.readLock();
+                // If ref has deleted itself, we can no longer fuzz on this thread.
+                if (gRefDeleted) {
+                    // Unlock since we're exiting the loop here.
+                    gRefDeletedLock.unlock();
+                    return;
+                }
+            }
+            // Execute the locked operation
+            kMaybeLockedOperations[opVal](&state);
+            // Unlock if we locked.
+            if (shouldLock) {
+                gRefDeletedLock.unlock();
+            }
+        }
+    }
+
+    // Instead of explicitly freeing this, we're going to remove our weak and
+    // strong references.
+    for (; state.weakCount > 0; state.weakCount--) {
+        weakRefs->decWeak(nullptr);
+    }
+
+    // Clean up any strong references
+    for (; state.strongCount > 0; state.strongCount--) {
+        ref->decStrong(nullptr);
+    }
+}
+
+void spawnThreads(FuzzedDataProvider* dataProvider) {
+    std::vector<std::thread> threads = std::vector<std::thread>();
+
+    // Get the number of threads to generate
+    uint8_t count = dataProvider->ConsumeIntegralInRange<uint8_t>(1, kMaxThreads);
+    // Generate threads
+    for (uint8_t i = 0; i < count; i++) {
+        uint8_t opCount = dataProvider->ConsumeIntegralInRange<uint8_t>(1, kMaxOperations);
+        std::vector<uint8_t> threadOperations = dataProvider->ConsumeBytes<uint8_t>(opCount);
+        std::thread tmpThread = std::thread(loop, threadOperations);
+        threads.push_back(std::move(tmpThread));
+    }
+
+    for (auto& th : threads) {
+        th.join();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    gHasModifiedRefs = false;
+    ref = new RefBaseSubclass(&gRefDeleted, gRefDeletedLock);
+    weakRefs = ref->getWeakRefs();
+    // Since we are modifying flags, (flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK
+    // is true. The destructor for RefBase should clean up weakrefs because of this.
+    FuzzedDataProvider dataProvider(data, size);
+    spawnThreads(&dataProvider);
+    LOG_ALWAYS_FATAL_IF(!gHasModifiedRefs && gRefDeleted, "ref(%p) was prematurely deleted!", ref);
+    // We need to explicitly delete this object
+    // if no refs have been added or deleted.
+    if (!gHasModifiedRefs && !gRefDeleted) {
+        delete ref;
+    }
+    LOG_ALWAYS_FATAL_IF(gHasModifiedRefs && !gRefDeleted,
+                        "ref(%p) should be deleted, is it leaking?", ref);
+    return 0;
+}
diff --git a/libutils/binder/RefBase_test.cpp b/libutils/binder/RefBase_test.cpp
new file mode 100644
index 0000000..d675598
--- /dev/null
+++ b/libutils/binder/RefBase_test.cpp
@@ -0,0 +1,447 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
+
+#include <thread>
+#include <atomic>
+#include <sched.h>
+#include <errno.h>
+
+// Enhanced version of StrongPointer_test, but using RefBase underneath.
+
+using namespace android;
+
+static constexpr int NITERS = 500000;
+
+static constexpr int INITIAL_STRONG_VALUE = 1 << 28;  // Mirroring RefBase definition.
+
+class Foo : public RefBase {
+public:
+    Foo(bool* deleted_check) : mDeleted(deleted_check) {
+        *mDeleted = false;
+    }
+
+    ~Foo() {
+        *mDeleted = true;
+    }
+private:
+    bool* mDeleted;
+};
+
+// A version of Foo that ensures that all objects are allocated at the same
+// address. No more than one can be allocated at a time. Thread-hostile.
+class FooFixedAlloc : public RefBase {
+public:
+    static void* operator new(size_t size) {
+        if (mAllocCount != 0) {
+            abort();
+        }
+        mAllocCount = 1;
+        if (theMemory == nullptr) {
+            theMemory = malloc(size);
+        }
+        return theMemory;
+    }
+
+    static void operator delete(void *p) {
+        if (mAllocCount != 1 || p != theMemory) {
+            abort();
+        }
+        mAllocCount = 0;
+    }
+
+    FooFixedAlloc(bool* deleted_check) : mDeleted(deleted_check) {
+        *mDeleted = false;
+    }
+
+    ~FooFixedAlloc() {
+        *mDeleted = true;
+    }
+private:
+    bool* mDeleted;
+    static int mAllocCount;
+    static void* theMemory;
+};
+
+int FooFixedAlloc::mAllocCount(0);
+void* FooFixedAlloc::theMemory(nullptr);
+
+TEST(RefBase, StrongMoves) {
+    bool isDeleted;
+    Foo* foo = new Foo(&isDeleted);
+    ASSERT_EQ(INITIAL_STRONG_VALUE, foo->getStrongCount());
+    ASSERT_FALSE(isDeleted) << "Already deleted...?";
+    sp<Foo> sp1(foo);
+    wp<Foo> wp1(sp1);
+    ASSERT_EQ(1, foo->getStrongCount());
+    // Weak count includes both strong and weak references.
+    ASSERT_EQ(2, foo->getWeakRefs()->getWeakCount());
+    {
+        sp<Foo> sp2 = std::move(sp1);
+        ASSERT_EQ(1, foo->getStrongCount())
+                << "std::move failed, incremented refcnt";
+        ASSERT_EQ(nullptr, sp1.get()) << "std::move failed, sp1 is still valid";
+        // The strong count isn't increasing, let's double check the old object
+        // is properly reset and doesn't early delete
+        sp1 = std::move(sp2);
+    }
+    ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!";
+    {
+        // Now let's double check it deletes on time
+        sp<Foo> sp2 = std::move(sp1);
+    }
+    ASSERT_TRUE(isDeleted) << "foo was leaked!";
+    ASSERT_TRUE(wp1.promote().get() == nullptr);
+}
+
+TEST(RefBase, WeakCopies) {
+    bool isDeleted;
+    Foo* foo = new Foo(&isDeleted);
+    EXPECT_EQ(0, foo->getWeakRefs()->getWeakCount());
+    ASSERT_FALSE(isDeleted) << "Foo (weak) already deleted...?";
+    wp<Foo> wp1(foo);
+    EXPECT_EQ(1, foo->getWeakRefs()->getWeakCount());
+    {
+        wp<Foo> wp2 = wp1;
+        ASSERT_EQ(2, foo->getWeakRefs()->getWeakCount());
+    }
+    EXPECT_EQ(1, foo->getWeakRefs()->getWeakCount());
+    ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!";
+    wp1 = nullptr;
+    ASSERT_FALSE(isDeleted) << "Deletion on wp destruction should no longer occur";
+}
+
+TEST(RefBase, Comparisons) {
+    bool isDeleted, isDeleted2, isDeleted3;
+    Foo* foo = new Foo(&isDeleted);
+    Foo* foo2 = new Foo(&isDeleted2);
+    sp<Foo> sp1(foo);
+    sp<Foo> sp2(foo2);
+    wp<Foo> wp1(sp1);
+    wp<Foo> wp2(sp1);
+    wp<Foo> wp3(sp2);
+    ASSERT_TRUE(wp1 == wp2);
+    ASSERT_TRUE(wp1 == sp1);
+    ASSERT_TRUE(wp3 == sp2);
+    ASSERT_TRUE(wp1 != sp2);
+    ASSERT_TRUE(wp1 <= wp2);
+    ASSERT_TRUE(wp1 >= wp2);
+    ASSERT_FALSE(wp1 != wp2);
+    ASSERT_FALSE(wp1 > wp2);
+    ASSERT_FALSE(wp1 < wp2);
+    ASSERT_FALSE(sp1 == sp2);
+    ASSERT_TRUE(sp1 != sp2);
+    bool sp1_smaller = sp1 < sp2;
+    wp<Foo>wp_smaller = sp1_smaller ? wp1 : wp3;
+    wp<Foo>wp_larger = sp1_smaller ? wp3 : wp1;
+    ASSERT_TRUE(wp_smaller < wp_larger);
+    ASSERT_TRUE(wp_smaller != wp_larger);
+    ASSERT_TRUE(wp_smaller <= wp_larger);
+    ASSERT_FALSE(wp_smaller == wp_larger);
+    ASSERT_FALSE(wp_smaller > wp_larger);
+    ASSERT_FALSE(wp_smaller >= wp_larger);
+    sp2 = nullptr;
+    ASSERT_TRUE(isDeleted2);
+    ASSERT_FALSE(isDeleted);
+    ASSERT_FALSE(wp3 == sp2);
+    // Comparison results on weak pointers should not be affected.
+    ASSERT_TRUE(wp_smaller < wp_larger);
+    ASSERT_TRUE(wp_smaller != wp_larger);
+    ASSERT_TRUE(wp_smaller <= wp_larger);
+    ASSERT_FALSE(wp_smaller == wp_larger);
+    ASSERT_FALSE(wp_smaller > wp_larger);
+    ASSERT_FALSE(wp_smaller >= wp_larger);
+    wp2 = nullptr;
+    ASSERT_FALSE(wp1 == wp2);
+    ASSERT_TRUE(wp1 != wp2);
+    wp1.clear();
+    ASSERT_TRUE(wp1 == wp2);
+    ASSERT_FALSE(wp1 != wp2);
+    wp3.clear();
+    ASSERT_TRUE(wp1 == wp3);
+    ASSERT_FALSE(wp1 != wp3);
+    ASSERT_FALSE(isDeleted);
+    sp1.clear();
+    ASSERT_TRUE(isDeleted);
+    ASSERT_TRUE(sp1 == sp2);
+    // Try to check that null pointers are properly initialized.
+    {
+        // Try once with non-null, to maximize chances of getting junk on the
+        // stack.
+        sp<Foo> sp3(new Foo(&isDeleted3));
+        wp<Foo> wp4(sp3);
+        wp<Foo> wp5;
+        ASSERT_FALSE(wp4 == wp5);
+        ASSERT_TRUE(wp4 != wp5);
+        ASSERT_FALSE(sp3 == wp5);
+        ASSERT_FALSE(wp5 == sp3);
+        ASSERT_TRUE(sp3 != wp5);
+        ASSERT_TRUE(wp5 != sp3);
+        ASSERT_TRUE(sp3 == wp4);
+    }
+    {
+        sp<Foo> sp3;
+        wp<Foo> wp4(sp3);
+        wp<Foo> wp5;
+        ASSERT_TRUE(wp4 == wp5);
+        ASSERT_FALSE(wp4 != wp5);
+        ASSERT_TRUE(sp3 == wp5);
+        ASSERT_TRUE(wp5 == sp3);
+        ASSERT_FALSE(sp3 != wp5);
+        ASSERT_FALSE(wp5 != sp3);
+        ASSERT_TRUE(sp3 == wp4);
+    }
+}
+
+// Check whether comparison against dead wp works, even if the object referenced
+// by the new wp happens to be at the same address.
+TEST(RefBase, ReplacedComparison) {
+    bool isDeleted, isDeleted2;
+    FooFixedAlloc* foo = new FooFixedAlloc(&isDeleted);
+    sp<FooFixedAlloc> sp1(foo);
+    wp<FooFixedAlloc> wp1(sp1);
+    ASSERT_TRUE(wp1 == sp1);
+    sp1.clear();  // Deallocates the object.
+    ASSERT_TRUE(isDeleted);
+    FooFixedAlloc* foo2 = new FooFixedAlloc(&isDeleted2);
+    ASSERT_FALSE(isDeleted2);
+    ASSERT_EQ(foo, foo2);  // Not technically a legal comparison, but ...
+    sp<FooFixedAlloc> sp2(foo2);
+    wp<FooFixedAlloc> wp2(sp2);
+    ASSERT_TRUE(sp2 == wp2);
+    ASSERT_FALSE(sp2 != wp2);
+    ASSERT_TRUE(sp2 != wp1);
+    ASSERT_FALSE(sp2 == wp1);
+    ASSERT_FALSE(sp2 == sp1);  // sp1 is null.
+    ASSERT_FALSE(wp1 == wp2);  // wp1 refers to old object.
+    ASSERT_TRUE(wp1 != wp2);
+    ASSERT_TRUE(wp1 > wp2 || wp1 < wp2);
+    ASSERT_TRUE(wp1 >= wp2 || wp1 <= wp2);
+    ASSERT_FALSE(wp1 >= wp2 && wp1 <= wp2);
+    ASSERT_FALSE(wp1 == nullptr);
+    wp1 = sp2;
+    ASSERT_TRUE(wp1 == wp2);
+    ASSERT_FALSE(wp1 != wp2);
+}
+
+TEST(RefBase, AssertWeakRefExistsSuccess) {
+    bool isDeleted;
+    sp<Foo> foo = sp<Foo>::make(&isDeleted);
+    wp<Foo> weakFoo = foo;
+
+    EXPECT_EQ(weakFoo, wp<Foo>::fromExisting(foo.get()));
+    EXPECT_EQ(weakFoo.unsafe_get(), wp<Foo>::fromExisting(foo.get()).unsafe_get());
+
+    EXPECT_FALSE(isDeleted);
+    foo = nullptr;
+    EXPECT_TRUE(isDeleted);
+}
+
+TEST(RefBase, AssertWeakRefExistsDeath) {
+    // uses some other refcounting method, or none at all
+    bool isDeleted;
+    Foo* foo = new Foo(&isDeleted);
+
+    // can only get a valid wp<> object when you construct it from an sp<>
+    EXPECT_DEATH(wp<Foo>::fromExisting(foo), "");
+
+    delete foo;
+}
+
+TEST(RefBase, DoubleOwnershipDeath) {
+    bool isDeleted;
+    auto foo = sp<Foo>::make(&isDeleted);
+
+    // if something else thinks it owns foo, should die
+    EXPECT_DEATH(delete foo.get(), "");
+
+    EXPECT_FALSE(isDeleted);
+}
+
+TEST(RefBase, StackOwnershipDeath) {
+    bool isDeleted;
+    EXPECT_DEATH({ Foo foo(&isDeleted); foo.incStrong(nullptr); }, "");
+}
+
+// Set up a situation in which we race with visit2AndRremove() to delete
+// 2 strong references.  Bar destructor checks that there are no early
+// deletions and prior updates are visible to destructor.
+class Bar : public RefBase {
+public:
+    Bar(std::atomic<int>* delete_count) : mVisited1(false), mVisited2(false),
+            mDeleteCount(delete_count) {
+    }
+
+    ~Bar() {
+        EXPECT_TRUE(mVisited1);
+        EXPECT_TRUE(mVisited2);
+        (*mDeleteCount)++;
+    }
+    bool mVisited1;
+    bool mVisited2;
+private:
+    std::atomic<int>* mDeleteCount;
+};
+
+static sp<Bar> buffer;
+static std::atomic<bool> bufferFull(false);
+
+// Wait until bufferFull has value val.
+static inline void waitFor(bool val) {
+    while (bufferFull != val) {}
+}
+
+cpu_set_t otherCpus;
+
+// Divide the cpus we're allowed to run on into myCpus and otherCpus.
+// Set origCpus to the processors we were originally allowed to run on.
+// Return false if origCpus doesn't include at least processors 0 and 1.
+static bool setExclusiveCpus(cpu_set_t* origCpus /* out */,
+        cpu_set_t* myCpus /* out */, cpu_set_t* otherCpus) {
+    if (sched_getaffinity(0, sizeof(cpu_set_t), origCpus) != 0) {
+        return false;
+    }
+    if (!CPU_ISSET(0,  origCpus) || !CPU_ISSET(1, origCpus)) {
+        return false;
+    }
+    CPU_ZERO(myCpus);
+    CPU_ZERO(otherCpus);
+    CPU_OR(myCpus, myCpus, origCpus);
+    CPU_OR(otherCpus, otherCpus, origCpus);
+    for (unsigned i = 0; i < CPU_SETSIZE; ++i) {
+        // I get the even cores, the other thread gets the odd ones.
+        if (i & 1) {
+            CPU_CLR(i, myCpus);
+        } else {
+            CPU_CLR(i, otherCpus);
+        }
+    }
+    return true;
+}
+
+static void visit2AndRemove() {
+    if (sched_setaffinity(0, sizeof(cpu_set_t), &otherCpus) != 0) {
+        FAIL() << "setaffinity returned:" << errno;
+    }
+    for (int i = 0; i < NITERS; ++i) {
+        waitFor(true);
+        buffer->mVisited2 = true;
+        buffer = nullptr;
+        bufferFull = false;
+    }
+}
+
+TEST(RefBase, RacingDestructors) {
+    cpu_set_t origCpus;
+    cpu_set_t myCpus;
+    // Restrict us and the helper thread to disjoint cpu sets.
+    // This prevents us from getting scheduled against each other,
+    // which would be atrociously slow.
+    if (setExclusiveCpus(&origCpus, &myCpus, &otherCpus)) {
+        std::thread t(visit2AndRemove);
+        std::atomic<int> deleteCount(0);
+        if (sched_setaffinity(0, sizeof(cpu_set_t), &myCpus) != 0) {
+            FAIL() << "setaffinity returned:" << errno;
+        }
+        for (int i = 0; i < NITERS; ++i) {
+            waitFor(false);
+            Bar* bar = new Bar(&deleteCount);
+            sp<Bar> sp3(bar);
+            buffer = sp3;
+            bufferFull = true;
+            ASSERT_TRUE(bar->getStrongCount() >= 1);
+            // Weak count includes strong count.
+            ASSERT_TRUE(bar->getWeakRefs()->getWeakCount() >= 1);
+            sp3->mVisited1 = true;
+            sp3 = nullptr;
+        }
+        t.join();
+        if (sched_setaffinity(0, sizeof(cpu_set_t), &origCpus) != 0) {
+            FAIL();
+        }
+        ASSERT_EQ(NITERS, deleteCount) << "Deletions missed!";
+    }  // Otherwise this is slow and probably pointless on a uniprocessor.
+}
+
+static wp<Bar> wpBuffer;
+static std::atomic<bool> wpBufferFull(false);
+
+// Wait until wpBufferFull has value val.
+static inline void wpWaitFor(bool val) {
+    while (wpBufferFull != val) {}
+}
+
+static void visit3AndRemove() {
+    if (sched_setaffinity(0, sizeof(cpu_set_t), &otherCpus) != 0) {
+        FAIL() << "setaffinity returned:" << errno;
+    }
+    for (int i = 0; i < NITERS; ++i) {
+        wpWaitFor(true);
+        {
+            sp<Bar> sp1 = wpBuffer.promote();
+            // We implicitly check that sp1 != NULL
+            sp1->mVisited2 = true;
+        }
+        wpBuffer = nullptr;
+        wpBufferFull = false;
+    }
+}
+
+TEST(RefBase, RacingPromotions) {
+    cpu_set_t origCpus;
+    cpu_set_t myCpus;
+    // Restrict us and the helper thread to disjoint cpu sets.
+    // This prevents us from getting scheduled against each other,
+    // which would be atrociously slow.
+    if (setExclusiveCpus(&origCpus, &myCpus, &otherCpus)) {
+        std::thread t(visit3AndRemove);
+        std::atomic<int> deleteCount(0);
+        if (sched_setaffinity(0, sizeof(cpu_set_t), &myCpus) != 0) {
+            FAIL() << "setaffinity returned:" << errno;
+        }
+        for (int i = 0; i < NITERS; ++i) {
+            Bar* bar = new Bar(&deleteCount);
+            wp<Bar> wp1(bar);
+            bar->mVisited1 = true;
+            if (i % (NITERS / 10) == 0) {
+                // Do this rarely, since it generates a log message.
+                wp1 = nullptr;  // No longer destroys the object.
+                wp1 = bar;
+            }
+            wpBuffer = wp1;
+            ASSERT_EQ(bar->getWeakRefs()->getWeakCount(), 2);
+            wpBufferFull = true;
+            // Promotion races with that in visit3AndRemove.
+            // This may or may not succeed, but it shouldn't interfere with
+            // the concurrent one.
+            sp<Bar> sp1 = wp1.promote();
+            wpWaitFor(false);  // Waits for other thread to drop strong pointer.
+            sp1 = nullptr;
+            // No strong pointers here.
+            sp1 = wp1.promote();
+            ASSERT_EQ(sp1.get(), nullptr) << "Dead wp promotion succeeded!";
+        }
+        t.join();
+        if (sched_setaffinity(0, sizeof(cpu_set_t), &origCpus) != 0) {
+            FAIL();
+        }
+        ASSERT_EQ(NITERS, deleteCount) << "Deletions missed!";
+    }  // Otherwise this is slow and probably pointless on a uniprocessor.
+}
diff --git a/libutils/binder/SharedBuffer.cpp b/libutils/binder/SharedBuffer.cpp
new file mode 100644
index 0000000..3e703db
--- /dev/null
+++ b/libutils/binder/SharedBuffer.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "sharedbuffer"
+
+#include "SharedBuffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <log/log.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+SharedBuffer* SharedBuffer::alloc(size_t size)
+{
+    // Don't overflow if the combined size of the buffer / header is larger than
+    // size_max.
+    LOG_ALWAYS_FATAL_IF((size >= (SIZE_MAX - sizeof(SharedBuffer))),
+                        "Invalid buffer size %zu", size);
+
+    SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
+    if (sb) {
+        // Should be std::atomic_init(&sb->mRefs, 1);
+        // But that generates a warning with some compilers.
+        // The following is OK on Android-supported platforms.
+        sb->mRefs.store(1, std::memory_order_relaxed);
+        sb->mSize = size;
+        sb->mClientMetadata = 0;
+    }
+    return sb;
+}
+
+
+void SharedBuffer::dealloc(const SharedBuffer* released)
+{
+    free(const_cast<SharedBuffer*>(released));
+}
+
+SharedBuffer* SharedBuffer::edit() const
+{
+    if (onlyOwner()) {
+        return const_cast<SharedBuffer*>(this);
+    }
+    SharedBuffer* sb = alloc(mSize);
+    if (sb) {
+        memcpy(sb->data(), data(), size());
+        release();
+    }
+    return sb;
+}
+
+SharedBuffer* SharedBuffer::editResize(size_t newSize) const
+{
+    if (onlyOwner()) {
+        SharedBuffer* buf = const_cast<SharedBuffer*>(this);
+        if (buf->mSize == newSize) return buf;
+        // Don't overflow if the combined size of the new buffer / header is larger than
+        // size_max.
+        LOG_ALWAYS_FATAL_IF((newSize >= (SIZE_MAX - sizeof(SharedBuffer))),
+                            "Invalid buffer size %zu", newSize);
+
+        buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
+        if (buf != nullptr) {
+            buf->mSize = newSize;
+            return buf;
+        }
+    }
+    SharedBuffer* sb = alloc(newSize);
+    if (sb) {
+        const size_t mySize = mSize;
+        memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize);
+        release();
+    }
+    return sb;    
+}
+
+SharedBuffer* SharedBuffer::attemptEdit() const
+{
+    if (onlyOwner()) {
+        return const_cast<SharedBuffer*>(this);
+    }
+    return nullptr;
+}
+
+SharedBuffer* SharedBuffer::reset(size_t new_size) const
+{
+    // cheap-o-reset.
+    SharedBuffer* sb = alloc(new_size);
+    if (sb) {
+        release();
+    }
+    return sb;
+}
+
+void SharedBuffer::acquire() const {
+    mRefs.fetch_add(1, std::memory_order_relaxed);
+}
+
+int32_t SharedBuffer::release(uint32_t flags) const
+{
+    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 (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 prevRefCount;
+}
+
+
+}; // namespace android
diff --git a/libutils/binder/SharedBuffer.h b/libutils/binder/SharedBuffer.h
new file mode 100644
index 0000000..476c842
--- /dev/null
+++ b/libutils/binder/SharedBuffer.h
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+/*
+ * DEPRECATED.  DO NOT USE FOR NEW CODE.
+ */
+
+#ifndef ANDROID_SHARED_BUFFER_H
+#define ANDROID_SHARED_BUFFER_H
+
+#include <atomic>
+#include <stdint.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class SharedBuffer
+{
+public:
+
+    /* flags to use with release() */
+    enum {
+        eKeepStorage = 0x00000001
+    };
+
+    /*! allocate a buffer of size 'size' and acquire() it.
+     *  call release() to free it.
+     */
+    static          SharedBuffer*           alloc(size_t size);
+    
+    /*! free the memory associated with the SharedBuffer.
+     * Fails if there are any users associated with this SharedBuffer.
+     * In other words, the buffer must have been release by all its
+     * users.
+     */
+    static          void                    dealloc(const SharedBuffer* released);
+
+    //! access the data for read
+    inline          const void*             data() const;
+    
+    //! access the data for read/write
+    inline          void*                   data();
+
+    //! get size of the buffer
+    inline          size_t                  size() const;
+ 
+    //! get back a SharedBuffer object from its data
+    static  inline  SharedBuffer*           bufferFromData(void* data);
+    
+    //! get back a SharedBuffer object from its data
+    static  inline  const SharedBuffer*     bufferFromData(const void* data);
+
+    //! get the size of a SharedBuffer object from its data
+    static  inline  size_t                  sizeFromData(const void* data);
+    
+    //! edit the buffer (get a writtable, or non-const, version of it)
+                    SharedBuffer*           edit() const;
+
+    //! edit the buffer, resizing if needed
+                    SharedBuffer*           editResize(size_t size) const;
+
+    //! like edit() but fails if a copy is required
+                    SharedBuffer*           attemptEdit() const;
+    
+    //! resize and edit the buffer, loose it's content.
+                    SharedBuffer*           reset(size_t size) const;
+
+    //! acquire/release a reference on this buffer
+                    void                    acquire() const;
+                    
+    /*! release a reference on this buffer, with the option of not
+     * freeing the memory associated with it if it was the last reference
+     * returns the previous reference count
+     */     
+                    int32_t                 release(uint32_t flags = 0) const;
+    
+    //! returns wether or not we're the only owner
+    inline          bool                    onlyOwner() const;
+    
+
+private:
+        inline SharedBuffer() { }
+        inline ~SharedBuffer() { }
+        SharedBuffer(const SharedBuffer&);
+        SharedBuffer& operator = (const SharedBuffer&);
+ 
+        // Must be sized to preserve correct alignment.
+        mutable std::atomic<int32_t>        mRefs;
+                size_t                      mSize;
+                uint32_t                    mReserved;
+public:
+        // mClientMetadata is reserved for client use.  It is initialized to 0
+        // and the clients can do whatever they want with it.  Note that this is
+        // placed last so that it is adjcent to the buffer allocated.
+                uint32_t                    mClientMetadata;
+};
+
+static_assert(sizeof(SharedBuffer) % 8 == 0
+        && (sizeof(size_t) > 4 || sizeof(SharedBuffer) == 16),
+        "SharedBuffer has unexpected size");
+
+// ---------------------------------------------------------------------------
+
+const void* SharedBuffer::data() const {
+    return this + 1;
+}
+
+void* SharedBuffer::data() {
+    return this + 1;
+}
+
+size_t SharedBuffer::size() const {
+    return mSize;
+}
+
+SharedBuffer* SharedBuffer::bufferFromData(void* data) {
+    return data ? static_cast<SharedBuffer *>(data)-1 : nullptr;
+}
+    
+const SharedBuffer* SharedBuffer::bufferFromData(const void* data) {
+    return data ? static_cast<const SharedBuffer *>(data)-1 : nullptr;
+}
+
+size_t SharedBuffer::sizeFromData(const void* data) {
+    return data ? bufferFromData(data)->mSize : 0;
+}
+
+bool SharedBuffer::onlyOwner() const {
+    return (mRefs.load(std::memory_order_acquire) == 1);
+}
+
+}  // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/libutils/binder/SharedBuffer_test.cpp b/libutils/binder/SharedBuffer_test.cpp
new file mode 100644
index 0000000..1d6317f
--- /dev/null
+++ b/libutils/binder/SharedBuffer_test.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define __STDC_LIMIT_MACROS
+
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <stdint.h>
+
+#include "SharedBuffer.h"
+
+extern "C" void __hwasan_init() __attribute__((weak));
+#define SKIP_WITH_HWASAN \
+    if (&__hwasan_init != 0) GTEST_SKIP()
+
+TEST(SharedBufferTest, alloc_death) {
+    EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX), "");
+    EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+}
+
+TEST(SharedBufferTest, alloc_max) {
+    SKIP_WITH_HWASAN;  // hwasan has a 2GiB allocation limit.
+
+    android::SharedBuffer* buf =
+            android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer) - 1);
+    if (buf != nullptr) {
+        EXPECT_NE(nullptr, buf->data());
+        buf->release();
+    }
+}
+
+TEST(SharedBufferTest, alloc_big) {
+    SKIP_WITH_HWASAN;  // hwasan has a 2GiB allocation limit.
+
+    android::SharedBuffer* buf = android::SharedBuffer::alloc(SIZE_MAX / 2);
+    if (buf != nullptr) {
+        EXPECT_NE(nullptr, buf->data());
+        buf->release();
+    }
+}
+
+TEST(SharedBufferTest, alloc_zero_size) {
+    android::SharedBuffer* buf = android::SharedBuffer::alloc(0);
+    ASSERT_NE(nullptr, buf);
+    ASSERT_EQ(0U, buf->size());
+    buf->release();
+}
+
+TEST(SharedBufferTest, editResize_death) {
+    android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+    EXPECT_DEATH(buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+    buf = android::SharedBuffer::alloc(10);
+    EXPECT_DEATH(buf->editResize(SIZE_MAX), "");
+}
+
+TEST(SharedBufferTest, editResize_null) {
+    // Big enough to fail, not big enough to abort.
+    SKIP_WITH_HWASAN;  // hwasan has a 2GiB allocation limit.
+    android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+    android::SharedBuffer* buf2 = buf->editResize(SIZE_MAX / 2);
+    if (buf2 == nullptr) {
+        buf->release();
+    } else {
+        EXPECT_NE(nullptr, buf2->data());
+        buf2->release();
+    }
+}
+
+TEST(SharedBufferTest, editResize_zero_size) {
+    android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+    buf = buf->editResize(0);
+    ASSERT_EQ(0U, buf->size());
+    buf->release();
+}
diff --git a/libutils/binder/String16.cpp b/libutils/binder/String16.cpp
new file mode 100644
index 0000000..07a3d23
--- /dev/null
+++ b/libutils/binder/String16.cpp
@@ -0,0 +1,384 @@
+/*
+ * 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.
+ */
+
+#include <utils/String16.h>
+
+#include <log/log.h>
+
+#include <ctype.h>
+
+#include "SharedBuffer.h"
+
+namespace android {
+
+static const StaticString16 emptyString(u"");
+static inline char16_t* getEmptyString() {
+    return const_cast<char16_t*>(emptyString.c_str());
+}
+
+// ---------------------------------------------------------------------------
+
+void* String16::alloc(size_t size)
+{
+    SharedBuffer* buf = SharedBuffer::alloc(size);
+    buf->mClientMetadata = kIsSharedBufferAllocated;
+    return buf;
+}
+
+char16_t* String16::allocFromUTF8(const char* u8str, size_t u8len)
+{
+    if (u8len == 0) return getEmptyString();
+
+    const uint8_t* u8cur = (const uint8_t*) u8str;
+
+    const ssize_t u16len = utf8_to_utf16_length(u8cur, u8len);
+    if (u16len < 0) {
+        return getEmptyString();
+    }
+
+    SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t) * (u16len + 1)));
+    if (buf) {
+        u8cur = (const uint8_t*) u8str;
+        char16_t* u16str = (char16_t*)buf->data();
+
+        utf8_to_utf16(u8cur, u8len, u16str, ((size_t) u16len) + 1);
+
+        //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
+        //printHexData(1, str, buf->size(), 16, 1);
+        //printf("\n");
+
+        return u16str;
+    }
+
+    return getEmptyString();
+}
+
+char16_t* String16::allocFromUTF16(const char16_t* u16str, size_t u16len) {
+    if (u16len >= SIZE_MAX / sizeof(char16_t)) {
+        android_errorWriteLog(0x534e4554, "73826242");
+        abort();
+    }
+
+    SharedBuffer* buf = static_cast<SharedBuffer*>(alloc((u16len + 1) * sizeof(char16_t)));
+    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        memcpy(str, u16str, u16len * sizeof(char16_t));
+        str[u16len] = 0;
+        return str;
+    }
+    return getEmptyString();
+}
+
+// ---------------------------------------------------------------------------
+
+String16::String16()
+    : mString(getEmptyString())
+{
+}
+
+String16::String16(const String16& o)
+    : mString(o.mString)
+{
+    acquire();
+}
+
+String16::String16(String16&& o) noexcept
+    : mString(o.mString)
+{
+    o.mString = getEmptyString();
+}
+
+String16::String16(const String16& o, size_t len, size_t begin)
+    : mString(getEmptyString())
+{
+    setTo(o, len, begin);
+}
+
+String16::String16(const char16_t* o) : mString(allocFromUTF16(o, strlen16(o))) {}
+
+String16::String16(const char16_t* o, size_t len) : mString(allocFromUTF16(o, len)) {}
+
+String16::String16(const String8& o) : mString(allocFromUTF8(o.c_str(), o.size())) {}
+
+String16::String16(const char* o)
+    : mString(allocFromUTF8(o, strlen(o)))
+{
+}
+
+String16::String16(const char* o, size_t len)
+    : mString(allocFromUTF8(o, len))
+{
+}
+
+String16::~String16()
+{
+    release();
+}
+
+String16& String16::operator=(String16&& other) noexcept {
+    release();
+    mString = other.mString;
+    other.mString = getEmptyString();
+    return *this;
+}
+
+size_t String16::size() const
+{
+    if (isStaticString()) {
+        return staticStringSize();
+    } else {
+        return SharedBuffer::sizeFromData(mString) / sizeof(char16_t) - 1;
+    }
+}
+
+void String16::setTo(const String16& other)
+{
+    release();
+    mString = other.mString;
+    acquire();
+}
+
+status_t String16::setTo(const String16& other, size_t len, size_t begin)
+{
+    const size_t N = other.size();
+    if (begin >= N) {
+        release();
+        mString = getEmptyString();
+        return OK;
+    }
+    if ((begin+len) > N) len = N-begin;
+    if (begin == 0 && len == N) {
+        setTo(other);
+        return OK;
+    }
+
+    if (&other == this) {
+        LOG_ALWAYS_FATAL("Not implemented");
+    }
+
+    return setTo(other.c_str() + begin, len);
+}
+
+status_t String16::setTo(const char16_t* other)
+{
+    return setTo(other, strlen16(other));
+}
+
+status_t String16::setTo(const char16_t* other, size_t len)
+{
+    if (len >= SIZE_MAX / sizeof(char16_t)) {
+        android_errorWriteLog(0x534e4554, "73826242");
+        abort();
+    }
+
+    SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        memmove(str, other, len*sizeof(char16_t));
+        str[len] = 0;
+        mString = str;
+        return OK;
+    }
+    return NO_MEMORY;
+}
+
+status_t String16::append(const String16& other) {
+    return append(other.c_str(), other.size());
+}
+
+status_t String16::append(const char16_t* chrs, size_t otherLen) {
+    const size_t myLen = size();
+
+    if (myLen == 0) return setTo(chrs, otherLen);
+
+    if (otherLen == 0) return OK;
+
+    size_t size = myLen;
+    if (__builtin_add_overflow(size, otherLen, &size) ||
+        __builtin_add_overflow(size, 1, &size) ||
+        __builtin_mul_overflow(size, sizeof(char16_t), &size)) return NO_MEMORY;
+
+    SharedBuffer* buf = static_cast<SharedBuffer*>(editResize(size));
+    if (!buf) return NO_MEMORY;
+
+    char16_t* str = static_cast<char16_t*>(buf->data());
+    memcpy(str + myLen, chrs, otherLen * sizeof(char16_t));
+    str[myLen + otherLen] = 0;
+    mString = str;
+    return OK;
+}
+
+status_t String16::insert(size_t pos, const char16_t* chrs) {
+    return insert(pos, chrs, strlen16(chrs));
+}
+
+status_t String16::insert(size_t pos, const char16_t* chrs, size_t otherLen) {
+    const size_t myLen = size();
+
+    if (myLen == 0) return setTo(chrs, otherLen);
+
+    if (otherLen == 0) return OK;
+
+    if (pos > myLen) pos = myLen;
+
+    size_t size = myLen;
+    if (__builtin_add_overflow(size, otherLen, &size) ||
+        __builtin_add_overflow(size, 1, &size) ||
+        __builtin_mul_overflow(size, sizeof(char16_t), &size)) return NO_MEMORY;
+
+    SharedBuffer* buf = static_cast<SharedBuffer*>(editResize(size));
+    if (!buf) return NO_MEMORY;
+
+    char16_t* str = static_cast<char16_t*>(buf->data());
+    if (pos < myLen) memmove(str + pos + otherLen, str + pos, (myLen - pos) * sizeof(char16_t));
+    memcpy(str + pos, chrs, otherLen * sizeof(char16_t));
+    str[myLen + otherLen] = 0;
+    mString = str;
+    return OK;
+}
+
+ssize_t String16::findFirst(char16_t c) const
+{
+    const char16_t* str = string();
+    const char16_t* p = str;
+    const char16_t* e = p + size();
+    while (p < e) {
+        if (*p == c) {
+            return p-str;
+        }
+        p++;
+    }
+    return -1;
+}
+
+ssize_t String16::findLast(char16_t c) const
+{
+    const char16_t* str = string();
+    const char16_t* p = str;
+    const char16_t* e = p + size();
+    while (p < e) {
+        e--;
+        if (*e == c) {
+            return e-str;
+        }
+    }
+    return -1;
+}
+
+bool String16::startsWith(const String16& prefix) const
+{
+    const size_t ps = prefix.size();
+    if (ps > size()) return false;
+    return strzcmp16(mString, ps, prefix.c_str(), ps) == 0;
+}
+
+bool String16::startsWith(const char16_t* prefix) const
+{
+    const size_t ps = strlen16(prefix);
+    if (ps > size()) return false;
+    return strncmp16(mString, prefix, ps) == 0;
+}
+
+bool String16::contains(const char16_t* chrs) const
+{
+    return strstr16(mString, chrs) != nullptr;
+}
+
+void* String16::edit() {
+    SharedBuffer* buf;
+    if (isStaticString()) {
+        buf = static_cast<SharedBuffer*>(alloc((size() + 1) * sizeof(char16_t)));
+        if (buf) {
+            memcpy(buf->data(), mString, (size() + 1) * sizeof(char16_t));
+        }
+    } else {
+        buf = SharedBuffer::bufferFromData(mString)->edit();
+        buf->mClientMetadata = kIsSharedBufferAllocated;
+    }
+    return buf;
+}
+
+void* String16::editResize(size_t newSize) {
+    SharedBuffer* buf;
+    if (isStaticString()) {
+        size_t copySize = (size() + 1) * sizeof(char16_t);
+        if (newSize < copySize) {
+            copySize = newSize;
+        }
+        buf = static_cast<SharedBuffer*>(alloc(newSize));
+        if (buf) {
+            memcpy(buf->data(), mString, copySize);
+        }
+    } else {
+        buf = SharedBuffer::bufferFromData(mString)->editResize(newSize);
+        buf->mClientMetadata = kIsSharedBufferAllocated;
+    }
+    return buf;
+}
+
+void String16::acquire()
+{
+    if (!isStaticString()) {
+        SharedBuffer::bufferFromData(mString)->acquire();
+    }
+}
+
+void String16::release()
+{
+    if (!isStaticString()) {
+        SharedBuffer::bufferFromData(mString)->release();
+    }
+}
+
+bool String16::isStaticString() const {
+    // See String16.h for notes on the memory layout of String16::StaticData and
+    // SharedBuffer.
+    static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
+    const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
+    return (*(p - 1) & kIsSharedBufferAllocated) == 0;
+}
+
+size_t String16::staticStringSize() const {
+    // See String16.h for notes on the memory layout of String16::StaticData and
+    // SharedBuffer.
+    static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
+    const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
+    return static_cast<size_t>(*(p - 1));
+}
+
+status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
+{
+    const size_t N = size();
+    const char16_t* str = string();
+    char16_t* edited = nullptr;
+    for (size_t i=0; i<N; i++) {
+        if (str[i] == replaceThis) {
+            if (!edited) {
+                SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
+                if (!buf) {
+                    return NO_MEMORY;
+                }
+                edited = (char16_t*)buf->data();
+                mString = str = edited;
+            }
+            edited[i] = withThis;
+        }
+    }
+    return OK;
+}
+
+}; // namespace android
diff --git a/libutils/binder/String16_fuzz.cpp b/libutils/binder/String16_fuzz.cpp
new file mode 100644
index 0000000..8f9781b
--- /dev/null
+++ b/libutils/binder/String16_fuzz.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <functional>
+#include <iostream>
+#include <vector>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/String16.h"
+static constexpr int MAX_STRING_BYTES = 256;
+static constexpr uint8_t MAX_OPERATIONS = 50;
+
+std::vector<std::function<void(FuzzedDataProvider&, android::String16, android::String16)>>
+        operations = {
+
+                // Bytes and size
+                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
+                    str1.c_str();
+                }),
+                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
+                    str1.isStaticString();
+                }),
+                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
+                    str1.size();
+                }),
+
+                // Comparison
+                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
+                    str1.startsWith(str2);
+                }),
+                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
+                    str1.contains(str2.c_str());
+                }),
+                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
+                    str1.compare(str2);
+                }),
+
+                // Append and format
+                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
+                    str1.append(str2);
+                }),
+                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
+                    android::String16 str2) -> void {
+                    int pos = dataProvider.ConsumeIntegralInRange<int>(0, str1.size());
+                    str1.insert(pos, str2.c_str());
+                }),
+
+                // Find and replace operations
+                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
+                    android::String16) -> void {
+                    char16_t findChar = dataProvider.ConsumeIntegral<char16_t>();
+                    str1.findFirst(findChar);
+                }),
+                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
+                    android::String16) -> void {
+                    char16_t findChar = dataProvider.ConsumeIntegral<char16_t>();
+                    str1.findLast(findChar);
+                }),
+                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
+                    android::String16) -> void {
+                    char16_t findChar = dataProvider.ConsumeIntegral<char16_t>();
+                    char16_t replaceChar = dataProvider.ConsumeIntegral<char16_t>();
+                    str1.replaceAll(findChar, replaceChar);
+                }),
+};
+
+void callFunc(uint8_t index, FuzzedDataProvider& dataProvider, android::String16 str1,
+              android::String16 str2) {
+    operations[index](dataProvider, str1, str2);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    FuzzedDataProvider dataProvider(data, size);
+    // We're generating two char vectors.
+    // First, generate lengths.
+    const size_t kVecOneLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);
+    const size_t kVecTwoLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);
+
+    // Next, populate the vectors
+    std::vector<char> vec = dataProvider.ConsumeBytesWithTerminator<char>(kVecOneLen);
+    std::vector<char> vec_two = dataProvider.ConsumeBytesWithTerminator<char>(kVecTwoLen);
+
+    // Get pointers to their data
+    char* char_one = vec.data();
+    char* char_two = vec_two.data();
+
+    // Create UTF16 representations
+    android::String16 str_one_utf16 = android::String16(char_one);
+    android::String16 str_two_utf16 = android::String16(char_two);
+
+    // Run operations against strings
+    int opsRun = 0;
+    while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
+        uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, operations.size() - 1);
+        callFunc(op, dataProvider, str_one_utf16, str_two_utf16);
+    }
+
+    return 0;
+}
diff --git a/libutils/binder/String16_test.cpp b/libutils/binder/String16_test.cpp
new file mode 100644
index 0000000..6f4642e
--- /dev/null
+++ b/libutils/binder/String16_test.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+::testing::AssertionResult Char16_tStringEquals(const char16_t* a, const char16_t* b) {
+    if (strcmp16(a, b) != 0) {
+        return ::testing::AssertionFailure()
+               << "\"" << String8(a).c_str() << "\" not equal to \"" << String8(b).c_str() << "\"";
+    }
+    return ::testing::AssertionSuccess();
+}
+
+#define EXPECT_STR16EQ(a, b) EXPECT_TRUE(Char16_tStringEquals(a, b))
+
+TEST(String16Test, FromChar16_t) {
+    String16 tmp(u"Verify me");
+    EXPECT_STR16EQ(u"Verify me", tmp.c_str());
+}
+
+TEST(String16Test, FromChar16_tSized) {
+    String16 tmp(u"Verify me", 7);
+    EXPECT_STR16EQ(u"Verify ", tmp.c_str());
+}
+
+TEST(String16Test, FromChar) {
+    String16 tmp("Verify me");
+    EXPECT_STR16EQ(u"Verify me", tmp.c_str());
+}
+
+TEST(String16Test, FromCharSized) {
+    String16 tmp("Verify me", 7);
+    EXPECT_STR16EQ(u"Verify ", tmp.c_str());
+}
+
+TEST(String16Test, Copy) {
+    String16 tmp("Verify me");
+    String16 another = tmp;
+    EXPECT_STR16EQ(u"Verify me", tmp.c_str());
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+}
+
+TEST(String16Test, CopyAssign) {
+    String16 tmp("Verify me");
+    String16 another;
+    another = tmp;
+    EXPECT_STR16EQ(u"Verify me", tmp.c_str());
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+}
+
+TEST(String16Test, Move) {
+    String16 tmp("Verify me");
+    String16 another(std::move(tmp));
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+}
+
+TEST(String16Test, MoveAssign) {
+    String16 tmp("Verify me");
+    String16 another;
+    another = std::move(tmp);
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+}
+
+TEST(String16Test, Size) {
+    String16 tmp("Verify me");
+    EXPECT_EQ(9U, tmp.size());
+}
+
+TEST(String16Test, setTo) {
+    String16 tmp("Verify me");
+    tmp.setTo(u"New content");
+    EXPECT_EQ(11U, tmp.size());
+    EXPECT_STR16EQ(u"New content", tmp.c_str());
+}
+
+TEST(String16Test, Append) {
+    String16 tmp("Verify me");
+    tmp.append(String16("Hello"));
+    EXPECT_EQ(14U, tmp.size());
+    EXPECT_STR16EQ(u"Verify meHello", tmp.c_str());
+}
+
+TEST(String16Test, Insert) {
+    String16 tmp("Verify me");
+    tmp.insert(6, u"Insert");
+    EXPECT_EQ(15U, tmp.size());
+    EXPECT_STR16EQ(u"VerifyInsert me", tmp.c_str());
+}
+
+TEST(String16Test, ReplaceAll) {
+    String16 tmp("Verify verify Verify");
+    tmp.replaceAll(u'r', u'!');
+    EXPECT_STR16EQ(u"Ve!ify ve!ify Ve!ify", tmp.c_str());
+}
+
+TEST(String16Test, Compare) {
+    String16 tmp("Verify me");
+    EXPECT_EQ(String16(u"Verify me"), tmp);
+}
+
+TEST(String16Test, StaticString) {
+    String16 nonStaticString("NonStatic");
+    StaticString16 staticString(u"Static");
+
+    EXPECT_TRUE(staticString.isStaticString());
+    EXPECT_FALSE(nonStaticString.isStaticString());
+}
+
+TEST(String16Test, StaticStringCopy) {
+    StaticString16 tmp(u"Verify me");
+    String16 another = tmp;
+    EXPECT_STR16EQ(u"Verify me", tmp.c_str());
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+    EXPECT_TRUE(tmp.isStaticString());
+    EXPECT_TRUE(another.isStaticString());
+}
+
+TEST(String16Test, StaticStringMove) {
+    StaticString16 tmp(u"Verify me");
+    String16 another(std::move(tmp));
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+    EXPECT_TRUE(another.isStaticString());
+}
+
+TEST(String16Test, StaticStringSize) {
+    StaticString16 tmp(u"Verify me");
+    EXPECT_EQ(9U, tmp.size());
+}
+
+TEST(String16Test, StaticStringSetTo) {
+    StaticString16 tmp(u"Verify me");
+    tmp.setTo(u"New content");
+    EXPECT_EQ(11U, tmp.size());
+    EXPECT_STR16EQ(u"New content", tmp);
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringAppend) {
+    StaticString16 tmp(u"Verify me");
+    tmp.append(String16("Hello"));
+    EXPECT_EQ(14U, tmp.size());
+    EXPECT_STR16EQ(u"Verify meHello", tmp.c_str());
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringInsert) {
+    StaticString16 tmp(u"Verify me");
+    tmp.insert(6, u"Insert");
+    EXPECT_EQ(15U, tmp.size());
+    EXPECT_STR16EQ(u"VerifyInsert me", tmp.c_str());
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringReplaceAll) {
+    StaticString16 tmp(u"Verify verify Verify");
+    tmp.replaceAll(u'r', u'!');
+    EXPECT_STR16EQ(u"Ve!ify ve!ify Ve!ify", tmp.c_str());
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringCompare) {
+    StaticString16 tmp(u"Verify me");
+    EXPECT_EQ(String16(u"Verify me"), tmp);
+}
+
+TEST(String16Test, StringSetToStaticString) {
+    StaticString16 tmp(u"Verify me");
+    String16 another(u"nonstatic");
+    another = tmp;
+    EXPECT_STR16EQ(u"Verify me", tmp.c_str());
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+}
+
+TEST(String16Test, StringCopyAssignFromStaticString) {
+    StaticString16 tmp(u"Verify me");
+    String16 another(u"nonstatic");
+    another = tmp;
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+    EXPECT_TRUE(another.isStaticString());
+    EXPECT_STR16EQ(u"Verify me", tmp.c_str());
+    EXPECT_TRUE(tmp.isStaticString());
+}
+
+TEST(String16Test, StringMoveAssignFromStaticString) {
+    StaticString16 tmp(u"Verify me");
+    String16 another(u"nonstatic");
+    another = std::move(tmp);
+    EXPECT_STR16EQ(u"Verify me", another.c_str());
+    EXPECT_TRUE(another.isStaticString());
+}
+
+TEST(String16Test, EmptyStringIsStatic) {
+    String16 tmp("");
+    EXPECT_TRUE(tmp.isStaticString());
+}
+
+TEST(String16Test, OverreadUtf8Conversion) {
+    char tmp[] = {'a', static_cast<char>(0xe0), '\0'};
+    String16 another(tmp);
+    EXPECT_TRUE(another.size() == 0);
+}
+
+TEST(String16Test, ValidUtf8Conversion) {
+    String16 another("abcdef");
+    EXPECT_EQ(6U, another.size());
+    EXPECT_STR16EQ(another.c_str(), u"abcdef");
+}
+
+TEST(String16Test, append) {
+    String16 s;
+    EXPECT_EQ(OK, s.append(String16(u"foo")));
+    EXPECT_STR16EQ(u"foo", s.c_str());
+    EXPECT_EQ(OK, s.append(String16(u"bar")));
+    EXPECT_STR16EQ(u"foobar", s.c_str());
+    EXPECT_EQ(OK, s.append(u"baz", 0));
+    EXPECT_STR16EQ(u"foobar", s.c_str());
+    EXPECT_EQ(NO_MEMORY, s.append(u"baz", SIZE_MAX));
+    EXPECT_STR16EQ(u"foobar", s.c_str());
+}
+
+TEST(String16Test, insert) {
+    String16 s;
+
+    // Inserting into the empty string inserts at the start.
+    EXPECT_EQ(OK, s.insert(123, u"foo"));
+    EXPECT_STR16EQ(u"foo", s.c_str());
+
+    // Inserting zero characters at any position is okay, but won't expand the string.
+    EXPECT_EQ(OK, s.insert(123, u"foo", 0));
+    EXPECT_STR16EQ(u"foo", s.c_str());
+
+    // Inserting past the end of a non-empty string appends.
+    EXPECT_EQ(OK, s.insert(123, u"bar"));
+    EXPECT_STR16EQ(u"foobar", s.c_str());
+
+    EXPECT_EQ(OK, s.insert(3, u"!"));
+    EXPECT_STR16EQ(u"foo!bar", s.c_str());
+
+    EXPECT_EQ(NO_MEMORY, s.insert(3, u"", SIZE_MAX));
+    EXPECT_STR16EQ(u"foo!bar", s.c_str());
+}
diff --git a/libutils/binder/String8.cpp b/libutils/binder/String8.cpp
new file mode 100644
index 0000000..6a75484
--- /dev/null
+++ b/libutils/binder/String8.cpp
@@ -0,0 +1,479 @@
+/*
+ * 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.
+ */
+
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include <utils/String8.h>
+
+#include <utils/Compat.h>
+#include <log/log.h>
+#include <utils/String16.h>
+
+#include <ctype.h>
+
+#include <limits>
+#include <string>
+
+#include "SharedBuffer.h"
+
+/*
+ * Functions outside android is below the namespace android, since they use
+ * functions and constants in android namespace.
+ */
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+static inline char* getEmptyString() {
+    static SharedBuffer* gEmptyStringBuf = [] {
+        SharedBuffer* buf = SharedBuffer::alloc(1);
+        char* str = static_cast<char*>(buf->data());
+        *str = 0;
+        return buf;
+    }();
+
+    gEmptyStringBuf->acquire();
+    return static_cast<char*>(gEmptyStringBuf->data());
+}
+
+// ---------------------------------------------------------------------------
+
+static char* allocFromUTF8(const char* in, size_t len)
+{
+    if (len > 0) {
+        if (len == SIZE_MAX) {
+            return nullptr;
+        }
+        SharedBuffer* buf = SharedBuffer::alloc(len+1);
+        ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+        if (buf) {
+            char* str = (char*)buf->data();
+            memcpy(str, in, len);
+            str[len] = 0;
+            return str;
+        }
+        return nullptr;
+    }
+
+    return getEmptyString();
+}
+
+static char* allocFromUTF16(const char16_t* in, size_t len)
+{
+    if (len == 0) return getEmptyString();
+
+     // Allow for closing '\0'
+    const ssize_t resultStrLen = utf16_to_utf8_length(in, len) + 1;
+    if (resultStrLen < 1) {
+        return getEmptyString();
+    }
+
+    SharedBuffer* buf = SharedBuffer::alloc(resultStrLen);
+    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+    if (!buf) {
+        return getEmptyString();
+    }
+
+    char* resultStr = (char*)buf->data();
+    utf16_to_utf8(in, len, resultStr, resultStrLen);
+    return resultStr;
+}
+
+static char* allocFromUTF32(const char32_t* in, size_t len)
+{
+    if (len == 0) {
+        return getEmptyString();
+    }
+
+    const ssize_t resultStrLen = utf32_to_utf8_length(in, len) + 1;
+    if (resultStrLen < 1) {
+        return getEmptyString();
+    }
+
+    SharedBuffer* buf = SharedBuffer::alloc(resultStrLen);
+    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+    if (!buf) {
+        return getEmptyString();
+    }
+
+    char* resultStr = (char*) buf->data();
+    utf32_to_utf8(in, len, resultStr, resultStrLen);
+
+    return resultStr;
+}
+
+// ---------------------------------------------------------------------------
+
+String8::String8()
+    : mString(getEmptyString())
+{
+}
+
+String8::String8(const String8& o)
+    : mString(o.mString)
+{
+    SharedBuffer::bufferFromData(mString)->acquire();
+}
+
+String8::String8(const char* o)
+    : mString(allocFromUTF8(o, strlen(o)))
+{
+    if (mString == nullptr) {
+        mString = getEmptyString();
+    }
+}
+
+String8::String8(const char* o, size_t len)
+    : mString(allocFromUTF8(o, len))
+{
+    if (mString == nullptr) {
+        mString = getEmptyString();
+    }
+}
+
+String8::String8(const String16& o) : mString(allocFromUTF16(o.c_str(), o.size())) {}
+
+String8::String8(const char16_t* o)
+    : mString(allocFromUTF16(o, strlen16(o)))
+{
+}
+
+String8::String8(const char16_t* o, size_t len)
+    : mString(allocFromUTF16(o, len))
+{
+}
+
+String8::String8(const char32_t* o)
+    : mString(allocFromUTF32(o, std::char_traits<char32_t>::length(o))) {}
+
+String8::String8(const char32_t* o, size_t len)
+    : mString(allocFromUTF32(o, len))
+{
+}
+
+String8::~String8()
+{
+    SharedBuffer::bufferFromData(mString)->release();
+}
+
+size_t String8::length() const
+{
+    return SharedBuffer::sizeFromData(mString)-1;
+}
+
+String8 String8::format(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    String8 result(formatV(fmt, args));
+
+    va_end(args);
+    return result;
+}
+
+String8 String8::formatV(const char* fmt, va_list args)
+{
+    String8 result;
+    result.appendFormatV(fmt, args);
+    return result;
+}
+
+void String8::clear() {
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = getEmptyString();
+}
+
+void String8::setTo(const String8& other)
+{
+    SharedBuffer::bufferFromData(other.mString)->acquire();
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = other.mString;
+}
+
+status_t String8::setTo(const char* other)
+{
+    const char *newString = allocFromUTF8(other, strlen(other));
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return OK;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::setTo(const char* other, size_t len)
+{
+    const char *newString = allocFromUTF8(other, len);
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return OK;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::setTo(const char16_t* other, size_t len)
+{
+    const char *newString = allocFromUTF16(other, len);
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return OK;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::setTo(const char32_t* other, size_t len)
+{
+    const char *newString = allocFromUTF32(other, len);
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return OK;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::append(const String8& other)
+{
+    const size_t otherLen = other.bytes();
+    if (bytes() == 0) {
+        setTo(other);
+        return OK;
+    } else if (otherLen == 0) {
+        return OK;
+    }
+
+    return real_append(other.c_str(), otherLen);
+}
+
+status_t String8::append(const char* other)
+{
+    return append(other, strlen(other));
+}
+
+status_t String8::append(const char* other, size_t otherLen)
+{
+    if (bytes() == 0) {
+        return setTo(other, otherLen);
+    } else if (otherLen == 0) {
+        return OK;
+    }
+
+    return real_append(other, otherLen);
+}
+
+status_t String8::appendFormat(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    status_t result = appendFormatV(fmt, args);
+
+    va_end(args);
+    return result;
+}
+
+status_t String8::appendFormatV(const char* fmt, va_list args)
+{
+    int n, result = OK;
+    va_list tmp_args;
+
+    /* args is undefined after vsnprintf.
+     * So we need a copy here to avoid the
+     * second vsnprintf access undefined args.
+     */
+    va_copy(tmp_args, args);
+    n = vsnprintf(nullptr, 0, fmt, tmp_args);
+    va_end(tmp_args);
+
+    if (n < 0) return UNKNOWN_ERROR;
+
+    if (n > 0) {
+        size_t oldLength = length();
+        if (static_cast<size_t>(n) > std::numeric_limits<size_t>::max() - 1 ||
+            oldLength > std::numeric_limits<size_t>::max() - n - 1) {
+            return NO_MEMORY;
+        }
+        char* buf = lockBuffer(oldLength + n);
+        if (buf) {
+            vsnprintf(buf + oldLength, n + 1, fmt, args);
+        } else {
+            result = NO_MEMORY;
+        }
+    }
+    return result;
+}
+
+status_t String8::real_append(const char* other, size_t otherLen) {
+    const size_t myLen = bytes();
+
+    SharedBuffer* buf;
+    size_t newLen;
+    if (__builtin_add_overflow(myLen, otherLen, &newLen) ||
+        __builtin_add_overflow(newLen, 1, &newLen) ||
+        (buf = SharedBuffer::bufferFromData(mString)->editResize(newLen)) == nullptr) {
+        return NO_MEMORY;
+    }
+
+    char* str = (char*)buf->data();
+    mString = str;
+    str += myLen;
+    memcpy(str, other, otherLen);
+    str[otherLen] = '\0';
+    return OK;
+}
+
+char* String8::lockBuffer(size_t size)
+{
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize(size+1);
+    if (buf) {
+        char* str = (char*)buf->data();
+        mString = str;
+        return str;
+    }
+    return nullptr;
+}
+
+void String8::unlockBuffer()
+{
+    unlockBuffer(strlen(mString));
+}
+
+status_t String8::unlockBuffer(size_t size)
+{
+    if (size != this->size()) {
+        SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+            ->editResize(size+1);
+        if (! buf) {
+            return NO_MEMORY;
+        }
+
+        char* str = (char*)buf->data();
+        str[size] = 0;
+        mString = str;
+    }
+
+    return OK;
+}
+
+ssize_t String8::find(const char* other, size_t start) const
+{
+    size_t len = size();
+    if (start >= len) {
+        return -1;
+    }
+    const char* s = mString+start;
+    const char* p = strstr(s, other);
+    return p ? p-mString : -1;
+}
+
+bool String8::removeAll(const char* other) {
+    ALOG_ASSERT(other, "String8::removeAll() requires a non-NULL string");
+
+    if (*other == '\0')
+        return true;
+
+    ssize_t index = find(other);
+    if (index < 0) return false;
+
+    char* buf = lockBuffer(size());
+    if (!buf) return false; // out of memory
+
+    size_t skip = strlen(other);
+    size_t len = size();
+    size_t tail = index;
+    while (size_t(index) < len) {
+        ssize_t next = find(other, index + skip);
+        if (next < 0) {
+            next = len;
+        }
+
+        memmove(buf + tail, buf + index + skip, next - index - skip);
+        tail += next - index - skip;
+        index = next;
+    }
+    unlockBuffer(tail);
+    return true;
+}
+
+void String8::toLower()
+{
+    const size_t length = size();
+    if (length == 0) return;
+
+    char* buf = lockBuffer(length);
+    for (size_t i = length; i > 0; --i) {
+        *buf = static_cast<char>(tolower(*buf));
+        buf++;
+    }
+    unlockBuffer(length);
+}
+
+// ---------------------------------------------------------------------------
+// Path functions
+
+String8 String8::getPathDir(void) const
+{
+    const char* cp;
+    const char*const str = mString;
+
+    cp = strrchr(str, OS_PATH_SEPARATOR);
+    if (cp == nullptr)
+        return String8("");
+    else
+        return String8(str, cp - str);
+}
+
+/*
+ * Helper function for finding the start of an extension in a pathname.
+ *
+ * Returns a pointer inside mString, or NULL if no extension was found.
+ */
+static const char* find_extension(const char* str) {
+    const char* lastSlash;
+    const char* lastDot;
+
+    // only look at the filename
+    lastSlash = strrchr(str, OS_PATH_SEPARATOR);
+    if (lastSlash == nullptr)
+        lastSlash = str;
+    else
+        lastSlash++;
+
+    // find the last dot
+    lastDot = strrchr(lastSlash, '.');
+    if (lastDot == nullptr)
+        return nullptr;
+
+    // looks good, ship it
+    return lastDot;
+}
+
+String8 String8::getPathExtension(void) const
+{
+    auto ext = find_extension(mString);
+    if (ext != nullptr)
+        return String8(ext);
+    else
+        return String8("");
+}
+
+}; // namespace android
diff --git a/libutils/binder/String8_fuzz.cpp b/libutils/binder/String8_fuzz.cpp
new file mode 100644
index 0000000..cbce050
--- /dev/null
+++ b/libutils/binder/String8_fuzz.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <functional>
+#include <iostream>
+#include <memory>
+
+#include "FuzzFormatTypes.h"
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/String8.h"
+
+static constexpr int MAX_STRING_BYTES = 256;
+static constexpr uint8_t MAX_OPERATIONS = 50;
+// Interestingly, 2147483614 (INT32_MAX - 33) seems to be the max value that is handled for format
+// flags. Unfortunately we need to use a smaller value so we avoid consuming too much memory.
+
+void fuzzFormat(FuzzedDataProvider* dataProvider, android::String8* str1, bool shouldAppend);
+std::vector<std::function<void(FuzzedDataProvider*, android::String8*, android::String8*)>>
+        operations = {
+                // Bytes and size
+                [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+                    str1->bytes();
+                },
+                [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+                    str1->empty();
+                },
+                [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+                    str1->length();
+                },
+
+                // Casing
+                [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+                    str1->toLower();
+                },
+                [](FuzzedDataProvider*, android::String8* str1, android::String8* str2) -> void {
+                    if (str2->size() == 0) return;
+
+                    str1->removeAll(str2->c_str());
+                },
+                [](FuzzedDataProvider*, android::String8* str1, android::String8* str2) -> void {
+                    const android::String8& constRef(*str2);
+                    str1->compare(constRef);
+                },
+
+                // Append and format
+                [](FuzzedDataProvider*, android::String8* str1, android::String8* str2) -> void {
+                    str1->append(str2->c_str());
+                },
+                [](FuzzedDataProvider* dataProvider, android::String8* str1, android::String8*)
+                        -> void { fuzzFormat(dataProvider, str1, dataProvider->ConsumeBool()); },
+
+                // Find operation
+                [](FuzzedDataProvider* dataProvider, android::String8* str1,
+                   android::String8* str2) -> void {
+                    // We need to get a value from our fuzzer here.
+                    int start_index = dataProvider->ConsumeIntegralInRange<int>(0, str1->size());
+                    str1->find(str2->c_str(), start_index);
+                },
+};
+
+void fuzzFormat(FuzzedDataProvider* dataProvider, android::String8* str1, bool shouldAppend) {
+    FormatChar formatType = dataProvider->ConsumeEnum<FormatChar>();
+
+    std::string formatString("%");
+    // Width specifier
+    if (dataProvider->ConsumeBool()) {
+        // Left pad with zeroes
+        if (dataProvider->ConsumeBool()) {
+            formatString.push_back('0');
+        }
+        // Right justify (or left justify if negative)
+        int32_t justify = dataProvider->ConsumeIntegralInRange<int32_t>(-kMaxFormatFlagValue,
+                                                                        kMaxFormatFlagValue);
+        formatString += std::to_string(justify);
+    }
+
+    // The # specifier only works with o, x, X, a, A, e, E, f, F, g, and G
+    if (canApplyFlag(formatType, '#') && dataProvider->ConsumeBool()) {
+        formatString.push_back('#');
+    }
+
+    // Precision specifier
+    if (canApplyFlag(formatType, '.') && dataProvider->ConsumeBool()) {
+        formatString.push_back('.');
+        formatString +=
+                std::to_string(dataProvider->ConsumeIntegralInRange<int>(0, kMaxFormatFlagValue));
+    }
+
+    formatString.push_back(kFormatChars.at(static_cast<uint8_t>(formatType)));
+
+    switch (formatType) {
+        case SIGNED_DECIMAL: {
+            int val = dataProvider->ConsumeIntegral<int>();
+            if (shouldAppend) {
+                str1->appendFormat(formatString.c_str(), val);
+            } else {
+                str1->format(formatString.c_str(), dataProvider->ConsumeIntegral<int>());
+            }
+            break;
+        }
+
+        case UNSIGNED_DECIMAL:
+        case UNSIGNED_OCTAL:
+        case UNSIGNED_HEX_LOWER:
+        case UNSIGNED_HEX_UPPER: {
+            // Unsigned integers for u, o, x, and X
+            uint val = dataProvider->ConsumeIntegral<uint>();
+            if (shouldAppend) {
+                str1->appendFormat(formatString.c_str(), val);
+            } else {
+                str1->format(formatString.c_str(), val);
+            }
+            break;
+        }
+
+        case FLOAT_LOWER:
+        case FLOAT_UPPER:
+        case EXPONENT_LOWER:
+        case EXPONENT_UPPER:
+        case SHORT_EXP_LOWER:
+        case SHORT_EXP_UPPER:
+        case HEX_FLOAT_LOWER:
+        case HEX_FLOAT_UPPER: {
+            // Floating points for f, F, e, E, g, G, a, and A
+            float val = dataProvider->ConsumeFloatingPoint<float>();
+            if (shouldAppend) {
+                str1->appendFormat(formatString.c_str(), val);
+            } else {
+                str1->format(formatString.c_str(), val);
+            }
+            break;
+        }
+
+        case CHAR: {
+            char val = dataProvider->ConsumeIntegral<char>();
+            if (shouldAppend) {
+                str1->appendFormat(formatString.c_str(), val);
+            } else {
+                str1->format(formatString.c_str(), val);
+            }
+            break;
+        }
+
+        case STRING: {
+            std::string val = dataProvider->ConsumeRandomLengthString(MAX_STRING_BYTES);
+            if (shouldAppend) {
+                str1->appendFormat(formatString.c_str(), val.c_str());
+            } else {
+                str1->format(formatString.c_str(), val.c_str());
+            }
+            break;
+        }
+        case POINTER: {
+            uintptr_t val = dataProvider->ConsumeIntegral<uintptr_t>();
+            if (shouldAppend) {
+                str1->appendFormat(formatString.c_str(), val);
+            } else {
+                str1->format(formatString.c_str(), val);
+            }
+            break;
+        }
+    }
+}
+
+void callFunc(uint8_t index, FuzzedDataProvider* dataProvider, android::String8* str1,
+              android::String8* str2) {
+    operations[index](dataProvider, str1, str2);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    FuzzedDataProvider dataProvider(data, size);
+    // Generate vector lengths
+    const size_t kVecOneLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);
+    const size_t kVecTwoLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);
+    // Populate vectors
+    std::vector<char> vec = dataProvider.ConsumeBytesWithTerminator<char>(kVecOneLen);
+    std::vector<char> vec_two = dataProvider.ConsumeBytesWithTerminator<char>(kVecTwoLen);
+    // Create UTF-8 pointers
+    android::String8 str_one_utf8 = android::String8(vec.data());
+    android::String8 str_two_utf8 = android::String8(vec_two.data());
+    // Run operations against strings
+    int opsRun = 0;
+    while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
+        uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, operations.size() - 1);
+        operations[op](&dataProvider, &str_one_utf8, &str_two_utf8);
+    }
+    // Just to be extra sure these can be freed, we're going to explicitly clear
+    // them
+    str_one_utf8.clear();
+    str_two_utf8.clear();
+    return 0;
+}
diff --git a/libutils/binder/String8_test.cpp b/libutils/binder/String8_test.cpp
new file mode 100644
index 0000000..6f7882a
--- /dev/null
+++ b/libutils/binder/String8_test.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "String8_test"
+
+#include <log/log.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+class String8Test : public testing::Test {
+protected:
+    virtual void SetUp() {
+    }
+
+    virtual void TearDown() {
+    }
+};
+
+TEST_F(String8Test, Cstr) {
+    String8 tmp("Hello, world!");
+
+    EXPECT_STREQ(tmp.c_str(), "Hello, world!");
+}
+
+TEST_F(String8Test, OperatorPlus) {
+    String8 src1("Hello, ");
+
+    // Test adding String8 + const char*
+    const char* ccsrc2 = "world!";
+    String8 dst1 = src1 + ccsrc2;
+    EXPECT_STREQ(dst1.c_str(), "Hello, world!");
+    EXPECT_STREQ(src1.c_str(), "Hello, ");
+    EXPECT_STREQ(ccsrc2, "world!");
+
+    // Test adding String8 + String8
+    String8 ssrc2("world!");
+    String8 dst2 = src1 + ssrc2;
+    EXPECT_STREQ(dst2.c_str(), "Hello, world!");
+    EXPECT_STREQ(src1.c_str(), "Hello, ");
+    EXPECT_STREQ(ssrc2.c_str(), "world!");
+}
+
+TEST_F(String8Test, OperatorPlusEquals) {
+    String8 src1("My voice");
+
+    // Testing String8 += String8
+    String8 src2(" is my passport.");
+    src1 += src2;
+    EXPECT_STREQ(src1.c_str(), "My voice is my passport.");
+    EXPECT_STREQ(src2.c_str(), " is my passport.");
+
+    // Adding const char* to the previous string.
+    const char* src3 = " Verify me.";
+    src1 += src3;
+    EXPECT_STREQ(src1.c_str(), "My voice is my passport. Verify me.");
+    EXPECT_STREQ(src2.c_str(), " is my passport.");
+    EXPECT_STREQ(src3, " Verify me.");
+}
+
+TEST_F(String8Test, SetToSizeMaxReturnsNoMemory) {
+    const char *in = "some string";
+    EXPECT_EQ(NO_MEMORY, String8("").setTo(in, SIZE_MAX));
+}
+
+// http://b/29250543
+TEST_F(String8Test, CorrectInvalidSurrogate) {
+    // d841d8 is an invalid start for a surrogate pair. Make sure this is handled by ignoring the
+    // first character in the pair and handling the rest correctly.
+    String16 string16(u"\xd841\xd841\xdc41\x0000");
+    String8 string8(string16);
+
+    EXPECT_EQ(4U, string8.length());
+}
+
+TEST_F(String8Test, CheckUtf32Conversion) {
+    // Since bound checks were added, check the conversion can be done without fatal errors.
+    // The utf8 lengths of these are chars are 1 + 2 + 3 + 4 = 10.
+    const char32_t string32[] = U"\x0000007f\x000007ff\x0000911\x0010fffe";
+    String8 string8(string32);
+    EXPECT_EQ(10U, string8.length());
+}
+
+TEST_F(String8Test, ValidUtf16Conversion) {
+    char16_t tmp[] = u"abcdef";
+    String8 valid = String8(String16(tmp));
+    EXPECT_STREQ(valid.c_str(), "abcdef");
+}
+
+TEST_F(String8Test, append) {
+    String8 s;
+    EXPECT_EQ(OK, s.append("foo"));
+    EXPECT_STREQ("foo", s.c_str());
+    EXPECT_EQ(OK, s.append("bar"));
+    EXPECT_STREQ("foobar", s.c_str());
+    EXPECT_EQ(OK, s.append("baz", 0));
+    EXPECT_STREQ("foobar", s.c_str());
+    EXPECT_EQ(NO_MEMORY, s.append("baz", SIZE_MAX));
+    EXPECT_STREQ("foobar", s.c_str());
+}
+
+TEST_F(String8Test, removeAll) {
+    String8 s("Hello, world!");
+
+    // NULL input should cause an assertion failure and error message in logcat
+    EXPECT_DEATH(s.removeAll(NULL), "");
+
+    // expect to return true and string content should remain unchanged
+    EXPECT_TRUE(s.removeAll(""));
+    EXPECT_STREQ("Hello, world!", s.c_str());
+
+    // expect to return false
+    EXPECT_FALSE(s.removeAll("x"));
+    EXPECT_STREQ("Hello, world!", s.c_str());
+
+    EXPECT_TRUE(s.removeAll("o"));
+    EXPECT_STREQ("Hell, wrld!", s.c_str());
+}
diff --git a/libutils/binder/StrongPointer.cpp b/libutils/binder/StrongPointer.cpp
new file mode 100644
index 0000000..ba52502
--- /dev/null
+++ b/libutils/binder/StrongPointer.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "sp"
+
+#include <log/log.h>
+
+namespace android {
+
+void sp_report_race() { LOG_ALWAYS_FATAL("sp<> assignment detected data race"); }
+}
diff --git a/libutils/binder/StrongPointer_test.cpp b/libutils/binder/StrongPointer_test.cpp
new file mode 100644
index 0000000..f27c1f1
--- /dev/null
+++ b/libutils/binder/StrongPointer_test.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
+
+using namespace android;
+
+class SPFoo : virtual public RefBase {
+  public:
+    explicit SPFoo(bool* deleted_check) : mDeleted(deleted_check) {
+        *mDeleted = false;
+    }
+
+    ~SPFoo() {
+        *mDeleted = true;
+    }
+
+  private:
+    bool* mDeleted;
+};
+
+class SPLightFoo : virtual public VirtualLightRefBase {
+  public:
+    explicit SPLightFoo(bool* deleted_check) : mDeleted(deleted_check) { *mDeleted = false; }
+
+    ~SPLightFoo() { *mDeleted = true; }
+
+  private:
+    bool* mDeleted;
+};
+
+template <typename T>
+class StrongPointer : public ::testing::Test {};
+
+using RefBaseTypes = ::testing::Types<SPFoo, SPLightFoo>;
+TYPED_TEST_CASE(StrongPointer, RefBaseTypes);
+
+TYPED_TEST(StrongPointer, move) {
+    bool isDeleted;
+    sp<TypeParam> sp1 = sp<TypeParam>::make(&isDeleted);
+    TypeParam* foo = sp1.get();
+    ASSERT_EQ(1, foo->getStrongCount());
+    {
+        sp<TypeParam> sp2 = std::move(sp1);
+        ASSERT_EQ(1, foo->getStrongCount()) << "std::move failed, incremented refcnt";
+        ASSERT_EQ(nullptr, sp1.get()) << "std::move failed, sp1 is still valid";
+        // The strong count isn't increasing, let's double check the old object
+        // is properly reset and doesn't early delete
+        sp1 = std::move(sp2);
+    }
+    ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!";
+    {
+        // Now let's double check it deletes on time
+        sp<TypeParam> sp2 = std::move(sp1);
+    }
+    ASSERT_TRUE(isDeleted) << "foo was leaked!";
+}
+
+TYPED_TEST(StrongPointer, NullptrComparison) {
+    sp<TypeParam> foo;
+    ASSERT_EQ(foo, nullptr);
+    ASSERT_EQ(nullptr, foo);
+}
+
+TYPED_TEST(StrongPointer, PointerComparison) {
+    bool isDeleted;
+    sp<TypeParam> foo = sp<TypeParam>::make(&isDeleted);
+    ASSERT_EQ(foo.get(), foo);
+    ASSERT_EQ(foo, foo.get());
+    ASSERT_NE(nullptr, foo);
+    ASSERT_NE(foo, nullptr);
+}
+
+TYPED_TEST(StrongPointer, Deleted) {
+    bool isDeleted;
+    sp<TypeParam> foo = sp<TypeParam>::make(&isDeleted);
+
+    auto foo2 = sp<TypeParam>::fromExisting(foo.get());
+
+    EXPECT_FALSE(isDeleted);
+    foo = nullptr;
+    EXPECT_FALSE(isDeleted);
+    foo2 = nullptr;
+    EXPECT_TRUE(isDeleted);
+}
+
+TYPED_TEST(StrongPointer, AssertStrongRefExists) {
+    bool isDeleted;
+    TypeParam* foo = new TypeParam(&isDeleted);
+    EXPECT_DEATH(sp<TypeParam>::fromExisting(foo), "");
+    delete foo;
+}
diff --git a/libutils/binder/Unicode.cpp b/libutils/binder/Unicode.cpp
new file mode 100644
index 0000000..364a177
--- /dev/null
+++ b/libutils/binder/Unicode.cpp
@@ -0,0 +1,541 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "unicode"
+
+#include <android-base/macros.h>
+#include <limits.h>
+#include <utils/Unicode.h>
+
+#include <log/log.h>
+
+extern "C" {
+
+static const char32_t kByteMask = 0x000000BF;
+static const char32_t kByteMark = 0x00000080;
+
+// Surrogates aren't valid for UTF-32 characters, so define some
+// constants that will let us screen them out.
+static const char32_t kUnicodeSurrogateHighStart  = 0x0000D800;
+// Unused, here for completeness:
+// static const char32_t kUnicodeSurrogateHighEnd = 0x0000DBFF;
+// static const char32_t kUnicodeSurrogateLowStart = 0x0000DC00;
+static const char32_t kUnicodeSurrogateLowEnd     = 0x0000DFFF;
+static const char32_t kUnicodeSurrogateStart      = kUnicodeSurrogateHighStart;
+static const char32_t kUnicodeSurrogateEnd        = kUnicodeSurrogateLowEnd;
+static const char32_t kUnicodeMaxCodepoint        = 0x0010FFFF;
+
+// Mask used to set appropriate bits in first byte of UTF-8 sequence,
+// indexed by number of bytes in the sequence.
+// 0xxxxxxx
+// -> (00-7f) 7bit. Bit mask for the first byte is 0x00000000
+// 110yyyyx 10xxxxxx
+// -> (c0-df)(80-bf) 11bit. Bit mask is 0x000000C0
+// 1110yyyy 10yxxxxx 10xxxxxx
+// -> (e0-ef)(80-bf)(80-bf) 16bit. Bit mask is 0x000000E0
+// 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
+// -> (f0-f7)(80-bf)(80-bf)(80-bf) 21bit. Bit mask is 0x000000F0
+static const char32_t kFirstByteMark[] = {
+    0x00000000, 0x00000000, 0x000000C0, 0x000000E0, 0x000000F0
+};
+
+// --------------------------------------------------------------------------
+// UTF-32
+// --------------------------------------------------------------------------
+
+/**
+ * Return number of UTF-8 bytes required for the character. If the character
+ * is invalid, return size of 0.
+ */
+static inline size_t utf32_codepoint_utf8_length(char32_t srcChar)
+{
+    // Figure out how many bytes the result will require.
+    if (srcChar < 0x00000080) {
+        return 1;
+    } else if (srcChar < 0x00000800) {
+        return 2;
+    } else if (srcChar < 0x00010000) {
+        if ((srcChar < kUnicodeSurrogateStart) || (srcChar > kUnicodeSurrogateEnd)) {
+            return 3;
+        } else {
+            // Surrogates are invalid UTF-32 characters.
+            return 0;
+        }
+    }
+    // Max code point for Unicode is 0x0010FFFF.
+    else if (srcChar <= kUnicodeMaxCodepoint) {
+        return 4;
+    } else {
+        // Invalid UTF-32 character.
+        return 0;
+    }
+}
+
+// Write out the source character to <dstP>.
+
+static inline void utf32_codepoint_to_utf8(uint8_t* dstP, char32_t srcChar, size_t bytes)
+{
+    dstP += bytes;
+    switch (bytes)
+    {   /* note: everything falls through. */
+        case 4: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+            FALLTHROUGH_INTENDED;
+        case 3: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+            FALLTHROUGH_INTENDED;
+        case 2: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+            FALLTHROUGH_INTENDED;
+        case 1: *--dstP = (uint8_t)(srcChar | kFirstByteMark[bytes]);
+    }
+}
+
+static inline int32_t utf32_at_internal(const char* cur, size_t *num_read)
+{
+    const char first_char = *cur;
+    if ((first_char & 0x80) == 0) { // ASCII
+        *num_read = 1;
+        return *cur;
+    }
+    cur++;
+    char32_t mask, to_ignore_mask;
+    size_t num_to_read = 0;
+    char32_t utf32 = first_char;
+    for (num_to_read = 1, mask = 0x40, to_ignore_mask = 0xFFFFFF80;
+         (first_char & mask);
+         num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
+        // 0x3F == 00111111
+        utf32 = (utf32 << 6) + (*cur++ & 0x3F);
+    }
+    to_ignore_mask |= mask;
+    utf32 &= ~(to_ignore_mask << (6 * (num_to_read - 1)));
+
+    *num_read = num_to_read;
+    return static_cast<int32_t>(utf32);
+}
+
+int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index)
+{
+    if (index >= src_len) {
+        return -1;
+    }
+    size_t unused_index;
+    if (next_index == nullptr) {
+        next_index = &unused_index;
+    }
+    size_t num_read;
+    int32_t ret = utf32_at_internal(src + index, &num_read);
+    if (ret >= 0) {
+        *next_index = index + num_read;
+    }
+
+    return ret;
+}
+
+ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len)
+{
+    if (src == nullptr || src_len == 0) {
+        return -1;
+    }
+
+    size_t ret = 0;
+    const char32_t *end = src + src_len;
+    while (src < end) {
+        size_t char_len = utf32_codepoint_utf8_length(*src++);
+        if (SSIZE_MAX - char_len < ret) {
+            // If this happens, we would overflow the ssize_t type when
+            // returning from this function, so we cannot express how
+            // long this string is in an ssize_t.
+            android_errorWriteLog(0x534e4554, "37723026");
+            return -1;
+        }
+        ret += char_len;
+    }
+    return ret;
+}
+
+void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len)
+{
+    if (src == nullptr || src_len == 0 || dst == nullptr) {
+        return;
+    }
+
+    const char32_t *cur_utf32 = src;
+    const char32_t *end_utf32 = src + src_len;
+    char *cur = dst;
+    while (cur_utf32 < end_utf32) {
+        size_t len = utf32_codepoint_utf8_length(*cur_utf32);
+        LOG_ALWAYS_FATAL_IF(dst_len < len, "%zu < %zu", dst_len, len);
+        utf32_codepoint_to_utf8((uint8_t *)cur, *cur_utf32++, len);
+        cur += len;
+        dst_len -= len;
+    }
+    LOG_ALWAYS_FATAL_IF(dst_len < 1, "dst_len < 1: %zu < 1", dst_len);
+    *cur = '\0';
+}
+
+// --------------------------------------------------------------------------
+// UTF-16
+// --------------------------------------------------------------------------
+
+int strcmp16(const char16_t *s1, const char16_t *s2)
+{
+  char16_t ch;
+  int d = 0;
+
+  while ( 1 ) {
+    d = (int)(ch = *s1++) - (int)*s2++;
+    if ( d || !ch )
+      break;
+  }
+
+  return d;
+}
+
+int strncmp16(const char16_t *s1, const char16_t *s2, size_t n)
+{
+  char16_t ch;
+  int d = 0;
+
+  if (n == 0) {
+    return 0;
+  }
+
+  do {
+    d = (int)(ch = *s1++) - (int)*s2++;
+    if ( d || !ch ) {
+      break;
+    }
+  } while (--n);
+
+  return d;
+}
+
+size_t strlen16(const char16_t *s)
+{
+  const char16_t *ss = s;
+  while ( *ss )
+    ss++;
+  return ss-s;
+}
+
+size_t strnlen16(const char16_t *s, size_t maxlen)
+{
+  const char16_t *ss = s;
+
+  /* Important: the maxlen test must precede the reference through ss;
+     since the byte beyond the maximum may segfault */
+  while ((maxlen > 0) && *ss) {
+    ss++;
+    maxlen--;
+  }
+  return ss-s;
+}
+
+char16_t* strstr16(const char16_t* src, const char16_t* target)
+{
+    const char16_t needle = *target;
+    if (needle == '\0') return (char16_t*)src;
+
+    const size_t target_len = strlen16(++target);
+    do {
+        do {
+            if (*src == '\0') {
+                return nullptr;
+            }
+        } while (*src++ != needle);
+    } while (strncmp16(src, target, target_len) != 0);
+    src--;
+
+    return (char16_t*)src;
+}
+
+int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2)
+{
+    const char16_t* e1 = s1+n1;
+    const char16_t* e2 = s2+n2;
+
+    while (s1 < e1 && s2 < e2) {
+        const int d = (int)*s1++ - (int)*s2++;
+        if (d) {
+            return d;
+        }
+    }
+
+    return n1 < n2
+        ? (0 - (int)*s2)
+        : (n1 > n2
+           ? ((int)*s1 - 0)
+           : 0);
+}
+
+// is_any_surrogate() returns true if w is either a high or low surrogate
+static constexpr bool is_any_surrogate(char16_t w) {
+    return (w & 0xf800) == 0xd800;
+}
+
+// is_surrogate_pair() returns true if w1 and w2 form a valid surrogate pair
+static constexpr bool is_surrogate_pair(char16_t w1, char16_t w2) {
+    return ((w1 & 0xfc00) == 0xd800) && ((w2 & 0xfc00) == 0xdc00);
+}
+
+// TODO: currently utf16_to_utf8_length() returns -1 if src_len == 0,
+// which is inconsistent with utf8_to_utf16_length(), here we keep the
+// current behavior as intended not to break compatibility
+ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len)
+{
+    if (src == nullptr || src_len == 0)
+        return -1;
+
+    const char16_t* const end = src + src_len;
+    const char16_t* in = src;
+    size_t utf8_len = 0;
+
+    while (in < end) {
+        char16_t w = *in++;
+        if (LIKELY(w < 0x0080)) {
+            utf8_len += 1;
+            continue;
+        }
+        if (LIKELY(w < 0x0800)) {
+            utf8_len += 2;
+            continue;
+        }
+        if (LIKELY(!is_any_surrogate(w))) {
+            utf8_len += 3;
+            continue;
+        }
+        if (in < end && is_surrogate_pair(w, *in)) {
+            utf8_len += 4;
+            in++;
+            continue;
+        }
+        /* skip if at the end of the string or invalid surrogate pair */
+    }
+    return (in == end && utf8_len < SSIZE_MAX) ? utf8_len : -1;
+}
+
+void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len)
+{
+    if (src == nullptr || src_len == 0 || dst == nullptr) {
+        return;
+    }
+
+    const char16_t* in = src;
+    const char16_t* const in_end = src + src_len;
+    char* out = dst;
+    const char* const out_end = dst + dst_len;
+    char16_t w2;
+
+    auto err_out = [&out, &out_end, &dst_len]() {
+        LOG_ALWAYS_FATAL_IF(out >= out_end,
+                "target utf8 string size %zu too short", dst_len);
+    };
+
+    while (in < in_end) {
+        char16_t w = *in++;
+        if (LIKELY(w < 0x0080)) {
+            if (out + 1 > out_end)
+                return err_out();
+            *out++ = (char)(w & 0xff);
+            continue;
+        }
+        if (LIKELY(w < 0x0800)) {
+            if (out + 2 > out_end)
+                return err_out();
+            *out++ = (char)(0xc0 | ((w >> 6) & 0x1f));
+            *out++ = (char)(0x80 | ((w >> 0) & 0x3f));
+            continue;
+        }
+        if (LIKELY(!is_any_surrogate(w))) {
+            if (out + 3 > out_end)
+                return err_out();
+            *out++ = (char)(0xe0 | ((w >> 12) & 0xf));
+            *out++ = (char)(0x80 | ((w >> 6) & 0x3f));
+            *out++ = (char)(0x80 | ((w >> 0) & 0x3f));
+            continue;
+        }
+        /* surrogate pair */
+        if (in < in_end && (w2 = *in, is_surrogate_pair(w, w2))) {
+            if (out + 4 > out_end)
+                return err_out();
+            char32_t dw = (char32_t)(0x10000 + ((w - 0xd800) << 10) + (w2 - 0xdc00));
+            *out++ = (char)(0xf0 | ((dw >> 18) & 0x07));
+            *out++ = (char)(0x80 | ((dw >> 12) & 0x3f));
+            *out++ = (char)(0x80 | ((dw >> 6)  & 0x3f));
+            *out++ = (char)(0x80 | ((dw >> 0)  & 0x3f));
+            in++;
+        }
+        /* We reach here in two cases:
+         *  1) (in == in_end), which means end of the input string
+         *  2) (w2 & 0xfc00) != 0xdc00, which means invalid surrogate pair
+         * In either case, we intentionally do nothing and skip
+         */
+    }
+    *out = '\0';
+    return;
+}
+
+// --------------------------------------------------------------------------
+// UTF-8
+// --------------------------------------------------------------------------
+
+static char32_t utf8_4b_to_utf32(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4) {
+    return ((c1 & 0x07) << 18) | ((c2 & 0x3f) << 12) | ((c3 & 0x3f) << 6) | (c4 & 0x3f);
+}
+
+// TODO: current behavior of converting UTF8 to UTF-16 has a few issues below
+//
+// 1. invalid trailing bytes (i.e. not b'10xxxxxx) are treated as valid trailing
+//    bytes and follows normal conversion rules
+// 2. invalid leading byte (b'10xxxxxx) is treated as a valid single UTF-8 byte
+// 3. invalid leading byte (b'11111xxx) is treated as a valid leading byte
+//    (same as b'11110xxx) for a 4-byte UTF-8 sequence
+// 4. an invalid 4-byte UTF-8 sequence that translates to a codepoint < U+10000
+//    will be converted as a valid UTF-16 character
+//
+// We keep the current behavior as is but with warnings logged, so as not to
+// break compatibility.  However, this needs to be addressed later.
+
+ssize_t utf8_to_utf16_length(const uint8_t* u8str, size_t u8len, bool overreadIsFatal)
+{
+    if (u8str == nullptr)
+        return -1;
+
+    const uint8_t* const in_end = u8str + u8len;
+    const uint8_t* in = u8str;
+    size_t utf16_len = 0;
+
+    while (in < in_end) {
+        uint8_t c = *in;
+        utf16_len++;
+        if (LIKELY((c & 0x80) == 0)) {
+            in++;
+            continue;
+        }
+        if (UNLIKELY(c < 0xc0)) {
+            ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+            in++;
+            continue;
+        }
+        if (LIKELY(c < 0xe0)) {
+            in += 2;
+            continue;
+        }
+        if (LIKELY(c < 0xf0)) {
+            in += 3;
+            continue;
+        } else {
+            uint8_t c2, c3, c4;
+            if (UNLIKELY(c >= 0xf8)) {
+                ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+            }
+            c2 = in[1]; c3 = in[2]; c4 = in[3];
+            if (utf8_4b_to_utf32(c, c2, c3, c4) >= 0x10000) {
+                utf16_len++;
+            }
+            in += 4;
+            continue;
+        }
+    }
+    if (in == in_end) {
+        return utf16_len < SSIZE_MAX ? utf16_len : -1;
+    }
+    if (overreadIsFatal)
+        LOG_ALWAYS_FATAL("Attempt to overread computing length of utf8 string");
+    return -1;
+}
+
+char16_t* utf8_to_utf16(const uint8_t* u8str, size_t u8len, char16_t* u16str, size_t u16len) {
+    // A value > SSIZE_MAX is probably a negative value returned as an error and casted.
+    LOG_ALWAYS_FATAL_IF(u16len == 0 || u16len > SSIZE_MAX, "u16len is %zu", u16len);
+    char16_t* end = utf8_to_utf16_no_null_terminator(u8str, u8len, u16str, u16len - 1);
+    *end = 0;
+    return end;
+}
+
+char16_t* utf8_to_utf16_no_null_terminator(
+        const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen) {
+    if (src == nullptr || srcLen == 0 || dstLen == 0) {
+        return dst;
+    }
+    // A value > SSIZE_MAX is probably a negative value returned as an error and casted.
+    LOG_ALWAYS_FATAL_IF(dstLen > SSIZE_MAX, "dstLen is %zu", dstLen);
+
+    const uint8_t* const in_end = src + srcLen;
+    const uint8_t* in = src;
+    const char16_t* const out_end = dst + dstLen;
+    char16_t* out = dst;
+    uint8_t c, c2, c3, c4;
+    char32_t w;
+
+    auto err_in = [&c, &out]() {
+        ALOGW("Unended UTF-8 byte: 0x%02x", c);
+        return out;
+    };
+
+    while (in < in_end && out < out_end) {
+        c = *in++;
+        if (LIKELY((c & 0x80) == 0)) {
+            *out++ = (char16_t)(c);
+            continue;
+        }
+        if (UNLIKELY(c < 0xc0)) {
+            ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+            *out++ = (char16_t)(c);
+            continue;
+        }
+        if (LIKELY(c < 0xe0)) {
+            if (UNLIKELY(in + 1 > in_end)) {
+                return err_in();
+            }
+            c2 = *in++;
+            *out++ = (char16_t)(((c & 0x1f) << 6) | (c2 & 0x3f));
+            continue;
+        }
+        if (LIKELY(c < 0xf0)) {
+            if (UNLIKELY(in + 2 > in_end)) {
+                return err_in();
+            }
+            c2 = *in++; c3 = *in++;
+            *out++ = (char16_t)(((c & 0x0f) << 12) |
+                                ((c2 & 0x3f) << 6) | (c3 & 0x3f));
+            continue;
+        } else {
+            if (UNLIKELY(in + 3 > in_end)) {
+                return err_in();
+            }
+            if (UNLIKELY(c >= 0xf8)) {
+                ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+            }
+            // Multiple UTF16 characters with surrogates
+            c2 = *in++; c3 = *in++; c4 = *in++;
+            w = utf8_4b_to_utf32(c, c2, c3, c4);
+            if (UNLIKELY(w < 0x10000)) {
+                *out++ = (char16_t)(w);
+            } else {
+                if (UNLIKELY(out + 2 > out_end)) {
+                    // Ooops.... not enough room for this surrogate pair.
+                    return out;
+                }
+                *out++ = (char16_t)(((w - 0x10000) >> 10) + 0xd800);
+                *out++ = (char16_t)(((w - 0x10000) & 0x3ff) + 0xdc00);
+            }
+            continue;
+        }
+    }
+    return out;
+}
+
+}
diff --git a/libutils/binder/Unicode_test.cpp b/libutils/binder/Unicode_test.cpp
new file mode 100644
index 0000000..7969525
--- /dev/null
+++ b/libutils/binder/Unicode_test.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Unicode_test"
+
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <log/log.h>
+#include <utils/Unicode.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+
+class UnicodeTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+    }
+
+    virtual void TearDown() {
+    }
+
+    char16_t const * const kSearchString = u"I am a leaf on the wind.";
+
+    constexpr static size_t BUFSIZE = 64;       // large enough for all tests
+
+    void TestUTF8toUTF16(std::initializer_list<uint8_t> input,
+                         std::initializer_list<char16_t> expect,
+                         const char* err_msg_length = "",
+                         ssize_t expected_length = 0) {
+        uint8_t empty_str[] = {};
+        char16_t output[BUFSIZE];
+
+        const size_t inlen = input.size(), outlen = expect.size();
+        ASSERT_LT(outlen, BUFSIZE);
+
+        const uint8_t *input_data = inlen ? std::data(input) : empty_str;
+        ssize_t measured = utf8_to_utf16_length(input_data, inlen);
+        EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+        utf8_to_utf16(input_data, inlen, output, outlen + 1);
+        for (size_t i = 0; i < outlen; i++) {
+            EXPECT_EQ(std::data(expect)[i], output[i]);
+        }
+        EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+    }
+
+    void TestUTF16toUTF8(std::initializer_list<char16_t> input,
+                         std::initializer_list<char> expect,
+                         const char* err_msg_length = "",
+                         ssize_t expected_length = 0) {
+        char16_t empty_str[] = {};
+        char output[BUFSIZE];
+
+        const size_t inlen = input.size(), outlen = expect.size();
+        ASSERT_LT(outlen, BUFSIZE);
+
+        const char16_t *input_data = inlen ? std::data(input) : empty_str;
+        ssize_t measured = utf16_to_utf8_length(input_data, inlen);
+        EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+        utf16_to_utf8(input_data, inlen, output, outlen + 1);
+        for (size_t i = 0; i < outlen; i++) {
+            EXPECT_EQ(std::data(expect)[i], output[i]);
+        }
+        EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+    }
+};
+
+TEST_F(UnicodeTest, UTF8toUTF16ZeroLength) {
+    TestUTF8toUTF16({}, {},
+        "Zero length input should return zero length output.");
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16ASCII) {
+    TestUTF8toUTF16(
+        { 0x30 },               // U+0030 or ASCII '0'
+        { 0x0030 },
+        "ASCII codepoints should have a length of 1 char16_t");
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16Plane1) {
+    TestUTF8toUTF16(
+        { 0xE2, 0x8C, 0xA3 },   // U+2323 SMILE
+        { 0x2323 },
+        "Plane 1 codepoints should have a length of 1 char16_t");
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16Surrogate) {
+    TestUTF8toUTF16(
+        { 0xF0, 0x90, 0x80, 0x80 },   // U+10000
+        { 0xD800, 0xDC00 },
+        "Surrogate pairs should have a length of 2 char16_t");
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16TruncatedUTF8) {
+    TestUTF8toUTF16(
+        { 0xE2, 0x8C },       // Truncated U+2323 SMILE
+        { },                  // Conversion should still work but produce nothing
+        "Truncated UTF-8 should return -1 to indicate invalid",
+        -1);
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16Normal) {
+    TestUTF8toUTF16({
+        0x30,                   // U+0030, 1 UTF-16 character
+        0xC4, 0x80,             // U+0100, 1 UTF-16 character
+        0xE2, 0x8C, 0xA3,       // U+2323, 1 UTF-16 character
+        0xF0, 0x90, 0x80, 0x80, // U+10000, 2 UTF-16 character
+    }, {
+        0x0030,
+        0x0100,
+        0x2323,
+        0xD800, 0xDC00
+    });
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16Invalid) {
+    // TODO: The current behavior of utf8_to_utf16 is to treat invalid
+    // leading byte (>= 0xf8) as a 4-byte UTF8 sequence, and to treat
+    // invalid trailing byte(s) (i.e. bytes not having MSB set) as if
+    // they are valid and do the normal conversion. However, a better
+    // handling would be to treat invalid sequences as errors, such
+    // cases need to be reported and invalid characters (e.g. U+FFFD)
+    // could be produced at the place of error.  Until a fix is ready
+    // and compatibility is not an issue, we will keep testing the
+    // current behavior
+    TestUTF8toUTF16({
+        0xf8,                   // invalid leading byte
+        0xc4, 0x00,             // U+0100 with invalid trailing byte
+        0xe2, 0x0c, 0xa3,       // U+2323 with invalid trailing bytes
+        0xf0, 0x10, 0x00, 0x00, // U+10000 with invalid trailing bytes
+    }, {
+        0x4022,                 // invalid leading byte (>=0xfc) is treated
+                                // as valid for 4-byte UTF8 sequence
+	0x000C,
+	0x00A3,                 // invalid leadnig byte (b'10xxxxxx) is
+                                // treated as valid single UTF-8 byte
+        0xD800,                 // invalid trailing bytes are treated
+        0xDC00,                 // as valid bytes and follow normal
+    });
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8ZeroLength) {
+    // TODO: The current behavior of utf16_to_utf8_length() is that
+    // it returns -1 if the input is a zero length UTF16 string.
+    // This is inconsistent with utf8_to_utf16_length() where a zero
+    // length string returns 0.  However, to fix the current behavior,
+    // we could have compatibility issue.  Until then, we will keep
+    // testing the current behavior
+    TestUTF16toUTF8({}, {},
+        "Zero length UTF16 input should return length of -1.", -1);
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8ASCII) {
+    TestUTF16toUTF8(
+        { 0x0030 },  // U+0030 or ASCII '0'
+        { '\x30' },
+        "ASCII codepoints in UTF16 should give a length of 1 in UTF8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Plane1) {
+    TestUTF16toUTF8(
+        { 0x2323 },  // U+2323 SMILE
+        { '\xE2', '\x8C', '\xA3' },
+        "Plane 1 codepoints should have a length of 3 char in UTF-8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Surrogate) {
+    TestUTF16toUTF8(
+        { 0xD800, 0xDC00 },  // U+10000
+        { '\xF0', '\x90', '\x80', '\x80' },
+        "Surrogate pairs should have a length of 4 chars");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8UnpairedSurrogate) {
+    TestUTF16toUTF8(
+        { 0xD800 },     // U+10000 with high surrogate pair only
+        { },            // Unpaired surrogate should be ignored
+        "A single unpaired high surrogate should have a length of 0 chars");
+
+    TestUTF16toUTF8(
+        { 0xDC00 },     // U+10000 with low surrogate pair only
+        { },            // Unpaired surrogate should be ignored
+        "A single unpaired low surrogate should have a length of 0 chars");
+
+    TestUTF16toUTF8(
+        // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+        { 0x0030, 0x0100, 0xDC00, 0x2323 },
+        { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+        "Unpaired high surrogate should be skipped in the middle");
+
+    TestUTF16toUTF8(
+        // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+        { 0x0030, 0x0100, 0xDC00, 0x2323 },
+        { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+        "Unpaired low surrogate should be skipped in the middle");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8CorrectInvalidSurrogate) {
+    // http://b/29250543
+    // d841d8 is an invalid start for a surrogate pair. Make sure this is handled by ignoring the
+    // first character in the pair and handling the rest correctly.
+    TestUTF16toUTF8(
+        { 0xD841, 0xD841, 0xDC41 },     // U+20441
+        { '\xF0', '\xA0', '\x91', '\x81' },
+        "Invalid start for a surrogate pair should be ignored");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Normal) {
+    TestUTF16toUTF8({
+        0x0024, // U+0024 ($) --> 0x24,           1 UTF-8 byte
+        0x00A3, // U+00A3 (£) --> 0xC2 0xA3,      2 UTF-8 bytes
+        0x0939, // U+0939 (ह) --> 0xE0 0xA4 0xB9, 3 UTF-8 bytes
+        0x20AC, // U+20AC (€) --> 0xE2 0x82 0xAC, 3 UTF-8 bytes
+        0xD55C, // U+D55C (한)--> 0xED 0x95 0x9C, 3 UTF-8 bytes
+        0xD801, 0xDC37, // U+10437 (𐐷) --> 0xF0 0x90 0x90 0xB7, 4 UTF-8 bytes
+    }, {
+        '\x24',
+        '\xC2', '\xA3',
+        '\xE0', '\xA4', '\xB9',
+        '\xE2', '\x82', '\xAC',
+        '\xED', '\x95', '\x9C',
+        '\xF0', '\x90', '\x90', '\xB7',
+    });
+}
+
+TEST_F(UnicodeTest, strstr16EmptyTarget) {
+    EXPECT_EQ(strstr16(kSearchString, u""), kSearchString)
+            << "should return the original pointer";
+}
+
+TEST_F(UnicodeTest, strstr16EmptyTarget_bug) {
+    // In the original code when target is an empty string strlen16() would
+    // start reading the memory until a "terminating null" (that is, zero)
+    // character is found.   This happens because "*target++" in the original
+    // code would increment the pointer beyond the actual string.
+    void* memptr;
+    const size_t alignment = sysconf(_SC_PAGESIZE);
+    const size_t size = 2 * alignment;
+    ASSERT_EQ(posix_memalign(&memptr, alignment, size), 0);
+    // Fill allocated memory.
+    memset(memptr, 'A', size);
+    // Create a pointer to an "empty" string on the first page.
+    char16_t* const emptyString = (char16_t* const)((char*)memptr + alignment - 4);
+    *emptyString = (char16_t)0;
+    // Protect the second page to show that strstr16() violates that.
+    ASSERT_EQ(mprotect((char*)memptr + alignment, alignment, PROT_NONE), 0);
+    // Test strstr16(): when bug is present a segmentation fault is raised.
+    ASSERT_EQ(strstr16((char16_t*)memptr, emptyString), (char16_t*)memptr)
+        << "should not read beyond the first char16_t.";
+    // Reset protection of the second page
+    ASSERT_EQ(mprotect((char*)memptr + alignment, alignment, PROT_READ | PROT_WRITE), 0);
+    // Free allocated memory.
+    free(memptr);
+}
+
+TEST_F(UnicodeTest, strstr16SameString) {
+    const char16_t* result = strstr16(kSearchString, kSearchString);
+    EXPECT_EQ(kSearchString, result)
+            << "should return the original pointer";
+}
+
+TEST_F(UnicodeTest, strstr16TargetStartOfString) {
+    const char16_t* result = strstr16(kSearchString, u"I am");
+    EXPECT_EQ(kSearchString, result)
+            << "should return the original pointer";
+}
+
+
+TEST_F(UnicodeTest, strstr16TargetEndOfString) {
+    const char16_t* result = strstr16(kSearchString, u"wind.");
+    EXPECT_EQ(kSearchString+19, result);
+}
+
+TEST_F(UnicodeTest, strstr16TargetWithinString) {
+    const char16_t* result = strstr16(kSearchString, u"leaf");
+    EXPECT_EQ(kSearchString+7, result);
+}
+
+TEST_F(UnicodeTest, strstr16TargetNotPresent) {
+    const char16_t* result = strstr16(kSearchString, u"soar");
+    EXPECT_EQ(nullptr, result);
+}
+
+// http://b/29267949
+// Test that overreading in utf8_to_utf16_length is detected
+TEST_F(UnicodeTest, InvalidUtf8OverreadDetected) {
+    // An utf8 char starting with \xc4 is two bytes long.
+    // Add extra zeros so no extra memory is read in case the code doesn't
+    // work as expected.
+    static char utf8[] = "\xc4\x00\x00\x00";
+    ASSERT_DEATH(utf8_to_utf16_length((uint8_t *) utf8, strlen(utf8),
+            true /* overreadIsFatal */), "" /* regex for ASSERT_DEATH */);
+}
+
+}
diff --git a/libutils/binder/VectorImpl.cpp b/libutils/binder/VectorImpl.cpp
new file mode 100644
index 0000000..d951b8b
--- /dev/null
+++ b/libutils/binder/VectorImpl.cpp
@@ -0,0 +1,677 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Vector"
+
+#include <utils/VectorImpl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <log/log.h>
+
+#include "SharedBuffer.h"
+
+/*****************************************************************************/
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+const size_t kMinVectorCapacity = 4;
+
+static inline size_t max(size_t a, size_t b) {
+    return a>b ? a : b;
+}
+
+// ----------------------------------------------------------------------------
+
+VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
+    : mStorage(nullptr), mCount(0), mFlags(flags), mItemSize(itemSize)
+{
+}
+
+VectorImpl::VectorImpl(const VectorImpl& rhs)
+    :   mStorage(rhs.mStorage), mCount(rhs.mCount),
+        mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
+{
+    if (mStorage) {
+        SharedBuffer::bufferFromData(mStorage)->acquire();
+    }
+}
+
+VectorImpl::~VectorImpl()
+{
+    ALOGW_IF(mCount,
+        "[%p] subclasses of VectorImpl must call finish_vector()"
+        " in their destructor. Leaking %d bytes.",
+        this, (int)(mCount*mItemSize));
+    // We can't call _do_destroy() here because the vtable is already gone.
+}
+
+VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
+{
+    LOG_ALWAYS_FATAL_IF(mItemSize != rhs.mItemSize,
+        "Vector<> have different types (this=%p, rhs=%p)", this, &rhs);
+    if (this != &rhs) {
+        release_storage();
+        if (rhs.mCount) {
+            mStorage = rhs.mStorage;
+            mCount = rhs.mCount;
+            SharedBuffer::bufferFromData(mStorage)->acquire();
+        } else {
+            mStorage = nullptr;
+            mCount = 0;
+        }
+    }
+    return *this;
+}
+
+void* VectorImpl::editArrayImpl()
+{
+    if (mStorage) {
+        const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage);
+        SharedBuffer* editable = sb->attemptEdit();
+        if (editable == nullptr) {
+            // If we're here, we're not the only owner of the buffer.
+            // We must make a copy of it.
+            editable = SharedBuffer::alloc(sb->size());
+            // Fail instead of returning a pointer to storage that's not
+            // editable. Otherwise we'd be editing the contents of a buffer
+            // for which we're not the only owner, which is undefined behaviour.
+            LOG_ALWAYS_FATAL_IF(editable == nullptr);
+            _do_copy(editable->data(), mStorage, mCount);
+            release_storage();
+            mStorage = editable->data();
+        }
+    }
+    return mStorage;
+}
+
+size_t VectorImpl::capacity() const
+{
+    if (mStorage) {
+        return SharedBuffer::bufferFromData(mStorage)->size() / mItemSize;
+    }
+    return 0;
+}
+
+ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
+{
+    return insertArrayAt(vector.arrayImpl(), index, vector.size());
+}
+
+ssize_t VectorImpl::appendVector(const VectorImpl& vector)
+{
+    return insertVectorAt(vector, size());
+}
+
+ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
+{
+    if (index > size())
+        return BAD_INDEX;
+    void* where = _grow(index, length);
+    if (where) {
+        _do_copy(where, array, length);
+    }
+    return where ? index : (ssize_t)NO_MEMORY;
+}
+
+ssize_t VectorImpl::appendArray(const void* array, size_t length)
+{
+    return insertArrayAt(array, size(), length);
+}
+
+ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
+{
+    return insertAt(nullptr, index, numItems);
+}
+
+ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems)
+{
+    if (index > size())
+        return BAD_INDEX;
+    void* where = _grow(index, numItems);
+    if (where) {
+        if (item) {
+            _do_splat(where, item, numItems);
+        } else {
+            _do_construct(where, numItems);
+        }
+    }
+    return where ? index : (ssize_t)NO_MEMORY;
+}
+
+static int sortProxy(const void* lhs, const void* rhs, void* func)
+{
+    return (*(VectorImpl::compar_t)func)(lhs, rhs);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_t cmp)
+{
+    return sort(sortProxy, (void*)cmp);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state)
+{
+    // the sort must be stable. we're using insertion sort which
+    // is well suited for small and already sorted arrays
+    // for big arrays, it could be better to use mergesort
+    const ssize_t count = size();
+    if (count > 1) {
+        void* array = const_cast<void*>(arrayImpl());
+        void* temp = nullptr;
+        ssize_t i = 1;
+        while (i < count) {
+            void* item = reinterpret_cast<char*>(array) + mItemSize*(i);
+            void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+            if (cmp(curr, item, state) > 0) {
+
+                if (!temp) {
+                    // we're going to have to modify the array...
+                    array = editArrayImpl();
+                    if (!array) return NO_MEMORY;
+                    temp = malloc(mItemSize);
+                    if (!temp) return NO_MEMORY;
+                    item = reinterpret_cast<char*>(array) + mItemSize*(i);
+                    curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+                } else {
+                    _do_destroy(temp, 1);
+                }
+
+                _do_copy(temp, item, 1);
+
+                ssize_t j = i-1;
+                void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
+                do {
+                    _do_destroy(next, 1);
+                    _do_copy(next, curr, 1);
+                    next = curr;
+                    --j;
+                    curr = nullptr;
+                    if (j >= 0) {
+                        curr = reinterpret_cast<char*>(array) + mItemSize*(j);
+                    }
+                } while (j>=0 && (cmp(curr, temp, state) > 0));
+
+                _do_destroy(next, 1);
+                _do_copy(next, temp, 1);
+            }
+            i++;
+        }
+
+        if (temp) {
+            _do_destroy(temp, 1);
+            free(temp);
+        }
+    }
+    return OK;
+}
+
+void VectorImpl::pop()
+{
+    if (size())
+        removeItemsAt(size()-1, 1);
+}
+
+void VectorImpl::push()
+{
+    push(nullptr);
+}
+
+void VectorImpl::push(const void* item)
+{
+    insertAt(item, size());
+}
+
+ssize_t VectorImpl::add()
+{
+    return add(nullptr);
+}
+
+ssize_t VectorImpl::add(const void* item)
+{
+    return insertAt(item, size());
+}
+
+ssize_t VectorImpl::replaceAt(size_t index)
+{
+    return replaceAt(nullptr, index);
+}
+
+ssize_t VectorImpl::replaceAt(const void* prototype, size_t index)
+{
+    ALOG_ASSERT(index<size(),
+        "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
+
+    if (index >= size()) {
+        return BAD_INDEX;
+    }
+
+    void* item = editItemLocation(index);
+    if (item != prototype) {
+        if (item == nullptr)
+            return NO_MEMORY;
+        _do_destroy(item, 1);
+        if (prototype == nullptr) {
+            _do_construct(item, 1);
+        } else {
+            _do_copy(item, prototype, 1);
+        }
+    }
+    return ssize_t(index);
+}
+
+ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
+{
+    size_t end;
+    LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(index, count, &end), "overflow: index=%zu count=%zu",
+                        index, count);
+    if (end > size()) return BAD_VALUE;
+    _shrink(index, count);
+    return index;
+}
+
+void VectorImpl::finish_vector()
+{
+    release_storage();
+    mStorage = nullptr;
+    mCount = 0;
+}
+
+void VectorImpl::clear()
+{
+    _shrink(0, mCount);
+}
+
+void* VectorImpl::editItemLocation(size_t index)
+{
+    ALOG_ASSERT(index<capacity(),
+        "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
+        this, (int)index, (int)capacity(), (int)mCount);
+
+    if (index < capacity()) {
+        void* buffer = editArrayImpl();
+        if (buffer) {
+            return reinterpret_cast<char*>(buffer) + index*mItemSize;
+        }
+    }
+    return nullptr;
+}
+
+const void* VectorImpl::itemLocation(size_t index) const
+{
+    ALOG_ASSERT(index<capacity(),
+        "[%p] itemLocation: index=%d, capacity=%d, count=%d",
+        this, (int)index, (int)capacity(), (int)mCount);
+
+    if (index < capacity()) {
+        const  void* buffer = arrayImpl();
+        if (buffer) {
+            return reinterpret_cast<const char*>(buffer) + index*mItemSize;
+        }
+    }
+    return nullptr;
+}
+
+ssize_t VectorImpl::setCapacity(size_t new_capacity)
+{
+    // The capacity must always be greater than or equal to the size
+    // of this vector.
+    if (new_capacity <= size()) {
+        return capacity();
+    }
+
+    size_t new_allocation_size = 0;
+    LOG_ALWAYS_FATAL_IF(__builtin_mul_overflow(new_capacity, mItemSize, &new_allocation_size));
+    SharedBuffer* sb = SharedBuffer::alloc(new_allocation_size);
+    if (sb) {
+        void* array = sb->data();
+        _do_copy(array, mStorage, size());
+        release_storage();
+        mStorage = const_cast<void*>(array);
+    } else {
+        return NO_MEMORY;
+    }
+    return new_capacity;
+}
+
+ssize_t VectorImpl::resize(size_t size) {
+    ssize_t result = OK;
+    if (size > mCount) {
+        result = insertAt(mCount, size - mCount);
+    } else if (size < mCount) {
+        result = removeItemsAt(size, mCount - size);
+    }
+    return result < 0 ? result : size;
+}
+
+void VectorImpl::release_storage()
+{
+    if (mStorage) {
+        const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage);
+        if (sb->release(SharedBuffer::eKeepStorage) == 1) {
+            _do_destroy(mStorage, mCount);
+            SharedBuffer::dealloc(sb);
+        }
+    }
+}
+
+void* VectorImpl::_grow(size_t where, size_t amount)
+{
+//    ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+//        this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+    ALOG_ASSERT(where <= mCount,
+            "[%p] _grow: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
+
+    size_t new_size;
+    LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(mCount, amount, &new_size), "new_size overflow");
+
+    if (capacity() < new_size) {
+        // NOTE: This implementation used to resize vectors as per ((3*x + 1) / 2)
+        // (sigh..). Also note, the " + 1" was necessary to handle the special case
+        // where x == 1, where the resized_capacity will be equal to the old
+        // capacity without the +1. The old calculation wouldn't work properly
+        // if x was zero.
+        //
+        // This approximates the old calculation, using (x + (x/2) + 1) instead.
+        size_t new_capacity = 0;
+        LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(new_size, (new_size / 2), &new_capacity),
+                            "new_capacity overflow");
+        LOG_ALWAYS_FATAL_IF(
+                __builtin_add_overflow(new_capacity, static_cast<size_t>(1u), &new_capacity),
+                "new_capacity overflow");
+        new_capacity = max(kMinVectorCapacity, new_capacity);
+
+        size_t new_alloc_size = 0;
+        LOG_ALWAYS_FATAL_IF(__builtin_mul_overflow(new_capacity, mItemSize, &new_alloc_size),
+                            "new_alloc_size overflow");
+
+        // ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
+        if ((mStorage) &&
+            (mCount==where) &&
+            (mFlags & HAS_TRIVIAL_COPY) &&
+            (mFlags & HAS_TRIVIAL_DTOR))
+        {
+            const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
+            SharedBuffer* sb = cur_sb->editResize(new_alloc_size);
+            if (sb) {
+                mStorage = sb->data();
+            } else {
+                return nullptr;
+            }
+        } else {
+            SharedBuffer* sb = SharedBuffer::alloc(new_alloc_size);
+            if (sb) {
+                void* array = sb->data();
+                if (where != 0) {
+                    _do_copy(array, mStorage, where);
+                }
+                if (where != mCount) {
+                    const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
+                    void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+                    _do_copy(dest, from, mCount-where);
+                }
+                release_storage();
+                mStorage = const_cast<void*>(array);
+            } else {
+                return nullptr;
+            }
+        }
+    } else {
+        void* array = editArrayImpl();
+        if (where != mCount) {
+            const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
+            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+            _do_move_forward(to, from, mCount - where);
+        }
+    }
+    mCount = new_size;
+    void* free_space = const_cast<void*>(itemLocation(where));
+    return free_space;
+}
+
+void VectorImpl::_shrink(size_t where, size_t amount)
+{
+    if (!mStorage)
+        return;
+
+//    ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+//        this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+    ALOG_ASSERT(where + amount <= mCount,
+            "[%p] _shrink: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
+
+    size_t new_size;
+    LOG_ALWAYS_FATAL_IF(__builtin_sub_overflow(mCount, amount, &new_size));
+
+    if (new_size < (capacity() / 2)) {
+        // NOTE: (new_size * 2) is safe because capacity didn't overflow and
+        // new_size < (capacity / 2)).
+        const size_t new_capacity = max(kMinVectorCapacity, new_size * 2);
+
+        // NOTE: (new_capacity * mItemSize), (where * mItemSize) and
+        // ((where + amount) * mItemSize) beyond this point are safe because
+        // we are always reducing the capacity of the underlying SharedBuffer.
+        // In other words, (old_capacity * mItemSize) did not overflow, and
+        // where < (where + amount) < new_capacity < old_capacity.
+        if ((where == new_size) &&
+            (mFlags & HAS_TRIVIAL_COPY) &&
+            (mFlags & HAS_TRIVIAL_DTOR))
+        {
+            const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
+            SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+            if (sb) {
+                mStorage = sb->data();
+            } else {
+                return;
+            }
+        } else {
+            SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+            if (sb) {
+                void* array = sb->data();
+                if (where != 0) {
+                    _do_copy(array, mStorage, where);
+                }
+                if (where != new_size) {
+                    const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
+                    void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
+                    _do_copy(dest, from, new_size - where);
+                }
+                release_storage();
+                mStorage = const_cast<void*>(array);
+            } else{
+                return;
+            }
+        }
+    } else {
+        void* array = editArrayImpl();
+        void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
+        _do_destroy(to, amount);
+        if (where != new_size) {
+            const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+            _do_move_backward(to, from, new_size - where);
+        }
+    }
+    mCount = new_size;
+}
+
+size_t VectorImpl::itemSize() const {
+    return mItemSize;
+}
+
+void VectorImpl::_do_construct(void* storage, size_t num) const
+{
+    if (!(mFlags & HAS_TRIVIAL_CTOR)) {
+        do_construct(storage, num);
+    }
+}
+
+void VectorImpl::_do_destroy(void* storage, size_t num) const
+{
+    if (!(mFlags & HAS_TRIVIAL_DTOR)) {
+        do_destroy(storage, num);
+    }
+}
+
+void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const
+{
+    if (!(mFlags & HAS_TRIVIAL_COPY)) {
+        do_copy(dest, from, num);
+    } else {
+        memcpy(dest, from, num*itemSize());
+    }
+}
+
+void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
+    do_splat(dest, item, num);
+}
+
+void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
+    do_move_forward(dest, from, num);
+}
+
+void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
+    do_move_backward(dest, from, num);
+}
+
+/*****************************************************************************/
+
+SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
+    : VectorImpl(itemSize, flags)
+{
+}
+
+SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
+: VectorImpl(rhs)
+{
+}
+
+SortedVectorImpl::~SortedVectorImpl()
+{
+}
+
+SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
+{
+    return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
+}
+
+ssize_t SortedVectorImpl::indexOf(const void* item) const
+{
+    return _indexOrderOf(item);
+}
+
+size_t SortedVectorImpl::orderOf(const void* item) const
+{
+    size_t o;
+    _indexOrderOf(item, &o);
+    return o;
+}
+
+ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
+{
+    if (order) *order = 0;
+    if (isEmpty()) {
+        return NAME_NOT_FOUND;
+    }
+    // binary search
+    ssize_t err = NAME_NOT_FOUND;
+    ssize_t l = 0;
+    ssize_t h = size()-1;
+    ssize_t mid;
+    const void* a = arrayImpl();
+    const size_t s = itemSize();
+    while (l <= h) {
+        mid = l + (h - l)/2;
+        const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
+        const int c = do_compare(curr, item);
+        if (c == 0) {
+            err = l = mid;
+            break;
+        } else if (c < 0) {
+            l = mid + 1;
+        } else {
+            h = mid - 1;
+        }
+    }
+    if (order) *order = l;
+    return err;
+}
+
+ssize_t SortedVectorImpl::add(const void* item)
+{
+    size_t order;
+    ssize_t index = _indexOrderOf(item, &order);
+    if (index < 0) {
+        index = VectorImpl::insertAt(item, order, 1);
+    } else {
+        index = VectorImpl::replaceAt(item, index);
+    }
+    return index;
+}
+
+ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
+{
+    // naive merge...
+    if (!vector.isEmpty()) {
+        const void* buffer = vector.arrayImpl();
+        const size_t is = itemSize();
+        size_t s = vector.size();
+        for (size_t i=0 ; i<s ; i++) {
+            ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
+            if (err<0) {
+                return err;
+            }
+        }
+    }
+    return OK;
+}
+
+ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
+{
+    // we've merging a sorted vector... nice!
+    ssize_t err = OK;
+    if (!vector.isEmpty()) {
+        // first take care of the case where the vectors are sorted together
+        if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
+            err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
+        } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
+            err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
+        } else {
+            // this could be made a little better
+            err = merge(static_cast<const VectorImpl&>(vector));
+        }
+    }
+    return err;
+}
+
+ssize_t SortedVectorImpl::remove(const void* item)
+{
+    ssize_t i = indexOf(item);
+    if (i>=0) {
+        VectorImpl::removeItemsAt(i, 1);
+    }
+    return i;
+}
+
+/*****************************************************************************/
+
+}; // namespace android
diff --git a/libutils/binder/Vector_benchmark.cpp b/libutils/binder/Vector_benchmark.cpp
new file mode 100644
index 0000000..c23d499
--- /dev/null
+++ b/libutils/binder/Vector_benchmark.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <benchmark/benchmark.h>
+#include <utils/Vector.h>
+#include <vector>
+
+void BM_fill_android_vector(benchmark::State& state) {
+    android::Vector<char> v;
+    while (state.KeepRunning()) {
+        v.push('A');
+    }
+}
+BENCHMARK(BM_fill_android_vector);
+
+void BM_fill_std_vector(benchmark::State& state) {
+    std::vector<char> v;
+    while (state.KeepRunning()) {
+        v.push_back('A');
+    }
+}
+BENCHMARK(BM_fill_std_vector);
+
+void BM_prepend_android_vector(benchmark::State& state) {
+    android::Vector<char> v;
+    while (state.KeepRunning()) {
+        v.insertAt('A', 0);
+    }
+}
+BENCHMARK(BM_prepend_android_vector);
+
+void BM_prepend_std_vector(benchmark::State& state) {
+    std::vector<char> v;
+    while (state.KeepRunning()) {
+        v.insert(v.begin(), 'A');
+    }
+}
+BENCHMARK(BM_prepend_std_vector);
+
+BENCHMARK_MAIN();
diff --git a/libutils/binder/Vector_fuzz.cpp b/libutils/binder/Vector_fuzz.cpp
new file mode 100644
index 0000000..3cef487
--- /dev/null
+++ b/libutils/binder/Vector_fuzz.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzer/FuzzedDataProvider.h>
+#include <log/log.h>
+#include <utils/Vector.h>
+
+#include <functional>
+
+using android::Vector;
+
+static constexpr uint16_t MAX_VEC_SIZE = 100;
+static constexpr bool kLog = false;
+
+struct NonTrivialDestructor {
+    NonTrivialDestructor() : mInit(1) {}
+    ~NonTrivialDestructor() {
+        LOG_ALWAYS_FATAL_IF(mInit != 1, "mInit should be 1, but it's: %d", mInit);
+        mInit--;
+        LOG_ALWAYS_FATAL_IF(mInit != 0, "mInit should be 0, but it's: %d", mInit);
+    }
+
+  private:
+    uint8_t mInit;
+};
+
+template <typename T>
+struct VectorFuzzerData {
+    Vector<T> vector;
+    const std::vector<std::function<void(FuzzedDataProvider&, Vector<T>&)>> funcs = {
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                // operator= Vector<TYPE>, still needs for SortedVector
+                if (kLog) ALOGI("operator=");
+                vector = testVector(provider);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("clear");
+                vector.clear();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("size");
+                vector.size();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("isEmpty");
+                vector.isEmpty();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("capacity");
+                vector.capacity();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+                if (kLog) ALOGI("setCapacity");
+                vector.setCapacity(vectorSize);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+                if (kLog) ALOGI("resize");
+                vector.resize(vectorSize);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("array");
+                vector.array();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("editArray");
+                vector.editArray();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("operator[]");
+                vector[idx];  // returns a const value for Vector
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("itemAt");
+                vector.itemAt(idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (vector.size() == 0) return;
+                if (kLog) ALOGI("top");
+                vector.top();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("editItemAt");
+                vector.editItemAt(idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (vector.size() == 0) return;
+                if (kLog) ALOGI("editTop");
+                vector.editTop() = T{};
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+                Vector vec2 = testVector(provider);
+                if (vec2.size() == 0) return;  // TODO: maybe we should support this?
+                if (kLog) ALOGI("insertVectorAt %d of size %zu", idx, vec2.size());
+                vector.insertVectorAt(vec2, idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (kLog) ALOGI("appendVector");
+                vector.appendVector(testVector(provider));
+            },
+            // TODO: insertArrayAt
+            // TODO: appendArray
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+                uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
+                if (kLog) ALOGI("insertAt");
+                vector.insertAt(idx, numItems);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+                uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
+                if (kLog) ALOGI("insertAt");
+                vector.insertAt(T{}, idx, numItems);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (vector.size() == 0) return;
+                if (kLog) ALOGI("pop");
+                vector.pop();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("push");
+                vector.push();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("add");
+                vector.add();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("add");
+                vector.add(T{});
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("replaceAt");
+                vector.replaceAt(idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("replaceAt");
+                vector.replaceAt(T{}, idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("remoteItemsAt");
+                vector.removeItemsAt(idx);  // TODO: different count
+            },
+            // removeAt is alias for removeItemsAt
+            // TODO: sort
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("getItemSize");
+                vector.getItemSize();
+            },
+            // TODO: iterators
+    };
+
+    Vector<T> testVector(FuzzedDataProvider& provider) {
+        Vector<T> vec;
+        size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+        return vec;
+    }
+
+    void fuzz(FuzzedDataProvider&& provider) {
+        while (provider.remaining_bytes()) {
+            size_t funcIdx = provider.ConsumeIntegralInRange<size_t>(0, funcs.size() - 1);
+            funcs[funcIdx](provider, vector);
+        }
+    }
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    FuzzedDataProvider provider(data, size);
+
+    provider.PickValueInArray<std::function<void()>>({
+            [&]() { VectorFuzzerData<uint8_t>().fuzz(std::move(provider)); },
+            [&]() { VectorFuzzerData<int32_t>().fuzz(std::move(provider)); },
+            [&]() { VectorFuzzerData<NonTrivialDestructor>().fuzz(std::move(provider)); },
+    })();
+
+    return 0;
+}
diff --git a/libutils/binder/Vector_test.cpp b/libutils/binder/Vector_test.cpp
new file mode 100644
index 0000000..6d90eaa
--- /dev/null
+++ b/libutils/binder/Vector_test.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2012 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 "Vector_test"
+
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+#include <unistd.h>
+
+#include <android/log.h>
+#include <gtest/gtest.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class VectorTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+    }
+
+    virtual void TearDown() {
+    }
+
+public:
+};
+
+
+TEST_F(VectorTest, CopyOnWrite_CopyAndAddElements) {
+
+    Vector<int> vector;
+    Vector<int> other;
+    vector.setCapacity(8);
+
+    vector.add(1);
+    vector.add(2);
+    vector.add(3);
+
+    EXPECT_EQ(3U, vector.size());
+
+    // copy the vector
+    other = vector;
+
+    EXPECT_EQ(3U, other.size());
+
+    // add an element to the first vector
+    vector.add(4);
+
+    // make sure the sizes are correct
+    EXPECT_EQ(4U, vector.size());
+    EXPECT_EQ(3U, other.size());
+
+    // add an element to the copy
+    other.add(5);
+
+    // make sure the sizes are correct
+    EXPECT_EQ(4U, vector.size());
+    EXPECT_EQ(4U, other.size());
+
+    // make sure the content of both vectors are correct
+    EXPECT_EQ(vector[3], 4);
+    EXPECT_EQ(other[3], 5);
+}
+
+TEST_F(VectorTest, SetCapacity_Overflow) {
+  Vector<int> vector;
+  EXPECT_DEATH(vector.setCapacity(SIZE_MAX / sizeof(int) + 1), "Assertion failed");
+}
+
+TEST_F(VectorTest, SetCapacity_ShrinkBelowSize) {
+  Vector<int> vector;
+  vector.add(1);
+  vector.add(2);
+  vector.add(3);
+  vector.add(4);
+
+  vector.setCapacity(8);
+  ASSERT_EQ(8U, vector.capacity());
+  vector.setCapacity(2);
+  ASSERT_EQ(8U, vector.capacity());
+}
+
+TEST_F(VectorTest, _grow_OverflowSize) {
+  Vector<int> vector;
+  vector.add(1);
+
+  // Checks that the size calculation (not the capacity calculation) doesn't
+  // overflow : the size here will be (1 + SIZE_MAX).
+  EXPECT_DEATH(vector.insertArrayAt(nullptr, 0, SIZE_MAX), "new_size overflow");
+}
+
+TEST_F(VectorTest, _grow_OverflowCapacityDoubling) {
+  Vector<int> vector;
+
+  // This should fail because the calculated capacity will overflow even though
+  // the size of the vector doesn't.
+  EXPECT_DEATH(vector.insertArrayAt(nullptr, 0, (SIZE_MAX - 1)), "new_capacity overflow");
+}
+
+TEST_F(VectorTest, _grow_OverflowBufferAlloc) {
+  Vector<int> vector;
+  // This should fail because the capacity * sizeof(int) overflows, even
+  // though the capacity itself doesn't.
+  EXPECT_DEATH(vector.insertArrayAt(nullptr, 0, (SIZE_MAX / 2)), "new_alloc_size overflow");
+}
+
+TEST_F(VectorTest, editArray_Shared) {
+  Vector<int> vector1;
+  vector1.add(1);
+  vector1.add(2);
+  vector1.add(3);
+  vector1.add(4);
+
+  Vector<int> vector2 = vector1;
+  ASSERT_EQ(vector1.array(), vector2.array());
+  // We must make a copy here, since we're not the exclusive owners
+  // of this array.
+  ASSERT_NE(vector1.editArray(), vector2.editArray());
+
+  // Vector doesn't implement operator ==.
+  ASSERT_EQ(vector1.size(), vector2.size());
+  for (size_t i = 0; i < vector1.size(); ++i) {
+    EXPECT_EQ(vector1[i], vector2[i]);
+  }
+}
+
+TEST_F(VectorTest, removeItemsAt_overflow) {
+    android::Vector<int> v;
+    for (int i = 0; i < 666; i++) v.add(i);
+
+    ASSERT_DEATH(v.removeItemsAt(SIZE_MAX, 666), "overflow");
+    ASSERT_DEATH(v.removeItemsAt(666, SIZE_MAX), "overflow");
+    ASSERT_DEATH(v.removeItemsAt(SIZE_MAX, SIZE_MAX), "overflow");
+}
+
+} // namespace android
diff --git a/libutils/binder/include/utils/Errors.h b/libutils/binder/include/utils/Errors.h
new file mode 100644
index 0000000..22fb36d
--- /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 <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <string>
+
+namespace android {
+
+/**
+ * The type used to return success/failure from frameworks APIs.
+ * See the anonymous enum below for valid values.
+ */
+typedef int32_t status_t;
+
+/*
+ * Error codes. 
+ * All error codes are negative values.
+ */
+
+enum {
+    OK                = 0,    // Preferred constant for checking success.
+#ifndef NO_ERROR
+    // Win32 #defines NO_ERROR as well.  It has the same value, so there's no
+    // real conflict, though it's a bit awkward.
+    NO_ERROR          = OK,   // Deprecated synonym for `OK`. Prefer `OK` because it doesn't conflict with Windows.
+#endif
+
+    UNKNOWN_ERROR       = (-2147483647-1), // INT32_MIN value
+
+    NO_MEMORY           = -ENOMEM,
+    INVALID_OPERATION   = -ENOSYS,
+    BAD_VALUE           = -EINVAL,
+    BAD_TYPE            = (UNKNOWN_ERROR + 1),
+    NAME_NOT_FOUND      = -ENOENT,
+    PERMISSION_DENIED   = -EPERM,
+    NO_INIT             = -ENODEV,
+    ALREADY_EXISTS      = -EEXIST,
+    DEAD_OBJECT         = -EPIPE,
+    FAILED_TRANSACTION  = (UNKNOWN_ERROR + 2),
+#if !defined(_WIN32)
+    BAD_INDEX           = -EOVERFLOW,
+    NOT_ENOUGH_DATA     = -ENODATA,
+    WOULD_BLOCK         = -EWOULDBLOCK, 
+    TIMED_OUT           = -ETIMEDOUT,
+    UNKNOWN_TRANSACTION = -EBADMSG,
+#else    
+    BAD_INDEX           = -E2BIG,
+    NOT_ENOUGH_DATA     = (UNKNOWN_ERROR + 3),
+    WOULD_BLOCK         = (UNKNOWN_ERROR + 4),
+    TIMED_OUT           = (UNKNOWN_ERROR + 5),
+    UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
+#endif    
+    FDS_NOT_ALLOWED     = (UNKNOWN_ERROR + 7),
+    UNEXPECTED_NULL     = (UNKNOWN_ERROR + 8),
+};
+
+// Human readable name of error
+std::string statusToString(status_t status);
+
+}  // namespace android
diff --git a/libutils/binder/include/utils/RefBase.h b/libutils/binder/include/utils/RefBase.h
new file mode 100644
index 0000000..5e3fa7d
--- /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 <StrongPointer.h>.
+
+// sp<> (and wp<>) are a type of smart pointer that use a well defined protocol
+// to operate. As long as the object they are templated with implements that
+// protocol, these smart pointers work. In several places the platform
+// instantiates sp<> with non-RefBase objects; the two are not tied to each
+// other.
+
+// RefBase is such an implementation and it supports strong pointers, weak
+// pointers and some magic features for the binder.
+
+// So, when using RefBase objects, you have the ability to use strong and weak
+// pointers through sp<> and wp<>.
+
+// Normally, when the last strong pointer goes away, the object is destroyed,
+// i.e. it's destructor is called. HOWEVER, parts of its associated memory is not
+// freed until the last weak pointer is released.
+
+// Weak pointers are essentially "safe" pointers. They are always safe to
+// access through promote(). They may return nullptr if the object was
+// destroyed because it ran out of strong pointers. This makes them good candidates
+// for keys in a cache for instance.
+
+// Weak pointers remain valid for comparison purposes even after the underlying
+// object has been destroyed. Even if object A is destroyed and its memory reused
+// for B, A remaining weak pointer to A will not compare equal to one to B.
+// This again makes them attractive for use as keys.
+
+// How is this supposed / intended to be used?
+
+// Our recommendation is to use strong references (sp<>) when there is an
+// ownership relation. e.g. when an object "owns" another one, use a strong
+// ref. And of course use strong refs as arguments of functions (it's extremely
+// rare that a function will take a wp<>).
+
+// Typically a newly allocated object will immediately be used to initialize
+// a strong pointer, which may then be used to construct or assign to other
+// strong and weak pointers.
+
+// Use weak references when there are no ownership relation. e.g. the keys in a
+// cache (you cannot use plain pointers because there is no safe way to acquire
+// a strong reference from a vanilla pointer).
+
+// This implies that two objects should never (or very rarely) have sp<> on
+// each other, because they can't both own each other.
+
+
+// Caveats with reference counting
+
+// Obviously, circular strong references are a big problem; this creates leaks
+// and it's hard to debug -- except it's in fact really easy because RefBase has
+// tons of debugging code for that. It can basically tell you exactly where the
+// leak is.
+
+// Another problem has to do with destructors with side effects. You must
+// assume that the destructor of reference counted objects can be called AT ANY
+// TIME. For instance code as simple as this:
+
+// void setStuff(const sp<Stuff>& stuff) {
+//   std::lock_guard<std::mutex> lock(mMutex);
+//   mStuff = stuff;
+// }
+
+// is very dangerous. This code WILL deadlock one day or another.
+
+// What isn't obvious is that ~Stuff() can be called as a result of the
+// assignment. And it gets called with the lock held. First of all, the lock is
+// protecting mStuff, not ~Stuff(). Secondly, if ~Stuff() uses its own internal
+// mutex, now you have mutex ordering issues.  Even worse, if ~Stuff() is
+// virtual, now you're calling into "user" code (potentially), by that, I mean,
+// code you didn't even write.
+
+// A correct way to write this code is something like:
+
+// void setStuff(const sp<Stuff>& stuff) {
+//   std::unique_lock<std::mutex> lock(mMutex);
+//   sp<Stuff> hold = mStuff;
+//   mStuff = stuff;
+//   lock.unlock();
+// }
+
+// More importantly, reference counted objects should do as little work as
+// possible in their destructor, or at least be mindful that their destructor
+// could be called from very weird and unintended places.
+
+// Other more specific restrictions for wp<> and sp<>:
+
+// Do not construct a strong pointer to "this" in an object's constructor.
+// The onFirstRef() callback would be made on an incompletely constructed
+// object.
+// Construction of a weak pointer to "this" in an object's constructor is also
+// discouraged. But the implementation was recently changed so that, in the
+// absence of extendObjectLifetime() calls, weak pointers no longer impact
+// object lifetime, and hence this no longer risks premature deallocation,
+// and hence usually works correctly.
+
+// Such strong or weak pointers can be safely created in the RefBase onFirstRef()
+// callback.
+
+// Use of wp::unsafe_get() for any purpose other than debugging is almost
+// always wrong.  Unless you somehow know that there is a longer-lived sp<> to
+// the same object, it may well return a pointer to a deallocated object that
+// has since been reallocated for a different purpose. (And if you know there
+// is a longer-lived sp<>, why not use an sp<> directly?) A wp<> should only be
+// dereferenced by using promote().
+
+// Any object inheriting from RefBase should always be destroyed as the result
+// of a reference count decrement, not via any other means.  Such objects
+// should never be stack allocated, or appear directly as data members in other
+// objects. Objects inheriting from RefBase should have their strong reference
+// count incremented as soon as possible after construction. Usually this
+// will be done via construction of an sp<> to the object, but may instead
+// involve other means of calling RefBase::incStrong().
+// Explicitly deleting or otherwise destroying a RefBase object with outstanding
+// wp<> or sp<> pointers to it will result in an abort or heap corruption.
+
+// It is particularly important not to mix sp<> and direct storage management
+// since the sp from raw pointer constructor is implicit. Thus if a RefBase-
+// -derived object of type T is managed without ever incrementing its strong
+// count, and accidentally passed to f(sp<T>), a strong pointer to the object
+// will be temporarily constructed and destroyed, prematurely deallocating the
+// object, and resulting in heap corruption. None of this would be easily
+// visible in the source. See below on
+// ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION for a compile time
+// option which helps avoid this case.
+
+// Extra Features:
+
+// RefBase::extendObjectLifetime() can be used to prevent destruction of the
+// object while there are still weak references. This is really special purpose
+// functionality to support Binder.
+
+// Wp::promote(), implemented via the attemptIncStrong() member function, is
+// used to try to convert a weak pointer back to a strong pointer.  It's the
+// normal way to try to access the fields of an object referenced only through
+// a wp<>.  Binder code also sometimes uses attemptIncStrong() directly.
+
+// RefBase provides a number of additional callbacks for certain reference count
+// events, as well as some debugging facilities.
+
+// Debugging support can be enabled by turning on DEBUG_REFS in RefBase.cpp.
+// Otherwise little checking is provided.
+
+// Thread safety:
+
+// Like std::shared_ptr, sp<> and wp<> allow concurrent accesses to DIFFERENT
+// sp<> and wp<> instances that happen to refer to the same underlying object.
+// They do NOT support concurrent access (where at least one access is a write)
+// to THE SAME sp<> or wp<>.  In effect, their thread-safety properties are
+// exactly like those of T*, NOT atomic<T*>.
+
+// Safety option: ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION
+//
+// This flag makes the semantics for using a RefBase object with wp<> and sp<>
+// much stricter by disabling implicit conversion from raw pointers to these
+// objects. In order to use this, apply this flag in Android.bp like so:
+//
+//    cflags: [
+//        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+//    ],
+//
+// REGARDLESS of whether this flag is on, best usage of sp<> is shown below. If
+// this flag is on, no other usage is possible (directly calling RefBase methods
+// is possible, but seeing code using 'incStrong' instead of 'sp<>', for
+// instance, should already set off big alarm bells. With carefully constructed
+// data structures, it should NEVER be necessary to directly use RefBase
+// methods). Proper RefBase usage:
+//
+//    class Foo : virtual public RefBase { ... };
+//
+//    // always construct an sp object with sp::make
+//    sp<Foo> myFoo = sp<Foo>::make(/*args*/);
+//
+//    // if you need a weak pointer, it must be constructed from a strong
+//    // pointer
+//    wp<Foo> weakFoo = myFoo; // NOT myFoo.get()
+//
+//    // If you are inside of a method of Foo and need access to a strong
+//    // explicitly call this function. This documents your intention to code
+//    // readers, and it will give a runtime error for what otherwise would
+//    // be potential double ownership
+//    .... Foo::someMethod(...) {
+//        // asserts if there is a memory issue
+//        sp<Foo> thiz = sp<Foo>::fromExisting(this);
+//    }
+//
+
+#ifndef ANDROID_REF_BASE_H
+#define ANDROID_REF_BASE_H
+
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <type_traits>  // for common_type.
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+// LightRefBase used to be declared in this header, so we have to include it
+#include <utils/LightRefBase.h>
+
+#include <utils/StrongPointer.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+#define COMPARE_WEAK(_op_)                                      \
+template<typename U>                                            \
+inline bool operator _op_ (const U* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}                                                               \
+/* Needed to handle type inference for nullptr: */              \
+inline bool operator _op_ (const T* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}
+
+template<template<typename C> class comparator, typename T, typename U>
+static inline bool _wp_compare_(T* a, U* b) {
+    return comparator<typename std::common_type<T*, U*>::type>()(a, b);
+}
+
+// Use std::less and friends to avoid undefined behavior when ordering pointers
+// to different objects.
+#define COMPARE_WEAK_FUNCTIONAL(_op_, _compare_)                 \
+template<typename U>                                             \
+inline bool operator _op_ (const U* o) const {                   \
+    return _wp_compare_<_compare_>(m_ptr, o);                    \
+}
+
+// ---------------------------------------------------------------------------
+
+// RefererenceRenamer is pure abstract, there is no virtual method
+// implementation to put in a translation unit in order to silence the
+// weak vtables warning.
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+class ReferenceRenamer {
+protected:
+    // destructor is purposely not virtual so we avoid code overhead from
+    // subclasses; we have to make it protected to guarantee that it
+    // cannot be called from this base class (and to make strict compilers
+    // happy).
+    ~ReferenceRenamer() { }
+public:
+    virtual void operator()(size_t i) const = 0;
+};
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+// ---------------------------------------------------------------------------
+
+class RefBase
+{
+public:
+            void            incStrong(const void* id) const;
+            void            incStrongRequireStrong(const void* id) const;
+            void            decStrong(const void* id) const;
+    
+            void            forceIncStrong(const void* id) const;
+
+            //! DEBUGGING ONLY: Get current strong ref count.
+            int32_t         getStrongCount() const;
+
+    class weakref_type
+    {
+    public:
+        RefBase*            refBase() const;
+
+        void                incWeak(const void* id);
+        void                incWeakRequireWeak(const void* id);
+        void                decWeak(const void* id);
+
+        // acquires a strong reference if there is already one.
+        bool                attemptIncStrong(const void* id);
+
+        // acquires a weak reference if there is already one.
+        // This is not always safe. see ProcessState.cpp and BpBinder.cpp
+        // for proper use.
+        bool                attemptIncWeak(const void* id);
+
+        //! DEBUGGING ONLY: Get current weak ref count.
+        int32_t             getWeakCount() const;
+
+        //! DEBUGGING ONLY: Print references held on object.
+        void                printRefs() const;
+
+        //! DEBUGGING ONLY: Enable tracking for this object.
+        // enable -- enable/disable tracking
+        // retain -- when tracking is enable, if true, then we save a stack trace
+        //           for each reference and dereference; when retain == false, we
+        //           match up references and dereferences and keep only the
+        //           outstanding ones.
+
+        void                trackMe(bool enable, bool retain);
+    };
+
+            weakref_type*   createWeak(const void* id) const;
+            
+            weakref_type*   getWeakRefs() const;
+
+            //! DEBUGGING ONLY: Print references held on object.
+    inline  void            printRefs() const { getWeakRefs()->printRefs(); }
+
+            //! DEBUGGING ONLY: Enable tracking of object.
+    inline  void            trackMe(bool enable, bool retain)
+    { 
+        getWeakRefs()->trackMe(enable, retain); 
+    }
+
+protected:
+    // When constructing these objects, prefer using sp::make<>. Using a RefBase
+    // object on the stack or with other refcount mechanisms (e.g.
+    // std::shared_ptr) is inherently wrong. RefBase types have an implicit
+    // ownership model and cannot be safely used with other ownership models.
+
+                            RefBase();
+    virtual                 ~RefBase();
+    
+    //! Flags for extendObjectLifetime()
+    enum {
+        OBJECT_LIFETIME_STRONG  = 0x0000,
+        OBJECT_LIFETIME_WEAK    = 0x0001,
+        OBJECT_LIFETIME_MASK    = 0x0001
+    };
+    
+            void            extendObjectLifetime(int32_t mode);
+            
+    //! Flags for onIncStrongAttempted()
+    enum {
+        FIRST_INC_STRONG = 0x0001
+    };
+    
+    // Invoked after creation of initial strong pointer/reference.
+    virtual void            onFirstRef();
+    // Invoked when either the last strong reference goes away, or we need to undo
+    // the effect of an unnecessary onIncStrongAttempted.
+    virtual void            onLastStrongRef(const void* id);
+    // Only called in OBJECT_LIFETIME_WEAK case.  Returns true if OK to promote to
+    // strong reference. May have side effects if it returns true.
+    // The first flags argument is always FIRST_INC_STRONG.
+    // TODO: Remove initial flag argument.
+    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
+    // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
+    // kind goes away.  Unused.
+    // TODO: Remove.
+    virtual void            onLastWeakRef(const void* id);
+
+private:
+    friend class weakref_type;
+    class weakref_impl;
+    
+                            RefBase(const RefBase& o);
+            RefBase&        operator=(const RefBase& o);
+
+private:
+    friend class ReferenceMover;
+
+    static void renameRefs(size_t n, const ReferenceRenamer& renamer);
+
+    static void renameRefId(weakref_type* ref,
+            const void* old_id, const void* new_id);
+
+    static void renameRefId(RefBase* ref,
+            const void* old_id, const void* new_id);
+
+        weakref_impl* const mRefs;
+};
+
+// ---------------------------------------------------------------------------
+
+template <typename T>
+class wp
+{
+public:
+    typedef typename RefBase::weakref_type weakref_type;
+
+    inline wp() : m_ptr(nullptr), m_refs(nullptr) { }
+
+    // if nullptr, returns nullptr
+    //
+    // if a weak pointer is already available, this will retrieve it,
+    // otherwise, this will abort
+    static inline wp<T> fromExisting(T* other);
+
+    // for more information about this flag, see above
+#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
+    wp(std::nullptr_t) : wp() {}
+#else
+    wp(T* other);  // NOLINT(implicit)
+    template <typename U>
+    wp(U* other);  // NOLINT(implicit)
+    wp& operator=(T* other);
+    template <typename U>
+    wp& operator=(U* other);
+#endif
+
+    wp(const wp<T>& other);
+    explicit wp(const sp<T>& other);
+
+    template<typename U> wp(const sp<U>& other);  // NOLINT(implicit)
+    template<typename U> wp(const wp<U>& other);  // NOLINT(implicit)
+
+    ~wp();
+
+    // Assignment
+
+    wp& operator = (const wp<T>& other);
+    wp& operator = (const sp<T>& other);
+
+    template<typename U> wp& operator = (const wp<U>& other);
+    template<typename U> wp& operator = (const sp<U>& other);
+
+    void set_object_and_refs(T* other, weakref_type* refs);
+
+    // promotion to sp
+
+    sp<T> promote() const;
+
+    // Reset
+
+    void clear();
+
+    // Accessors
+
+    inline  weakref_type* get_refs() const { return m_refs; }
+
+    inline  T* unsafe_get() const { return m_ptr; }
+
+    // Operators
+
+    COMPARE_WEAK(==)
+    COMPARE_WEAK(!=)
+    COMPARE_WEAK_FUNCTIONAL(>, std::greater)
+    COMPARE_WEAK_FUNCTIONAL(<, std::less)
+    COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
+    COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
+
+    template<typename U>
+    inline bool operator == (const wp<U>& o) const {
+        return m_refs == o.m_refs;  // Implies m_ptr == o.mptr; see invariants below.
+    }
+
+    template<typename U>
+    inline bool operator == (const sp<U>& o) const {
+        // Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
+        // object at the same address.
+        if (o == nullptr) {
+          return m_ptr == nullptr;
+        } else {
+          return m_refs == o->getWeakRefs();  // Implies m_ptr == o.mptr.
+        }
+    }
+
+    template<typename U>
+    inline bool operator != (const sp<U>& o) const {
+        return !(*this == o);
+    }
+
+    template<typename U>
+    inline bool operator > (const wp<U>& o) const {
+        if (m_ptr == o.m_ptr) {
+            return _wp_compare_<std::greater>(m_refs, o.m_refs);
+        } else {
+            return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
+        }
+    }
+
+    template<typename U>
+    inline bool operator < (const wp<U>& o) const {
+        if (m_ptr == o.m_ptr) {
+            return _wp_compare_<std::less>(m_refs, o.m_refs);
+        } else {
+            return _wp_compare_<std::less>(m_ptr, o.m_ptr);
+        }
+    }
+    template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
+    template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
+    template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
+
+private:
+    template<typename Y> friend class sp;
+    template<typename Y> friend class wp;
+
+    T*              m_ptr;
+    weakref_type*   m_refs;
+};
+
+#undef COMPARE_WEAK
+#undef COMPARE_WEAK_FUNCTIONAL
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+// Implementation invariants:
+// Either
+// 1) m_ptr and m_refs are both null, or
+// 2) m_refs == m_ptr->mRefs, or
+// 3) *m_ptr is no longer live, and m_refs points to the weakref_type object that corresponded
+//    to m_ptr while it was live. *m_refs remains live while a wp<> refers to it.
+//
+// The m_refs field in a RefBase object is allocated on construction, unique to that RefBase
+// object, and never changes. Thus if two wp's have identical m_refs fields, they are either both
+// null or point to the same object. If two wp's have identical m_ptr fields, they either both
+// point to the same live object and thus have the same m_ref fields, or at least one of the
+// objects is no longer live.
+//
+// Note that the above comparison operations go out of their way to provide an ordering consistent
+// with ordinary pointer comparison; otherwise they could ignore m_ptr, and just compare m_refs.
+
+template <typename T>
+wp<T> wp<T>::fromExisting(T* other) {
+    if (!other) return nullptr;
+
+    auto refs = other->getWeakRefs();
+    refs->incWeakRequireWeak(other);
+
+    wp<T> ret;
+    ret.m_ptr = other;
+    ret.m_refs = refs;
+    return ret;
+}
+
+#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
+template<typename T>
+wp<T>::wp(T* other)
+    : m_ptr(other)
+{
+    m_refs = other ? m_refs = other->createWeak(this) : nullptr;
+}
+
+template <typename T>
+template <typename U>
+wp<T>::wp(U* other) : m_ptr(other) {
+    m_refs = other ? other->createWeak(this) : nullptr;
+}
+
+template <typename T>
+wp<T>& wp<T>::operator=(T* other) {
+    weakref_type* newRefs = other ? other->createWeak(this) : nullptr;
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = newRefs;
+    return *this;
+}
+
+template <typename T>
+template <typename U>
+wp<T>& wp<T>::operator=(U* other) {
+    weakref_type* newRefs = other ? other->createWeak(this) : 0;
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = newRefs;
+    return *this;
+}
+#endif
+
+template<typename T>
+wp<T>::wp(const wp<T>& other)
+    : m_ptr(other.m_ptr), m_refs(other.m_refs)
+{
+    if (m_ptr) m_refs->incWeak(this);
+}
+
+template<typename T>
+wp<T>::wp(const sp<T>& other)
+    : m_ptr(other.m_ptr)
+{
+    m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const wp<U>& other)
+    : m_ptr(other.m_ptr)
+{
+    if (m_ptr) {
+        m_refs = other.m_refs;
+        m_refs->incWeak(this);
+    } else {
+        m_refs = nullptr;
+    }
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const sp<U>& other)
+    : m_ptr(other.m_ptr)
+{
+    m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
+}
+
+template<typename T>
+wp<T>::~wp()
+{
+    if (m_ptr) m_refs->decWeak(this);
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const wp<T>& other)
+{
+    weakref_type* otherRefs(other.m_refs);
+    T* otherPtr(other.m_ptr);
+    if (otherPtr) otherRefs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = otherRefs;
+    return *this;
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const sp<T>& other)
+{
+    weakref_type* newRefs =
+        other != nullptr ? other->createWeak(this) : nullptr;
+    T* otherPtr(other.m_ptr);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const wp<U>& other)
+{
+    weakref_type* otherRefs(other.m_refs);
+    U* otherPtr(other.m_ptr);
+    if (otherPtr) otherRefs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = otherRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const sp<U>& other)
+{
+    weakref_type* newRefs =
+        other != nullptr ? other->createWeak(this) : 0;
+    U* otherPtr(other.m_ptr);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T>
+void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
+{
+    if (other) refs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = refs;
+}
+
+template<typename T>
+sp<T> wp<T>::promote() const
+{
+    sp<T> result;
+    if (m_ptr && m_refs->attemptIncStrong(&result)) {
+        result.set_pointer(m_ptr);
+    }
+    return result;
+}
+
+template<typename T>
+void wp<T>::clear()
+{
+    if (m_ptr) {
+        m_refs->decWeak(this);
+        m_refs = 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<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
+    // Using a sp<RefBase> override doesn't work; it's a bit like we wanted
+    // a template<typename TYPE inherits RefBase> template...
+
+    template<typename TYPE> static inline
+    void move_references(sp<TYPE>* dest, sp<TYPE> const* src, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            sp<TYPE>* d_;
+            sp<TYPE> const* s_;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the sp<>'s this pointer
+                TYPE::renameRefId(d_[i].get(), &s_[i], &d_[i]);
+            }
+        public:
+            Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d_(d), s_(s) { }
+            virtual ~Renamer() { }
+        };
+
+        memmove(dest, src, n*sizeof(sp<TYPE>));
+        TYPE::renameRefs(n, Renamer(dest, src));
+    }
+
+
+    template<typename TYPE> static inline
+    void move_references(wp<TYPE>* dest, wp<TYPE> const* src, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            wp<TYPE>* d_;
+            wp<TYPE> const* s_;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the wp<>'s this pointer
+                TYPE::renameRefId(d_[i].get_refs(), &s_[i], &d_[i]);
+            }
+        public:
+            Renamer(wp<TYPE>* rd, wp<TYPE> const* rs) : d_(rd), s_(rs) { }
+            virtual ~Renamer() { }
+        };
+
+        memmove(dest, src, n*sizeof(wp<TYPE>));
+        TYPE::renameRefs(n, Renamer(dest, src));
+    }
+};
+
+// specialization for moving sp<> and wp<> types.
+// these are used by the [Sorted|Keyed]Vector<> implementations
+// sp<> and wp<> need to be handled specially, because they do not
+// have trivial copy operation in the general case (see RefBase.cpp
+// when DEBUG ops are enabled), but can be implemented very
+// efficiently in most cases.
+
+template<typename TYPE> inline
+void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+}  // namespace android
+
+namespace libutilsinternal {
+template <typename T, typename = void>
+struct is_complete_type : std::false_type {};
+
+template <typename T>
+struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
+}  // namespace libutilsinternal
+
+namespace std {
+
+// Define `RefBase` specific versions of `std::make_shared` and
+// `std::make_unique` to block people from using them. Using them to allocate
+// `RefBase` objects results in double ownership. Use
+// `sp<T>::make(...)` instead.
+//
+// Note: We exclude incomplete types because `std::is_base_of` is undefined in
+// that case.
+
+template <typename T, typename... Args,
+          typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
+          typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
+shared_ptr<T> make_shared(Args...) {  // SEE COMMENT ABOVE.
+    static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
+}
+
+template <typename T, typename... Args,
+          typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
+          typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
+unique_ptr<T> make_unique(Args...) {  // SEE COMMENT ABOVE.
+    static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
+}
+
+}  // namespace std
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_REF_BASE_H
diff --git a/libutils/binder/include/utils/String16.h b/libutils/binder/include/utils/String16.h
new file mode 100644
index 0000000..c713576
--- /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 <iostream>
+#include <string>
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/TypeHelpers.h>
+
+#if __has_include(<string_view>)
+#include <string_view>
+#define HAS_STRING_VIEW
+#endif
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+template <size_t N>
+class StaticString16;
+
+// DO NOT USE: please use std::u16string
+
+//! This is a string holding UTF-16 characters.
+class String16
+{
+public:
+                                String16();
+                                String16(const String16& o);
+                                String16(String16&& o) noexcept;
+                                String16(const String16& o,
+                                         size_t len,
+                                         size_t begin=0);
+    explicit                    String16(const char16_t* o);
+    explicit                    String16(const char16_t* o, size_t len);
+    explicit                    String16(const String8& o);
+    explicit                    String16(const char* o);
+    explicit                    String16(const char* o, size_t len);
+
+                                ~String16();
+
+    inline  const char16_t*     c_str() const;
+
+            size_t              size() const;
+    inline  bool                empty() const;
+
+    inline  size_t              length() const;
+
+            void                setTo(const String16& other);
+            status_t            setTo(const char16_t* other);
+            status_t            setTo(const char16_t* other, size_t len);
+            status_t            setTo(const String16& other,
+                                      size_t len,
+                                      size_t begin=0);
+
+            status_t            append(const String16& other);
+            status_t            append(const char16_t* other, size_t len);
+
+    inline  String16&           operator=(const String16& other);
+            String16&           operator=(String16&& other) noexcept;
+
+    inline  String16&           operator+=(const String16& other);
+    inline  String16            operator+(const String16& other) const;
+
+            status_t            insert(size_t pos, const char16_t* chrs);
+            status_t            insert(size_t pos,
+                                       const char16_t* chrs, size_t len);
+
+            ssize_t             findFirst(char16_t c) const;
+            ssize_t             findLast(char16_t c) const;
+
+            bool                startsWith(const String16& prefix) const;
+            bool                startsWith(const char16_t* prefix) const;
+
+            bool                contains(const char16_t* chrs) const;
+    inline  bool                contains(const String16& other) const;
+
+            status_t            replaceAll(char16_t replaceThis,
+                                           char16_t withThis);
+
+    inline  int                 compare(const String16& other) const;
+
+    inline  bool                operator<(const String16& other) const;
+    inline  bool                operator<=(const String16& other) const;
+    inline  bool                operator==(const String16& other) const;
+    inline  bool                operator!=(const String16& other) const;
+    inline  bool                operator>=(const String16& other) const;
+    inline  bool                operator>(const String16& other) const;
+
+    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 <size_t N>
+    struct StaticData {
+        // The high bit of 'size' is used as a flag.
+        static_assert(N - 1 < kIsSharedBufferAllocated, "StaticString16 too long!");
+        constexpr StaticData() : size(N - 1), data{0} {}
+        const uint32_t size;
+        char16_t data[N];
+
+        constexpr StaticData(const StaticData<N>&) = default;
+    };
+
+    /*
+     * Helper function for constructing a StaticData object.
+     */
+    template <size_t N>
+    static constexpr const StaticData<N> makeStaticData(const char16_t (&s)[N]) {
+        StaticData<N> r;
+        // The 'size' field is at the same location where mClientMetadata would
+        // be for a SharedBuffer.  We do NOT set kIsSharedBufferAllocated flag
+        // here.
+        for (size_t i = 0; i < N - 1; ++i) r.data[i] = s[i];
+        return r;
+    }
+
+    template <size_t N>
+    explicit constexpr String16(const StaticData<N>& s) : mString(s.data) {}
+
+// These symbols are for potential backward compatibility with prebuilts. To be removed.
+#ifdef ENABLE_STRING16_OBSOLETE_METHODS
+public:
+#else
+private:
+#endif
+    inline  const char16_t*     string() const;
+};
+
+// String16 can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+ANDROID_TRIVIAL_MOVE_TRAIT(String16)
+
+static inline std::ostream& operator<<(std::ostream& os, const String16& str) {
+    os << String8(str);
+    return os;
+}
+
+// ---------------------------------------------------------------------------
+
+/*
+ * A StaticString16 object is a specialized String16 object.  Instead of holding
+ * the string data in a ref counted SharedBuffer object, it holds data in a
+ * buffer within StaticString16 itself.  Note that this buffer is NOT ref
+ * counted and is assumed to be available for as long as there is at least a
+ * String16 object using it.  Therefore, one must be extra careful to NEVER
+ * assign a StaticString16 to a String16 that outlives the StaticString16
+ * object.
+ *
+ * THE SAFEST APPROACH IS TO USE StaticString16 ONLY AS GLOBAL VARIABLES.
+ *
+ * A StaticString16 SHOULD NEVER APPEAR IN APIs.  USE String16 INSTEAD.
+ */
+template <size_t N>
+class StaticString16 : public String16 {
+public:
+    constexpr StaticString16(const char16_t (&s)[N]) : String16(mData), mData(makeStaticData(s)) {}
+
+    constexpr StaticString16(const StaticString16<N>& other)
+        : String16(mData), mData(other.mData) {}
+
+    constexpr StaticString16(const StaticString16<N>&&) = delete;
+
+    // There is no reason why one would want to 'new' a StaticString16.  Delete
+    // it to discourage misuse.
+    static void* operator new(std::size_t) = delete;
+
+private:
+    const StaticData<N> mData;
+};
+
+template <typename F>
+StaticString16(const F&)->StaticString16<sizeof(F) / sizeof(char16_t)>;
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline int compare_type(const String16& lhs, const String16& rhs)
+{
+    return lhs.compare(rhs);
+}
+
+inline int strictly_order_type(const String16& lhs, const String16& rhs)
+{
+    return compare_type(lhs, rhs) < 0;
+}
+
+inline const char16_t* String16::c_str() const
+{
+    return mString;
+}
+
+inline const char16_t* String16::string() const
+{
+    return mString;
+}
+
+inline bool String16::empty() const
+{
+    return length() == 0;
+}
+
+inline size_t String16::length() const
+{
+    return size();
+}
+
+inline bool String16::contains(const String16& other) const
+{
+    return contains(other.c_str());
+}
+
+inline String16& String16::operator=(const String16& other)
+{
+    setTo(other);
+    return *this;
+}
+
+inline String16& String16::operator+=(const String16& other)
+{
+    append(other);
+    return *this;
+}
+
+inline String16 String16::operator+(const String16& other) const
+{
+    String16 tmp(*this);
+    tmp += other;
+    return tmp;
+}
+
+inline int String16::compare(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size());
+}
+
+inline bool String16::operator<(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) < 0;
+}
+
+inline bool String16::operator<=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
+}
+
+inline bool String16::operator==(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) == 0;
+}
+
+inline bool String16::operator!=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) != 0;
+}
+
+inline bool String16::operator>=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
+}
+
+inline bool String16::operator>(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) > 0;
+}
+
+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 0000000..6d25072
--- /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 <iostream>
+
+#include <utils/Errors.h>
+#include <utils/Unicode.h>
+#include <utils/TypeHelpers.h>
+
+#include <string.h> // for strcmp
+#include <stdarg.h>
+
+#if __has_include(<string>)
+#include <string>
+#define HAS_STRING
+#endif
+
+#if __has_include(<string_view>)
+#include <string_view>
+#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 0000000..54aa691
--- /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 <functional>
+#include <type_traits>  // for common_type.
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+template<typename T> class wp;
+
+// ---------------------------------------------------------------------------
+
+template<typename T>
+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> foo = new Foo(...); // DO NOT DO THIS
+    //
+    // Instead, prefer to do this:
+    //
+    //     sp<Foo> foo = sp<Foo>::make(...); // DO THIS
+    //
+    // Sometimes, in order to use this, when a constructor is marked as private,
+    // you may need to add this to your class:
+    //
+    //     friend class sp<Foo>;
+    template <typename... Args>
+    static inline sp<T> make(Args&&... args);
+
+    // if nullptr, returns nullptr
+    //
+    // if a strong pointer is already available, this will retrieve it,
+    // otherwise, this will abort
+    static inline sp<T> fromExisting(T* other);
+
+    // for more information about this macro and correct RefBase usage, see
+    // the comment at the top of utils/RefBase.h
+#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
+    sp(std::nullptr_t) : sp() {}
+#else
+    sp(T* other);  // NOLINT(implicit)
+    template <typename U>
+    sp(U* other);  // NOLINT(implicit)
+    sp& operator=(T* other);
+    template <typename U>
+    sp& operator=(U* other);
+#endif
+
+    sp(const sp<T>& other);
+    sp(sp<T>&& other) noexcept;
+
+    template<typename U> sp(const sp<U>& other);  // NOLINT(implicit)
+    template<typename U> sp(sp<U>&& other);  // NOLINT(implicit)
+
+    // Cast a strong pointer directly from one type to another. Constructors
+    // allow changing types, but only if they are pointer-compatible. This does
+    // a static_cast internally.
+    template <typename U>
+    static inline sp<T> cast(const sp<U>& other);
+
+    ~sp();
+
+    // Assignment
+
+    sp& operator = (const sp<T>& other);
+    sp& operator=(sp<T>&& other) noexcept;
+
+    template<typename U> sp& operator = (const sp<U>& other);
+    template<typename U> sp& operator = (sp<U>&& other);
+
+    //! Special optimization for use by ProcessState (and nobody else).
+    void force_set(T* other);
+
+    // Reset
+
+    void clear();
+
+    // Accessors
+
+    inline T&       operator* () const     { return *m_ptr; }
+    inline T*       operator-> () const    { return m_ptr;  }
+    inline T*       get() const            { return m_ptr; }
+    inline explicit operator bool () const { return m_ptr != nullptr; }
+
+    // Punt these to the wp<> implementation.
+    template<typename U>
+    inline bool operator == (const wp<U>& o) const {
+        return o == *this;
+    }
+
+    template<typename U>
+    inline bool operator != (const wp<U>& o) const {
+        return o != *this;
+    }
+
+private:
+    template<typename Y> friend class sp;
+    template<typename Y> friend class wp;
+    void set_pointer(T* ptr);
+    T* m_ptr;
+};
+
+#define COMPARE_STRONG(_op_)                                           \
+    template <typename T, typename U>                                  \
+    static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
+        return t.get() _op_ u.get();                                   \
+    }                                                                  \
+    template <typename T, typename U>                                  \
+    static inline bool operator _op_(const T* t, const sp<U>& u) {     \
+        return t _op_ u.get();                                         \
+    }                                                                  \
+    template <typename T, typename U>                                  \
+    static inline bool operator _op_(const sp<T>& t, const U* u) {     \
+        return t.get() _op_ u;                                         \
+    }                                                                  \
+    template <typename T>                                              \
+    static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
+        return t.get() _op_ nullptr;                                   \
+    }                                                                  \
+    template <typename T>                                              \
+    static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
+        return nullptr _op_ t.get();                                   \
+    }
+
+template <template <typename C> class comparator, typename T, typename U>
+static inline bool _sp_compare_(T* a, U* b) {
+    return comparator<typename std::common_type<T*, U*>::type>()(a, b);
+}
+
+#define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_)                     \
+    template <typename T, typename U>                                  \
+    static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
+        return _sp_compare_<_compare_>(t.get(), u.get());              \
+    }                                                                  \
+    template <typename T, typename U>                                  \
+    static inline bool operator _op_(const T* t, const sp<U>& u) {     \
+        return _sp_compare_<_compare_>(t, u.get());                    \
+    }                                                                  \
+    template <typename T, typename U>                                  \
+    static inline bool operator _op_(const sp<T>& t, const U* u) {     \
+        return _sp_compare_<_compare_>(t.get(), u);                    \
+    }                                                                  \
+    template <typename T>                                              \
+    static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
+        return _sp_compare_<_compare_>(t.get(), nullptr);              \
+    }                                                                  \
+    template <typename T>                                              \
+    static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
+        return _sp_compare_<_compare_>(nullptr, t.get());              \
+    }
+
+COMPARE_STRONG(==)
+COMPARE_STRONG(!=)
+COMPARE_STRONG_FUNCTIONAL(>, std::greater)
+COMPARE_STRONG_FUNCTIONAL(<, std::less)
+COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
+COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
+
+#undef COMPARE_STRONG
+#undef COMPARE_STRONG_FUNCTIONAL
+
+// For code size reasons, we do not want these inlined or templated.
+void sp_report_race();
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+// TODO: Ideally we should find a way to increment the reference count before running the
+// constructor, so that generating an sp<> to this in the constructor is no longer dangerous.
+template <typename T>
+template <typename... Args>
+sp<T> sp<T>::make(Args&&... args) {
+    T* t = new T(std::forward<Args>(args)...);
+    sp<T> result;
+    result.m_ptr = t;
+    t->incStrong(t);
+    return result;
+}
+
+template <typename T>
+sp<T> sp<T>::fromExisting(T* other) {
+    if (other) {
+        other->incStrongRequireStrong(other);
+        sp<T> result;
+        result.m_ptr = other;
+        return result;
+    }
+    return nullptr;
+}
+
+#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
+template<typename T>
+sp<T>::sp(T* other)
+        : m_ptr(other) {
+    if (other) {
+        other->incStrong(this);
+    }
+}
+
+template <typename T>
+template <typename U>
+sp<T>::sp(U* other) : m_ptr(other) {
+    if (other) {
+        (static_cast<T*>(other))->incStrong(this);
+    }
+}
+
+template <typename T>
+sp<T>& sp<T>::operator=(T* other) {
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (other) {
+        other->incStrong(this);
+    }
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
+    m_ptr = other;
+    return *this;
+}
+#endif
+
+template<typename T>
+sp<T>::sp(const sp<T>& other)
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
+}
+
+template <typename T>
+sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
+    other.m_ptr = nullptr;
+}
+
+template<typename T> template<typename U>
+sp<T>::sp(const sp<U>& other)
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
+}
+
+template<typename T> template<typename U>
+sp<T>::sp(sp<U>&& other)
+        : m_ptr(other.m_ptr) {
+    other.m_ptr = nullptr;
+}
+
+template <typename T>
+template <typename U>
+sp<T> sp<T>::cast(const sp<U>& other) {
+    return sp<T>::fromExisting(static_cast<T*>(other.get()));
+}
+
+template<typename T>
+sp<T>::~sp() {
+    if (m_ptr)
+        m_ptr->decStrong(this);
+}
+
+template<typename T>
+sp<T>& sp<T>::operator =(const sp<T>& other) {
+    // Force m_ptr to be read twice, to heuristically check for data races.
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    T* otherPtr(other.m_ptr);
+    if (otherPtr) otherPtr->incStrong(this);
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
+    m_ptr = otherPtr;
+    return *this;
+}
+
+template <typename T>
+sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
+    m_ptr = other.m_ptr;
+    other.m_ptr = nullptr;
+    return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator =(const sp<U>& other) {
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    T* otherPtr(other.m_ptr);
+    if (otherPtr) otherPtr->incStrong(this);
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
+    m_ptr = otherPtr;
+    return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator =(sp<U>&& other) {
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (m_ptr) m_ptr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
+    m_ptr = other.m_ptr;
+    other.m_ptr = nullptr;
+    return *this;
+}
+
+#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator =(U* other) {
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (other) (static_cast<T*>(other))->incStrong(this);
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
+    m_ptr = other;
+    return *this;
+}
+#endif
+
+template<typename T>
+void sp<T>::force_set(T* other) {
+    other->forceIncStrong(this);
+    m_ptr = other;
+}
+
+template<typename T>
+void sp<T>::clear() {
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (oldPtr) {
+        oldPtr->decStrong(this);
+        if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
+        m_ptr = nullptr;
+    }
+}
+
+template<typename T>
+void sp<T>::set_pointer(T* ptr) {
+    m_ptr = ptr;
+}
+
+}  // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRONG_POINTER_H
diff --git a/libutils/binder/include/utils/Unicode.h b/libutils/binder/include/utils/Unicode.h
new file mode 100644
index 0000000..d60d5d6
--- /dev/null
+++ b/libutils/binder/include/utils/Unicode.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UNICODE_H
+#define ANDROID_UNICODE_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+extern "C" {
+
+// Standard string functions on char16_t strings.
+int strcmp16(const char16_t *, const char16_t *);
+int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
+size_t strlen16(const char16_t *);
+size_t strnlen16(const char16_t *, size_t);
+char16_t *strstr16(const char16_t*, const char16_t*);
+
+// Version of comparison that supports embedded NULs.
+// This is different than strncmp() because we don't stop
+// at a nul character and consider the strings to be different
+// if the lengths are different (thus we need to supply the
+// lengths of both strings).  This can also be used when
+// your string is not nul-terminated as it will have the
+// equivalent result as strcmp16 (unlike strncmp16).
+int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
+
+/**
+ * Measure the length of a UTF-32 string in UTF-8. If the string is invalid
+ * such as containing a surrogate character, -1 will be returned.
+ */
+ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
+
+/**
+ * Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
+ * large enough to store the string, the part of the "src" string is stored
+ * into "dst" as much as possible. See the examples for more detail.
+ * Returns the size actually used for storing the string.
+ * dst" is not nul-terminated when dst_len is fully used (like strncpy).
+ *
+ * \code
+ * Example 1
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" >= 7
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
+ * (note that "dst" is nul-terminated)
+ *
+ * Example 2
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 5
+ * ->
+ * Returned value == 3
+ * "dst" becomes \xE3\x81\x82\0
+ * (note that "dst" is nul-terminated, but \u3044 is not stored in "dst"
+ * since "dst" does not have enough size to store the character)
+ *
+ * Example 3
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 6
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84
+ * (note that "dst" is NOT nul-terminated, like strncpy)
+ * \endcode
+ */
+void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len);
+
+/**
+ * Returns the unicode value at "index".
+ * Returns -1 when the index is invalid (equals to or more than "src_len").
+ * If returned value is positive, it is able to be converted to char32_t, which
+ * is unsigned. Then, if "next_index" is not NULL, the next index to be used is
+ * stored in "next_index". "next_index" can be NULL.
+ */
+int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
+
+
+/**
+ * Returns the UTF-8 length of UTF-16 string "src".
+ */
+ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
+
+/**
+ * Converts a UTF-16 string to UTF-8. The destination buffer must be large
+ * enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
+ * NUL terminator.
+ */
+void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len);
+
+/**
+ * Returns the UTF-16 length of UTF-8 string "src". Returns -1 in case
+ * it's invalid utf8. No buffer over-read occurs because of bound checks. Using overreadIsFatal you
+ * can ask to log a message and fail in case the invalid utf8 could have caused an override if no
+ * bound checks were used (otherwise -1 is returned).
+ */
+ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen, bool overreadIsFatal = false);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs.
+ * Returns a pointer to the end of the string (where a NUL terminator might go
+ * if you wanted to add one). At most dstLen characters are written; it won't emit half a surrogate
+ * pair. If dstLen == 0 nothing is written and dst is returned. If dstLen > SSIZE_MAX it aborts
+ * (this being probably a negative number returned as an error and casted to unsigned).
+ */
+char16_t* utf8_to_utf16_no_null_terminator(
+        const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs. At most dstLen - 1
+ * characters are written; it won't emit half a surrogate pair; and a NUL terminator is appended
+ * after. dstLen - 1 can be measured beforehand using utf8_to_utf16_length. Aborts if dstLen == 0
+ * (at least one character is needed for the NUL terminator) or dstLen > SSIZE_MAX (the latter
+ * case being likely a negative number returned as an error and casted to unsigned) . Returns a
+ * pointer to the NUL terminator.
+ */
+char16_t *utf8_to_utf16(
+        const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
+
+}
+
+#endif
diff --git a/libutils/binder/include/utils/Vector.h b/libutils/binder/include/utils/Vector.h
new file mode 100644
index 0000000..d5db3cb
--- /dev/null
+++ b/libutils/binder/include/utils/Vector.h
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VECTOR_H
+#define ANDROID_VECTOR_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+#include <utils/TypeHelpers.h>
+#include <utils/VectorImpl.h>
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+/*
+ * Used to exclude some functions from CFI.
+ */
+#if __has_attribute(no_sanitize)
+#define UTILS_VECTOR_NO_CFI __attribute__((no_sanitize("cfi")))
+#else
+#define UTILS_VECTOR_NO_CFI
+#endif
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <typename TYPE>
+class SortedVector;
+
+/*!
+ * The main templated vector class ensuring type safety
+ * while making use of VectorImpl.
+ * This is the class users want to use.
+ *
+ * DO NOT USE: please use std::vector
+ */
+
+template <class TYPE>
+class Vector : private VectorImpl
+{
+public:
+            typedef TYPE    value_type;
+
+    /*!
+     * Constructors and destructors
+     */
+
+                            Vector();
+                            Vector(const Vector<TYPE>& rhs);
+    explicit                Vector(const SortedVector<TYPE>& rhs);
+    virtual                 ~Vector();
+
+    /*! copy operator */
+    Vector<TYPE>& operator=(const Vector<TYPE>& rhs);        // NOLINT(cert-oop54-cpp)
+    Vector<TYPE>& operator=(const SortedVector<TYPE>& rhs);  // NOLINT(cert-oop54-cpp)
+
+    /*
+     * empty the vector
+     */
+
+    inline  void            clear()             { VectorImpl::clear(); }
+
+    /*!
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return VectorImpl::size(); }
+    //! returns whether or not the vector is empty
+    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
+    //! sets the capacity. capacity can never be reduced less than size()
+    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }
+
+    /*!
+     * set the size of the vector. items are appended with the default
+     * constructor, or removed from the end as needed.
+     */
+    inline  ssize_t         resize(size_t size)         { return VectorImpl::resize(size); }
+
+    /*!
+     * C-style array access
+     */
+
+    //! read-only C-style access
+    inline  const TYPE*     array() const;
+    //! read-write C-style access
+            TYPE*           editArray();
+
+    /*!
+     * accessors
+     */
+
+    //! read-only access to an item at a given index
+    inline  const TYPE&     operator [] (size_t index) const;
+    //! alternate name for operator []
+    inline  const TYPE&     itemAt(size_t index) const;
+    //! stack-usage of the vector. returns the top of the stack (last element)
+            const TYPE&     top() const;
+
+    /*!
+     * modifying the array
+     */
+
+    //! copy-on write support, grants write access to an item
+            TYPE&           editItemAt(size_t index);
+    //! grants right access to the top of the stack (last element)
+            TYPE&           editTop();
+
+            /*!
+             * append/insert another vector
+             */
+
+    //! insert another vector at a given index
+            ssize_t         insertVectorAt(const Vector<TYPE>& vector, size_t index);
+
+    //! append another vector at the end of this one
+            ssize_t         appendVector(const Vector<TYPE>& vector);
+
+
+    //! insert an array at a given index
+            ssize_t         insertArrayAt(const TYPE* array, size_t index, size_t length);
+
+    //! append an array at the end of this vector
+            ssize_t         appendArray(const TYPE* array, size_t length);
+
+            /*!
+             * add/insert/replace items
+             */
+
+    //! insert one or several items initialized with their default constructor
+    inline  ssize_t         insertAt(size_t index, size_t numItems = 1);
+    //! insert one or several items initialized from a prototype item
+            ssize_t         insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
+    //! pop the top of the stack (removes the last element). No-op if the stack's empty
+    inline  void            pop();
+    //! pushes an item initialized with its default constructor
+    inline  void            push();
+    //! pushes an item on the top of the stack
+            void            push(const TYPE& item);
+    //! same as push() but returns the index the item was added at (or an error)
+    inline  ssize_t         add();
+    //! same as push() but returns the index the item was added at (or an error)
+            ssize_t         add(const TYPE& item);
+    //! replace an item with a new one initialized with its default constructor
+    inline  ssize_t         replaceAt(size_t index);
+    //! replace an item with a new one
+            ssize_t         replaceAt(const TYPE& item, size_t index);
+
+    /*!
+     * remove items
+     */
+
+    //! remove several items
+    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
+    //! remove one item
+    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }
+
+    /*!
+     * sort (stable) the array
+     */
+
+     typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
+     typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
+
+     inline status_t        sort(compar_t cmp);
+     inline status_t        sort(compar_r_t cmp, void* state);
+
+     // for debugging only
+     inline size_t getItemSize() const { return itemSize(); }
+
+
+     /*
+      * these inlines add some level of compatibility with STL. eventually
+      * we should probably turn things around.
+      */
+     typedef TYPE* iterator;
+     typedef TYPE const* const_iterator;
+
+     inline iterator begin() { return editArray(); }
+     inline iterator end()   { return editArray() + size(); }
+     inline const_iterator begin() const { return array(); }
+     inline const_iterator end() const   { return array() + size(); }
+     inline void reserve(size_t n) { setCapacity(n); }
+     inline bool empty() const{ return isEmpty(); }
+     inline void push_back(const TYPE& item)  { insertAt(item, size(), 1); }
+     inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
+     inline iterator erase(iterator pos) {
+         ssize_t index = removeItemsAt(static_cast<size_t>(pos-array()));
+         return begin() + index;
+     }
+
+protected:
+    virtual void    do_construct(void* storage, size_t num) const;
+    virtual void    do_destroy(void* storage, size_t num) const;
+    virtual void    do_copy(void* dest, const void* from, size_t num) const;
+    virtual void    do_splat(void* dest, const void* item, size_t num) const;
+    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
+    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
+};
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+Vector<TYPE>::Vector()
+    : VectorImpl(sizeof(TYPE),
+                ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
+                |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0))
+                )
+{
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
+    : VectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+    : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::~Vector() {
+    finish_vector();
+}
+
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(const Vector<TYPE>& rhs)  // NOLINT(cert-oop54-cpp)
+{
+    VectorImpl::operator=(rhs);
+    return *this;
+}
+
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(
+        const SortedVector<TYPE>& rhs)  // NOLINT(cert-oop54-cpp)
+{
+    VectorImpl::operator=(static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+const TYPE* Vector<TYPE>::array() const {
+    return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* Vector<TYPE>::editArray() {
+    return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::operator[](size_t index) const {
+    LOG_FATAL_IF(index>=size(),
+            "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
+            int(index), int(size()));
+    return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::itemAt(size_t index) const {
+    return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::top() const {
+    return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editItemAt(size_t index) {
+    return *( static_cast<TYPE *>(editItemLocation(index)) );
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editTop() {
+    return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
+    return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
+    return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
+    return VectorImpl::insertArrayAt(array, index, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
+    return VectorImpl::appendArray(array, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
+    return VectorImpl::insertAt(&item, index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push(const TYPE& item) {
+    return VectorImpl::push(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add(const TYPE& item) {
+    return VectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
+    return VectorImpl::replaceAt(&item, index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
+    return VectorImpl::insertAt(index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::pop() {
+    VectorImpl::pop();
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push() {
+    VectorImpl::push();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add() {
+    return VectorImpl::add();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(size_t index) {
+    return VectorImpl::replaceAt(index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
+    return VectorImpl::removeItemsAt(index, count);
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
+    return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_t>(cmp));
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
+    return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_r_t>(cmp), state);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_construct(void* storage, size_t num) const {
+    construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
+    destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+    copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+    splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+    move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+    move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+}  // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/libutils/binder/include/utils/VectorImpl.h b/libutils/binder/include/utils/VectorImpl.h
new file mode 100644
index 0000000..41b9f33
--- /dev/null
+++ b/libutils/binder/include/utils/VectorImpl.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VECTOR_IMPL_H
+#define ANDROID_VECTOR_IMPL_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts in here...
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/*!
+ * Implementation of the guts of the vector<> class
+ * this ensures backward binary compatibility and
+ * reduces code size.
+ * For performance reasons, we expose mStorage and mCount
+ * so these fields are set in stone.
+ *
+ */
+
+class VectorImpl
+{
+public:
+    enum { // flags passed to the ctor
+        HAS_TRIVIAL_CTOR    = 0x00000001,
+        HAS_TRIVIAL_DTOR    = 0x00000002,
+        HAS_TRIVIAL_COPY    = 0x00000004,
+    };
+
+                            VectorImpl(size_t itemSize, uint32_t flags);
+                            VectorImpl(const VectorImpl& rhs);
+    virtual                 ~VectorImpl();
+
+    /*! must be called from subclasses destructor */
+            void            finish_vector();
+
+            VectorImpl&     operator = (const VectorImpl& rhs);    
+            
+    /*! C-style array access */
+    inline  const void*     arrayImpl() const       { return mStorage; }
+            void*           editArrayImpl();
+            
+    /*! vector stats */
+    inline  size_t          size() const        { return mCount; }
+    inline  bool            isEmpty() const     { return mCount == 0; }
+            size_t          capacity() const;
+            ssize_t         setCapacity(size_t size);
+            ssize_t         resize(size_t size);
+
+            /*! append/insert another vector or array */
+            ssize_t         insertVectorAt(const VectorImpl& vector, size_t index);
+            ssize_t         appendVector(const VectorImpl& vector);
+            ssize_t         insertArrayAt(const void* array, size_t index, size_t length);
+            ssize_t         appendArray(const void* array, size_t length);
+            
+            /*! add/insert/replace items */
+            ssize_t         insertAt(size_t where, size_t numItems = 1);
+            ssize_t         insertAt(const void* item, size_t where, size_t numItems = 1);
+            void            pop();
+            void            push();
+            void            push(const void* item);
+            ssize_t         add();
+            ssize_t         add(const void* item);
+            ssize_t         replaceAt(size_t index);
+            ssize_t         replaceAt(const void* item, size_t index);
+
+            /*! remove items */
+            ssize_t         removeItemsAt(size_t index, size_t count = 1);
+            void            clear();
+
+            const void*     itemLocation(size_t index) const;
+            void*           editItemLocation(size_t index);
+
+            typedef int (*compar_t)(const void* lhs, const void* rhs);
+            typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
+            status_t        sort(compar_t cmp);
+            status_t        sort(compar_r_t cmp, void* state);
+
+protected:
+            size_t          itemSize() const;
+            void            release_storage();
+
+    virtual void            do_construct(void* storage, size_t num) const = 0;
+    virtual void            do_destroy(void* storage, size_t num) const = 0;
+    virtual void            do_copy(void* dest, const void* from, size_t num) const = 0;
+    virtual void            do_splat(void* dest, const void* item, size_t num) const = 0;
+    virtual void            do_move_forward(void* dest, const void* from, size_t num) const = 0;
+    virtual void            do_move_backward(void* dest, const void* from, size_t num) const = 0;
+    
+private:
+        void* _grow(size_t where, size_t amount);
+        void  _shrink(size_t where, size_t amount);
+
+        inline void _do_construct(void* storage, size_t num) const;
+        inline void _do_destroy(void* storage, size_t num) const;
+        inline void _do_copy(void* dest, const void* from, size_t num) const;
+        inline void _do_splat(void* dest, const void* item, size_t num) const;
+        inline void _do_move_forward(void* dest, const void* from, size_t num) const;
+        inline void _do_move_backward(void* dest, const void* from, size_t num) const;
+
+            // These 2 fields are exposed in the inlines below,
+            // so they're set in stone.
+            void *      mStorage;   // base address of the vector
+            size_t      mCount;     // number of items
+
+    const   uint32_t    mFlags;
+    const   size_t      mItemSize;
+};
+
+
+
+class SortedVectorImpl : public VectorImpl
+{
+public:
+                            SortedVectorImpl(size_t itemSize, uint32_t flags);
+    explicit                SortedVectorImpl(const VectorImpl& rhs);
+    virtual                 ~SortedVectorImpl();
+    
+    SortedVectorImpl&     operator = (const SortedVectorImpl& rhs);    
+
+    //! finds the index of an item
+            ssize_t         indexOf(const void* item) const;
+
+    //! finds where this item should be inserted
+            size_t          orderOf(const void* item) const;
+
+    //! add an item in the right place (or replaces it if there is one)
+            ssize_t         add(const void* item);
+
+    //! merges a vector into this one
+            ssize_t         merge(const VectorImpl& vector);
+            ssize_t         merge(const SortedVectorImpl& vector);
+             
+    //! removes an item
+            ssize_t         remove(const void* item);
+        
+protected:
+    virtual int             do_compare(const void* lhs, const void* rhs) const = 0;
+
+private:
+            ssize_t         _indexOrderOf(const void* item, size_t* order = nullptr) const;
+
+            // these are made private, because they can't be used on a SortedVector
+            // (they don't have an implementation either)
+            ssize_t         add();
+            void            pop();
+            void            push();
+            void            push(const void* item);
+            ssize_t         insertVectorAt(const VectorImpl& vector, size_t index);
+            ssize_t         appendVector(const VectorImpl& vector);
+            ssize_t         insertArrayAt(const void* array, size_t index, size_t length);
+            ssize_t         appendArray(const void* array, size_t length);
+            ssize_t         insertAt(size_t where, size_t numItems = 1);
+            ssize_t         insertAt(const void* item, size_t where, size_t numItems = 1);
+            ssize_t         replaceAt(size_t index);
+            ssize_t         replaceAt(const void* item, size_t index);
+};
+
+}  // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_IMPL_H