Merge "IMemory: add read/readRange APIs."
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index 547f7e7..e97797d 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -30,26 +30,13 @@
 
 vintf::Transport getTransportFromManifest(
         const FQName &fqName, const std::string &instanceName,
-        const std::string &manifestName,
         const vintf::HalManifest *vm) {
     if (vm == nullptr) {
-        LOG(WARNING) << "getTransportFromManifest: No " << manifestName << " manifest defined, "
-                     << "using default transport for " << fqName.string();
         return vintf::Transport::EMPTY;
     }
-    vintf::Transport tr = vm->getTransport(fqName.package(),
+    return vm->getTransport(fqName.package(),
             vintf::Version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()},
             fqName.name(), instanceName);
-    if (tr == vintf::Transport::EMPTY) {
-        LOG(WARNING) << "getTransportFromManifest: Cannot find entry "
-                     << fqName.string()
-                     << " in " << manifestName << " manifest, using default transport.";
-    } else {
-        LOG(DEBUG) << "getTransportFromManifest: " << fqName.string()
-                   << " declares transport method " << to_string(tr)
-                   << " in " << manifestName << " manifest";
-    }
-    return tr;
 }
 
 vintf::Transport getTransport(const std::string &interfaceName, const std::string &instanceName) {
@@ -68,13 +55,22 @@
                    << " does not specify an interface name. Using default transport.";
         return vintf::Transport::EMPTY;
     }
-    // TODO(b/34772739): modify the list if other packages are added to system/manifest.xml
-    if (fqName.inPackage("android.hidl")) {
-        return getTransportFromManifest(fqName, instanceName, "framework",
-                vintf::VintfObject::GetFrameworkHalManifest());
+
+    vintf::Transport tr = getTransportFromManifest(fqName, instanceName,
+            vintf::VintfObject::GetFrameworkHalManifest());
+    if (tr != vintf::Transport::EMPTY) {
+        return tr;
     }
-    return getTransportFromManifest(fqName, instanceName, "device",
+    tr = getTransportFromManifest(fqName, instanceName,
             vintf::VintfObject::GetDeviceHalManifest());
+    if (tr != vintf::Transport::EMPTY) {
+        return tr;
+    }
+
+    LOG(WARNING) << "getTransportFromManifest: Cannot find entry "
+                 << fqName.string()
+                 << " in either framework or device manifest, using default transport.";
+    return vintf::Transport::EMPTY;
 }
 
 namespace details {
diff --git a/base/Status.cpp b/base/Status.cpp
index 449aff3..3b31ee6 100644
--- a/base/Status.cpp
+++ b/base/Status.cpp
@@ -70,7 +70,6 @@
         EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_STATE),
         EXCEPTION_TO_STRING_PAIR(EX_NETWORK_MAIN_THREAD),
         EXCEPTION_TO_STRING_PAIR(EX_UNSUPPORTED_OPERATION),
-        EXCEPTION_TO_STRING_PAIR(EX_SERVICE_SPECIFIC),
         EXCEPTION_TO_STRING_PAIR(EX_HAS_REPLY_HEADER),
         EXCEPTION_TO_STRING_PAIR(EX_TRANSACTION_FAILED)
     }};
@@ -91,15 +90,6 @@
     return Status(exceptionCode, OK, message);
 }
 
-Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode) {
-    return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode);
-}
-
-Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode,
-                                        const char *message) {
-    return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode, message);
-}
-
 Status Status::fromStatusT(status_t status) {
     Status ret;
     ret.setFromStatusT(status);
@@ -121,11 +111,6 @@
     mMessage = message;
 }
 
-void Status::setServiceSpecificError(int32_t errorCode, const char *message) {
-    setException(EX_SERVICE_SPECIFIC, message);
-    mErrorCode = errorCode;
-}
-
 void Status::setFromStatusT(status_t status) {
     mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
     mErrorCode = status;
@@ -143,9 +128,7 @@
         stream << "No error";
     } else {
         stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '";
-        if (s.exceptionCode() == Status::EX_SERVICE_SPECIFIC) {
-            stream << s.serviceSpecificErrorCode() << ": ";
-        } else if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
+        if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
             stream << statusToString(s.transactionError()) << ": ";
         }
         stream << s.exceptionMessage() << "'";
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 7737011..f2e1265 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -270,7 +270,7 @@
         return mName;
     }
 
