Merge changes from topic "may15" into sc-dev

* changes:
  Apply "attributionTags" to all component types.
  Apply AttributionSource during Intent delivery.
This commit is contained in:
Jeff Sharkey
2021-05-16 17:54:40 +00:00
committed by Android (Google) Code Review
19 changed files with 158 additions and 63 deletions

View File

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

View File

@@ -3509,7 +3509,8 @@ public final class ActivityThread extends ClientTransactionHandler
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo));
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
appContext.getAttributionSource());
if (r.state != null) {
r.state.setClassLoader(cl);
}
@@ -3801,7 +3802,8 @@ public final class ActivityThread extends ClientTransactionHandler
for (int i=0; i<N; i++) {
ReferrerIntent intent = intents.get(i);
intent.setExtrasClassLoader(r.activity.getClassLoader());
intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo));
intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
r.activity.getAttributionSource());
r.activity.mFragments.noteStateNotSaved();
mInstrumentation.callActivityOnNewIntent(r.activity, intent);
}
@@ -4241,10 +4243,15 @@ 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);
}
java.lang.ClassLoader cl = context.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess(
isProtectedComponent(data.info) || isProtectedBroadcast(data.intent));
isProtectedComponent(data.info) || isProtectedBroadcast(data.intent),
context.getAttributionSource());
data.setExtrasClassLoader(cl);
receiver = packageInfo.getAppFactory()
.instantiateReceiver(cl, data.info.name, data.intent);
@@ -4435,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(
@@ -4469,7 +4480,8 @@ public final class ActivityThread extends ClientTransactionHandler
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info));
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
s.getAttributionSource());
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
@@ -4499,7 +4511,8 @@ public final class ActivityThread extends ClientTransactionHandler
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info));
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
s.getAttributionSource());
boolean doRebind = s.onUnbind(data.intent);
try {
if (doRebind) {
@@ -4588,7 +4601,8 @@ public final class ActivityThread extends ClientTransactionHandler
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess(isProtectedComponent(createData.info));
data.args.prepareToEnterProcess(isProtectedComponent(createData.info),
s.getAttributionSource());
}
int res;
if (!data.taskRemoved) {
@@ -5241,7 +5255,8 @@ public final class ActivityThread extends ClientTransactionHandler
try {
if (ri.mData != null) {
ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
ri.mData.prepareToEnterProcess(isProtectedComponent(r.activityInfo));
ri.mData.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
r.activity.getAttributionSource());
}
if (DEBUG_RESULTS) Slog.v(TAG,
"Delivering result to activity " + r + " : " + ri);
@@ -7342,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();

View File

@@ -1774,7 +1774,8 @@ class ContextImpl extends Context {
intent.setExtrasClassLoader(getClassLoader());
// TODO: determine at registration time if caller is
// protecting themselves with signature permission
intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent));
intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
getAttributionSource());
}
return intent;
} catch (RemoteException e) {
@@ -3035,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;

View File

@@ -1651,7 +1651,8 @@ public final class LoadedApk {
intent.setExtrasClassLoader(cl);
// TODO: determine at registration time if caller is
// protecting themselves with signature permission
intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent));
intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
mContext.getAttributionSource());
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);

View File

