2009-03-04 03:31:44 +00:00
|
|
|
/*
|
|
|
|
* 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_PARCEL_H
|
|
|
|
#define ANDROID_PARCEL_H
|
|
|
|
|
|
|
|
#include <cutils/native_handle.h>
|
|
|
|
#include <utils/Errors.h>
|
|
|
|
#include <utils/RefBase.h>
|
|
|
|
#include <utils/String16.h>
|
|
|
|
#include <utils/Vector.h>
|
2012-08-13 02:37:16 +00:00
|
|
|
#include <utils/Flattenable.h>
|
2014-01-29 04:12:59 +00:00
|
|
|
#include <linux/binder.h>
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
namespace android {
|
|
|
|
|
2013-07-30 04:24:40 +00:00
|
|
|
template <typename T> class Flattenable;
|
2012-08-13 02:37:16 +00:00
|
|
|
template <typename T> class LightFlattenable;
|
2009-03-04 03:31:44 +00:00
|
|
|
class IBinder;
|
2010-07-27 16:49:11 +00:00
|
|
|
class IPCThreadState;
|
2009-03-04 03:31:44 +00:00
|
|
|
class ProcessState;
|
|
|
|
class String8;
|
|
|
|
class TextOutput;
|
|
|
|
|
2013-07-30 04:24:40 +00:00
|
|
|
class Parcel {
|
2013-11-05 16:53:55 +00:00
|
|
|
friend class IPCThreadState;
|
2009-03-04 03:31:44 +00:00
|
|
|
public:
|
2011-09-24 04:17:56 +00:00
|
|
|
class ReadableBlob;
|
|
|
|
class WritableBlob;
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
Parcel();
|
|
|
|
~Parcel();
|
|
|
|
|
|
|
|
const uint8_t* data() const;
|
|
|
|
size_t dataSize() const;
|
|
|
|
size_t dataAvail() const;
|
|
|
|
size_t dataPosition() const;
|
|
|
|
size_t dataCapacity() const;
|
2011-09-29 03:19:47 +00:00
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
status_t setDataSize(size_t size);
|
|
|
|
void setDataPosition(size_t pos) const;
|
|
|
|
status_t setDataCapacity(size_t size);
|
|
|
|
|
|
|
|
status_t setData(const uint8_t* buffer, size_t len);
|
|
|
|
|
2011-04-13 17:21:56 +00:00
|
|
|
status_t appendFrom(const Parcel *parcel,
|
|
|
|
size_t start, size_t len);
|
2009-03-04 03:31:44 +00:00
|
|
|
|
2011-10-04 04:09:35 +00:00
|
|
|
bool pushAllowFds(bool allowFds);
|
|
|
|
void restoreAllowFds(bool lastValue);
|
2011-09-29 03:19:47 +00:00
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
bool hasFileDescriptors() const;
|
|
|
|
|
2010-06-18 20:07:53 +00:00
|
|
|
// Writes the RPC header.
|
2009-03-04 03:31:44 +00:00
|
|
|
status_t writeInterfaceToken(const String16& interface);
|
2010-07-07 23:06:39 +00:00
|
|
|
|
2010-06-18 20:07:53 +00:00
|
|
|
// Parses the RPC header, returning true if the interface name
|
|
|
|
// in the header matches the expected interface from the caller.
|
2010-07-27 16:49:11 +00:00
|
|
|
//
|
|
|
|
// Additionally, enforceInterface does part of the work of
|
|
|
|
// propagating the StrictMode policy mask, populating the current
|
|
|
|
// IPCThreadState, which as an optimization may optionally be
|
|
|
|
// passed in.
|
2010-07-07 23:06:39 +00:00
|
|
|
bool enforceInterface(const String16& interface,
|
2010-07-27 16:49:11 +00:00
|
|
|
IPCThreadState* threadState = NULL) const;
|
2010-06-18 20:07:53 +00:00
|
|
|
bool checkInterface(IBinder*) const;
|
2009-05-23 02:00:22 +00:00
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
void freeData();
|
|
|
|
|
2014-01-29 04:12:59 +00:00
|
|
|
private:
|
|
|
|
const binder_size_t* objects() const;
|
|
|
|
|
|
|
|
public:
|
2009-03-04 03:31:44 +00:00
|
|
|
size_t objectsCount() const;
|
|
|
|
|
|
|
|
status_t errorCheck() const;
|
|
|
|
void setError(status_t err);
|
|
|
|
|
|
|
|
status_t write(const void* data, size_t len);
|
|
|
|
void* writeInplace(size_t len);
|
|
|
|
status_t writeUnpadded(const void* data, size_t len);
|
|
|
|
status_t writeInt32(int32_t val);
|
2014-12-01 18:01:10 +00:00
|
|
|
status_t writeUint32(uint32_t val);
|
2009-03-04 03:31:44 +00:00
|
|
|
status_t writeInt64(int64_t val);
|
|
|
|
status_t writeFloat(float val);
|
|
|
|
status_t writeDouble(double val);
|
|
|
|
status_t writeCString(const char* str);
|
|
|
|
status_t writeString8(const String8& str);
|
|
|
|
status_t writeString16(const String16& str);
|
|
|
|
status_t writeString16(const char16_t* str, size_t len);
|
|
|
|
status_t writeStrongBinder(const sp<IBinder>& val);
|
|
|
|
status_t writeWeakBinder(const wp<IBinder>& val);
|
2013-10-16 17:57:51 +00:00
|
|
|
status_t writeInt32Array(size_t len, const int32_t *val);
|
2014-03-13 21:17:40 +00:00
|
|
|
status_t writeByteArray(size_t len, const uint8_t *val);
|
2013-07-30 04:24:40 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
status_t write(const Flattenable<T>& val);
|
2009-03-04 03:31:44 +00:00
|
|
|
|
2012-08-13 02:37:16 +00:00
|
|
|
template<typename T>
|
|
|
|
status_t write(const LightFlattenable<T>& val);
|
|
|
|
|
|
|
|
|
2009-05-21 23:29:38 +00:00
|
|
|
// 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).
|
|
|
|
// Doesn't take ownership of the native_handle.
|
|
|
|
status_t writeNativeHandle(const native_handle* handle);
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
// Place a file descriptor into the parcel. The given fd must remain
|
|
|
|
// valid for the lifetime of the parcel.
|
2011-11-05 02:01:44 +00:00
|
|
|
// The Parcel does not take ownership of the given fd unless you ask it to.
|
|
|
|
status_t writeFileDescriptor(int fd, bool takeOwnership = false);
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
// Place a file descriptor into the parcel. A dup of the fd is made, which
|
|
|
|
// will be closed once the parcel is destroyed.
|
|
|
|
status_t writeDupFileDescriptor(int fd);
|
2011-09-24 04:17:56 +00:00
|
|
|
|
2013-09-05 15:41:06 +00:00
|
|
|
// Writes a raw fd and optional comm channel fd to the parcel as a ParcelFileDescriptor.
|
|
|
|
// A dup's of the fds are made, which will be closed once the parcel is destroyed.
|
|
|
|
// Null values are passed as -1.
|
|
|
|
status_t writeParcelFileDescriptor(int fd, int commChannel = -1);
|
|
|
|
|
2011-09-24 04:17:56 +00:00
|
|
|
// Writes a blob to the parcel.
|
|
|
|
// If the blob is small, then it is stored in-place, otherwise it is
|
|
|
|
// transferred by way of an anonymous shared memory region.
|
|
|
|
// The caller should call release() on the blob after writing its contents.
|
|
|
|
status_t writeBlob(size_t len, WritableBlob* outBlob);
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
status_t writeObject(const flat_binder_object& val, bool nullMetaData);
|
|
|
|
|
Add Parcel::readExceptionCode() and Parcel::writeNoException()
Add native Parcel methods analogous to the Java versions.
Currently, these don't do much, but upcoming StrictMode work changes
the RPC calling conventions in some cases, so it's important that
everybody uses these consistently, rather than having a lot of code
trying to parse RPC responses out of Parcels themselves.
As a summary, the current convention that Java Binder services use is
to prepend the reply Parcel with an int32 signaling the exception
status:
0: no exception
-1: Security exception
-2: Bad Parcelable
-3: ...
-4: ...
-5: ...
... followed by Parceled String if the exception code is non-zero.
With an upcoming change, it'll be the case that a response Parcel can,
non-exceptionally return rich data in the header, and also return data
to the caller. The important thing to note in this new case is that
the first int32 in the reply parcel *will not be zero*, so anybody
manually checking for it with reply.readInt32() will get false
negative failures.
Short summary: If you're calling into a Java service and manually
checking the exception status with reply.readInt32(), change it to
reply.readExceptionCode().
Change-Id: I23f9a0e53a8cfbbd9759242cfde16723641afe04
2010-07-13 22:33:35 +00:00
|
|
|
// Like Parcel.java's writeNoException(). Just writes a zero int32.
|
|
|
|
// Currently the native implementation doesn't do any of the StrictMode
|
|
|
|
// stack gathering and serialization that the Java implementation does.
|
|
|
|
status_t writeNoException();
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
void remove(size_t start, size_t amt);
|
|
|
|
|
|
|
|
status_t read(void* outData, size_t len) const;
|
|
|
|
const void* readInplace(size_t len) const;
|
|
|
|
int32_t readInt32() const;
|
|
|
|
status_t readInt32(int32_t *pArg) const;
|
2014-12-01 18:01:10 +00:00
|
|
|
uint32_t readUint32() const;
|
|
|
|
status_t readUint32(uint32_t *pArg) const;
|
2009-03-04 03:31:44 +00:00
|
|
|
int64_t readInt64() const;
|
|
|
|
status_t readInt64(int64_t *pArg) const;
|
|
|
|
float readFloat() const;
|
|
|
|
status_t readFloat(float *pArg) const;
|
|
|
|
double readDouble() const;
|
|
|
|
status_t readDouble(double *pArg) const;
|
2009-08-17 20:33:27 +00:00
|
|
|
intptr_t readIntPtr() const;
|
|
|
|
status_t readIntPtr(intptr_t *pArg) const;
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
const char* readCString() const;
|
|
|
|
String8 readString8() const;
|
|
|
|
String16 readString16() const;
|
|
|
|
const char16_t* readString16Inplace(size_t* outLen) const;
|
|
|
|
sp<IBinder> readStrongBinder() const;
|
|
|
|
wp<IBinder> readWeakBinder() const;
|
2013-07-30 04:24:40 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
status_t read(Flattenable<T>& val) const;
|
Add Parcel::readExceptionCode() and Parcel::writeNoException()
Add native Parcel methods analogous to the Java versions.
Currently, these don't do much, but upcoming StrictMode work changes
the RPC calling conventions in some cases, so it's important that
everybody uses these consistently, rather than having a lot of code
trying to parse RPC responses out of Parcels themselves.
As a summary, the current convention that Java Binder services use is
to prepend the reply Parcel with an int32 signaling the exception
status:
0: no exception
-1: Security exception
-2: Bad Parcelable
-3: ...
-4: ...
-5: ...
... followed by Parceled String if the exception code is non-zero.
With an upcoming change, it'll be the case that a response Parcel can,
non-exceptionally return rich data in the header, and also return data
to the caller. The important thing to note in this new case is that
the first int32 in the reply parcel *will not be zero*, so anybody
manually checking for it with reply.readInt32() will get false
negative failures.
Short summary: If you're calling into a Java service and manually
checking the exception status with reply.readInt32(), change it to
reply.readExceptionCode().
Change-Id: I23f9a0e53a8cfbbd9759242cfde16723641afe04
2010-07-13 22:33:35 +00:00
|
|
|
|
2012-08-13 02:37:16 +00:00
|
|
|
template<typename T>
|
|
|
|
status_t read(LightFlattenable<T>& val) const;
|
|
|
|
|
Add Parcel::readExceptionCode() and Parcel::writeNoException()
Add native Parcel methods analogous to the Java versions.
Currently, these don't do much, but upcoming StrictMode work changes
the RPC calling conventions in some cases, so it's important that
everybody uses these consistently, rather than having a lot of code
trying to parse RPC responses out of Parcels themselves.
As a summary, the current convention that Java Binder services use is
to prepend the reply Parcel with an int32 signaling the exception
status:
0: no exception
-1: Security exception
-2: Bad Parcelable
-3: ...
-4: ...
-5: ...
... followed by Parceled String if the exception code is non-zero.
With an upcoming change, it'll be the case that a response Parcel can,
non-exceptionally return rich data in the header, and also return data
to the caller. The important thing to note in this new case is that
the first int32 in the reply parcel *will not be zero*, so anybody
manually checking for it with reply.readInt32() will get false
negative failures.
Short summary: If you're calling into a Java service and manually
checking the exception status with reply.readInt32(), change it to
reply.readExceptionCode().
Change-Id: I23f9a0e53a8cfbbd9759242cfde16723641afe04
2010-07-13 22:33:35 +00:00
|
|
|
// Like Parcel.java's readExceptionCode(). Reads the first int32
|
|
|
|
// off of a Parcel's header, returning 0 or the negative error
|
|
|
|
// code on exceptions, but also deals with skipping over rich
|
|
|
|
// response headers. Callers should use this to read & parse the
|
|
|
|
// response headers rather than doing it by hand.
|
|
|
|
int32_t readExceptionCode() const;
|
|
|
|
|
2009-05-21 23:29:38 +00:00
|
|
|
// Retrieve native_handle from the parcel. This returns a copy of the
|
|
|
|
// parcel's native_handle (the caller takes ownership). The caller
|
|
|
|
// must free the native_handle with native_handle_close() and
|
|
|
|
// native_handle_delete().
|
|
|
|
native_handle* readNativeHandle() const;
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Retrieve a file descriptor from the parcel. This returns the raw fd
|
|
|
|
// in the parcel, which you do not own -- use dup() to get your own copy.
|
|
|
|
int readFileDescriptor() const;
|
2011-09-24 04:17:56 +00:00
|
|
|
|
2013-09-05 15:41:06 +00:00
|
|
|
// Reads a ParcelFileDescriptor from the parcel. Returns the raw fd as
|
|
|
|
// the result, and the optional comm channel fd in outCommChannel.
|
|
|
|
// Null values are returned as -1.
|
|
|
|
int readParcelFileDescriptor(int& outCommChannel) const;
|
|
|
|
|
2011-09-24 04:17:56 +00:00
|
|
|
// Reads a blob from the parcel.
|
|
|
|
// The caller should call release() on the blob after reading its contents.
|
|
|
|
status_t readBlob(size_t len, ReadableBlob* outBlob) const;
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
const flat_binder_object* readObject(bool nullMetaData) const;
|
|
|
|
|
|
|
|
// Explicitly close all file descriptors in the parcel.
|
|
|
|
void closeFileDescriptors();
|
2014-11-11 20:22:53 +00:00
|
|
|
|
|
|
|
// Debugging: get metrics on current allocations.
|
|
|
|
static size_t getGlobalAllocSize();
|
|
|
|
static size_t getGlobalAllocCount();
|
|
|
|
|
2014-01-29 04:12:59 +00:00
|
|
|
private:
|
2009-03-04 03:31:44 +00:00
|
|
|
typedef void (*release_func)(Parcel* parcel,
|
|
|
|
const uint8_t* data, size_t dataSize,
|
2014-01-29 04:12:59 +00:00
|
|
|
const binder_size_t* objects, size_t objectsSize,
|
2009-03-04 03:31:44 +00:00
|
|
|
void* cookie);
|
|
|
|
|
2014-01-29 04:12:59 +00:00
|
|
|
uintptr_t ipcData() const;
|
2009-03-04 03:31:44 +00:00
|
|
|
size_t ipcDataSize() const;
|
2014-01-29 04:12:59 +00:00
|
|
|
uintptr_t ipcObjects() const;
|
2009-03-04 03:31:44 +00:00
|
|
|
size_t ipcObjectsCount() const;
|
|
|
|
void ipcSetDataReference(const uint8_t* data, size_t dataSize,
|
2014-01-29 04:12:59 +00:00
|
|
|
const binder_size_t* objects, size_t objectsCount,
|
2009-03-04 03:31:44 +00:00
|
|
|
release_func relFunc, void* relCookie);
|
|
|
|
|
2014-01-29 04:12:59 +00:00
|
|
|
public:
|
2009-03-04 03:31:44 +00:00
|
|
|
void print(TextOutput& to, uint32_t flags = 0) const;
|
2011-09-24 04:17:56 +00:00
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
private:
|
|
|
|
Parcel(const Parcel& o);
|
|
|
|
Parcel& operator=(const Parcel& o);
|
|
|
|
|
|
|
|
status_t finishWrite(size_t len);
|
|
|
|
void releaseObjects();
|
|
|
|
void acquireObjects();
|
|
|
|
status_t growData(size_t len);
|
|
|
|
status_t restartWrite(size_t desired);
|
|
|
|
status_t continueWrite(size_t desired);
|
2013-11-05 16:53:55 +00:00
|
|
|
status_t writePointer(uintptr_t val);
|
|
|
|
status_t readPointer(uintptr_t *pArg) const;
|
|
|
|
uintptr_t readPointer() const;
|
2009-03-04 03:31:44 +00:00
|
|
|
void freeDataNoInit();
|
|
|
|
void initState();
|
|
|
|
void scanForFds() const;
|
|
|
|
|
2009-08-17 20:33:27 +00:00
|
|
|
template<class T>
|
|
|
|
status_t readAligned(T *pArg) const;
|
|
|
|
|
|
|
|
template<class T> T readAligned() const;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
status_t writeAligned(T val);
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
status_t mError;
|
|
|
|
uint8_t* mData;
|
|
|
|
size_t mDataSize;
|
|
|
|
size_t mDataCapacity;
|
|
|
|
mutable size_t mDataPos;
|
2014-01-29 04:12:59 +00:00
|
|
|
binder_size_t* mObjects;
|
2009-03-04 03:31:44 +00:00
|
|
|
size_t mObjectsSize;
|
|
|
|
size_t mObjectsCapacity;
|
|
|
|
mutable size_t mNextObjectHint;
|
|
|
|
|
|
|
|
mutable bool mFdsKnown;
|
|
|
|
mutable bool mHasFds;
|
2011-09-29 03:19:47 +00:00
|
|
|
bool mAllowFds;
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
release_func mOwner;
|
|
|
|
void* mOwnerCookie;
|
2011-09-24 04:17:56 +00:00
|
|
|
|
|
|
|
class Blob {
|
|
|
|
public:
|
|
|
|
Blob();
|
|
|
|
~Blob();
|
|
|
|
|
|
|
|
void release();
|
|
|
|
inline size_t size() const { return mSize; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void init(bool mapped, void* data, size_t size);
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
bool mMapped;
|
|
|
|
void* mData;
|
|
|
|
size_t mSize;
|
|
|
|
};
|
|
|
|
|
2013-07-30 04:24:40 +00:00
|
|
|
class FlattenableHelperInterface {
|
|
|
|
protected:
|
|
|
|
~FlattenableHelperInterface() { }
|
|
|
|
public:
|
|
|
|
virtual size_t getFlattenedSize() const = 0;
|
|
|
|
virtual size_t getFdCount() const = 0;
|
|
|
|
virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const = 0;
|
|
|
|
virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class FlattenableHelper : public FlattenableHelperInterface {
|
|
|
|
friend class Parcel;
|
|
|
|
const Flattenable<T>& val;
|
|
|
|
explicit FlattenableHelper(const Flattenable<T>& val) : val(val) { }
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual size_t getFlattenedSize() const {
|
|
|
|
return val.getFlattenedSize();
|
|
|
|
}
|
|
|
|
virtual size_t getFdCount() const {
|
|
|
|
return val.getFdCount();
|
|
|
|
}
|
|
|
|
virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const {
|
|
|
|
return val.flatten(buffer, size, fds, count);
|
|
|
|
}
|
|
|
|
virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) {
|
|
|
|
return const_cast<Flattenable<T>&>(val).unflatten(buffer, size, fds, count);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
status_t write(const FlattenableHelperInterface& val);
|
|
|
|
status_t read(FlattenableHelperInterface& val) const;
|
|
|
|
|
2011-09-24 04:17:56 +00:00
|
|
|
public:
|
|
|
|
class ReadableBlob : public Blob {
|
|
|
|
friend class Parcel;
|
|
|
|
public:
|
|
|
|
inline const void* data() const { return mData; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class WritableBlob : public Blob {
|
|
|
|
friend class Parcel;
|
|
|
|
public:
|
|
|
|
inline void* data() { return mData; }
|
|
|
|
};
|
2009-03-04 03:31:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2013-07-30 04:24:40 +00:00
|
|
|
template<typename T>
|
|
|
|
status_t Parcel::write(const Flattenable<T>& val) {
|
|
|
|
const FlattenableHelper<T> helper(val);
|
|
|
|
return write(helper);
|
|
|
|
}
|
|
|
|
|
2012-08-13 02:37:16 +00:00
|
|
|
template<typename T>
|
|
|
|
status_t Parcel::write(const LightFlattenable<T>& val) {
|
2013-07-30 04:24:40 +00:00
|
|
|
size_t size(val.getFlattenedSize());
|
2012-08-13 02:37:16 +00:00
|
|
|
if (!val.isFixedSize()) {
|
|
|
|
status_t err = writeInt32(size);
|
|
|
|
if (err != NO_ERROR) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
2012-08-31 21:25:22 +00:00
|
|
|
if (size) {
|
|
|
|
void* buffer = writeInplace(size);
|
2013-07-30 04:24:40 +00:00
|
|
|
if (buffer == NULL)
|
|
|
|
return NO_MEMORY;
|
|
|
|
return val.flatten(buffer, size);
|
2012-08-31 21:25:22 +00:00
|
|
|
}
|
|
|
|
return NO_ERROR;
|
2012-08-13 02:37:16 +00:00
|
|
|
}
|
|
|
|
|
2013-07-30 04:24:40 +00:00
|
|
|
template<typename T>
|
|
|
|
status_t Parcel::read(Flattenable<T>& val) const {
|
|
|
|
FlattenableHelper<T> helper(val);
|
|
|
|
return read(helper);
|
|
|
|
}
|
|
|
|
|
2012-08-13 02:37:16 +00:00
|
|
|
template<typename T>
|
|
|
|
status_t Parcel::read(LightFlattenable<T>& val) const {
|
|
|
|
size_t size;
|
|
|
|
if (val.isFixedSize()) {
|
2013-07-30 04:24:40 +00:00
|
|
|
size = val.getFlattenedSize();
|
2012-08-13 02:37:16 +00:00
|
|
|
} else {
|
|
|
|
int32_t s;
|
|
|
|
status_t err = readInt32(&s);
|
|
|
|
if (err != NO_ERROR) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
size = s;
|
|
|
|
}
|
2012-08-31 21:25:22 +00:00
|
|
|
if (size) {
|
|
|
|
void const* buffer = readInplace(size);
|
|
|
|
return buffer == NULL ? NO_MEMORY :
|
|
|
|
val.unflatten(buffer, size);
|
|
|
|
}
|
|
|
|
return NO_ERROR;
|
2012-08-13 02:37:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
|
|
|
|
{
|
|
|
|
parcel.print(to);
|
|
|
|
return to;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Generic acquire and release of objects.
|
|
|
|
void acquire_object(const sp<ProcessState>& proc,
|
|
|
|
const flat_binder_object& obj, const void* who);
|
|
|
|
void release_object(const sp<ProcessState>& proc,
|
|
|
|
const flat_binder_object& obj, const void* who);
|
|
|
|
|
|
|
|
void flatten_binder(const sp<ProcessState>& proc,
|
|
|
|
const sp<IBinder>& binder, flat_binder_object* out);
|
|
|
|
void flatten_binder(const sp<ProcessState>& proc,
|
|
|
|
const wp<IBinder>& binder, flat_binder_object* out);
|
|
|
|
status_t unflatten_binder(const sp<ProcessState>& proc,
|
|
|
|
const flat_binder_object& flat, sp<IBinder>* out);
|
|
|
|
status_t unflatten_binder(const sp<ProcessState>& proc,
|
|
|
|
const flat_binder_object& flat, wp<IBinder>* out);
|
|
|
|
|
|
|
|
}; // namespace android
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#endif // ANDROID_PARCEL_H
|