-    size_t size() const {
+    uint64_t size() const {
         return mSize;
     }
 
@@ -280,9 +280,9 @@
     static const size_t kOffsetOfName;
 
 private:
-    hidl_handle mHandle;
-    size_t mSize;
-    hidl_string mName;
+    hidl_handle mHandle __attribute__ ((aligned(8)));
+    uint64_t mSize __attribute__ ((aligned(8)));
+    hidl_string mName __attribute__ ((aligned(8)));
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -293,6 +293,7 @@
         : mBuffer(NULL),
           mSize(0),
           mOwnsBuffer(true) {
+        static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
     }
 
     hidl_vec(const hidl_vec<T> &other) : hidl_vec() {
@@ -817,7 +818,7 @@
 
 ///////////////////// toString functions
 
-namespace details {
+std::string toString(const void *t);
 
 // toString alias for numeric types
 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
@@ -825,6 +826,8 @@
     return std::to_string(t);
 }
 
+namespace details {
+
 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
 inline std::string toHexString(T t, bool prefix = true) {
     std::ostringstream os;
@@ -843,8 +846,48 @@
     return toHexString(static_cast<int32_t>(t), prefix);
 }
 
-inline std::string toString(const void *t, bool prefix = true) {
-    return toHexString(reinterpret_cast<uintptr_t>(t), prefix);
+template<typename Array>
+std::string arrayToString(const Array &a, size_t size);
+
+template<size_t SIZE1>
+std::string arraySizeToString() {
+    return std::string{"["} + toString(SIZE1) + "]";
+}
+
+template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
+std::string arraySizeToString() {
+    return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
+}
+
+template<typename T, size_t SIZE1>
+std::string toString(details::const_accessor<T, SIZE1> a) {
+    return arrayToString(a, SIZE1);
+}
+
+template<typename Array>
+std::string arrayToString(const Array &a, size_t size) {
+    using android::hardware::toString;
+    std::string os;
+    os += "{";
+    for (size_t i = 0; i < size; ++i) {
+        if (i > 0) {
+            os += ", ";
+        }
+        os += toString(a[i]);
+    }
+    os += "}";
+    return os;
+}
+
+template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
+std::string toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
+    return arrayToString(a, SIZE1);
+}
+
+}  //namespace details
+
+inline std::string toString(const void *t) {
+    return details::toHexString(reinterpret_cast<uintptr_t>(t));
 }
 
 // debug string dump. There will be quotes around the string!
@@ -867,68 +910,27 @@
     return std::string{"death_recipient@"} + toString(dr.get());
 }
 
-template<typename Array>
-std::string arrayToString(const Array &a, size_t size);
-
 // debug string dump, assuming that toString(T) is defined.
 template<typename T>
 std::string toString(const hidl_vec<T> &a) {
     std::string os;
     os += "[" + toString(a.size()) + "]";
-    os += arrayToString(a, a.size());
+    os += details::arrayToString(a, a.size());
     return os;
 }
 
-template<size_t SIZE1>
-std::string arraySizeToString() {
-    return std::string{"["} + toString(SIZE1) + "]";
-}
-
-template<typename T, size_t SIZE1>
-std::string toString(const_accessor<T, SIZE1> a) {
-    return arrayToString(a, SIZE1);
-}
-
 template<typename T, size_t SIZE1>
 std::string toString(const hidl_array<T, SIZE1> &a) {
-    return arraySizeToString<SIZE1>()
-            + toString(const_accessor<T, SIZE1>(a.data()));
-}
-
-template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
-std::string arraySizeToString() {
-    return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
-}
-
-
-template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
-std::string toString(const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
-    return arrayToString(a, SIZE1);
+    return details::arraySizeToString<SIZE1>()
+            + details::toString(details::const_accessor<T, SIZE1>(a.data()));
 }
 
 template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
 std::string toString(const hidl_array<T, SIZE1, SIZE2, SIZES...> &a) {
-    return arraySizeToString<SIZE1, SIZE2, SIZES...>()
-            + toString(const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
+    return details::arraySizeToString<SIZE1, SIZE2, SIZES...>()
+            + details::toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
 }
 
-template<typename Array>
-std::string arrayToString(const Array &a, size_t size) {
-    std::string os;
-    os += "{";
-    for (size_t i = 0; i < size; ++i) {
-        if (i > 0) {
-            os += ", ";
-        }
-        os += toString(a[i]);
-    }
-    os += "}";
-    return os;
-}
-
-}  // namespace details
-
-
 }  // namespace hardware
 }  // namespace android
 
diff --git a/base/include/hidl/MQDescriptor.h b/base/include/hidl/MQDescriptor.h
index 90b30d1..48e59dd 100644
--- a/base/include/hidl/MQDescriptor.h
+++ b/base/include/hidl/MQDescriptor.h
@@ -246,7 +246,6 @@
 template<typename T, MQFlavor flavor>
 int32_t MQDescriptor<T, flavor>::getFlags() const { return mFlags; }
 
