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

Commit 7645452c authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Allow senders to specify the delivery group via matching filters.

Senders can specify an IntentFilter object that should match
against another broadcast intent to be considered in the same
delivery group.

Bug: 249160234
Test: atest services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
Test: atest services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
Test: atest tests/app/src/android/app/cts/BroadcastOptionsTest.java
Test: atest tests/tests/content/src/android/content/cts/IntentFilterTest.java

Change-Id: I36f1e3ffab8e30371a9968cb23c7b345c3301682
parent 03ad7a2c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -779,13 +779,19 @@ package android.app {
  }
  public class BroadcastOptions {
    method public void clearDeliveryGroupMatchingFilter();
    method public void clearDeliveryGroupMatchingKey();
    method public void clearDeliveryGroupPolicy();
    method public void clearRequireCompatChange();
    method @Nullable public android.content.IntentFilter getDeliveryGroupMatchingFilter();
    method @Nullable public String getDeliveryGroupMatchingKey();
    method public int getDeliveryGroupPolicy();
    method public boolean isPendingIntentBackgroundActivityLaunchAllowed();
    method public static android.app.BroadcastOptions makeBasic();
    method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long);
    method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
    method public void setDeliveryGroupMatchingFilter(@NonNull android.content.IntentFilter);
    method public void setDeliveryGroupMatchingKey(@NonNull String, @NonNull String);
    method public void setDeliveryGroupPolicy(int);
    method public void setDontSendToRestrictedApps(boolean);
    method public void setPendingIntentBackgroundActivityLaunchAllowed(boolean);
@@ -3170,7 +3176,9 @@ package android.content {
  }
  public class IntentFilter implements android.os.Parcelable {
    method @NonNull public final android.os.PersistableBundle getExtras();
    method public final int getOrder();
    method public final void setExtras(@NonNull android.os.PersistableBundle);
    method public final void setOrder(int);
  }
