Merge change 2351 into donut

* changes:
  Fix a major bug in Bundle when unparcelling from AIDL.
This commit is contained in:
Android (Google) Code Review
2009-05-22 14:51:22 -07:00
3 changed files with 69 additions and 75 deletions

View File

@@ -78,6 +78,10 @@ public final class Bundle implements Parcelable, Cloneable {
readFromParcel(parcelledData); readFromParcel(parcelledData);
} }
/* package */ Bundle(Parcel parcelledData, int length) {
readFromParcelInner(parcelledData, length);
}
/** /**
* Constructs a new, empty Bundle that uses a specific ClassLoader for * Constructs a new, empty Bundle that uses a specific ClassLoader for
* instantiating Parcelable and Serializable objects. * instantiating Parcelable and Serializable objects.
@@ -155,13 +159,14 @@ public final class Bundle implements Parcelable, Cloneable {
return; return;
} }
mParcelledData.setDataPosition(0); int N = mParcelledData.readInt();
Bundle b = mParcelledData.readBundleUnpacked(mClassLoader); if (N < 0) {
mMap = b.mMap; return;
}
mHasFds = mParcelledData.hasFileDescriptors(); if (mMap == null) {
mFdsKnown = true; mMap = new HashMap<String, Object>();
}
mParcelledData.readMapInternal(mMap, N, mClassLoader);
mParcelledData.recycle(); mParcelledData.recycle();
mParcelledData = null; mParcelledData = null;
} }
@@ -1427,7 +1432,25 @@ public final class Bundle implements Parcelable, Cloneable {
* @param parcel The parcel to copy this bundle to. * @param parcel The parcel to copy this bundle to.
*/ */
public void writeToParcel(Parcel parcel, int flags) { public void writeToParcel(Parcel parcel, int flags) {
parcel.writeBundle(this); if (mParcelledData != null) {
int length = mParcelledData.dataSize();
parcel.writeInt(length);
parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
parcel.appendFrom(mParcelledData, 0, length);
} else {
parcel.writeInt(-1); // dummy, will hold length
parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
int oldPos = parcel.dataPosition();
parcel.writeMapInternal(mMap);
int newPos = parcel.dataPosition();
// Backpatch length
parcel.setDataPosition(oldPos - 8);
int length = newPos - oldPos;
parcel.writeInt(length);
parcel.setDataPosition(newPos);
}
} }
/** /**
@@ -1436,8 +1459,33 @@ public final class Bundle implements Parcelable, Cloneable {
* @param parcel The parcel to overwrite this bundle from. * @param parcel The parcel to overwrite this bundle from.
*/ */
public void readFromParcel(Parcel parcel) { public void readFromParcel(Parcel parcel) {
mParcelledData = parcel; int length = parcel.readInt();
mHasFds = mParcelledData.hasFileDescriptors(); if (length < 0) {
throw new RuntimeException("Bad length in parcel: " + length);
}
readFromParcelInner(parcel, length);
}
void readFromParcelInner(Parcel parcel, int length) {
int magic = parcel.readInt();
if (magic != 0x4C444E42) {
//noinspection ThrowableInstanceNeverThrown
String st = Log.getStackTraceString(new RuntimeException());
Log.e("Bundle", "readBundle: bad magic number");
Log.e("Bundle", "readBundle: trace = " + st);
}
// Advance within this Parcel
int offset = parcel.dataPosition();
parcel.setDataPosition(offset + length);
Parcel p = Parcel.obtain();
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
p.setDataPosition(0);
mParcelledData = p;
mHasFds = p.hasFileDescriptors();
mFdsKnown = true; mFdsKnown = true;
} }

View File