-namespace details {
 template<typename T, MQFlavor flavor>
 std::string toString(const MQDescriptor<T, flavor> &q) {
     std::string os;
@@ -263,7 +262,6 @@
        + ", .quantum = " + toString(q.getQuantum()) + "}";
     return os;
 }
-}  // namespace details
 
 }  // namespace hardware
 }  // namespace android
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index c5c5bd9..a4a83f4 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -62,7 +62,6 @@
         EX_ILLEGAL_STATE = -5,
         EX_NETWORK_MAIN_THREAD = -6,
         EX_UNSUPPORTED_OPERATION = -7,
-        EX_SERVICE_SPECIFIC = -8,
 
         // This is special and Java specific; see Parcel.java.
         EX_HAS_REPLY_HEADER = -128,
@@ -75,19 +74,14 @@
     static Status ok();
     // Authors should explicitly pick whether their integer is:
     //  - an exception code (EX_* above)
-    //  - service specific error code
     //  - status_t
     //
-    //  Prefer a generic exception code when possible, then a service specific
-    //  code, and finally a status_t for low level failures or legacy support.
-    //  Exception codes and service specific errors map to nicer exceptions for
-    //  Java clients.
+    // Prefer a generic exception code when possible or a status_t
+    // for low level transport errors. Service specific errors
+    // should be at a higher level in HIDL.
     static Status fromExceptionCode(int32_t exceptionCode);
     static Status fromExceptionCode(int32_t exceptionCode,
                                     const char *message);
-    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
-    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
-                                           const char *message);
     static Status fromStatusT(status_t status);
 
     Status() = default;
@@ -100,8 +94,6 @@
 
     // Set one of the pre-defined exception types defined above.
     void setException(int32_t ex, const char *message);
-    // Set a service specific exception with error code.
-    void setServiceSpecificError(int32_t errorCode, const char *message);
     // Setting a |status| != OK causes generated code to return |status|
     // from Binder transactions, rather than writing an exception into the
     // reply Parcel.  This is the least preferable way of reporting errors.
@@ -113,9 +105,6 @@
     status_t transactionError() const {
         return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
     }
-    int32_t serviceSpecificErrorCode() const {
-        return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0;
-    }
 
     bool isOk() const { return mException == EX_NONE; }
 
@@ -132,7 +121,6 @@
     //
     // Otherwise, we always write |mException| to the parcel.
     // If |mException| !=  EX_NONE, we write |mMessage| as well.
-    // If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well.
     int32_t mException = EX_NONE;
     int32_t mErrorCode = 0;
     std::string mMessage;
diff --git a/test_main.cpp b/test_main.cpp
index b799f6e..7ff8ae3 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -364,10 +364,6 @@
 
     EXPECT_THAT(toString(Status::fromStatusT(-EBUSY)), HasSubstr("busy"));
 
-    auto s = toString(Status::fromServiceSpecificError(20));
-    EXPECT_THAT(s, HasSubstr("EX_SERVICE_SPECIFIC"));
-    EXPECT_THAT(s, HasSubstr("20"));
-
     EXPECT_THAT(toString(Status::fromExceptionCode(Status::EX_NULL_POINTER)),
             HasSubstr("EX_NULL_POINTER"));
 
diff --git a/transport/Android.bp b/transport/Android.bp
index b1df04e..1c1a310 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -58,6 +58,7 @@
     srcs: [
         "HidlBinderSupport.cpp",
         "HidlPassthroughSupport.cpp",
+        "HidlTransportSupport.cpp",
         "LegacySupport.cpp",
         "ServiceManagement.cpp",
         "Static.cpp"
diff --git a/transport/HidlBinderSupport.cpp b/transport/HidlBinderSupport.cpp
index 746c2f9..c0601ca 100644
--- a/transport/HidlBinderSupport.cpp
+++ b/transport/HidlBinderSupport.cpp
@@ -30,6 +30,8 @@
 
 const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle);
 const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName);
+static_assert(hidl_memory::kOffsetOfHandle == 0, "wrong offset");
+static_assert(hidl_memory::kOffsetOfName == 24, "wrong offset");
 
 status_t readEmbeddedFromParcel(hidl_memory * /* memory */,
         const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
@@ -69,6 +71,7 @@
 }
 // static
 const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer);
+static_assert(hidl_string::kOffsetOfBuffer == 0, "wrong offset");
 
 status_t readEmbeddedFromParcel(hidl_string * /* string */,
         const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
@@ -106,7 +109,6 @@
 
 status_t readFromParcel(Status *s, const Parcel& parcel) {
     int32_t exception;
-    int32_t errorCode;
     status_t status = parcel.readInt32(&exception);
     if (status != OK) {
         s->setFromStatusT(status);
@@ -142,19 +144,7 @@
         return status;
     }
 
-    if (exception == Status::EX_SERVICE_SPECIFIC) {
-        status = parcel.readInt32(&errorCode);
-    }
-    if (status != OK) {
-        s->setFromStatusT(status);
-        return status;
-    }
-
-    if (exception == Status::EX_SERVICE_SPECIFIC) {
-        s->setServiceSpecificError(errorCode, String8(message));
-    } else {
-        s->setException(exception, String8(message));
-    }
+    s->setException(exception, String8(message));
 
     return status;
 }
@@ -173,11 +163,6 @@
         return status;
     }
     status = parcel->writeString16(String16(s.exceptionMessage()));
