Add support for decoding UTF16 to UTF8

This is helpful because many native service developers use std::string
internally, and String16 doesn't work very well with many C++
primitives.

Bug: 26729450
Test: Integration test appears to show this is correct.

Change-Id: Ib75068881da28fd8515685bcbcbe864ba3b7ec23
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index e30e65d..e50e155 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -743,6 +743,37 @@
     return NULL;
 }
 
+status_t Parcel::writeUtf8AsUtf16(const std::string& str) {
+    const uint8_t* strData = (uint8_t*)str.data();
+    const size_t strLen= str.length();
+    const ssize_t utf16Len = utf8_to_utf16_length(strData, strLen);
+    if (utf16Len < 0 || utf16Len> std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t err = writeInt32(utf16Len);
+    if (err) {
+        return err;
+    }
+
+    // Allocate enough bytes to hold our converted string and its terminating NULL.
+    void* dst = writeInplace((utf16Len + 1) * sizeof(char16_t));
+    if (!dst) {
+        return NO_MEMORY;
+    }
+
+    utf8_to_utf16(strData, strLen, (char16_t*)dst);
+
+    return NO_ERROR;
+}
+
+status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) {
+  if (!str) {
+    return writeInt32(-1);
+  }
+  return writeUtf8AsUtf16(*str);
+}
+
 status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
 {
     if (!val) {
@@ -846,6 +877,15 @@
     return writeNullableTypedVector(val, &Parcel::writeString16);
 }
 
+status_t Parcel::writeUtf8VectorAsUtf16Vector(
+                        const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) {
+    return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16);
+}
+
+status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) {
+    return writeTypedVector(val, &Parcel::writeUtf8AsUtf16);
+}
+
 status_t Parcel::writeInt32(int32_t val)
 {
     return writeAligned(val);
@@ -1485,6 +1525,14 @@
     return readTypedVector(val, &Parcel::readString16);
 }
 
+status_t Parcel::readUtf8VectorFromUtf16Vector(
+        std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16);
+}
+
+status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const {
+    return readTypedVector(val, &Parcel::readUtf8FromUtf16);
+}
 
 status_t Parcel::readInt32(int32_t *pArg) const
 {
@@ -1643,6 +1691,46 @@
     return int8_t(readInt32());
 }
 
+status_t Parcel::readUtf8FromUtf16(std::string* str) const {
+    size_t utf16Size = 0;
+    const char16_t* src = readString16Inplace(&utf16Size);
+    if (!src) {
+        return UNEXPECTED_NULL;
+    }
+
+    // Save ourselves the trouble, we're done.
+    if (utf16Size == 0u) {
+        str->clear();
+       return NO_ERROR;
+    }
+
+    ssize_t utf8Size = utf16_to_utf8_length(src, utf16Size);
+    if (utf8Size < 0) {
+        return BAD_VALUE;
+    }
+    // Note that while it is probably safe to assume string::resize keeps a
+    // spare byte around for the trailing null, we're going to be explicit.
+    str->resize(utf8Size + 1);
+    utf16_to_utf8(src, utf16Size, &((*str)[0]));
+    str->resize(utf8Size);
+    return NO_ERROR;
+}
+
+status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const {
+    const int32_t start = dataPosition();
+    int32_t size;
+    status_t status = readInt32(&size);
+    str->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    setDataPosition(start);
+    str->reset(new std::string());
+    return readUtf8FromUtf16(str->get());
+}
+
 const char* Parcel::readCString() const
 {
     const size_t avail = mDataSize-mDataPos;