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

Commit 5060f9ea authored by Evan Severson's avatar Evan Severson
Browse files

Correct some issues with AttributionSource.Builder

1. The constructor that takes an AttributionSource doesn't copy all
   fields.
2. The existence of mBuilderFieldsSet clears all fields copied from the
   previously mentioned constructor leading to an almost blank
   AttributionSource besides UID and fields that have been overridden
   with setField() methods. It is not clear why these field flags were
   introduced anyways.
3. build() always overwrites the token field to sDefaultToken, in the
   copy case we want to preserve the token.

Flag: EXEMPT bug fix
Test: CtsAppOpsTestCases CtsAttributionSourceTestCases
      CtsPermission{,Ui}TestCases
Fixes: 362756144
Change-Id: Ib11cf90f18a769d4821f633bf9e44612f4fae13e
parent 18fa0832
Loading
Loading
Loading
Loading
+19 −37
Original line number Diff line number Diff line
@@ -629,11 +629,10 @@ public final class AttributionSource implements Parcelable {
     * A builder for {@link AttributionSource}
     */
    public static final class Builder {
        private boolean mHasBeenUsed;
        private @NonNull final AttributionSourceState mAttributionSourceState =
                new AttributionSourceState();

        private long mBuilderFieldsSet = 0L;

        /**
         * Creates a new Builder.
         *
@@ -642,8 +641,17 @@ public final class AttributionSource implements Parcelable {
         */
        public Builder(int uid) {
            mAttributionSourceState.uid = uid;
            mAttributionSourceState.pid = Process.INVALID_PID;
            mAttributionSourceState.deviceId = Context.DEVICE_ID_DEFAULT;
            mAttributionSourceState.token = sDefaultToken;
        }

        /**
         * Creates a builder that is ready to build a new {@link AttributionSource} where
         * all fields (primitive, immutable data, pointers) are copied from the given
         * {@link AttributionSource}. Builder methods can still be used to mutate fields further.
         * @param current The source to copy fields from.
         */
        public Builder(@NonNull AttributionSource current) {
            if (current == null) {
                throw new IllegalArgumentException("current AttributionSource can not be null");
@@ -652,10 +660,11 @@ public final class AttributionSource implements Parcelable {
            mAttributionSourceState.pid = current.getPid();
            mAttributionSourceState.packageName = current.getPackageName();
            mAttributionSourceState.attributionTag = current.getAttributionTag();
            mAttributionSourceState.token = current.getToken();
            mAttributionSourceState.renouncedPermissions =
                current.mAttributionSourceState.renouncedPermissions;
            mBuilderFieldsSet |= 0x2 | 0x4 | 0x8 | 0x10;
            mAttributionSourceState.deviceId = current.getDeviceId();
            mAttributionSourceState.next = current.mAttributionSourceState.next;
            mAttributionSourceState.token = current.getToken();
        }

        /**
@@ -667,7 +676,6 @@ public final class AttributionSource implements Parcelable {
         */
        public @NonNull Builder setPid(int value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x2;
            mAttributionSourceState.pid = value;
            return this;
        }
@@ -677,7 +685,6 @@ public final class AttributionSource implements Parcelable {
         */
        public @NonNull Builder setPackageName(@Nullable String value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x4;
            mAttributionSourceState.packageName = value;
            return this;
        }
@@ -687,7 +694,6 @@ public final class AttributionSource implements Parcelable {
         */
        public @NonNull Builder setAttributionTag(@Nullable String value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x8;
            mAttributionSourceState.attributionTag = value;
            return this;
        }
@@ -718,11 +724,11 @@ public final class AttributionSource implements Parcelable {
         */
        @SystemApi
        @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
        public @NonNull Builder setRenouncedPermissions(@Nullable Set<String> value) {
        public @NonNull Builder setRenouncedPermissions(
                @Nullable Set<String> renouncedPermissions) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x10;
            mAttributionSourceState.renouncedPermissions = (value != null)
                    ? value.toArray(new String[0]) : null;
            mAttributionSourceState.renouncedPermissions = (renouncedPermissions != null)
                    ? renouncedPermissions.toArray(new String[0]) : null;
            return this;
        }

@@ -735,7 +741,6 @@ public final class AttributionSource implements Parcelable {
        @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
        public @NonNull Builder setDeviceId(int deviceId) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x20;
            mAttributionSourceState.deviceId = deviceId;
            return this;
        }
@@ -745,7 +750,6 @@ public final class AttributionSource implements Parcelable {
         */
        public @NonNull Builder setNext(@Nullable AttributionSource value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x40;
            mAttributionSourceState.next = (value != null) ? new AttributionSourceState[]
                    {value.mAttributionSourceState} : mAttributionSourceState.next;
            return this;
@@ -760,7 +764,6 @@ public final class AttributionSource implements Parcelable {
            if (value == null) {
                throw new IllegalArgumentException("Null AttributionSource not permitted.");
            }
            mBuilderFieldsSet |= 0x40;
            mAttributionSourceState.next =
                    new AttributionSourceState[]{value.mAttributionSourceState};
            return this;
@@ -769,28 +772,7 @@ public final class AttributionSource implements Parcelable {
        /** Builds the instance. This builder should not be touched after calling this! */
        public @NonNull AttributionSource build() {
            checkNotUsed();
            mBuilderFieldsSet |= 0x80; // Mark builder used

            if ((mBuilderFieldsSet & 0x2) == 0) {
                mAttributionSourceState.pid = Process.INVALID_PID;
            }
            if ((mBuilderFieldsSet & 0x4) == 0) {
                mAttributionSourceState.packageName = null;
            }
            if ((mBuilderFieldsSet & 0x8) == 0) {
                mAttributionSourceState.attributionTag = null;
            }
            if ((mBuilderFieldsSet & 0x10) == 0) {
                mAttributionSourceState.renouncedPermissions = null;
            }
            if ((mBuilderFieldsSet & 0x20) == 0) {
                mAttributionSourceState.deviceId = Context.DEVICE_ID_DEFAULT;
            }
            if ((mBuilderFieldsSet & 0x40) == 0) {
                mAttributionSourceState.next = null;
            }

            mAttributionSourceState.token = sDefaultToken;
            mHasBeenUsed = true;

            if (mAttributionSourceState.next == null) {
                // The NDK aidl backend doesn't support null parcelable arrays.
@@ -800,7 +782,7 @@ public final class AttributionSource implements Parcelable {
        }

        private void checkNotUsed() {
            if ((mBuilderFieldsSet & 0x80) != 0) {
            if (mHasBeenUsed) {
                throw new IllegalStateException(
                        "This Builder should not be reused. Use a new Builder instance instead");
            }