-    if (s.exceptionCode() != Status::EX_SERVICE_SPECIFIC) {
-        // We have no more information to write.
-        return status;
-    }
-    status = parcel->writeInt32(s.serviceSpecificErrorCode());
     return status;
 }
 
diff --git a/transport/HidlPassthroughSupport.cpp b/transport/HidlPassthroughSupport.cpp
index 43724f9..981a139 100644
--- a/transport/HidlPassthroughSupport.cpp
+++ b/transport/HidlPassthroughSupport.cpp
@@ -21,6 +21,7 @@
 
 namespace android {
 namespace hardware {
+namespace details {
 
 sp<::android::hidl::base::V1_0::IBase> wrapPassthrough(
         sp<::android::hidl::base::V1_0::IBase> iface) {
@@ -28,7 +29,7 @@
         // doesn't know how to handle it.
         return iface;
     }
-    std::string myDescriptor = details::getDescriptor(iface.get());
+    std::string myDescriptor = getDescriptor(iface.get());
     if (myDescriptor.empty()) {
         // interfaceDescriptor fails
         return nullptr;
@@ -40,6 +41,6 @@
     return func(reinterpret_cast<void *>(iface.get()));
 }
 
-
+}  // namespace details
 }  // namespace hardware
 }  // namespace android
diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp
new file mode 100644
index 0000000..a5ec8e2
--- /dev/null
+++ b/transport/HidlTransportSupport.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+#include <hidl/HidlTransportSupport.h>
+
+#include <hidl/HidlBinderSupport.h>
+
+namespace android {
+namespace hardware {
+
+void configureRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
+    // TODO(b/32756130) this should be transport-dependent
+    configureBinderRpcThreadpool(maxThreads, callerWillJoin);
+}
+void joinRpcThreadpool() {
+    // TODO(b/32756130) this should be transport-dependent
+    joinBinderRpcThreadpool();
+}
+
+}
+}
\ No newline at end of file
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index ba11937..8b98021 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -147,7 +147,7 @@
     if (_hidl_err != ::android::OK) { return _hidl_err; }
 
     const native_handle_t *_hidl_mq_handle_ptr;
-   _hidl_err = parcel.readEmbeddedNativeHandle(
+   _hidl_err = parcel.readNullableEmbeddedNativeHandle(
             parentHandle,
             parentOffset + MQDescriptor<T, flavor>::kOffsetOfHandle,
             &_hidl_mq_handle_ptr);
diff --git a/transport/include/hidl/HidlPassthroughSupport.h b/transport/include/hidl/HidlPassthroughSupport.h
index 2b2f86b..0a8f15b 100644
--- a/transport/include/hidl/HidlPassthroughSupport.h
+++ b/transport/include/hidl/HidlPassthroughSupport.h
@@ -21,6 +21,7 @@
 
 namespace android {
 namespace hardware {
+namespace details {
 
 /*
  * Wrap the given interface with the smallest BsChild possible. Will return the
@@ -29,6 +30,7 @@
 sp<::android::hidl::base::V1_0::IBase> wrapPassthrough(
         sp<::android::hidl::base::V1_0::IBase> iface);
 
+}  // namespace details
 }  // namespace hardware
 }  // namespace android
 
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index 86379a9..8a2a70a 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -40,18 +40,14 @@
  *   configureRpcThreadPool(1, true); // transport won't launch any threads by itself
  *
  */
-inline void configureRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
-    // TODO(b/32756130) this should be transport-dependent
-    configureBinderRpcThreadpool(maxThreads, callerWillJoin);
-}
+void configureRpcThreadpool(size_t maxThreads, bool callerWillJoin);
 
 /* Joins a threadpool that you configured earlier with
  * configureRpcThreadPool(x, true);
  */
-inline void joinRpcThreadpool() {
-    // TODO(b/32756130) this should be transport-dependent
-    joinBinderRpcThreadpool();
-}
+void joinRpcThreadpool();
+
+namespace details {
 
 // cast the interface IParent to IChild.
 // Return nullptr if parent is null or any failure.
@@ -75,6 +71,8 @@
     return sp<IChild>(static_cast<IChild *>(parent.get()));
 }
 
+}  // namespace details
+
 }  // namespace hardware
 }  // namespace android