diff --git a/core/api/current.txt b/core/api/current.txt index e2981f5936c6b..a9df1a4ab1b37 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -11882,7 +11882,6 @@ package android.content.pm { field public static final int SCREEN_ORIENTATION_USER_LANDSCAPE = 11; // 0xb field public static final int SCREEN_ORIENTATION_USER_PORTRAIT = 12; // 0xc field public static final int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 1; // 0x1 - field public String[] attributionTags; field public int colorMode; field public int configChanges; field public int documentLaunchMode; @@ -12074,6 +12073,7 @@ package android.content.pm { method public final int getLogoResource(); method public boolean isEnabled(); field public android.content.pm.ApplicationInfo applicationInfo; + field public String[] attributionTags; field public int descriptionRes; field public boolean directBootAware; field public boolean enabled; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index a8f7a14068ba0..b1438eae65064 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3510,7 +3510,7 @@ public final class ActivityThread extends ClientTransactionHandler StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo), - activity.getAttributionSource()); + appContext.getAttributionSource()); if (r.state != null) { r.state.setClassLoader(cl); } @@ -4442,6 +4442,10 @@ public final class ActivityThread extends ClientTransactionHandler if (data.info.splitName != null) { context = (ContextImpl) context.createContextForSplit(data.info.splitName); } + if (data.info.attributionTags != null && data.info.attributionTags.length > 0) { + final String attributionTag = data.info.attributionTags[0]; + context = (ContextImpl) context.createAttributionContext(attributionTag); + } // Service resources must be initialized with the same loaders as the application // context. context.getResources().addLoaders( @@ -7353,6 +7357,10 @@ public final class ActivityThread extends ClientTransactionHandler throw new RuntimeException(e); } } + if (info.attributionTags != null && info.attributionTags.length > 0) { + final String attributionTag = info.attributionTags[0]; + c = c.createAttributionContext(attributionTag); + } try { final java.lang.ClassLoader cl = c.getClassLoader(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 17cba84acbebb..73c17b9cc96f7 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -3036,8 +3036,16 @@ class ContextImpl extends Context { } } + final String attributionTag; + if (activityInfo.attributionTags != null && activityInfo.attributionTags.length > 0) { + attributionTag = activityInfo.attributionTags[0]; + } else { + attributionTag = null; + } + ContextImpl context = new ContextImpl(null, mainThread, packageInfo, ContextParams.EMPTY, - null, null, activityInfo.splitName, activityToken, null, 0, classLoader, null); + attributionTag, null, activityInfo.splitName, activityToken, null, 0, classLoader, + null); context.mContextType = CONTEXT_TYPE_ACTIVITY; context.mIsConfigurationBasedContext = true; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index fbed90787a97c..03f6380e279f2 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -17,8 +17,8 @@ package android.content.pm; import android.annotation.IntDef; -import android.annotation.SuppressLint; import android.annotation.TestApi; +import android.app.Activity; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; @@ -1174,13 +1174,6 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { */ public WindowLayout windowLayout; - /** - * Attribution tags for finer grained calls if a {@link - * android.content.Context#sendBroadcast(Intent, String)} is used with a permission. - */ - @SuppressLint("MissingNullability") - public String[] attributionTags; - public ActivityInfo() { } @@ -1209,7 +1202,6 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { mMaxAspectRatio = orig.mMaxAspectRatio; mMinAspectRatio = orig.mMinAspectRatio; supportsSizeChanges = orig.supportsSizeChanges; - attributionTags = orig.attributionTags; } /** @@ -1532,15 +1524,6 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { if (supportsSizeChanges) { pw.println(prefix + "supportsSizeChanges=true"); } - if (attributionTags != null && attributionTags.length > 0) { - StringBuilder tags = new StringBuilder(); - tags.append(attributionTags[0]); - for (int i = 1; i < attributionTags.length; i++) { - tags.append(", "); - tags.append(attributionTags[i]); - } - pw.println(prefix + "attributionTags=[" + tags + "]"); - } super.dumpBack(pw, prefix, dumpFlags); } @@ -1586,7 +1569,6 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { dest.writeFloat(mMaxAspectRatio); dest.writeFloat(mMinAspectRatio); dest.writeBoolean(supportsSizeChanges); - dest.writeString8Array(attributionTags); } /** @@ -1706,7 +1688,6 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { mMaxAspectRatio = source.readFloat(); mMinAspectRatio = source.readFloat(); supportsSizeChanges = source.readBoolean(); - attributionTags = source.createString8Array(); } /** diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java index c67d00e88707e..42847c85103c7 100644 --- a/core/java/android/content/pm/ComponentInfo.java +++ b/core/java/android/content/pm/ComponentInfo.java @@ -16,8 +16,14 @@ package android.content.pm; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.Service; import android.compat.annotation.UnsupportedAppUsage; +import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Parcel; @@ -51,6 +57,25 @@ public class ComponentInfo extends PackageItemInfo { */ public String splitName; + /** + * Set of attribution tags that should be automatically applied to this + * component. + *

+ * When this component represents an {@link Activity}, {@link Service}, + * {@link ContentResolver} or {@link BroadcastReceiver}, each instance will + * be automatically configured with {@link Context#createAttributionContext} + * using the first attribution tag contained here. + *

+ * Additionally, when this component represents a {@link BroadcastReceiver} + * and the sender of a broadcast requires the receiver to hold one or more + * specific permissions, those permission checks will be performed using + * each of the attributions tags contained here. + * + * @see Context#createAttributionContext(String) + */ + @SuppressLint({"MissingNullability", "MutableBareField"}) + public String[] attributionTags; + /** * A string resource identifier (in the package's resources) containing * a user-readable description of the component. From the "description" @@ -87,6 +112,7 @@ public class ComponentInfo extends PackageItemInfo { applicationInfo = orig.applicationInfo; processName = orig.processName; splitName = orig.splitName; + attributionTags = orig.attributionTags; descriptionRes = orig.descriptionRes; enabled = orig.enabled; exported = orig.exported; @@ -172,6 +198,15 @@ public class ComponentInfo extends PackageItemInfo { if (splitName != null) { pw.println(prefix + "splitName=" + splitName); } + if (attributionTags != null && attributionTags.length > 0) { + StringBuilder tags = new StringBuilder(); + tags.append(attributionTags[0]); + for (int i = 1; i < attributionTags.length; i++) { + tags.append(", "); + tags.append(attributionTags[i]); + } + pw.println(prefix + "attributionTags=[" + tags + "]"); + } pw.println(prefix + "enabled=" + enabled + " exported=" + exported + " directBootAware=" + directBootAware); if (descriptionRes != 0) { @@ -200,6 +235,7 @@ public class ComponentInfo extends PackageItemInfo { applicationInfo.writeToParcel(dest, parcelableFlags); dest.writeString8(processName); dest.writeString8(splitName); + dest.writeString8Array(attributionTags); dest.writeInt(descriptionRes); dest.writeInt(enabled ? 1 : 0); dest.writeInt(exported ? 1 : 0); @@ -211,6 +247,7 @@ public class ComponentInfo extends PackageItemInfo { applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source); processName = source.readString8(); splitName = source.readString8(); + attributionTags = source.createString8Array(); descriptionRes = source.readInt(); enabled = (source.readInt() != 0); exported = (source.readInt() != 0); diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java index a9d70c524af07..d407b106b5a30 100644 --- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java +++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java @@ -713,6 +713,7 @@ public class PackageInfoWithoutStateUtils { componentInfo.directBootAware = mainComponent.isDirectBootAware(); componentInfo.enabled = mainComponent.isEnabled(); componentInfo.splitName = mainComponent.getSplitName(); + componentInfo.attributionTags = mainComponent.getAttributionTags(); } private static void assignSharedFieldsForPackageItemInfo( diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java index 9285ccb3cf0ca..6f478accedd77 100644 --- a/core/java/android/content/pm/parsing/component/ParsedActivity.java +++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java @@ -82,9 +82,6 @@ public class ParsedActivity extends ParsedMainComponent { @Nullable ActivityInfo.WindowLayout windowLayout; - @Nullable - String[] attributionTags; - public ParsedActivity(ParsedActivity other) { super(other); this.theme = other.theme; @@ -110,7 +107,6 @@ public class ParsedActivity extends ParsedMainComponent { this.rotationAnimation = other.rotationAnimation; this.colorMode = other.colorMode; this.windowLayout = other.windowLayout; - this.attributionTags = other.attributionTags; } /** @@ -176,7 +172,6 @@ public class ParsedActivity extends ParsedMainComponent { alias.requestedVrComponent = target.requestedVrComponent; alias.directBootAware = target.directBootAware; alias.setProcessName(target.getProcessName()); - alias.attributionTags = target.attributionTags; return alias; // Not all attributes from the target ParsedActivity are copied to the alias. @@ -304,7 +299,6 @@ public class ParsedActivity extends ParsedMainComponent { } else { dest.writeBoolean(false); } - dest.writeString8Array(this.attributionTags); } public ParsedActivity() { @@ -338,7 +332,6 @@ public class ParsedActivity extends ParsedMainComponent { if (in.readBoolean()) { windowLayout = new ActivityInfo.WindowLayout(in); } - this.attributionTags = in.createString8Array(); } public static final Parcelable.Creator CREATOR = new Creator() { @@ -452,9 +445,4 @@ public class ParsedActivity extends ParsedMainComponent { public ActivityInfo.WindowLayout getWindowLayout() { return windowLayout; } - - @Nullable - public String[] getAttributionTags() { - return attributionTags; - } } diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java index aa740bdbc4068..92a90e98cb43d 100644 --- a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java @@ -102,7 +102,8 @@ public class ParsedActivityUtils { R.styleable.AndroidManifestActivity_name, R.styleable.AndroidManifestActivity_process, R.styleable.AndroidManifestActivity_roundIcon, - R.styleable.AndroidManifestActivity_splitName); + R.styleable.AndroidManifestActivity_splitName, + R.styleable.AndroidManifestActivity_attributionTags); if (result.isError()) { return result; } @@ -212,11 +213,6 @@ public class ParsedActivityUtils { pkg.setVisibleToInstantApps(true); } - String attributionTags = sa.getString(R.styleable.AndroidManifestActivity_attributionTags); - if (attributionTags != null) { - activity.attributionTags = attributionTags.split("\\|"); - } - return parseActivityOrAlias(activity, pkg, tag, parser, res, sa, receiver, false /*isAlias*/, visibleToEphemeral, input, R.styleable.AndroidManifestActivity_parentActivityName, @@ -281,7 +277,8 @@ public class ParsedActivityUtils { R.styleable.AndroidManifestActivityAlias_name, null /*processAttr*/, R.styleable.AndroidManifestActivityAlias_roundIcon, - null /*splitNameAttr*/); + null /*splitNameAttr*/, + R.styleable.AndroidManifestActivityAlias_attributionTags); if (result.isError()) { return result; } diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponent.java b/core/java/android/content/pm/parsing/component/ParsedMainComponent.java index a5e394d823567..033e30fe75821 100644 --- a/core/java/android/content/pm/parsing/component/ParsedMainComponent.java +++ b/core/java/android/content/pm/parsing/component/ParsedMainComponent.java @@ -39,6 +39,8 @@ public class ParsedMainComponent extends ParsedComponent { @Nullable String splitName; + @Nullable + String[] attributionTags; public ParsedMainComponent() { } @@ -51,6 +53,7 @@ public class ParsedMainComponent extends ParsedComponent { this.exported = other.exported; this.order = other.order; this.splitName = other.splitName; + this.attributionTags = other.attributionTags; } public ParsedMainComponent setProcessName(String processName) { @@ -84,6 +87,7 @@ public class ParsedMainComponent extends ParsedComponent { dest.writeBoolean(this.exported); dest.writeInt(this.order); dest.writeString(this.splitName); + dest.writeString8Array(this.attributionTags); } protected ParsedMainComponent(Parcel in) { @@ -94,6 +98,7 @@ public class ParsedMainComponent extends ParsedComponent { this.exported = in.readBoolean(); this.order = in.readInt(); this.splitName = in.readString(); + this.attributionTags = in.createString8Array(); } public static final Parcelable.Creator CREATOR = @@ -135,6 +140,11 @@ public class ParsedMainComponent extends ParsedComponent { return splitName; } + @Nullable + public String[] getAttributionTags() { + return attributionTags; + } + public ParsedMainComponent setDirectBootAware(boolean value) { directBootAware = value; return this; @@ -149,4 +159,9 @@ public class ParsedMainComponent extends ParsedComponent { splitName = value; return this; } + + public ParsedMainComponent setAttributionTags(@Nullable String[] value) { + attributionTags = value; + return this; + } } diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java index f70d62b56d496..54bcbdddfb342 100644 --- a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java @@ -48,7 +48,8 @@ class ParsedMainComponentUtils { TypedArray array, int flags, boolean useRoundIcon, ParseInput input, int bannerAttr, int descriptionAttr, @Nullable Integer directBootAwareAttr, @Nullable Integer enabledAttr, int iconAttr, int labelAttr, int logoAttr, int nameAttr, - @Nullable Integer processAttr, int roundIconAttr, @Nullable Integer splitNameAttr) { + @Nullable Integer processAttr, int roundIconAttr, @Nullable Integer splitNameAttr, + @Nullable Integer attributionTagsAttr) { ParseResult result = ParsedComponentUtils.parseComponent(component, tag, pkg, array, useRoundIcon, input, bannerAttr, descriptionAttr, iconAttr, labelAttr, logoAttr, nameAttr, roundIconAttr); @@ -94,6 +95,13 @@ class ParsedMainComponentUtils { component.splitName = array.getNonConfigurationString(splitNameAttr, 0); } + if (attributionTagsAttr != null) { + final String attributionTags = array.getNonConfigurationString(attributionTagsAttr, 0); + if (attributionTags != null) { + component.attributionTags = attributionTags.split("\\|"); + } + } + return input.success(component); } diff --git a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java index 4deab56c32104..28fd919e2b7e7 100644 --- a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java @@ -74,7 +74,8 @@ public class ParsedProviderUtils { R.styleable.AndroidManifestProvider_name, R.styleable.AndroidManifestProvider_process, R.styleable.AndroidManifestProvider_roundIcon, - R.styleable.AndroidManifestProvider_splitName); + R.styleable.AndroidManifestProvider_splitName, + R.styleable.AndroidManifestProvider_attributionTags); if (result.isError()) { return result; } diff --git a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java index 739bee2fb7d9e..ae107ce65bf8a 100644 --- a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java @@ -68,7 +68,8 @@ public class ParsedServiceUtils { R.styleable.AndroidManifestService_name, R.styleable.AndroidManifestService_process, R.styleable.AndroidManifestService_roundIcon, - R.styleable.AndroidManifestService_splitName + R.styleable.AndroidManifestService_splitName, + R.styleable.AndroidManifestService_attributionTags ); if (result.isError()) { diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 638627422eff3..ef0dc37329c71 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -2593,6 +2593,12 @@ + + + + + - - + +