@@ -457,7 +457,7 @@ public final class Parcel {
* Flatten a Map into the parcel at the current dataPosition(), * Flatten a Map into the parcel at the current dataPosition(),
* growing dataCapacity() if needed. The Map keys must be String objects. * growing dataCapacity() if needed. The Map keys must be String objects.
*/ */
private void writeMapInternal(Map<String,Object> val) { /* package */ void writeMapInternal(Map<String,Object> val) {
if (val == null) { if (val == null) {
writeInt(-1); writeInt(-1);
return; return;
@@ -480,23 +480,7 @@ public final class Parcel {
return; return;
} }
if (val.mParcelledData != null) { val.writeToParcel(this, 0);
int length = val.mParcelledData.dataSize();
appendFrom(val.mParcelledData, 0, length);
} else {
writeInt(-1); // dummy, will hold length
int oldPos = dataPosition();
writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
writeMapInternal(val.mMap);
int newPos = dataPosition();
// Backpatch length
setDataPosition(oldPos - 4);
int length = newPos - oldPos;
writeInt(length);
setDataPosition(newPos);
}
} }
/** /**
@@ -1352,60 +1336,18 @@ public final class Parcel {
* Returns null if the previously written Bundle object was null. * Returns null if the previously written Bundle object was null.
*/ */
public final Bundle readBundle(ClassLoader loader) { public final Bundle readBundle(ClassLoader loader) {
int offset = dataPosition();
int length = readInt(); int length = readInt();
if (length < 0) { if (length < 0) {
return null; return null;
} }
int magic = readInt();
if (magic != 0x4C444E42) {
//noinspection ThrowableInstanceNeverThrown
String st = Log.getStackTraceString(new RuntimeException());
Log.e("Bundle", "readBundle: bad magic number");
Log.e("Bundle", "readBundle: trace = " + st);
}
// Advance within this Parcel final Bundle bundle = new Bundle(this, length);
setDataPosition(offset + length + 4);
Parcel p = new Parcel(0);
p.setDataPosition(0);
p.appendFrom(this, offset, length + 4);
p.setDataPosition(0);
final Bundle bundle = new Bundle(p);
if (loader != null) { if (loader != null) {
bundle.setClassLoader(loader); bundle.setClassLoader(loader);
} }
return bundle; return bundle;
} }
/**
* Read and return a new Bundle object from the parcel at the current
* dataPosition(). Returns null if the previously written Bundle object was
* null. The returned bundle will have its contents fully unpacked using
* the given ClassLoader.
*/
/* package */ Bundle readBundleUnpacked(ClassLoader loader) {
int length = readInt();
if (length == -1) {
return null;
}
int magic = readInt();
if (magic != 0x4C444E42) {
//noinspection ThrowableInstanceNeverThrown
String st = Log.getStackTraceString(new RuntimeException());
Log.e("Bundle", "readBundleUnpacked: bad magic number");
Log.e("Bundle", "readBundleUnpacked: trace = " + st);
}
Bundle m = new Bundle(loader);
int N = readInt();
if (N < 0) {
return null;
}
readMapInternal(m.mMap, N, loader);
return m;
}
/** /**
* Read and return a byte[] object from the parcel. * Read and return a byte[] object from the parcel.
*/ */
@@ -1998,7 +1940,7 @@ public final class Parcel {
private native void init(int obj); private native void init(int obj);
private native void destroy(); private native void destroy();
private void readMapInternal(Map outVal, int N, /* package */ void readMapInternal(Map outVal, int N,
ClassLoader loader) { ClassLoader loader) {
while (N > 0) { while (N > 0) {
Object key = readValue(loader); Object key = readValue(loader);

View File

@@ -409,12 +409,16 @@ status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len)
mObjects[idx++] = off; mObjects[idx++] = off;
mObjectsSize++; mObjectsSize++;
const flat_binder_object* flat flat_binder_object* flat
= reinterpret_cast<flat_binder_object*>(mData + off); = reinterpret_cast<flat_binder_object*>(mData + off);
acquire_object(proc, *flat, this); acquire_object(proc, *flat, this);
// take note if the object is a file descriptor
if (flat->type == BINDER_TYPE_FD) { 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; mHasFds = mFdsKnown = true;
} }
} }