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:
Bernardo Rufino
2021-10-07 14:00:56 +01:00
parent fa565ffc48
commit 172c97db77
3 changed files with 53 additions and 10 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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},