Merge changes I68ed9d1c,I4ebccfd0,I3507bdfd,Iaf02f55c into cw-e-dev am: d6ad64f894
am: a20eb797c4

* commit 'a20eb797c462189ba6641308d80e638501db0a18':
  system_server BINDER_TYPE_FD sockets using ashmem accessors
  Parcel: file descriptor leak
  Parcel: include Android coding standard
  Parcel: LOG_TAG cleanup
diff --git a/Android.mk b/Android.mk
index d5860ef..bd432f3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,6 +36,7 @@
     PermissionCache.cpp \
     ProcessState.cpp \
     Static.cpp \
+    Status.cpp \
     TextOutput.cpp \
 
 LOCAL_PATH:= $(call my-dir)
diff --git a/Binder.cpp b/Binder.cpp
index 9d200fb..e39093d 100644
--- a/Binder.cpp
+++ b/Binder.cpp
@@ -16,7 +16,7 @@
 
 #include <binder/Binder.h>
 
-#include <stdatomic.h>
+#include <atomic>
 #include <utils/misc.h>
 #include <binder/BpBinder.h>
 #include <binder/IInterface.h>
@@ -70,9 +70,8 @@
 
 // ---------------------------------------------------------------------------
 
-BBinder::BBinder()
+BBinder::BBinder() : mExtras(nullptr)
 {
-  atomic_init(&mExtras, static_cast<uintptr_t>(0));
 }
 
 bool BBinder::isBinderAlive() const
@@ -139,19 +138,16 @@
     const void* objectID, void* object, void* cleanupCookie,
     object_cleanup_func func)
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    atomic_load_explicit(&mExtras, memory_order_acquire));
+    Extras* e = mExtras.load(std::memory_order_acquire);
 
     if (!e) {
         e = new Extras;
-        uintptr_t expected = 0;
-        if (!atomic_compare_exchange_strong_explicit(
-                                        &mExtras, &expected,
-                                        reinterpret_cast<uintptr_t>(e),
-                                        memory_order_release,
-                                        memory_order_acquire)) {
+        Extras* expected = nullptr;
+        if (!mExtras.compare_exchange_strong(expected, e,
+                                             std::memory_order_release,
+                                             std::memory_order_acquire)) {
             delete e;
-            e = reinterpret_cast<Extras*>(expected);  // Filled in by CAS
+            e = expected;  // Filled in by CAS
         }
         if (e == 0) return; // out of memory
     }
@@ -160,18 +156,9 @@
     e->mObjects.attach(objectID, object, cleanupCookie, func);
 }
 
-// The C11 standard doesn't allow atomic loads from const fields,
-// though C++11 does.  Fudge it until standards get straightened out.
-static inline uintptr_t load_const_atomic(const atomic_uintptr_t* p,
-                                          memory_order mo) {
-    atomic_uintptr_t* non_const_p = const_cast<atomic_uintptr_t*>(p);
-    return atomic_load_explicit(non_const_p, mo);
-}
-
 void* BBinder::findObject(const void* objectID) const
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    load_const_atomic(&mExtras, memory_order_acquire));
+    Extras* e = mExtras.load(std::memory_order_acquire);
     if (!e) return NULL;
 
     AutoMutex _l(e->mLock);
@@ -180,8 +167,7 @@
 
 void BBinder::detachObject(const void* objectID)
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    atomic_load_explicit(&mExtras, memory_order_acquire));
+    Extras* e = mExtras.load(std::memory_order_acquire);
     if (!e) return;
 
     AutoMutex _l(e->mLock);
@@ -195,8 +181,7 @@
 
 BBinder::~BBinder()
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    atomic_load_explicit(&mExtras, memory_order_relaxed));
+    Extras* e = mExtras.load(std::memory_order_relaxed);
     if (e) delete e;
 }
 
