-
if (binder != NULL) {
-
IBinder *local = binder->localBinder();
-
if (!local) {
-
BpBinder *proxy = binder->remoteBinder();
-
if (proxy == NULL) {
-
LOGE(“null proxy”);
-
}
-
const int32_t handle = proxy ? proxy->handle() : 0;
-
obj.type = BINDER_TYPE_HANDLE;
-
obj.handle = handle;
-
obj.cookie = NULL;
-
} else {
-
obj.type = BINDER_TYPE_BINDER;
-
obj.binder = local->getWeakRefs();
-
obj.cookie = local;
-
}
-
} else {
-
obj.type = BINDER_TYPE_BINDER;
-
obj.binder = NULL;
-
obj.cookie = NULL;
-
}
-
return finish_flatten_binder(binder, obj, out);
-
}
-
status_t flatten_binder(const sp& proc,
-
const wp& binder, Parcel* out)
-
{
-
flat_binder_object obj;
-
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-
if (binder != NULL) {
-
sp real = binder.promote();
-
if (real != NULL) {
-
IBinder *local = real->localBinder();
-
if (!local) {
-
BpBinder *proxy = real->remoteBinder();
-
if (proxy == NULL) {
-
LOGE(“null proxy”);
-
}
-
const int32_t handle = proxy ? proxy->handle() : 0;
-
obj.type = BINDER_TYPE_WEAK_HANDLE;
-
obj.handle = handle;
-
obj.cookie = NULL;
-
} else {
-
obj.type = BINDER_TYPE_WEAK_BINDER;
-
obj.binder = binder.get_refs();
-
obj.cookie = binder.unsafe_get();
-
}
-
return finish_flatten_binder(real, obj, out);
-
}
-
// XXX How to deal? In order to flatten the given binder,
-
// we need to probe it for information, which requires a primary
-
// reference… but we don’t have one.
-
//
-
// The OpenBinder implementation uses a dynamic_cast<> here,
-
// but we can’t do that with the different reference counting
-
// implementation we are using.
-
LOGE(“Unable to unflatten Binder weak reference!”);
-
obj.type = BINDER_TYPE_BINDER;
-
obj.binder = NULL;
-
obj.cookie = NULL;
-
return finish_flatten_binder(NULL, obj, out);
-
} else {
-
obj.type = BINDER_TYPE_BINDER;
-
obj.binder = NULL;
-
obj.cookie = NULL;
-
return finish_flatten_binder(NULL, obj, out);
-
}
-
}
-
inline static status_t finish_unflatten_binder(
-
BpBinder* proxy, const flat_binder_object& flat, const Parcel& in)
-
{
-
return NO_ERROR;
-
}
-
status_t unflatten_binder(const sp& proc,
-
const Parcel& in, sp* out)
-
{
-
const flat_binder_object* flat = in.readObject(false);
-
if (flat) {
-
switch (flat->type) {
-
case BINDER_TYPE_BINDER:
-
*out = static_cast<IBinder*>(flat->cookie);
-
return finish_unflatten_binder(NULL, *flat, in);
-
case BINDER_TYPE_HANDLE:
-
*out = proc->getStrongProxyForHandle(flat->handle);
-
return finish_unflatten_binder(
-
static_cast<BpBinder*>(out->get()), *flat, in);
-
}
-
}
-
return BAD_TYPE;
-
}
-
status_t unflatten_binder(const sp& proc,
-
const Parcel& in, wp* out)
-
{
-
const flat_binder_object* flat = in.readObject(false);
-
if (flat) {
-
switch (flat->type) {
-
case BINDER_TYPE_BINDER:
-
*out = static_cast<IBinder*>(flat->cookie);
-
return finish_unflatten_binder(NULL, *flat, in);
-
case BINDER_TYPE_WEAK_BINDER:
-
if (flat->binder != NULL) {
-
out->set_object_and_refs(
-
static_cast<IBinder*>(flat->cookie),
-
static_castRefBase::weakref\_type\*(flat->binder));
-
} else {
-
*out = NULL;
-
}
-
return finish_unflatten_binder(NULL, *flat, in);
-
case BINDER_TYPE_HANDLE:
-
case BINDER_TYPE_WEAK_HANDLE:
-
*out = proc->getWeakProxyForHandle(flat->handle);
-
return finish_unflatten_binder(
-
static_cast<BpBinder*>(out->unsafe_get()), *flat, in);
-
}
-
}
-
return BAD_TYPE;
-
}
-
// ---------------------------------------------------------------------------
-
Parcel::Parcel()
-
{
-
initState();
-
}
-
Parcel::~Parcel()
-
{
-
freeDataNoInit();
-
}
-
const uint8_t* Parcel::data() const
-
{
-
return mData;
-
}
-
size_t Parcel::dataSize() const
-
{
-
return (mDataSize > mDataPos ? mDataSize : mDataPos);
-
}
-
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 Parcel::dataPosition() const
-
{
-
return mDataPos;
-
}
-
size_t Parcel::dataCapacity() const
-
{
-
return mDataCapacity;
-
}
-
status_t Parcel::setDataSize(size_t size)
-
{
-
status_t err;
-
err = continueWrite(size);
-
if (err == NO_ERROR) {
-
mDataSize = size;
-
LOGV(“setDataSize Setting data size of %p to %d/n”, this, mDataSize);
-
}
-
return err;
-
}
-
void Parcel::setDataPosition(size_t pos) const
-
{
-
mDataPos = pos;
-
mNextObjectHint = 0;
-
}
-
status_t Parcel::setDataCapacity(size_t size)
-
{
-
if (size > mDataSize) return continueWrite(size);
-
return NO_ERROR;
-
}
-
status_t Parcel::setData(const uint8_t* buffer, size_t len)
-
{
-
status_t err = restartWrite(len);
-
if (err == NO_ERROR) {
-
memcpy(const_cast<uint8_t*>(data()), buffer, len);
-
mDataSize = len;
-
mFdsKnown = false;
-
}
-
return err;
-
}
-
status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len)
-
{
-
const sp proc(ProcessState::self());
-
status_t err;
-
uint8_t *data = parcel->mData;
-
size_t *objects = parcel->mObjects;
-
size_t size = parcel->mObjectsSize;
-
int startPos = mDataPos;
-
int firstIndex = -1, lastIndex = -2;
-
if (len == 0) {
-
return NO_ERROR;
-
}
-
// range checks against the source parcel size
-
if ((offset > parcel->mDataSize)
-
|| (len > parcel->mDataSize)
-
|| (offset + len > parcel->mDataSize)) {
-
return BAD_VALUE;
-
}
-
// Count objects in range
-
for (int i = 0; i < (int) size; i++) {
-
size_t off = objects[i];
-
if ((off >= offset) && (off < offset + len)) {
-
if (firstIndex == -1) {
-
firstIndex = i;
-
}
-
lastIndex = i;
-
}
-
}
-
int numObjects = lastIndex - firstIndex + 1;
-
// grow data
-
err = growData(len);
-
if (err != NO_ERROR) {
-
return err;
-
}
-
// append data
-
memcpy(mData + mDataPos, data + offset, len);
-
mDataPos += len;
-
mDataSize += len;
-
if (numObjects > 0) {
-
// grow objects
-
if (mObjectsCapacity < mObjectsSize + numObjects) {
-
int newSize = ((mObjectsSize + numObjects)*3)/2;
-
size_t *objects =
-
(size_t*)realloc(mObjects, newSize*sizeof(size_t));
-
if (objects == (size_t*)0) {
-
return NO_MEMORY;
-
}
-
mObjects = objects;
-
mObjectsCapacity = newSize;
-
}
-
// append and acquire objects
-
int idx = mObjectsSize;
-
for (int i = firstIndex; i <= lastIndex; i++) {
-
size_t off = objects[i] - offset + startPos;
-
mObjects[idx++] = off;
-
mObjectsSize++;
-
flat_binder_object* flat
-
= reinterpret_cast<flat_binder_object*>(mData + off);
-
acquire_object(proc, *flat, this);
-
if (flat->type == BINDER_TYPE_FD) {
-
// If this is a file descriptor, we need to dup it so the
-
// new Parcel now owns its own fd, and can declare that we
-
// officially know we have fds.
-
flat->handle = dup(flat->handle);
-
flat->cookie = (void*)1;
-
mHasFds = mFdsKnown = true;
-
}
-
}
-
}
-
return NO_ERROR;
-
}
-
bool Parcel::hasFileDescriptors() const
-
{
-
if (!mFdsKnown) {
-
scanForFds();
-
}
-
return mHasFds;
-
}
-
status_t Parcel::writeInterfaceToken(const String16& interface)
-
{
-
// currently the interface identification token is just its name as a string
-
return writeString16(interface);
-
}
-
bool Parcel::checkInterface(IBinder* binder) const
-
{
-
return enforceInterface(binder->getInterfaceDescriptor());
-
}
-
bool Parcel::enforceInterface(const String16& interface) const
-
{
-
const String16 str(readString16());
-
if (str == interface) {
-
return true;
-
} else {
-
LOGW(“**** enforceInterface() expected ‘%s’ but read ‘%s’/n”,
-
String8(interface).string(), String8(str).string());
-
return false;
-
}
-
}
-
const size_t* Parcel::objects() const
-
{
-
return mObjects;
-
}
-
size_t Parcel::objectsCount() const
-
{
-
return mObjectsSize;
-
}
-
status_t Parcel::errorCheck() const
-
{
-
return mError;
-
}
-
void Parcel::setError(status_t err)
-
{
-
mError = err;
-
}
-
status_t Parcel::finishWrite(size_t len)
-
{
-
//printf(“Finish write of %d/n”, len);
-
mDataPos += len;
-
LOGV(“finishWrite Setting data pos of %p to %d/n”, this, mDataPos);
-
if (mDataPos > mDataSize) {
-
mDataSize = mDataPos;
-
LOGV(“finishWrite Setting data size of %p to %d/n”, this, mDataSize);
-
}
-
//printf(“New pos=%d, size=%d/n”, mDataPos, mDataSize);
-
return NO_ERROR;
-
}
-
status_t Parcel::writeUnpadded(const void* data, size_t len)
-
{
-
size_t end = mDataPos + len;
-
if (end < mDataPos) {
-
// integer overflow
-
return BAD_VALUE;
-
}
-
if (end <= mDataCapacity) {
-
restart_write:
-
memcpy(mData+mDataPos, data, len);
-
return finishWrite(len);
-
}
-
status_t err = growData(len);
-
if (err == NO_ERROR) goto restart_write;
-
return err;
-
}
-
status_t Parcel::write(const void* data, size_t len)
-
{
-
void* const d = writeInplace(len);
-
if (d) {
-
memcpy(d, data, len);
-
return NO_ERROR;
-
}
-
return mError;
-
}
-
void* Parcel::writeInplace(size_t len)
-
{
-
const size_t padded = PAD_SIZE(len);
-
// sanity check for integer overflow
-
if (mDataPos+padded < mDataPos) {
-
return NULL;
-
}
-
if ((mDataPos+padded) <= mDataCapacity) {
-
restart_write:
-
//printf(“Writing %ld bytes, padded to %ld/n”, len, padded);
-
uint8_t* const data = mData+mDataPos;
-
// Need to pad at end?
-
if (padded != len) {
-
#if BYTE_ORDER == BIG_ENDIAN
-
static const uint32_t mask[4] = {
-
0x00000000, 0xffffff00, 0xffff0000, 0xff000000
-
};
-
#endif
-
#if BYTE_ORDER == LITTLE_ENDIAN
-
static const uint32_t mask[4] = {
-
0x00000000, 0x00ffffff, 0x0000ffff, 0x000000ff
-
};
-
#endif
-
//printf(“Applying pad mask: %p to %p/n”, (void*)mask[padded-len],
-
// *reinterpret_cast<void**>(data+padded-4));
-
*reinterpret_cast<uint32_t*>(data+padded-4) &= mask[padded-len];
-
}
-
finishWrite(padded);
-
return data;
-
}
-
status_t err = growData(padded);
-
if (err == NO_ERROR) goto restart_write;
-
return NULL;
-
}
-
status_t Parcel::writeInt32(int32_t val)
-
{
-
return writeAligned(val);
-
}
-
status_t Parcel::writeInt64(int64_t val)
-
{
-
return writeAligned(val);
-
}
-
status_t Parcel::writeFloat(float val)
-
{
-
return writeAligned(val);
-
}
-
status_t Parcel::writeDouble(double val)
-
{
-
return writeAligned(val);
-
}
-
status_t Parcel::writeIntPtr(intptr_t val)
-
{
-
return writeAligned(val);
-
}
-
status_t Parcel::writeCString(const char* str)
-
{
-
return write(str, strlen(str)+1);
-
}
-
status_t Parcel::writeString8(const String8& str)
-
{
-
status_t err = writeInt32(str.bytes());
-
if (err == NO_ERROR) {
-
err = write(str.string(), str.bytes()+1);
-
}
-
return err;
-
}
-
status_t Parcel::writeString16(const String16& str)
-
{
-
return writeString16(str.string(), str.size());
-
}
-
status_t Parcel::writeString16(const char16_t* str, size_t len)
-
{
-
if (str == NULL) return writeInt32(-1);
-
status_t err = writeInt32(len);
-
if (err == NO_ERROR) {
-
len *= sizeof(char16_t);
-
uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t));
-
if (data) {
-
memcpy(data, str, len);
-
*reinterpret_cast<char16_t*>(data+len) = 0;
-
return NO_ERROR;
-
}
-
err = mError;
-
}
-
return err;
-
}
-
status_t Parcel::writeStrongBinder(const sp& val)
-
{
-
return flatten_binder(ProcessState::self(), val, this);
-
}
-
status_t Parcel::writeWeakBinder(const wp& val)
-
{
-
return flatten_binder(ProcessState::self(), val, this);
-
}
-
status_t Parcel::writeNativeHandle(const native_handle* handle)
-
{
-
if (!handle || handle->version != sizeof(native_handle))
-
return BAD_TYPE;
-
status_t err;
-
err = writeInt32(handle->numFds);
-
if (err != NO_ERROR) return err;
-
err = writeInt32(handle->numInts);
-
if (err != NO_ERROR) return err;
-
for (int i=0 ; err==NO_ERROR && inumFds ; i++)
-
err = writeDupFileDescriptor(handle->data[i]);
-
if (err != NO_ERROR) {
-
LOGD(“write native handle, write dup fd failed”);
-
return err;
-
}
-
err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts);
-
return err;
-
}
-
status_t Parcel::writeFileDescriptor(int fd)
-
{
-
flat_binder_object obj;
-
obj.type = BINDER_TYPE_FD;
-
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-
obj.handle = fd;
-
obj.cookie = (void*)0;
-
return writeObject(obj, true);
-
}
-
status_t Parcel::writeDupFileDescriptor(int fd)
-
{
-
flat_binder_object obj;
-
obj.type = BINDER_TYPE_FD;
-
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-
obj.handle = dup(fd);
-
obj.cookie = (void*)1;
-
return writeObject(obj, true);
-
}
-
status_t Parcel::write(const Flattenable& val)
-
{
-
status_t err;
-
// size if needed
-
size_t len = val.getFlattenedSize();
-
size_t fd_count = val.getFdCount();
-
err = this->writeInt32(len);
-
if (err) return err;
-
err = this->writeInt32(fd_count);
-
if (err) return err;
-
// payload
-
void* buf = this->writeInplace(PAD_SIZE(len));
-
if (buf == NULL)
-
return BAD_VALUE;
-
int* fds = NULL;
-
if (fd_count) {
-
fds = new int[fd_count];
-
}
-
err = val.flatten(buf, len, fds, fd_count);
-
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
-
err = this->writeDupFileDescriptor( fds[i] );
-
}
-
if (fd_count) {
-
delete [] fds;
-
}
-
return err;
-
}
-
status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
-
{
-
const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;
-
const bool enoughObjects = mObjectsSize < mObjectsCapacity;
-
if (enoughData && enoughObjects) {
-
restart_write:
-
*reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
-
// Need to write meta-data?
-
if (nullMetaData || val.binder != NULL) {
-
mObjects[mObjectsSize] = mDataPos;
-
acquire_object(ProcessState::self(), val, this);
-
mObjectsSize++;
-
}
-
// remember if it’s a file descriptor
-
if (val.type == BINDER_TYPE_FD) {
-
mHasFds = mFdsKnown = true;
-
}
-
return finishWrite(sizeof(flat_binder_object));
-
}
-
if (!enoughData) {
-
const status_t err = growData(sizeof(val));
-
if (err != NO_ERROR) return err;
-
}
-
if (!enoughObjects) {
-
size_t newSize = ((mObjectsSize+2)*3)/2;
-
size_t* objects = (size_t*)realloc(mObjects, newSize*sizeof(size_t));
-
if (objects == NULL) return NO_MEMORY;
-
mObjects = objects;
-
mObjectsCapacity = newSize;
-
}
-
goto restart_write;
-
}
-
void Parcel::remove(size_t start, size_t amt)
-
{
-
LOG_ALWAYS_FATAL(“Parcel::remove() not yet implemented!”);
-
}
-
status_t Parcel::read(void* outData, size_t len) const
-
{
-
if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) {
-
memcpy(outData, mData+mDataPos, len);
-
mDataPos += PAD_SIZE(len);
-
LOGV(“read Setting data pos of %p to %d/n”, this, mDataPos);
-
return NO_ERROR;
-
}
-
return NOT_ENOUGH_DATA;
-
}
-
const void* Parcel::readInplace(size_t len) const
-
{
-
if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) {
-
const void* data = mData+mDataPos;
-
mDataPos += PAD_SIZE(len);
-
LOGV(“readInplace Setting data pos of %p to %d/n”, this, mDataPos);
-
return data;
-
}
-
return NULL;
-
}
-
template
-
status_t Parcel::readAligned(T *pArg) const {
-
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
-
if ((mDataPos+sizeof(T)) <= mDataSize) {
-
const void* data = mData+mDataPos;
-
mDataPos += sizeof(T);
-
*pArg = *reinterpret_cast<const T*>(data);
-
return NO_ERROR;
-
} else {
-
return NOT_ENOUGH_DATA;
-
}
-
}
-
template
-
T Parcel::readAligned() const {
-
T result;
-
if (readAligned(&result) != NO_ERROR) {
-
result = 0;
-
}
-
return result;
-
}
-
template
-
status_t Parcel::writeAligned(T val) {
-
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
-
if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-
restart_write:
-
*reinterpret_cast<T*>(mData+mDataPos) = val;
-
return finishWrite(sizeof(val));
-
}
-
status_t err = growData(sizeof(val));
-
if (err == NO_ERROR) goto restart_write;
-
return err;
-
}
-
status_t Parcel::readInt32(int32_t *pArg) const
-
{
-
return readAligned(pArg);
-
}
-
int32_t Parcel::readInt32() const
-
{
-
return readAligned<int32_t>();
-
}
-
status_t Parcel::readInt64(int64_t *pArg) const
-
{
-
return readAligned(pArg);
-
}
-
int64_t Parcel::readInt64() const
-
{
-
return readAligned<int64_t>();
-
}
-
status_t Parcel::readFloat(float *pArg) const
-
{
-
return readAligned(pArg);
-
}
-
float Parcel::readFloat() const
-
{
-
return readAligned<float>();
-
}
-
status_t Parcel::readDouble(double *pArg) const
-
{
-
return readAligned(pArg);
-
}
-
double Parcel::readDouble() const
-
{
-
return readAligned<double>();
-
}
-
status_t Parcel::readIntPtr(intptr_t *pArg) const
-
{
-
return readAligned(pArg);
-
}
-
intptr_t Parcel::readIntPtr() const
-
{
-
return readAligned<intptr_t>();
-
}
-
const char* Parcel::readCString() const
-
{
-
const size_t avail = mDataSize-mDataPos;
-
if (avail > 0) {
-
const char* str = reinterpret_cast<const char*>(mData+mDataPos);
-
// is the string’s trailing NUL within the parcel’s valid bounds?
-
const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
-
if (eos) {
-
const size_t len = eos - str;
-
mDataPos += PAD_SIZE(len+1);
-
LOGV(“readCString Setting data pos of %p to %d/n”, this, mDataPos);
-
return str;
-
}
-
}
-
return NULL;
-
}
-
String8 Parcel::readString8() const
-
{
-
int32_t size = readInt32();
-
// watch for potential int overflow adding 1 for trailing NUL
-
if (size > 0 && size < INT32_MAX) {
-
const char* str = (const char*)readInplace(size+1);
-
if (str) return String8(str, size);
-
}
-
return String8();
-
}
-
String16 Parcel::readString16() const
-
{
-
size_t len;
-
const char16_t* str = readString16Inplace(&len);
-
if (str) return String16(str, len);
-
LOGE(“Reading a NULL string not supported here.”);
-
return String16();
-
}
-
const char16_t* Parcel::readString16Inplace(size_t* outLen) const
-
{
-
int32_t size = readInt32();
-
// watch for potential int overflow from size+1
-
if (size >= 0 && size < INT32_MAX) {
-
*outLen = size;
-
const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
-
if (str != NULL) {
-
return str;
-
}
-
}
-
*outLen = 0;
-
return NULL;
-
}
-
sp Parcel::readStrongBinder() const
-
{
-
sp val;
-
unflatten_binder(ProcessState::self(), *this, &val);
-
return val;
-
}
-
wp Parcel::readWeakBinder() const
-
{
-
wp val;
-
unflatten_binder(ProcessState::self(), *this, &val);
-
return val;
-
}
-
native_handle* Parcel::readNativeHandle() const
-
{
-
int numFds, numInts;
-
status_t err;
-
err = readInt32(&numFds);
-
if (err != NO_ERROR) return 0;
-
err = readInt32(&numInts);
-
if (err != NO_ERROR) return 0;
-
native_handle* h = native_handle_create(numFds, numInts);
-
for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
-
h->data[i] = dup(readFileDescriptor());
-
if (h->data[i] < 0) err = BAD_VALUE;
-
}
-
err = read(h->data + numFds, sizeof(int)*numInts);
-
if (err != NO_ERROR) {
-
native_handle_close(h);
-
native_handle_delete(h);
-
h = 0;
-
}
-
return h;
-
}
-
int Parcel::readFileDescriptor() const
-
{
-
const flat_binder_object* flat = readObject(true);
-
if (flat) {
-
switch (flat->type) {
-
case BINDER_TYPE_FD:
-
//LOGI(“Returning file descriptor %ld from parcel %p/n”, flat->handle, this);
-
return flat->handle;
-
}
-
}
-
return BAD_TYPE;
-
}
-
status_t Parcel::read(Flattenable& val) const
-
{
-
// size
-
const size_t len = this->readInt32();
-
const size_t fd_count = this->readInt32();
-
// payload
-
void const* buf = this->readInplace(PAD_SIZE(len));
-
if (buf == NULL)
-
return BAD_VALUE;
-
int* fds = NULL;
-
if (fd_count) {
-
fds = new int[fd_count];
-
}
-
status_t err = NO_ERROR;
-
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
-
fds[i] = dup(this->readFileDescriptor());
-
if (fds[i] < 0) err = BAD_VALUE;
-
}
-
if (err == NO_ERROR) {
-
err = val.unflatten(buf, len, fds, fd_count);
-
}
-
if (fd_count) {
-
delete [] fds;
-
}
-
return err;
-
}
-
const flat_binder_object* Parcel::readObject(bool nullMetaData) const
-
{
-
const size_t DPOS = mDataPos;
-
if ((DPOS+sizeof(flat_binder_object)) <= mDataSize) {
-
const flat_binder_object* obj
-
= reinterpret_cast<const flat_binder_object*>(mData+DPOS);
-
mDataPos = DPOS + sizeof(flat_binder_object);
-
if (!nullMetaData && (obj->cookie == NULL && obj->binder == NULL)) {
-
// When transferring a NULL object, we don’t write it into
-
// the object list, so we don’t want to check for it when
-
// reading.
-
LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);
-
return obj;
-
}
-
// Ensure that this object is valid…
-
size_t* const OBJS = mObjects;
-
const size_t N = mObjectsSize;
-
size_t opos = mNextObjectHint;
-
if (N > 0) {
-
LOGV(“Parcel %p looking for obj at %d, hint=%d/n”,
-
this, DPOS, opos);
-
// Start at the current hint position, looking for an object at
-
// the current data position.
-
if (opos < N) {
-
while (opos < (N-1) && OBJS[opos] < DPOS) {
-
opos++;
-
}
-
} else {
-
opos = N-1;
-
}
-
if (OBJS[opos] == DPOS) {
-
// Found it!
-
LOGV(“Parcel found obj %d at index %d with forward search”,
-
this, DPOS, opos);
-
mNextObjectHint = opos+1;
-
LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);
-
return obj;
-
}
-
// Look backwards for it…
-
while (opos > 0 && OBJS[opos] > DPOS) {
-
opos–;
-
}
-
if (OBJS[opos] == DPOS) {
-
// Found it!
-
LOGV(“Parcel found obj %d at index %d with backward search”,
-
this, DPOS, opos);
-
mNextObjectHint = opos+1;
-
LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);
-
return obj;
-
}
-
}
-
LOGW(“Attempt to read object from Parcel %p at offset %d that is not in the object list”,
-
this, DPOS);
-
}
-
return NULL;
-
}
-
void Parcel::closeFileDescriptors()
-
{
-
size_t i = mObjectsSize;
-
if (i > 0) {
-
//LOGI(“Closing file descriptors for %d objects…”, mObjectsSize);
-
}
-
while (i > 0) {
-
i–;
-
const flat_binder_object* flat
-
= reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);
-
if (flat->type == BINDER_TYPE_FD) {
-
//LOGI(“Closing fd: %ld/n”, flat->handle);
-
close(flat->handle);
-
}
-
}
-
}
-
const uint8_t* Parcel::ipcData() const
-
{
-
return mData;
-
}
-
size_t Parcel::ipcDataSize() const
-
{
-
return (mDataSize > mDataPos ? mDataSize : mDataPos);
-
}
-
const size_t* Parcel::ipcObjects() const
-
{
-
return mObjects;
-
}
-
size_t Parcel::ipcObjectsCount() const
-
{
-
return mObjectsSize;
-
}
-
void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,
-
const size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie)
-
{
-
freeDataNoInit();
-
mError = NO_ERROR;
-
mData = const_cast<uint8_t*>(data);
-
mDataSize = mDataCapacity = dataSize;
-
//LOGI(“setDataReference Setting data size of %p to %lu (pid=%d)/n”, this, mDataSize, getpid());
-
mDataPos = 0;
-
LOGV(“setDataReference Setting data pos of %p to %d/n”, this, mDataPos);
-
mObjects = const_cast<size_t*>(objects);
-
mObjectsSize = mObjectsCapacity = objectsCount;
-
mNextObjectHint = 0;
-
mOwner = relFunc;
-
mOwnerCookie = relCookie;
-
scanForFds();
-
}
-
void Parcel::print(TextOutput& to, uint32_t flags) const
-
{
-
to << “Parcel(”;
-
if (errorCheck() != NO_ERROR) {
-
const status_t err = errorCheck();
-
to << “Error: " << (void*)err << " /”" << strerror(-err) << “/”";
-
} else if (dataSize() > 0) {
-
const uint8_t* DATA = data();
-
to << indent << HexDump(DATA, dataSize()) << dedent;
-
const size_t* OBJS = objects();
-
const size_t N = objectsCount();
-
for (size_t i=0; i<N; i++) {
-
const flat_binder_object* flat
-
= reinterpret_cast<const flat_binder_object*>(DATA+OBJS[i]);
-
to << endl << “Object #” << i << " @ " << (void*)OBJS[i] << ": "
-
<< TypeCode(flat->type & 0x7f7f7f00)
-
<< " = " << flat->binder;
-
}
-
} else {
-
to << “NULL”;
-
}
-
to << “)”;
-
}
-
void Parcel::releaseObjects()
-
{
-
const sp proc(ProcessState::self());
-
size_t i = mObjectsSize;
-
uint8_t* const data = mData;
-
size_t* const objects = mObjects;
-
while (i > 0) {
-
i–;
-
const flat_binder_object* flat
-
= reinterpret_cast<flat_binder_object*>(data+objects[i]);
-
release_object(proc, *flat, this);
-
}
-
}
-
void Parcel::acquireObjects()
-
{
-
const sp proc(ProcessState::self());
-
size_t i = mObjectsSize;
-
uint8_t* const data = mData;
-
size_t* const objects = mObjects;
-
while (i > 0) {
-
i–;
-
const flat_binder_object* flat
-
= reinterpret_cast<flat_binder_object*>(data+objects[i]);
-
acquire_object(proc, *flat, this);
-
}
-
}
-
void Parcel::freeData()
-
{
-
freeDataNoInit();
-
initState();
-
}
-
void Parcel::freeDataNoInit()
-
{
-
if (mOwner) {
-
//LOGI(“Freeing data ref of %p (pid=%d)/n”, this, getpid());
-
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
-
} else {
-
releaseObjects();
-
if (mData) free(mData);
-
if (mObjects) free(mObjects);
-
}
-
}
-
status_t Parcel::growData(size_t len)
-
{
-
size_t newSize = ((mDataSize+len)*3)/2;
-
return (newSize <= mDataSize)
-
? (status_t) NO_MEMORY
-
: continueWrite(newSize);
-
}
-
status_t Parcel::restartWrite(size_t desired)
-
{
-
if (mOwner) {
-
freeData();
-
return continueWrite(desired);
-
}
-
uint8_t* data = (uint8_t*)realloc(mData, desired);
-
if (!data && desired > mDataCapacity) {
-
mError = NO_MEMORY;
-
return NO_MEMORY;
-
}
-
releaseObjects();
-
if (data) {
-
mData = data;
-
mDataCapacity = desired;
-
}
-
mDataSize = mDataPos = 0;
-
LOGV(“restartWrite Setting data size of %p to %d/n”, this, mDataSize);
-
LOGV(“restartWrite Setting data pos of %p to %d/n”, this, mDataPos);
-
free(mObjects);
-
mObjects = NULL;
-
mObjectsSize = mObjectsCapacity = 0;
-
mNextObjectHint = 0;
-
mHasFds = false;
-
mFdsKnown = true;
-
return NO_ERROR;
-
}
-
status_t Parcel::continueWrite(size_t desired)
-
{
-
// If shrinking, first adjust for any objects that appear
-
// after the new data size.
-
size_t objectsSize = mObjectsSize;
-
if (desired < mDataSize) {
-
if (desired == 0) {
-
objectsSize = 0;
-
} else {
-
while (objectsSize > 0) {
-
if (mObjects[objectsSize-1] < desired)
-
break;
-
objectsSize–;
-
}
-
}
-
}
-
if (mOwner) {
-
// If the size is going to zero, just release the owner’s data.
-
if (desired == 0) {
-
freeData();
-
return NO_ERROR;
-
}
-
// If there is a different owner, we need to take
-
// posession.
-
uint8_t* data = (uint8_t*)malloc(desired);
-
if (!data) {
-
mError = NO_MEMORY;
-
return NO_MEMORY;
-
}
-
size_t* objects = NULL;
-
if (objectsSize) {
-
objects = (size_t*)malloc(objectsSize*sizeof(size_t));
-
if (!objects) {
-
mError = NO_MEMORY;
-
return NO_MEMORY;
-
}
-
// Little hack to only acquire references on objects
-
// we will be keeping.
-
size_t oldObjectsSize = mObjectsSize;
-
mObjectsSize = objectsSize;
-
acquireObjects();
-
mObjectsSize = oldObjectsSize;
-
}
-
if (mData) {
-
memcpy(data, mData, mDataSize < desired ? mDataSize : desired);
-
}
-
if (objects && mObjects) {
-
memcpy(objects, mObjects, objectsSize*sizeof(size_t));
-
}
-
//LOGI(“Freeing data ref of %p (pid=%d)/n”, this, getpid());
-
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
-
mOwner = NULL;
-
mData = data;
-
mObjects = objects;
-
mDataSize = (mDataSize < desired) ? mDataSize : desired;
-
LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);
-
mDataCapacity = desired;
-
mObjectsSize = mObjectsCapacity = objectsSize;
-
mNextObjectHint = 0;
-
} else if (mData) {
-
if (objectsSize < mObjectsSize) {
-
// Need to release refs on any objects we are dropping.
-
const sp proc(ProcessState::self());
-
for (size_t i=objectsSize; i<mObjectsSize; i++) {
-
const flat_binder_object* flat
-
= reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);
-
if (flat->type == BINDER_TYPE_FD) {
-
// will need to rescan because we may have lopped off the only FDs
-
mFdsKnown = false;
-
}
-
release_object(proc, *flat, this);
-
}
-
size_t* objects =
-
(size_t*)realloc(mObjects, objectsSize*sizeof(size_t));
-
if (objects) {
-
mObjects = objects;
-
}
-
mObjectsSize = objectsSize;
-
mNextObjectHint = 0;
-
}
-
// We own the data, so we can just do a realloc().
-
if (desired > mDataCapacity) {
-
uint8_t* data = (uint8_t*)realloc(mData, desired);
-
if (data) {
-
mData = data;
-
mDataCapacity = desired;
-
} else if (desired > mDataCapacity) {
-
mError = NO_MEMORY;
-
return NO_MEMORY;
-
}
-
} else {
-
mDataSize = desired;
-
LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);
-
if (mDataPos > desired) {
-
mDataPos = desired;
-
LOGV(“continueWrite Setting data pos of %p to %d/n”, this, mDataPos);
-
}
-
}
-
} else {
-
// This is the first data. Easy!
-
uint8_t* data = (uint8_t*)malloc(desired);
-
if (!data) {
-
mError = NO_MEMORY;
-
return NO_MEMORY;
-
}
-
if(!(mDataCapacity == 0 && mObjects == NULL
-
&& mObjectsCapacity == 0)) {
-
LOGE(“continueWrite: %d/%p/%d/%d”, mDataCapacity, mObjects, mObjectsCapacity, desired);
-
}
-
mData = data;
-
mDataSize = mDataPos = 0;
-
LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);
-
LOGV(“continueWrite Setting data pos of %p to %d/n”, this, mDataPos);
-
mDataCapacity = desired;
-
}
-
return NO_ERROR;
-
}
-
void Parcel::initState()
-
{
-
mError = NO_ERROR;
-
mData = 0;
-
mDataSize = 0;
-
mDataCapacity = 0;
-
mDataPos = 0;
-
LOGV(“initState Setting data size of %p to %d/n”, this, mDataSize);
-
LOGV(“initState Setting data pos of %p to %d/n”, this, mDataPos);
-
mObjects = NULL;
-
mObjectsSize = 0;
-
mObjectsCapacity = 0;
-
mNextObjectHint = 0;
-
mHasFds = false;
-
mFdsKnown = true;
-
mOwner = NULL;
-
}
-
void Parcel::scanForFds() const
-
{
-
bool hasFds = false;
-
for (size_t i=0; i<mObjectsSize; i++) {
-
const flat_binder_object* flat
-
= reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]);
-
if (flat->type == BINDER_TYPE_FD) {
-
hasFds = true;
-
break;
-
}
-
}
-
mHasFds = hasFds;
-
mFdsKnown = true;
-
}
-
}; // namespace android
本文的源码使用的是Android 2.1版本。
上一篇中我们透过源码看到了Parcel背后的机制,本质上把它当成一个Serialize就可以了,只是它是在内存中完成的序列化和反序列化,利用的是连续的内存空间,因此会更加高效。
我们接下来要说的是Parcel类如何应用。就应用程序而言,最常见使用Parcel类的场景就是在Activity间传递数据。没错,在Activity间使用Intent传递数据的时候,可以通过Parcelable机制传递复杂的对象。
在下面的程序中,MyColor用于保存一个颜色值,MainActivity在用户点击屏幕时将MyColor对象设成红色,传递到SubActivity中,此时SubActivity的TextView显示为红色的背景;当点击SubActivity时,将颜色值改为绿色,返回MainActivity,期望的是MainActivity的TextView显示绿色背景。
来看一下MyColor类的实现代码:
[java] view plain copy
-
package com.wenbin.test;
-
import android.graphics.Color;
-
import android.os.Parcel;
-
import android.os.Parcelable;
-
/**
-
* @author 曹文斌
-
* http://blog.csdn.net/caowenbin
-
*
-
*/
-
public class MyColor implements Parcelable {
-
private int color=Color.BLACK;
-
MyColor(){
-
color=Color.BLACK;
-
}
-
MyColor(Parcel in){
-
color=in.readInt();
-
}
-
public int getColor(){
-
return color;
-
}
-
public void setColor(int color){
-
this.color=color;
-
}
-
@Override
-
public int describeContents() {
-
return 0;
-
}
-
@Override
-
public void writeToParcel(Parcel dest, int flags) {
-
dest.writeInt(color);
-
}
-
public static final Parcelable.Creator CREATOR
-
= new Parcelable.Creator() {
-
public MyColor createFromParcel(Parcel in) {
-
return new MyColor(in);
-
}
-
public MyColor[] newArray(int size) {
-
return new MyColor[size];
-
}
-
};
-
}
该类实现了Parcelable接口,提供了默认的构造函数,同时也提供了可从Parcel对象开始的构造函数,另外还实现了一个static的构造器用于构造对象和数组。代码很简单,不一一解释了。
再看MainActivity的代码:
[java] view plain copy
-
package com.wenbin.test;
-
import android.app.Activity;
-
import android.content.Intent;
-
import android.graphics.Color;
-
import android.os.Bundle;
-
import android.view.MotionEvent;
-
/**
-
* @author 曹文斌
-
* http://blog.csdn.net/caowenbin
-
*
-
*/
-
public class MainActivity extends Activity {
-
private final int SUB_ACTIVITY=0;
-
private MyColor color=new MyColor();
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
}
-
@Override
-
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
更多Android高级工程师进阶学习资料
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
@Override
-
public void writeToParcel(Parcel dest, int flags) {
-
dest.writeInt(color);
-
}
-
public static final Parcelable.Creator CREATOR
-
= new Parcelable.Creator() {
-
public MyColor createFromParcel(Parcel in) {
-
return new MyColor(in);
-
}
-
public MyColor[] newArray(int size) {
-
return new MyColor[size];
-
}
-
};
-
}
该类实现了Parcelable接口,提供了默认的构造函数,同时也提供了可从Parcel对象开始的构造函数,另外还实现了一个static的构造器用于构造对象和数组。代码很简单,不一一解释了。
再看MainActivity的代码:
[java] view plain copy
-
package com.wenbin.test;
-
import android.app.Activity;
-
import android.content.Intent;
-
import android.graphics.Color;
-
import android.os.Bundle;
-
import android.view.MotionEvent;
-
/**
-
* @author 曹文斌
-
* http://blog.csdn.net/caowenbin
-
*
-
*/
-
public class MainActivity extends Activity {
-
private final int SUB_ACTIVITY=0;
-
private MyColor color=new MyColor();
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
}
-
@Override
-
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-1SXjxuVY-1713786849009)]
[外链图片转存中…(img-E46V1hzt-1713786849011)]
[外链图片转存中…(img-d4BwJoWV-1713786849012)]
[外链图片转存中…(img-qMbYwmrP-1713786849013)]
[外链图片转存中…(img-p7WK8ziC-1713786849014)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
[外链图片转存中…(img-zKqUcegJ-1713786849015)]
更多Android高级工程师进阶学习资料
进阶学习视频
[外链图片转存中…(img-rxgGxNRU-1713786849017)]
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-cWADbeU9-1713786849018)]
里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!