Merge "Support subattribution for manifest receivers" into sc-dev

This commit is contained in:
Chad Brubaker
2021-03-12 06:30:28 +00:00
committed by Android (Google) Code Review
8 changed files with 94 additions and 30 deletions

View File

@@ -329,6 +329,7 @@ package android {
field public static final int apiKey = 16843281; // 0x1010211
field public static final int appCategory = 16844101; // 0x1010545
field public static final int appComponentFactory = 16844154; // 0x101057a
field public static final int attributionTags = 16844353; // 0x1010641
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f

View File

@@ -1086,6 +1086,13 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
*/
public WindowLayout windowLayout;
/**
* Attribution tags for finer grained calls if a {@android.content.Context#sendBroadcast(Intent,
* String)} is used with a permission.
* @hide
*/
public String[] attributionTags;
public ActivityInfo() {
}
@@ -1114,6 +1121,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
maxAspectRatio = orig.maxAspectRatio;
minAspectRatio = orig.minAspectRatio;
supportsSizeChanges = orig.supportsSizeChanges;
attributionTags = orig.attributionTags;
}
/**
@@ -1361,6 +1369,15 @@ 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);
}
@@ -1406,6 +1423,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
dest.writeFloat(maxAspectRatio);
dest.writeFloat(minAspectRatio);
dest.writeBoolean(supportsSizeChanges);
dest.writeString8Array(attributionTags);
}
/**
@@ -1525,6 +1543,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
maxAspectRatio = source.readFloat();
minAspectRatio = source.readFloat();
supportsSizeChanges = source.readBoolean();
attributionTags = source.createString8Array();
}
/**

View File

@@ -482,6 +482,7 @@ public class PackageInfoWithoutStateUtils {
ai.rotationAnimation = a.getRotationAnimation();
ai.colorMode = a.getColorMode();
ai.windowLayout = a.getWindowLayout();
ai.attributionTags = a.getAttributionTags();
if ((flags & PackageManager.GET_META_DATA) != 0) {
ai.metaData = a.getMetaData();
}

View File

@@ -82,6 +82,9 @@ public class ParsedActivity extends ParsedMainComponent {
@Nullable
ActivityInfo.WindowLayout windowLayout;
@Nullable
String[] attributionTags;
public ParsedActivity(ParsedActivity other) {
super(other);
this.theme = other.theme;
@@ -107,6 +110,7 @@ public class ParsedActivity extends ParsedMainComponent {
this.rotationAnimation = other.rotationAnimation;
this.colorMode = other.colorMode;
this.windowLayout = other.windowLayout;
this.attributionTags = other.attributionTags;
}
/**
@@ -172,6 +176,7 @@ 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.
@@ -299,6 +304,7 @@ public class ParsedActivity extends ParsedMainComponent {
} else {
dest.writeBoolean(false);
}
dest.writeString8Array(this.attributionTags);
}
public ParsedActivity() {
@@ -332,6 +338,7 @@ 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>() {
@@ -445,4 +452,9 @@ public class ParsedActivity extends ParsedMainComponent {
public ActivityInfo.WindowLayout getWindowLayout() {
return windowLayout;
}
@Nullable
public String[] getAttributionTags() {
return attributionTags;
}
}

View File

@@ -210,6 +210,11 @@ 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,

View File

@@ -829,7 +829,6 @@
{@code FLAG_ACTIVITY_MULTIPLE_TASK} is set.-->
<enum name="singleInstancePerTask" value="4" />
</attr>
<!-- Specify the orientation an activity should be run in. If not
specified, it will run in the current preferred orientation
of the screen.
@@ -1603,6 +1602,12 @@
<enum name="sync" value="2" />
</attr>
<!-- Attribution tag to be used for permission sub-attribution if a
permission is checked in {@link android.content.Context#sendBroadcast(Intent, String)}.
Multiple tags can be specified separated by '|'.
-->
<attr name="attributionTags" format="string" />
<!-- The <code>manifest</code> tag is the root of an
<code>AndroidManifest.xml</code> file,
describing the contents of an Android package (.apk) file. One
@@ -2825,6 +2830,10 @@
<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"/>
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new

View File

@@ -3087,6 +3087,7 @@
<public name="passwordsActivity"/>
<public name="selectableAsDefault"/>
<public name="isAccessibilityTool"/>
<public name="attributionTags"/>
</public-group>
<public-group type="drawable" first-id="0x010800b5">

View File

@@ -1416,7 +1416,7 @@ public final class BroadcastQueue {
}
}
if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
r.requiredPermissions != null && r.requiredPermissions.length > 0) {
r.requiredPermissions != null && r.requiredPermissions.length > 0) {
for (int i = 0; i < r.requiredPermissions.length; i++) {
String requiredPermission = r.requiredPermissions[i];
try {
@@ -1424,7 +1424,7 @@ public final class BroadcastQueue {
checkPermission(requiredPermission,
info.activityInfo.applicationInfo.packageName,
UserHandle
.getUserId(info.activityInfo.applicationInfo.uid));
.getUserId(info.activityInfo.applicationInfo.uid));
} catch (RemoteException e) {
perm = PackageManager.PERMISSION_DENIED;
}
@@ -1439,36 +1439,18 @@ public final class BroadcastQueue {
break;
}
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.getAppOpsManager().noteOpNoThrow(appOp,
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
null /* default featureId */,
"Broadcast delivered to " + info.activityInfo.name)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
+ component.flattenToShortString()
+ " requires appop " + AppOpsManager.permissionToOp(
requiredPermission)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
break;
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp) {
if (!noteOpForManifestReceiver(appOp, r, info, component)) {
skip = true;
break;
}
}
}
}
if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.getAppOpsManager().noteOpNoThrow(r.appOp,
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
null /* default featureId */, "Broadcast delivered to " + info.activityInfo.name)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
+ component.flattenToShortString()
+ " requires appop " + AppOpsManager.opToName(r.appOp)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
if (!skip && r.appOp != AppOpsManager.OP_NONE) {
if (!noteOpForManifestReceiver(r.appOp, r, info, component)) {
skip = true;
}
}
boolean isSingleton = false;
try {
@@ -1717,6 +1699,40 @@ public final class BroadcastQueue {
mPendingBroadcastRecvIndex = recIdx;
}
private boolean noteOpForManifestReceiver(int appOp, BroadcastRecord r, ResolveInfo info,
ComponentName component) {
if (info.activityInfo.attributionTags == null) {
return noteOpForManifestReceiverInner(appOp, r, info, component, null);
} else {
// Attribution tags provided, noteOp each tag
for (String tag : info.activityInfo.attributionTags) {
if (!noteOpForManifestReceiverInner(appOp, r, info, component, tag)) {
return false;
}
}
return true;
}
}
private boolean noteOpForManifestReceiverInner(int appOp, BroadcastRecord r, ResolveInfo info,
ComponentName component, String tag) {
if (mService.getAppOpsManager().noteOpNoThrow(appOp,
info.activityInfo.applicationInfo.uid,
info.activityInfo.packageName,
tag,
"Broadcast delivered to " + info.activityInfo.name)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
+ component.flattenToShortString()
+ " requires appop " + AppOpsManager.opToName(appOp)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
return false;
}
return true;
}
private void maybeAddAllowBackgroundActivityStartsToken(ProcessRecord proc, BroadcastRecord r) {
if (r == null || proc == null || !r.allowBackgroundActivityStarts) {
return;