Add range-based Parcel.hasFileDescriptors(offset, length)
To be used by lazy values in bundle. I ended up opening up as public API for apps to use it too because I saw no reason not to, can change if folks prefer it to be @hide though. Test: atest -d android.os.cts.ParcelTest android.os.cts.BundleTest android.os.BundleTest android.os.ParcelTest Bug: 195622897 Change-Id: I7bf580f94313669fe67998b32b2723544c594cde
This commit is contained in:
@@ -29976,6 +29976,7 @@ package android.os {
|
||||
method public int dataSize();
|
||||
method public void enforceInterface(@NonNull String);
|
||||
method public boolean hasFileDescriptors();
|
||||
method public boolean hasFileDescriptors(int, int);
|
||||
method public byte[] marshall();
|
||||
method @NonNull public static android.os.Parcel obtain();
|
||||
method @NonNull public static android.os.Parcel obtain(@NonNull android.os.IBinder);
|
||||
|
||||
@@ -361,6 +361,8 @@ public final class Parcel {
|
||||
long thisNativePtr, long otherNativePtr, int offset, int length);
|
||||
@CriticalNative
|
||||
private static native boolean nativeHasFileDescriptors(long nativePtr);
|
||||
private static native boolean nativeHasFileDescriptorsInRange(
|
||||
long nativePtr, int offset, int length);
|
||||
private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName);
|
||||
private static native void nativeEnforceInterface(long nativePtr, String interfaceName);
|
||||
|
||||
@@ -687,10 +689,25 @@ public final class Parcel {
|
||||
/**
|
||||
* Report whether the parcel contains any marshalled file descriptors.
|
||||
*/
|
||||
public final boolean hasFileDescriptors() {
|
||||
public boolean hasFileDescriptors() {
|
||||
return nativeHasFileDescriptors(mNativePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report whether the parcel contains any marshalled file descriptors in the range defined by
|
||||
* {@code offset} and {@code length}.
|
||||
*
|
||||
* @param offset The offset from which the range starts. Should be between 0 and
|
||||
* {@link #dataSize()}.
|
||||
* @param length The length of the range. Should be between 0 and {@link #dataSize()} - {@code
|
||||
* offset}.
|
||||
* @return whether there are file descriptors or not.
|
||||
* @throws IllegalArgumentException if the parameters are out of the permitted ranges.
|
||||
*/
|
||||
public boolean hasFileDescriptors(int offset, int length) {
|
||||
return nativeHasFileDescriptorsInRange(mNativePtr, offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the object used in {@link #readValue(ClassLoader)} / {@link #writeValue(Object)}
|
||||
* has file descriptors.
|
||||
@@ -3495,15 +3512,26 @@ public final class Parcel {
|
||||
int start = dataPosition();
|
||||
int type = readInt();
|
||||
if (isLengthPrefixed(type)) {
|
||||
int length = readInt();
|
||||
setDataPosition(MathUtils.addOrThrow(dataPosition(), length));
|
||||
return new LazyValue(this, start, length, type, loader);
|
||||
int objectLength = readInt();
|
||||
int end = MathUtils.addOrThrow(dataPosition(), objectLength);
|
||||
int valueLength = end - start;
|
||||
setDataPosition(end);
|
||||
return new LazyValue(this, start, valueLength, type, loader);
|
||||
} else {
|
||||
return readValue(type, loader, /* clazz */ null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class LazyValue implements Supplier<Object> {
|
||||
/**
|
||||
* | 4B | 4B |
|
||||
* mSource = Parcel{... | type | length | object | ...}
|
||||
* a b c d
|
||||
* length = d - c
|
||||
* mPosition = a
|
||||
* mLength = d - a
|
||||
*/
|
||||
private final int mPosition;
|
||||
private final int mLength;
|
||||
private final int mType;
|
||||
@@ -3551,7 +3579,7 @@ public final class Parcel {
|
||||
public void writeToParcel(Parcel out) {
|
||||
Parcel source = mSource;
|
||||
if (source != null) {
|
||||
out.appendFrom(source, mPosition, mLength + 8);
|
||||
out.appendFrom(source, mPosition, mLength);
|
||||
} else {
|
||||
out.writeValue(mObject);
|
||||
}
|
||||
@@ -3560,7 +3588,7 @@ public final class Parcel {
|
||||
public boolean hasFileDescriptors() {
|
||||
Parcel source = mSource;
|
||||
return (source != null)
|
||||
? getValueParcel(source).hasFileDescriptors()
|
||||
? source.hasFileDescriptors(mPosition, mLength)
|
||||
: Parcel.hasFileDescriptors(mObject);
|
||||
}
|
||||
|
||||
@@ -3621,10 +3649,7 @@ public final class Parcel {
|
||||
Parcel parcel = mValueParcel;
|
||||
if (parcel == null) {
|
||||
parcel = Parcel.obtain();
|
||||
// mLength is the length of object representation, excluding the type and length.
|
||||
// mPosition is the position of the entire value container, right before the type.
|
||||
// So, we add 4 bytes for the type + 4 bytes for the length written.
|
||||
parcel.appendFrom(source, mPosition, mLength + 8);
|
||||
parcel.appendFrom(source, mPosition, mLength);
|
||||
mValueParcel = parcel;
|
||||
}
|
||||
return parcel;
|
||||
|
||||
@@ -655,6 +655,22 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jboolean android_os_Parcel_hasFileDescriptorsInRange(JNIEnv* env, jclass clazz,
|
||||
jlong nativePtr, jint offset,
|
||||
jint length) {
|
||||
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
|
||||
if (parcel != NULL) {
|
||||
bool result;
|
||||
status_t err = parcel->hasFileDescriptorsInRange(offset, length, result);
|
||||
if (err != NO_ERROR) {
|
||||
signalExceptionForError(env, clazz, err);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
// String tries to allocate itself on the stack, within a known size, but will
|
||||
// make a heap allocation if not.
|
||||
template <size_t StackReserve>
|
||||
@@ -847,6 +863,7 @@ static const JNINativeMethod gParcelMethods[] = {
|
||||
{"nativeAppendFrom", "(JJII)J", (void*)android_os_Parcel_appendFrom},
|
||||
// @CriticalNative
|
||||
{"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
|
||||
{"nativeHasFileDescriptorsInRange", "(JII)Z", (void*)android_os_Parcel_hasFileDescriptorsInRange},
|
||||
{"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
|
||||
{"nativeEnforceInterface", "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user