@@ -252,7 +237,7 @@
 BpRefBase::~BpRefBase()
 {
     if (mRemote) {
-        if (!(mState&kRemoteAcquired)) {
+        if (!(mState.load(std::memory_order_relaxed)&kRemoteAcquired)) {
             mRemote->decStrong(this);
         }
         mRefs->decWeak(this);
@@ -261,7 +246,7 @@
 
 void BpRefBase::onFirstRef()
 {
-    android_atomic_or(kRemoteAcquired, &mState);
+    mState.fetch_or(kRemoteAcquired, std::memory_order_relaxed);
 }
 
 void BpRefBase::onLastStrongRef(const void* /*id*/)
diff --git a/Debug.cpp b/Debug.cpp
index bdb7182..a8f2da5 100644
--- a/Debug.cpp
+++ b/Debug.cpp
@@ -138,7 +138,7 @@
         *pos = 0;
         return pos;
     }
-    
+
     if( fullContext ) {
         *pos++ = '0';
         *pos++ = 'x';
@@ -167,21 +167,21 @@
     if (func == NULL) func = defaultPrintFunc;
 
     size_t offset;
-    
+
     unsigned char *pos = (unsigned char *)buf;
-    
+
     if (pos == NULL) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         func(cookie, "(NULL)");
         return;
     }
-    
+
     if (length == 0) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         func(cookie, "(empty)");
         return;
     }
-    
+
     if ((int32_t)length < 0) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         char buf[64];
@@ -189,12 +189,12 @@
         func(cookie, buf);
         return;
     }
-    
+
     char buffer[256];
     static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
-    
+
     if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
-    
+
     const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
     bool newLine = false;
     if (cStyle) {
@@ -205,7 +205,7 @@
         func(cookie, "\n");
         newLine = true;
     }
-    
+
     for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
         long remain = length;
 
@@ -217,21 +217,20 @@
 
         size_t index;
         size_t word;
-        
+
         for (word = 0; word < bytesPerLine; ) {
 
             const size_t startIndex = word+(alignment-(alignment?1:0));
-            const ssize_t dir = -1;
 
             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
-            
+
                 if (!cStyle) {
                     if (index == 0 && word > 0 && alignment > 0) {
                         *c++ = ' ';
                     }
-                
+
                     if (remain-- > 0) {
-                        const unsigned char val = *(pos+startIndex+(index*dir));
+                        const unsigned char val = *(pos+startIndex-index);
                         *c++ = makehexdigit(val>>4);
                         *c++ = makehexdigit(val);
                     } else if (!oneLine) {
@@ -248,14 +247,14 @@
                             *c++ = '0';
                             *c++ = 'x';
                         }
-                        const unsigned char val = *(pos+startIndex+(index*dir));
+                        const unsigned char val = *(pos+startIndex-index);
                         *c++ = makehexdigit(val>>4);
                         *c++ = makehexdigit(val);
                         remain--;
                     }
                 }
             }
-            
+
             word += index;
         }
 
@@ -272,7 +271,7 @@
                     *c++ = ' ';
                 }
             }
-            
+
             *c++ = '\'';
             if (length > bytesPerLine) *c++ = '\n';
         } else {
@@ -284,7 +283,7 @@
         *c = 0;
         func(cookie, buffer);
         newLine = true;
-        
+
         if (length <= bytesPerLine) break;
         length -= bytesPerLine;
     }
diff --git a/Parcel.cpp b/Parcel.cpp
index 1429a5c..c481751 100644
--- a/Parcel.cpp
+++ b/Parcel.cpp
@@ -32,6 +32,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
+#include <binder/Status.h>
 #include <binder/TextOutput.h>
 
 #include <cutils/ashmem.h>
@@ -71,9 +72,6 @@
 // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
 #define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
 
-// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
-#define EX_HAS_REPLY_HEADER -128
-
 // XXX This can be made public if we want to provide
 // support for typed data.
 struct small_flat_data
@@ -346,6 +344,39 @@
     return BAD_TYPE;
 }
 