@@ -1190,6 +1190,11 @@ public final class BluetoothDevice implements Parcelable {
return devices;
}
/** {@hide} */
public void prepareToEnterProcess(AttributionSource attributionSource) {
setAttributionSource(attributionSource);
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof BluetoothDevice) {

View File

@@ -1034,14 +1034,14 @@ public class ClipData implements Parcelable {
}
/** {@hide} */
public void prepareToEnterProcess() {
public void prepareToEnterProcess(AttributionSource source) {
final int size = mItems.size();
for (int i = 0; i < size; i++) {
final Item item = mItems.get(i);
if (item.mIntent != null) {
// We can't recursively claim that this data is from a protected
// component, since it may have been filled in by a malicious app
item.mIntent.prepareToEnterProcess(false);
item.mIntent.prepareToEnterProcess(false, source);
}
}
}

View File

@@ -31,6 +31,7 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.AppGlobals;
import android.bluetooth.BluetoothDevice;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -11439,7 +11440,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* @hide
*/
public void prepareToEnterProcess(boolean fromProtectedComponent) {
public void prepareToEnterProcess(boolean fromProtectedComponent, AttributionSource source) {
// We just entered destination process, so we should be able to read all
// parcelables inside.
setDefusable(true);
@@ -11447,10 +11448,10 @@ public class Intent implements Parcelable, Cloneable {
if (mSelector != null) {
// We can't recursively claim that this data is from a protected
// component, since it may have been filled in by a malicious app
mSelector.prepareToEnterProcess(false);
mSelector.prepareToEnterProcess(false, source);
}
if (mClipData != null) {
mClipData.prepareToEnterProcess();
mClipData.prepareToEnterProcess(source);
}
if (mContentUserHint != UserHandle.USER_CURRENT) {
@@ -11463,6 +11464,14 @@ public class Intent implements Parcelable, Cloneable {
if (fromProtectedComponent) {
mLocalFlags |= LOCAL_FLAG_FROM_PROTECTED_COMPONENT;
}
// Special attribution fix-up logic for any BluetoothDevice extras
// passed via Bluetooth intents
if (mAction != null && mAction.startsWith("android.bluetooth.")
&& hasExtra(BluetoothDevice.EXTRA_DEVICE)) {
final BluetoothDevice device = getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
device.prepareToEnterProcess(source);
}
}
/** @hide */

View File

@@ -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();
}
/**

View File

@@ -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.
* <p>
* 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.
* <p>
* 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);

View File

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

View File

@@ -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<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
@@ -452,9 +445,4 @@ public class ParsedActivity extends ParsedMainComponent {
public ActivityInfo.WindowLayout getWindowLayout() {
return windowLayout;
}
@Nullable
public String[] getAttributionTags() {
return attributionTags;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()) {

View File

@@ -7505,7 +7505,8 @@ public final class ViewRootImpl implements ViewParent,
final View prevDragView = mCurrentDragView;
if (what == DragEvent.ACTION_DROP && event.mClipData != null) {
event.mClipData.prepareToEnterProcess();
event.mClipData.prepareToEnterProcess(
mView.getContext().getAttributionSource());
}
// Now dispatch the drag/drop event

View File

@@ -2593,6 +2593,12 @@
<!-- The code for this component is located in the given split.
<p>NOTE: This is only applicable to instant app. -->
<attr name="splitName" />
<!-- Set of attribution tags that should be automatically applied to this component.
<p>
Each instance of this ContentProvider will be automatically configured with
Context.createAttributionContext() using the first attribution tag
contained here. -->
<attr name="attributionTags" />
</declare-styleable>
<!-- Attributes that can be supplied in an AndroidManifest.xml
@@ -2728,6 +2734,12 @@
<attr name="useAppZygote" format="boolean" />
<!-- If this is a foreground service, specify its category. -->
<attr name="foregroundServiceType" />
<!-- Set of attribution tags that should be automatically applied to this component.
<p>
Each instance of this Service will be automatically configured with
Context.createAttributionContext() using the first attribution tag
contained here. -->
<attr name="attributionTags" />
</declare-styleable>
<!-- The <code>receiver</code> tag declares an
@@ -2765,6 +2777,12 @@
<attr name="exported" />
<attr name="singleUser" />
<attr name="directBootAware" />
<!-- Set of attribution tags that should be automatically applied to this component.
<p>
Each instance of this BroadcastReceiver will be automatically configured with
Context.createAttributionContext() using the first attribution tag
contained here. -->
<attr name="attributionTags" />
</declare-styleable>
<!-- The <code>activity</code> tag declares an
@@ -2892,10 +2910,12 @@
<p> See {@link android.content.pm.ActivityInfo#FLAG_PREFER_MINIMAL_POST_PROCESSING} -->
<attr name="preferMinimalPostProcessing" format="boolean"/>
<!-- Specify the attributionTags to be used if a permission is required due to
{@link android.content.Context#sendBroadcast(Intent, String)} being used.
Multiple tags can be specified separated by '|'. -->
<attr name="attributionTags"/>
<!-- Set of attribution tags that should be automatically applied to this component.
<p>
Each instance of this Activity will be automatically configured with
Context.createAttributionContext() using the first attribution tag
contained here. -->
<attr name="attributionTags" />
<!-- Specifies whether a home sound effect should be played if the home app moves to
front after an activity with this flag set to <code>true</code>.
<p>The default value of this attribute is <code>true</code>.
@@ -2942,6 +2962,7 @@
<attr name="enabled" />
<attr name="exported" />
<attr name="parentActivityName" />
<attr name="attributionTags" />
</declare-styleable>
<!-- The <code>meta-data</code> tag is used to attach additional

View File

@@ -444,6 +444,7 @@ public class PackageInfoUtils {
componentInfo.directBootAware = mainComponent.isDirectBootAware();
componentInfo.enabled = mainComponent.isEnabled();
componentInfo.splitName = mainComponent.getSplitName();
componentInfo.attributionTags = mainComponent.getAttributionTags();
}
private static void assignStateFieldsForPackageItemInfo(