+117 −18
Original line number Diff line number Diff line
@@ -67,8 +67,9 @@ public class BroadcastOptions extends ComponentOptions {
    private long mIdForResponseEvent;
    private @Nullable IntentFilter mRemoveMatchingFilter;
    private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
    private @Nullable String mDeliveryGroupKey;
    private @Nullable String mDeliveryGroupMatchingKey;
    private @Nullable BundleMerger mDeliveryGroupExtrasMerger;
    private @Nullable IntentFilter mDeliveryGroupMatchingFilter;

    /**
     * Change ID which is invalid.
@@ -214,10 +215,10 @@ public class BroadcastOptions extends ComponentOptions {
            "android:broadcast.deliveryGroupPolicy";

    /**
     * Corresponds to {@link #setDeliveryGroupKey(String, String)}.
     * Corresponds to {@link #setDeliveryGroupMatchingKey(String, String)}.
     */
    private static final String KEY_DELIVERY_GROUP_KEY =
            "android:broadcast.deliveryGroupKey";
            "android:broadcast.deliveryGroupMatchingKey";

    /**
     * Corresponds to {@link #setDeliveryGroupExtrasMerger(BundleMerger)}.
@@ -225,6 +226,12 @@ public class BroadcastOptions extends ComponentOptions {
    private static final String KEY_DELIVERY_GROUP_EXTRAS_MERGER =
            "android:broadcast.deliveryGroupExtrasMerger";

    /**
     * Corresponds to {@link #setDeliveryGroupMatchingFilter(IntentFilter)}.
     */
    private static final String KEY_DELIVERY_GROUP_MATCHING_FILTER =
            "android:broadcast.deliveryGroupMatchingFilter";

    /**
     * The list of delivery group policies which specify how multiple broadcasts belonging to
     * the same delivery group has to be handled.
@@ -313,9 +320,11 @@ public class BroadcastOptions extends ComponentOptions {
                IntentFilter.class);
        mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY,
                DELIVERY_GROUP_POLICY_ALL);
        mDeliveryGroupKey = opts.getString(KEY_DELIVERY_GROUP_KEY);
        mDeliveryGroupMatchingKey = opts.getString(KEY_DELIVERY_GROUP_KEY);
        mDeliveryGroupExtrasMerger = opts.getParcelable(KEY_DELIVERY_GROUP_EXTRAS_MERGER,
                BundleMerger.class);
        mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER,
                IntentFilter.class);
    }

    /**
@@ -764,7 +773,7 @@ public class BroadcastOptions extends ComponentOptions {

    /**
     * Clears any previously set delivery group policies using
     * {@link #setDeliveryGroupKey(String, String)} and resets the delivery group policy to
     * {@link #setDeliveryGroupMatchingKey(String, String)} and resets the delivery group policy to
     * the default value ({@link #DELIVERY_GROUP_POLICY_ALL}).
     *
     * @hide
@@ -776,22 +785,92 @@ public class BroadcastOptions extends ComponentOptions {

    /**
     * Set namespace and key to identify the delivery group that this broadcast belongs to.
     * If no namespace and key is set, then by default {@link Intent#filterEquals(Intent)} will be
     * used to identify the delivery group.
     *
     * <p> If {@code namespace} and {@code key} are specified, then another broadcast will be
     * considered to be in the same delivery group as this iff it has the same {@code namespace}
     * and {@code key}.
     *
     * <p> If neither matching key using this API nor matching filter using
     * {@link #setDeliveryGroupMatchingFilter(IntentFilter)} is specified, then by default
     * {@link Intent#filterEquals(Intent)} will be used to identify the delivery group.
     *
     * @hide
     */
    public void setDeliveryGroupKey(@NonNull String namespace, @NonNull String key) {
    @SystemApi
    public void setDeliveryGroupMatchingKey(@NonNull String namespace, @NonNull String key) {
        Preconditions.checkArgument(!namespace.contains("/"),
                "namespace should not contain '/'");
        Preconditions.checkArgument(!key.contains("/"),
                "key should not contain '/'");
        mDeliveryGroupKey = namespace + "/" + key;
        mDeliveryGroupMatchingKey = namespace + "/" + key;
    }

    /** @hide */
    public String getDeliveryGroupKey() {
        return mDeliveryGroupKey;
    /**
     * Return the namespace and key that is used to identify the delivery group that this
     * broadcast belongs to.
     *
     * @return the delivery group namespace and key that was previously set using
     *         {@link #setDeliveryGroupMatchingKey(String, String)}, concatenated with a {@code /}.
     * @hide
     */
    @SystemApi
    @Nullable
    public String getDeliveryGroupMatchingKey() {
        return mDeliveryGroupMatchingKey;
    }

    /**
     * Clears the namespace and key that was previously set using
     * {@link #setDeliveryGroupMatchingKey(String, String)}.
     *
     * @hide
     */
    @SystemApi
    public void clearDeliveryGroupMatchingKey() {
        mDeliveryGroupMatchingKey = null;
    }

    /**
     * Set the {@link IntentFilter} object to identify the delivery group that this broadcast
     * belongs to.
     *
     * <p> If a {@code matchingFilter} is specified, then another broadcast will be considered
     * to be in the same delivery group as this iff the {@code matchingFilter} matches it's intent.
     *
     * <p> If neither matching key using {@link #setDeliveryGroupMatchingKey(String, String)} nor
     * matching filter using this API is specified, then by default
     * {@link Intent#filterEquals(Intent)} will be used to identify the delivery group.
     *
     * @hide
     */
    @SystemApi
    public void setDeliveryGroupMatchingFilter(@NonNull IntentFilter matchingFilter) {
        mDeliveryGroupMatchingFilter = Objects.requireNonNull(matchingFilter);
    }

    /**
     * Return the {@link IntentFilter} object that is used to identify the delivery group
     * that this broadcast belongs to.
     *
     * @return the {@link IntentFilter} object that was previously set using
     *         {@link #setDeliveryGroupMatchingFilter(IntentFilter)}.
     * @hide
     */
    @SystemApi
    @Nullable
    public IntentFilter getDeliveryGroupMatchingFilter() {
        return mDeliveryGroupMatchingFilter;
    }

    /**
     * Clears the {@link IntentFilter} object that was previously set using
     * {@link #setDeliveryGroupMatchingFilter(IntentFilter)}.
     *
     * @hide
     */
    @SystemApi
    public void clearDeliveryGroupMatchingFilter() {
        mDeliveryGroupMatchingFilter = null;
    }

    /**
@@ -804,15 +883,32 @@ public class BroadcastOptions extends ComponentOptions {
     * @hide
     */
    public void setDeliveryGroupExtrasMerger(@NonNull BundleMerger extrasMerger) {
        Preconditions.checkNotNull(extrasMerger);
        mDeliveryGroupExtrasMerger = extrasMerger;
        mDeliveryGroupExtrasMerger = Objects.requireNonNull(extrasMerger);
    }

    /** @hide */
    public @Nullable BundleMerger getDeliveryGroupExtrasMerger() {
    /**
     * Return the {@link BundleMerger} that specifies how to merge the extras data from
     * broadcasts in a delivery group.
     *
     * @return the {@link BundleMerger} object that was previously set using
     *         {@link #setDeliveryGroupExtrasMerger(BundleMerger)}.
     * @hide
     */
    @Nullable
    public BundleMerger getDeliveryGroupExtrasMerger() {
        return mDeliveryGroupExtrasMerger;
    }

    /**
     * Clear the {@link BundleMerger} object that was previously set using
     * {@link #setDeliveryGroupExtrasMerger(BundleMerger)}.
     *
     * @hide
     */
    public void clearDeliveryGroupExtrasMerger() {
        mDeliveryGroupExtrasMerger = null;
    }

    /**
     * Returns the created options as a Bundle, which can be passed to
     * {@link android.content.Context#sendBroadcast(android.content.Intent)
@@ -871,8 +967,8 @@ public class BroadcastOptions extends ComponentOptions {
        if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) {
            b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy);
        }
        if (mDeliveryGroupKey != null) {
            b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupKey);
        if (mDeliveryGroupMatchingKey != null) {
            b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKey);
        }
        if (mDeliveryGroupPolicy == DELIVERY_GROUP_POLICY_MERGED) {
            if (mDeliveryGroupExtrasMerger != null) {
@@ -883,6 +979,9 @@ public class BroadcastOptions extends ComponentOptions {
                        + "when delivery group policy is 'MERGED'");
            }
        }
        if (mDeliveryGroupMatchingFilter != null) {
            b.putParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, mDeliveryGroupMatchingFilter);
        }
        return b.isEmpty() ? null : b;
    }
}
+487 −1

File changed.

Preview size limit exceeded, changes collapsed.

+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ option java_multiple_files = true;

import "frameworks/base/core/proto/android/content/component_name.proto";
import "frameworks/base/core/proto/android/os/patternmatcher.proto";
import "frameworks/base/core/proto/android/os/persistablebundle.proto";
import "frameworks/base/core/proto/android/privacy.proto";

// Next Tag: 14
@@ -87,6 +88,7 @@ message IntentFilterProto {
    optional bool has_partial_types = 9;
    optional bool get_auto_verify = 10;
    repeated string mime_groups = 11;
    optional android.os.PersistableBundleProto extras = 12;
}

message AuthorityEntryProto {
+28 −7
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.app.compat.CompatChanges;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.os.Binder;
@@ -870,14 +871,34 @@ final class BroadcastRecord extends Binder {
        }
    }

    public boolean matchesDeliveryGroup(@NonNull BroadcastRecord other) {
        final String key = (options != null) ? options.getDeliveryGroupKey() : null;
        final String otherKey = (other.options != null)
                ? other.options.getDeliveryGroupKey() : null;
        if (key == null && otherKey == null) {
            return intent.filterEquals(other.intent);
    boolean matchesDeliveryGroup(@NonNull BroadcastRecord other) {
        return matchesDeliveryGroup(this, other);
    }
        return Objects.equals(key, otherKey);

    private static boolean matchesDeliveryGroup(@NonNull BroadcastRecord newRecord,
            @NonNull BroadcastRecord oldRecord) {
        final String newMatchingKey = getDeliveryGroupMatchingKey(newRecord);
        final String oldMatchingKey = getDeliveryGroupMatchingKey(oldRecord);
        final IntentFilter newMatchingFilter = getDeliveryGroupMatchingFilter(newRecord);
        // If neither delivery group key nor matching filter is specified, then use
        // Intent.filterEquals() to identify the delivery group.
        if (newMatchingKey == null && oldMatchingKey == null && newMatchingFilter == null) {
            return newRecord.intent.filterEquals(oldRecord.intent);
        }
        if (newMatchingFilter != null && !newMatchingFilter.asPredicate().test(oldRecord.intent)) {
            return false;
        }
        return Objects.equals(newMatchingKey, oldMatchingKey);
    }

    @Nullable
    private static String getDeliveryGroupMatchingKey(@NonNull BroadcastRecord record) {
        return record.options == null ? null : record.options.getDeliveryGroupMatchingKey();
    }

    @Nullable
    private static IntentFilter getDeliveryGroupMatchingFilter(@NonNull BroadcastRecord record) {
        return record.options == null ? null : record.options.getDeliveryGroupMatchingFilter();
    }

    @Override
Loading