+namespace {
+
+template<typename T>
+status_t readTypedVector(std::vector<T>* val, const Parcel* p,
+                         status_t(Parcel::*read_func)(T*) const) {
+    val->clear();
+
+    int32_t size;
+    status_t status = p->readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return UNEXPECTED_NULL;
+    }
+
+    val->resize(size);
+
+    for (auto& v: *val) {
+        status = (p->*read_func)(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+}  // namespace
+
 // ---------------------------------------------------------------------------
 
 Parcel::Parcel()
@@ -386,13 +417,11 @@
 
 size_t Parcel::dataAvail() const
 {
-    // TODO: decide what to do about the possibility that this can
-    // report an available-data size that exceeds a Java int's max
-    // positive value, causing havoc.  Fortunately this will only
-    // happen if someone constructs a Parcel containing more than two
-    // gigabytes of data, which on typical phone hardware is simply
-    // not possible.
-    return dataSize() - dataPosition();
+    size_t result = dataSize() - dataPosition();
+    if (result > INT32_MAX) {
+        abort();
+    }
+    return result;
 }
 
 size_t Parcel::dataPosition() const
@@ -753,6 +782,104 @@
     return NULL;
 }
 
+namespace {
+
+template<typename T, typename U>
+status_t unsafeWriteTypedVector(const std::vector<T>& val, Parcel* p,
+                                status_t(Parcel::*write_func)(U)) {
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = p->writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = (p->*write_func)(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+template<typename T>
+status_t writeTypedVector(const std::vector<T>& val, Parcel* p,
+                          status_t(Parcel::*write_func)(const T&)) {
+    return unsafeWriteTypedVector(val, p, write_func);
+}
+
+template<typename T>
+status_t writeTypedVector(const std::vector<T>& val, Parcel* p,
+                          status_t(Parcel::*write_func)(T)) {
+    return unsafeWriteTypedVector(val, p, write_func);
+}
+
+}  // namespace
+
+status_t Parcel::writeByteVector(const std::vector<int8_t>& val)
+{
+    status_t status;
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    status = writeInt32(val.size());
+    if (status != OK) {
+        return status;
+    }
+
+    void* data = writeInplace(val.size());
+    if (!data) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    memcpy(data, val.data(), val.size());
+    return status;
+}
+
+status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeInt32);
+}
+
+status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeInt64);
+}
+
+status_t Parcel::writeFloatVector(const std::vector<float>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeFloat);
+}
+
+status_t Parcel::writeDoubleVector(const std::vector<double>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeDouble);
+}
+
+status_t Parcel::writeBoolVector(const std::vector<bool>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeBool);
+}
+
+status_t Parcel::writeCharVector(const std::vector<char16_t>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeChar);
+}
+
+status_t Parcel::writeString16Vector(const std::vector<String16>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeString16);
+}
+
 status_t Parcel::writeInt32(int32_t val)
 {
     return writeAligned(val);
@@ -796,6 +923,21 @@
     return ret;
 }
 
+status_t Parcel::writeBool(bool val)
+{
+    return writeInt32(int32_t(val));
+}
+
+status_t Parcel::writeChar(char16_t val)
+{
+    return writeInt32(int32_t(val));
+}
+
+status_t Parcel::writeByte(int8_t val)
+{
+    return writeInt32(int32_t(val));
+}
+
 status_t Parcel::writeInt64(int64_t val)
 {
     return writeAligned(val);
@@ -882,6 +1024,15 @@
     return flatten_binder(ProcessState::self(), val, this);
 }
 
+status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
+{
+    return writeTypedVector(val, this, &Parcel::writeStrongBinder);
+}
+
+status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
+    return readTypedVector(val, this, &Parcel::readStrongBinder);
+}
+
 status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
 {
     return flatten_binder(ProcessState::self(), val, this);
@@ -1085,7 +1236,8 @@
 
 status_t Parcel::writeNoException()
 {
-    return writeInt32(0);
+    binder::Status status;
+    return status.writeToParcel(this);
 }
 
 void Parcel::remove(size_t /*start*/, size_t /*amt*/)
@@ -1168,6 +1320,93 @@
     return err;
 }
 
