Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 172c97db authored by Bernardo Rufino's avatar Bernardo Rufino
Browse files

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
parent fa565ffc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+35 −10
Original line number Diff line number Diff line
@@ -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;
+17 −0
Original line number Diff line number Diff line
@@ -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},