Add marshal() and unmarshal() APIs.

Expose marshal/unmarshal APIs from binder_ndk because we need
to pass large data that exceeds binder memory limitation across
binder for auto use case. We need to serialize parcel to a shared
memory file and unmarshal it into a parcel. We would only marshal
stable AIDL generated parcelable.

Test: Add a unit test to CTS.
Bug: 197781220
Change-Id: I774663d619ad0ca04f23044d2245021b265b32c1
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index b2f21c7..c320e8d 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -673,4 +673,32 @@
     return new AParcel(nullptr);
 }
 
+binder_status_t AParcel_marshal(const AParcel* parcel, uint8_t* buffer, size_t start, size_t len) {
+    if (parcel->get()->objectsCount()) {
+        return STATUS_INVALID_OPERATION;
+    }
+    int32_t dataSize = AParcel_getDataSize(parcel);
+    if (len > static_cast<size_t>(dataSize) || start > static_cast<size_t>(dataSize) - len) {
+        return STATUS_BAD_VALUE;
+    }
+    const uint8_t* internalBuffer = parcel->get()->data();
+    memcpy(buffer, internalBuffer + start, len);
+    return STATUS_OK;
+}
+
+binder_status_t AParcel_unmarshal(AParcel* parcel, const uint8_t* buffer, size_t len) {
+    status_t status = parcel->get()->setDataSize(len);
+    if (status != ::android::OK) {
+        return PruneStatusT(status);
+    }
+    parcel->get()->setDataPosition(0);
+
+    void* raw = parcel->get()->writeInplace(len);
+    if (raw == nullptr) {
+        return STATUS_NO_MEMORY;
+    }
+    memcpy(raw, buffer, len);
+    return STATUS_OK;
+}
+
 // @END