+status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        status = UNEXPECTED_NULL;
+        return status;
+    }
+    if (size_t(size) > dataAvail()) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    const void* data = readInplace(size);
+    if (!data) {
+        status = BAD_VALUE;
+        return status;
+    }
+    val->resize(size);
+    memcpy(val->data(), data, size);
+
+    return status;
+}
+
+status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const {
+    return readTypedVector(val, this, &Parcel::readInt32);
+}
+
+status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const {
+    return readTypedVector(val, this, &Parcel::readInt64);
+}
+
+status_t Parcel::readFloatVector(std::vector<float>* val) const {
+    return readTypedVector(val, this, &Parcel::readFloat);
+}
+
+status_t Parcel::readDoubleVector(std::vector<double>* val) const {
+    return readTypedVector(val, this, &Parcel::readDouble);
+}
+
+status_t Parcel::readBoolVector(std::vector<bool>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return UNEXPECTED_NULL;
+    }
+
+    val->resize(size);
+
+    /* C++ bool handling means a vector of bools isn't necessarily addressable
+     * (we might use individual bits)
+     */
+    bool data;
+    for (int32_t i = 0; i < size; ++i) {
+        status = readBool(&data);
+        (*val)[i] = data;
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readCharVector(std::vector<char16_t>* val) const {
+    return readTypedVector(val, this, &Parcel::readChar);
+}
+
+status_t Parcel::readString16Vector(std::vector<String16>* val) const {
+    return readTypedVector(val, this, &Parcel::readString16);
+}
+
+
 status_t Parcel::readInt32(int32_t *pArg) const
 {
     return readAligned(pArg);
@@ -1286,6 +1525,44 @@
     return readAligned<intptr_t>();
 }
 
+status_t Parcel::readBool(bool *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = (tmp != 0);
+    return ret;
+}
+
+bool Parcel::readBool() const
+{
+    return readInt32() != 0;
+}
+
+status_t Parcel::readChar(char16_t *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = char16_t(tmp);
+    return ret;
+}
+
+char16_t Parcel::readChar() const
+{
+    return char16_t(readInt32());
+}
+
+status_t Parcel::readByte(int8_t *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = int8_t(tmp);
+    return ret;
+}
+
+int8_t Parcel::readByte() const
+{
+    return int8_t(readInt32());
+}
 
 const char* Parcel::readCString() const
 {
@@ -1324,6 +1601,19 @@
     return String16();
 }
 
+status_t Parcel::readString16(String16* pArg) const
+{
+    size_t len;
+    const char16_t* str = readString16Inplace(&len);
+    if (str) {
+        pArg->setTo(str, len);
+        return 0;
+    } else {
+        *pArg = String16();
+        return UNEXPECTED_NULL;
+    }
+}
+
 const char16_t* Parcel::readString16Inplace(size_t* outLen) const
 {
     int32_t size = readInt32();
@@ -1339,10 +1629,15 @@
     return NULL;
 }
 
+status_t Parcel::readStrongBinder(sp<IBinder>* val) const
+{
+    return unflatten_binder(ProcessState::self(), *this, val);
+}
+
 sp<IBinder> Parcel::readStrongBinder() const
 {
     sp<IBinder> val;
-    unflatten_binder(ProcessState::self(), *this, &val);
+    readStrongBinder(&val);
     return val;
 }
 
@@ -1355,18 +1650,9 @@
 
 int32_t Parcel::readExceptionCode() const
 {
-  int32_t exception_code = readAligned<int32_t>();
-  if (exception_code == EX_HAS_REPLY_HEADER) {
-    int32_t header_start = dataPosition();
-    int32_t header_size = readAligned<int32_t>();
-    // Skip over fat responses headers.  Not used (or propagated) in
-    // native code
-    setDataPosition(header_start + header_size);
-    // And fat response headers are currently only used when there are no
-    // exceptions, so return no error:
-    return 0;
-  }
-  return exception_code;
+    binder::Status status;
+    status.readFromParcel(*this);
+    return status.exceptionCode();
 }
 
 native_handle* Parcel::readNativeHandle() const
@@ -1679,8 +1965,14 @@
         if (mData) {
             LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity);
             pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
-            gParcelGlobalAllocSize -= mDataCapacity;
-            gParcelGlobalAllocCount--;
+            if (mDataCapacity <= gParcelGlobalAllocSize) {
+              gParcelGlobalAllocSize = gParcelGlobalAllocSize - mDataCapacity;
+            } else {
+              gParcelGlobalAllocSize = 0;
+            }
+            if (gParcelGlobalAllocCount > 0) {
+              gParcelGlobalAllocCount--;
+            }
             pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
             free(mData);
         }
@@ -1859,6 +2151,7 @@
                 pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
                 gParcelGlobalAllocSize += desired;
                 gParcelGlobalAllocSize -= mDataCapacity;
+                gParcelGlobalAllocCount++;
                 pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
                 mData = data;
                 mDataCapacity = desired;
diff --git a/Status.cpp b/Status.cpp
new file mode 100644
index 0000000..41fff3d
--- /dev/null
+++ b/Status.cpp
@@ -0,0 +1,133 @@
+/*
+ * 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 <binder/Status.h>
+
+namespace android {
+namespace binder {
+
+Status Status::fromExceptionCode(int32_t exception_code) {
+    return Status(exception_code, "");
+}
+
+Status Status::fromStatusT(status_t status) {
+    Status ret;
+    ret.setFromStatusT(status);
+    return ret;
+}
+
+Status Status::ok() {
+    return Status();
+}
+
+Status::Status(int32_t exception_code, const String8& message)
+    : mException(exception_code),
+      mMessage(message) {}
+
+Status::Status(int32_t exception_code, const char* message)
+    : mException(exception_code),
+      mMessage(message) {}
+
+status_t Status::readFromParcel(const Parcel& parcel) {
+    status_t status = parcel.readInt32(&mException);
+    if (status != OK) {
+        setFromStatusT(status);
+        return status;
+    }
+
+    // Skip over fat response headers.  Not used (or propagated) in native code.
+    if (mException == EX_HAS_REPLY_HEADER) {
+        // Note that the header size includes the 4 byte size field.
+        const int32_t header_start = parcel.dataPosition();
+        int32_t header_size;
+        status = parcel.readInt32(&header_size);
+        if (status != OK) {
+            setFromStatusT(status);
+            return status;
+        }
+        parcel.setDataPosition(header_start + header_size);
+        // And fat response headers are currently only used when there are no
+        // exceptions, so act like there was no error.
+        mException = EX_NONE;
+    }
+
+    if (mException == EX_NONE) {
+        return status;
+    }
+
+    // The remote threw an exception.  Get the message back.
+    mMessage = String8(parcel.readString16());
+
+    return status;
+}
+
+status_t Status::writeToParcel(Parcel* parcel) const {
+    status_t status = parcel->writeInt32(mException);
+    if (status != OK) { return status; }
+    if (mException == EX_NONE) {
+        // We have no more information to write.
+        return status;
+    }
+    status = parcel->writeString16(String16(mMessage));
+    return status;
+}
+
+void Status::setFromStatusT(status_t status) {
+    switch (status) {
+        case NO_ERROR:
+            mException = EX_NONE;
+            mMessage.clear();
+            break;
+        case UNEXPECTED_NULL:
+            mException = EX_NULL_POINTER;
+            mMessage.setTo("Unexpected null reference in Parcel");
+            break;
+        default:
+            mException = EX_TRANSACTION_FAILED;
+            mMessage.setTo("Transaction failed");
+            break;
+    }
+}
+
+void Status::setException(int32_t ex, const String8& message) {
+    mException = ex;
+    mMessage.setTo(message);
+}
+
+void Status::getException(int32_t* returned_exception,
+                          String8* returned_message) const {
+    if (returned_exception) {
+        *returned_exception = mException;
+    }
+    if (returned_message) {
+        returned_message->setTo(mMessage);
+    }
+}
+
+String8 Status::toString8() const {
+    String8 ret;
+    if (mException == EX_NONE) {
+        ret.append("No error");
+    } else {
+        ret.appendFormat("Status(%d): '", mException);
+        ret.append(String8(mMessage));
+        ret.append("'");
+    }
+    return ret;
+}
+
+}  // namespace binder
+}  // namespace android
diff --git a/include/hwbinder/Binder.h b/include/hwbinder/Binder.h
index 86628a0..f849fd4 100644
--- a/include/hwbinder/Binder.h
+++ b/include/hwbinder/Binder.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_BINDER_H
 #define ANDROID_BINDER_H
 
-#include <stdatomic.h>
+#include <atomic>
 #include <stdint.h>
 #include <binder/IBinder.h>
 
@@ -71,7 +71,7 @@
 
     class Extras;
 
-    atomic_uintptr_t    mExtras;  // should be atomic<Extras *>
+    std::atomic<Extras*> mExtras;
             void*       mReserved0;
 };
 
@@ -95,7 +95,7 @@
 
     IBinder* const          mRemote;
     RefBase::weakref_type*  mRefs;
-    volatile int32_t        mState;
+    std::atomic<int32_t>    mState;
 };
 
 }; // namespace android
diff --git a/include/hwbinder/Parcel.h b/include/hwbinder/Parcel.h
index 16cd6cf..430c3ff 100644
--- a/include/hwbinder/Parcel.h
+++ b/include/hwbinder/Parcel.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_PARCEL_H
 #define ANDROID_PARCEL_H
 
+#include <vector>
+
 #include <cutils/native_handle.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -25,6 +27,8 @@
 #include <utils/Flattenable.h>
 #include <linux/binder.h>
 
+#include <binder/IInterface.h>
+
 // ---------------------------------------------------------------------------
 namespace android {
 
@@ -108,6 +112,20 @@
     status_t            writeWeakBinder(const wp<IBinder>& val);
     status_t            writeInt32Array(size_t len, const int32_t *val);
     status_t            writeByteArray(size_t len, const uint8_t *val);
+    status_t            writeBool(bool val);
+    status_t            writeChar(char16_t val);
+    status_t            writeByte(int8_t val);
+
+    status_t            writeByteVector(const std::vector<int8_t>& val);
+    status_t            writeInt32Vector(const std::vector<int32_t>& val);
+    status_t            writeInt64Vector(const std::vector<int64_t>& val);
+    status_t            writeFloatVector(const std::vector<float>& val);
+    status_t            writeDoubleVector(const std::vector<double>& val);
+    status_t            writeBoolVector(const std::vector<bool>& val);
+    status_t            writeCharVector(const std::vector<char16_t>& val);
+    status_t            writeString16Vector(const std::vector<String16>& val);
+
+    status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
 
     template<typename T>
     status_t            write(const Flattenable<T>& val);
@@ -118,7 +136,7 @@
 
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
-    // when this function returns). 
+    // when this function returns).
     // Doesn't take ownership of the native_handle.
     status_t            writeNativeHandle(const native_handle* handle);
     
@@ -169,15 +187,37 @@
     status_t            readDouble(double *pArg) const;
     intptr_t            readIntPtr() const;
     status_t            readIntPtr(intptr_t *pArg) const;
+    bool                readBool() const;
+    status_t            readBool(bool *pArg) const;
+    char16_t            readChar() const;
+    status_t            readChar(char16_t *pArg) const;
+    int8_t              readByte() const;
+    status_t            readByte(int8_t *pArg) const;
 
     const char*         readCString() const;
     String8             readString8() const;
     String16            readString16() const;
+    status_t            readString16(String16* pArg) const;
     const char16_t*     readString16Inplace(size_t* outLen) const;
     sp<IBinder>         readStrongBinder() const;
+    status_t            readStrongBinder(sp<IBinder>* val) const;
     wp<IBinder>         readWeakBinder() const;
 
     template<typename T>
+    status_t            readStrongBinder(sp<T>* val) const;
+
+    status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
+
+    status_t            readByteVector(std::vector<int8_t>* val) const;
+    status_t            readInt32Vector(std::vector<int32_t>* val) const;
+    status_t            readInt64Vector(std::vector<int64_t>* val) const;
+    status_t            readFloatVector(std::vector<float>* val) const;
+    status_t            readDoubleVector(std::vector<double>* val) const;
+    status_t            readBoolVector(std::vector<bool>* val) const;
+    status_t            readCharVector(std::vector<char16_t>* val) const;
+    status_t            readString16Vector(std::vector<String16>* val) const;
+
+    template<typename T>
     status_t            read(Flattenable<T>& val) const;
 
     template<typename T>
@@ -402,6 +442,22 @@
     return NO_ERROR;
 }
 
+template<typename T>
+status_t Parcel::readStrongBinder(sp<T>* val) const {
+    sp<IBinder> tmp;
+    status_t ret = readStrongBinder(&tmp);
+
+    if (ret == OK) {
+        *val = interface_cast<T>(tmp);
+
+        if (val->get() == nullptr) {
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    return ret;
+}
+
 // ---------------------------------------------------------------------------
 
 inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/include/hwbinder/Status.h b/include/hwbinder/Status.h
new file mode 100644
index 0000000..04738f8
--- /dev/null
+++ b/include/hwbinder/Status.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BINDER_STATUS_H
+#define ANDROID_BINDER_STATUS_H
+
+#include <cstdint>
+
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace binder {
+
+// An object similar in function to a status_t except that it understands
+// how exceptions are encoded in the prefix of a Parcel. Used like:
+//
+//     Parcel data;
+//     Parcel reply;
+//     status_t status;
+//     binder::Status remote_exception;
+//     if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
+//         (status = data.writeInt32(function_input)) != OK) {
+//         // We failed to write into the memory of our local parcel?
+//     }
+//     if ((status = remote()->transact(transaction, data, &reply)) != OK) {
+//        // Something has gone wrong in the binder driver or libbinder.
+//     }
+//     if ((status = remote_exception.readFromParcel(reply)) != OK) {
+//         // The remote didn't correctly write the exception header to the
+//         // reply.
+//     }
+//     if (!remote_exception.isOk()) {
+//         // The transaction went through correctly, but the remote reported an
+//         // exception during handling.
+//     }
+//
+class Status final {
+public:
+    // Keep the exception codes in sync with android/os/Parcel.java.
+    enum Exception {
+        EX_NONE = 0,
+        EX_SECURITY = -1,
+        EX_BAD_PARCELABLE = -2,
+        EX_ILLEGAL_ARGUMENT = -3,
+        EX_NULL_POINTER = -4,
+        EX_ILLEGAL_STATE = -5,
+        EX_NETWORK_MAIN_THREAD = -6,
+        EX_UNSUPPORTED_OPERATION = -7,
+        EX_TRANSACTION_FAILED = -8,
+
+        // This is special and Java specific; see Parcel.java.
+        EX_HAS_REPLY_HEADER = -128,
+    };
+
+    // Allow authors to explicitly pick whether their integer is a status_t or
+    // exception code.
+    static Status fromExceptionCode(int32_t exception_code);
+    static Status fromStatusT(status_t status);
+    // A more readable alias for the default constructor.
+    static Status ok();
+
+    Status() = default;
+    Status(int32_t exception_code, const String8& message);
+    Status(int32_t exception_code, const char* message);
+
+
+    // Status objects are copyable and contain just simple data.
+    Status(const Status& status) = default;
+    Status(Status&& status) = default;
+    Status& operator=(const Status& status) = default;
+
+    ~Status() = default;
+
+    // Bear in mind that if the client or service is a Java endpoint, this
+    // is not the logic which will provide/interpret the data here.
+    status_t readFromParcel(const Parcel& parcel);
+    status_t writeToParcel(Parcel* parcel) const;
+
+    // Set one of the pre-defined exception types defined above.
+    void setException(int32_t ex, const String8& message);
+    // A few of the status_t values map to exception codes, but most of them
+    // simply map to "transaction failed."
+    void setFromStatusT(status_t status);
+
+    // Get information about an exception.
+    // Any argument may be given as nullptr.
+    void getException(int32_t* returned_exception,
+                      String8* returned_message) const;
+    int32_t exceptionCode() const  { return mException; }
+    const String8& exceptionMessage() const { return mMessage; }
+
+    bool isOk() const { return mException == EX_NONE; }
+
+    // For logging.
+    String8 toString8() const;
+
+private:
+    // We always write |mException| to the parcel.
+    // If |mException| !=  EX_NONE, we write message as well.
+    int32_t mException = EX_NONE;
+    String8 mMessage;
+};  // class Status
+
+}  // namespace binder
+}  // namespace android
+
+#endif // ANDROID_BINDER_STATUS_H