Add Cross-UID ActivityEmbedding trust model APIs
By default activity embedding should be restricted, and apps have to opt in explicitly to allow other hosts to embed them. An app can declare a list of known trusted embedding host certificates in AndroidManifest for individual activities or entire application. Alternatively, an app can allow embedding by all hosts in untrusted mode. In this case interactions and operations that the client host can perform on the embedded container will be limited to prevent tapjacking and overlay attacks. Bug: 197364677 Test: ActivityEmbeddingCrossUidTests Change-Id: I78c303237fdc77bdf55bd74580ac0b19c8de622b
This commit is contained in:
@@ -341,6 +341,7 @@ package android {
|
||||
field public static final int allowSingleTap = 16843353; // 0x1010259
|
||||
field public static final int allowTaskReparenting = 16843268; // 0x1010204
|
||||
field public static final int allowUndo = 16843999; // 0x10104df
|
||||
field public static final int allowUntrustedActivityEmbedding;
|
||||
field public static final int alpha = 16843551; // 0x101031f
|
||||
field public static final int alphabeticModifiers = 16844110; // 0x101054e
|
||||
field public static final int alphabeticShortcut = 16843235; // 0x10101e3
|
||||
@@ -905,6 +906,7 @@ package android {
|
||||
field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
|
||||
field public static final int keycode = 16842949; // 0x10100c5
|
||||
field public static final int killAfterRestore = 16843420; // 0x101029c
|
||||
field public static final int knownActivityEmbeddingCerts;
|
||||
field public static final int knownCerts = 16844330; // 0x101062a
|
||||
field public static final int lStar = 16844359; // 0x1010647
|
||||
field public static final int label = 16842753; // 0x1010001
|
||||
@@ -10966,6 +10968,7 @@ package android.content.pm {
|
||||
ctor public ActivityInfo(android.content.pm.ActivityInfo);
|
||||
method public int describeContents();
|
||||
method public void dump(android.util.Printer, String);
|
||||
method @NonNull public java.util.Set<java.lang.String> getKnownActivityEmbeddingCerts();
|
||||
method public final int getThemeResource();
|
||||
field public static final int COLOR_MODE_DEFAULT = 0; // 0x0
|
||||
field public static final int COLOR_MODE_HDR = 2; // 0x2
|
||||
@@ -10993,6 +10996,7 @@ package android.content.pm {
|
||||
field public static final int DOCUMENT_LAUNCH_NEVER = 3; // 0x3
|
||||
field public static final int DOCUMENT_LAUNCH_NONE = 0; // 0x0
|
||||
field public static final int FLAG_ALLOW_TASK_REPARENTING = 64; // 0x40
|
||||
field public static final int FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING = 268435456; // 0x10000000
|
||||
field public static final int FLAG_ALWAYS_RETAIN_TASK_STATE = 8; // 0x8
|
||||
field public static final int FLAG_AUTO_REMOVE_FROM_RECENTS = 8192; // 0x2000
|
||||
field public static final int FLAG_CLEAR_TASK_ON_LAUNCH = 4; // 0x4
|
||||
@@ -11082,6 +11086,7 @@ package android.content.pm {
|
||||
method public void dump(android.util.Printer, String);
|
||||
method public static CharSequence getCategoryTitle(android.content.Context, int);
|
||||
method public int getGwpAsanMode();
|
||||
method @NonNull public java.util.Set<java.lang.String> getKnownActivityEmbeddingCerts();
|
||||
method public int getMemtagMode();
|
||||
method public int getNativeHeapZeroInitialized();
|
||||
method public int getRequestRawExternalStorageAccess();
|
||||
|
||||
@@ -18,6 +18,8 @@ package android.content.pm;
|
||||
|
||||
import android.annotation.FloatRange;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.Activity;
|
||||
import android.app.compat.CompatChanges;
|
||||
@@ -35,10 +37,16 @@ import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Printer;
|
||||
|
||||
import com.android.internal.util.Parcelling;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Information you can retrieve about a particular application
|
||||
@@ -48,6 +56,9 @@ import java.lang.annotation.RetentionPolicy;
|
||||
*/
|
||||
public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
|
||||
private static final Parcelling.BuiltIn.ForStringSet sForStringSet =
|
||||
Parcelling.Cache.getOrCreate(Parcelling.BuiltIn.ForStringSet.class);
|
||||
|
||||
// NOTE: When adding new data members be sure to update the copy-constructor, Parcel
|
||||
// constructor, and writeToParcel.
|
||||
|
||||
@@ -524,6 +535,13 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_PREFER_MINIMAL_POST_PROCESSING = 0x2000000;
|
||||
|
||||
/**
|
||||
* Bit in {@link #flags}: If set, indicates that the activity can be embedded by untrusted
|
||||
* hosts. In this case the interactions with and visibility of the embedded activity may be
|
||||
* limited. Set from the {@link android.R.attr#allowUntrustedActivityEmbedding} attribute.
|
||||
*/
|
||||
public static final int FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING = 0x10000000;
|
||||
|
||||
/**
|
||||
* @hide Bit in {@link #flags}: If set, this component will only be seen
|
||||
* by the system user. Only works with broadcast receivers. Set from the
|
||||
@@ -561,7 +579,8 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
* {@link #FLAG_STATE_NOT_NEEDED}, {@link #FLAG_EXCLUDE_FROM_RECENTS},
|
||||
* {@link #FLAG_ALLOW_TASK_REPARENTING}, {@link #FLAG_NO_HISTORY},
|
||||
* {@link #FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS},
|
||||
* {@link #FLAG_HARDWARE_ACCELERATED}, {@link #FLAG_SINGLE_USER}.
|
||||
* {@link #FLAG_HARDWARE_ACCELERATED}, {@link #FLAG_SINGLE_USER},
|
||||
* {@link #FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING}.
|
||||
*/
|
||||
public int flags;
|
||||
|
||||
@@ -1079,6 +1098,13 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
|
||||
private static final long CHECK_MIN_WIDTH_HEIGHT_FOR_MULTI_WINDOW = 197654537L;
|
||||
|
||||
/**
|
||||
* Optional set of a certificates identifying apps that are allowed to embed this activity. From
|
||||
* the "knownActivityEmbeddingCerts" attribute.
|
||||
*/
|
||||
@Nullable
|
||||
private Set<String> mKnownActivityEmbeddingCerts;
|
||||
|
||||
/**
|
||||
* Convert Java change bits to native.
|
||||
*
|
||||
@@ -1227,6 +1253,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
launchMode = orig.launchMode;
|
||||
documentLaunchMode = orig.documentLaunchMode;
|
||||
permission = orig.permission;
|
||||
mKnownActivityEmbeddingCerts = orig.mKnownActivityEmbeddingCerts;
|
||||
taskAffinity = orig.taskAffinity;
|
||||
targetActivity = orig.targetActivity;
|
||||
flags = orig.flags;
|
||||
@@ -1442,6 +1469,31 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
return mMinAspectRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the trusted host certificate digests of apps that are allowed to embed this activity.
|
||||
* The digests are computed using the SHA-256 digest algorithm.
|
||||
* @see android.R.attr#knownActivityEmbeddingCerts
|
||||
*/
|
||||
@NonNull
|
||||
public Set<String> getKnownActivityEmbeddingCerts() {
|
||||
return mKnownActivityEmbeddingCerts == null ? Collections.emptySet()
|
||||
: mKnownActivityEmbeddingCerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the trusted host certificates of apps that are allowed to embed this activity.
|
||||
* @see #getKnownActivityEmbeddingCerts()
|
||||
* @hide
|
||||
*/
|
||||
public void setKnownActivityEmbeddingCerts(@NonNull Set<String> knownActivityEmbeddingCerts) {
|
||||
// Convert the provided digest to upper case for consistent Set membership
|
||||
// checks when verifying the signing certificate digests of requesting apps.
|
||||
mKnownActivityEmbeddingCerts = new ArraySet<>();
|
||||
for (String knownCert : knownActivityEmbeddingCerts) {
|
||||
mKnownActivityEmbeddingCerts.add(knownCert.toUpperCase(Locale.US));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isChangeEnabled(long changeId) {
|
||||
return CompatChanges.isChangeEnabled(changeId, applicationInfo.packageName,
|
||||
UserHandle.getUserHandleForUid(applicationInfo.uid));
|
||||
@@ -1573,6 +1625,9 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
if (supportsSizeChanges) {
|
||||
pw.println(prefix + "supportsSizeChanges=true");
|
||||
}
|
||||
if (mKnownActivityEmbeddingCerts != null) {
|
||||
pw.println(prefix + "knownActivityEmbeddingCerts=" + mKnownActivityEmbeddingCerts);
|
||||
}
|
||||
super.dumpBack(pw, prefix, dumpFlags);
|
||||
}
|
||||
|
||||
@@ -1618,6 +1673,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
dest.writeFloat(mMaxAspectRatio);
|
||||
dest.writeFloat(mMinAspectRatio);
|
||||
dest.writeBoolean(supportsSizeChanges);
|
||||
sForStringSet.parcel(mKnownActivityEmbeddingCerts, dest, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1739,6 +1795,10 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
mMaxAspectRatio = source.readFloat();
|
||||
mMinAspectRatio = source.readFloat();
|
||||
supportsSizeChanges = source.readBoolean();
|
||||
mKnownActivityEmbeddingCerts = sForStringSet.unparcel(source);
|
||||
if (mKnownActivityEmbeddingCerts.isEmpty()) {
|
||||
mKnownActivityEmbeddingCerts = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.os.Parcelable;
|
||||
import android.os.UserHandle;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Printer;
|
||||
import android.util.SparseArray;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -52,7 +53,9 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@@ -62,6 +65,8 @@ import java.util.UUID;
|
||||
*/
|
||||
public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
private static ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(ForBoolean.class);
|
||||
private static final Parcelling.BuiltIn.ForStringSet sForStringSet =
|
||||
Parcelling.Cache.getOrCreate(Parcelling.BuiltIn.ForStringSet.class);
|
||||
|
||||
/**
|
||||
* Default task affinity of all activities in this application. See
|
||||
@@ -1550,6 +1555,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
*/
|
||||
private int localeConfigRes;
|
||||
|
||||
/**
|
||||
* Optional set of a certificates identifying apps that are allowed to embed activities of this
|
||||
* application. From the "knownActivityEmbeddingCerts" attribute.
|
||||
*/
|
||||
@Nullable
|
||||
private Set<String> mKnownActivityEmbeddingCerts;
|
||||
|
||||
public void dump(Printer pw, String prefix) {
|
||||
dump(pw, prefix, DUMP_FLAG_ALL);
|
||||
}
|
||||
@@ -1673,6 +1685,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
}
|
||||
}
|
||||
pw.println(prefix + "createTimestamp=" + createTimestamp);
|
||||
if (mKnownActivityEmbeddingCerts != null) {
|
||||
pw.println(prefix + "knownActivityEmbeddingCerts=" + mKnownActivityEmbeddingCerts);
|
||||
}
|
||||
super.dumpBack(pw, prefix);
|
||||
}
|
||||
|
||||
@@ -1787,6 +1802,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
}
|
||||
proto.end(detailToken);
|
||||
}
|
||||
if (!ArrayUtils.isEmpty(mKnownActivityEmbeddingCerts)) {
|
||||
for (String knownCert : mKnownActivityEmbeddingCerts) {
|
||||
proto.write(ApplicationInfoProto.KNOWN_ACTIVITY_EMBEDDING_CERTS, knownCert);
|
||||
}
|
||||
}
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
@@ -1837,6 +1857,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
super(orig);
|
||||
taskAffinity = orig.taskAffinity;
|
||||
permission = orig.permission;
|
||||
mKnownActivityEmbeddingCerts = orig.mKnownActivityEmbeddingCerts;
|
||||
processName = orig.processName;
|
||||
className = orig.className;
|
||||
theme = orig.theme;
|
||||
@@ -2006,6 +2027,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
}
|
||||
}
|
||||
dest.writeInt(localeConfigRes);
|
||||
sForStringSet.parcel(mKnownActivityEmbeddingCerts, dest, flags);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<ApplicationInfo> CREATOR
|
||||
@@ -2102,6 +2124,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
}
|
||||
}
|
||||
localeConfigRes = source.readInt();
|
||||
mKnownActivityEmbeddingCerts = sForStringSet.unparcel(source);
|
||||
if (mKnownActivityEmbeddingCerts.isEmpty()) {
|
||||
mKnownActivityEmbeddingCerts = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2658,7 +2684,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
return localeConfigRes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List of all shared libraries this application is linked against. This
|
||||
* list will only be set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
|
||||
@@ -2675,4 +2700,29 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
return sharedLibraryInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the trusted host certificate digests of apps that are allowed to embed activities of
|
||||
* this application. The digests are computed using the SHA-256 digest algorithm.
|
||||
* @see android.R.attr#knownActivityEmbeddingCerts
|
||||
*/
|
||||
@NonNull
|
||||
public Set<String> getKnownActivityEmbeddingCerts() {
|
||||
return mKnownActivityEmbeddingCerts == null ? Collections.emptySet()
|
||||
: mKnownActivityEmbeddingCerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the trusted host certificates of apps that are allowed to embed activities of this
|
||||
* application.
|
||||
* @see #getKnownActivityEmbeddingCerts()
|
||||
* @hide
|
||||
*/
|
||||
public void setKnownActivityEmbeddingCerts(@NonNull Set<String> knownActivityEmbeddingCerts) {
|
||||
// Convert the provided digest to upper case for consistent Set membership
|
||||
// checks when verifying the signing certificate digests of requesting apps.
|
||||
mKnownActivityEmbeddingCerts = new ArraySet<>();
|
||||
for (String knownCert : knownActivityEmbeddingCerts) {
|
||||
mKnownActivityEmbeddingCerts.add(knownCert.toUpperCase(Locale.US));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,4 +115,5 @@ message ApplicationInfoProto {
|
||||
}
|
||||
optional Detail detail = 17;
|
||||
repeated string overlay_paths = 18;
|
||||
repeated string known_activity_embedding_certs = 19;
|
||||
}
|
||||
|
||||
@@ -1048,6 +1048,24 @@
|
||||
<p>The default value of this attribute is <code>false</code>. -->
|
||||
<attr name="allowEmbedded" format="boolean" />
|
||||
|
||||
<!-- A reference to an array resource containing the signing certificate digests, one of which a
|
||||
client is required to be signed with in order to embed the activity. If the client is not
|
||||
signed with one of the certificates in the set, and the activity does not allow embedding
|
||||
by untrusted hosts via {@link android.R.attr#allowUntrustedActivityEmbedding} flag, the
|
||||
embedding request will fail.
|
||||
<p>The digest should be computed over the DER encoding of the trusted certificate using the
|
||||
SHA-256 digest algorithm.
|
||||
<p>If only a single signer is declared this can also be a string resource, or the digest
|
||||
can be declared inline as the value for this attribute.
|
||||
<p>If the attribute is declared both on the application and the activity level, the value
|
||||
on the activity level takes precedence. -->
|
||||
<attr name="knownActivityEmbeddingCerts" format="reference|string" />
|
||||
|
||||
<!-- Indicate that the activity can be embedded by untrusted hosts. In this case the
|
||||
interactions and visibility of the embedded activity may be limited.
|
||||
<p>The default value of this attribute is <code>false</code>. -->
|
||||
<attr name="allowUntrustedActivityEmbedding" format="boolean" />
|
||||
|
||||
<!-- Specifies whether this {@link android.app.Activity} should be shown on
|
||||
top of the lock screen whenever the lockscreen is up and this activity has another
|
||||
activity behind it with the {@link android.R.attr#showWhenLocked} attribute set. That
|
||||
@@ -2011,6 +2029,7 @@
|
||||
when the application's user data is cleared. The default value is false.
|
||||
-->
|
||||
<attr name="resetEnabledSettingsOnAppDataCleared" format="boolean" />
|
||||
<attr name="knownActivityEmbeddingCerts" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- An attribution is a logical part of an app and is identified by a tag.
|
||||
@@ -3033,6 +3052,8 @@
|
||||
<!-- Indicates whether the activity can be displayed on a remote device which may or
|
||||
may not be running Android. -->
|
||||
<attr name="canDisplayOnRemoteDevices" format="boolean"/>
|
||||
<attr name="allowUntrustedActivityEmbedding" />
|
||||
<attr name="knownActivityEmbeddingCerts" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>activity-alias</code> tag declares a new
|
||||
@@ -3073,6 +3094,8 @@
|
||||
<attr name="exported" />
|
||||
<attr name="parentActivityName" />
|
||||
<attr name="attributionTags" />
|
||||
<attr name="allowUntrustedActivityEmbedding" />
|
||||
<attr name="knownActivityEmbeddingCerts" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>meta-data</code> tag is used to attach additional
|
||||
|
||||
@@ -3276,6 +3276,8 @@
|
||||
<public name="toExtendBottom" />
|
||||
<public name="tileService" />
|
||||
<public name="windowSplashScreenBehavior" />
|
||||
<public name="allowUntrustedActivityEmbedding" />
|
||||
<public name="knownActivityEmbeddingCerts" />
|
||||
</staging-public-group>
|
||||
|
||||
<staging-public-group type="id" first-id="0x01de0000">
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.ActivityInfo;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/** @hide **/
|
||||
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
|
||||
public interface ParsedActivity extends ParsedMainComponent {
|
||||
@@ -59,6 +61,12 @@ public interface ParsedActivity extends ParsedMainComponent {
|
||||
@Nullable
|
||||
String getPermission();
|
||||
|
||||
/**
|
||||
* Gets the trusted host certificates of apps that are allowed to embed this activity.
|
||||
*/
|
||||
@NonNull
|
||||
Set<String> getKnownActivityEmbeddingCerts();
|
||||
|
||||
int getPersistableMode();
|
||||
|
||||
int getPrivateFlags();
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
|
||||
|
||||
import static com.android.server.pm.pkg.parsing.ParsingPackageImpl.sForInternedString;
|
||||
import static com.android.server.pm.pkg.parsing.ParsingPackageImpl.sForStringSet;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -33,12 +34,17 @@ import android.content.pm.PackageManager;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.DataClass;
|
||||
import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
|
||||
import com.android.server.pm.pkg.parsing.ParsingUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
**/
|
||||
@@ -63,6 +69,8 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
@Nullable
|
||||
@DataClass.ParcelWith(ForInternedString.class)
|
||||
private String permission;
|
||||
@Nullable
|
||||
private Set<String> mKnownActivityEmbeddingCerts;
|
||||
|
||||
private int launchMode;
|
||||
private int documentLaunchMode;
|
||||
@@ -113,6 +121,7 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
this.rotationAnimation = other.rotationAnimation;
|
||||
this.colorMode = other.colorMode;
|
||||
this.windowLayout = other.windowLayout;
|
||||
this.mKnownActivityEmbeddingCerts = other.mKnownActivityEmbeddingCerts;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,6 +248,25 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Set<String> getKnownActivityEmbeddingCerts() {
|
||||
return mKnownActivityEmbeddingCerts == null ? Collections.emptySet()
|
||||
: mKnownActivityEmbeddingCerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the trusted host certificates of apps that are allowed to embed this activity.
|
||||
*/
|
||||
public void setKnownActivityEmbeddingCerts(@NonNull Set<String> knownActivityEmbeddingCerts) {
|
||||
// Convert the provided digest to upper case for consistent Set membership
|
||||
// checks when verifying the signing certificate digests of requesting apps.
|
||||
this.mKnownActivityEmbeddingCerts = new ArraySet<>();
|
||||
for (String knownCert : knownActivityEmbeddingCerts) {
|
||||
this.mKnownActivityEmbeddingCerts.add(knownCert.toUpperCase(Locale.US));
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("Activity{");
|
||||
@@ -287,6 +315,7 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
} else {
|
||||
dest.writeBoolean(false);
|
||||
}
|
||||
sForStringSet.parcel(this.mKnownActivityEmbeddingCerts, dest, flags);
|
||||
}
|
||||
|
||||
public ParsedActivityImpl() {
|
||||
@@ -320,6 +349,7 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
if (in.readBoolean()) {
|
||||
windowLayout = new ActivityInfo.WindowLayout(in);
|
||||
}
|
||||
this.mKnownActivityEmbeddingCerts = sForStringSet.unparcel(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -344,7 +374,7 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
//
|
||||
// To regenerate run:
|
||||
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedActivityImpl.java
|
||||
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java
|
||||
//
|
||||
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
|
||||
// Settings > Editor > Code Style > Formatter Control
|
||||
@@ -360,6 +390,7 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
@Nullable String taskAffinity,
|
||||
int privateFlags,
|
||||
@Nullable String permission,
|
||||
@Nullable Set<String> knownActivityEmbeddingCerts,
|
||||
int launchMode,
|
||||
int documentLaunchMode,
|
||||
int maxRecents,
|
||||
@@ -383,6 +414,7 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
this.taskAffinity = taskAffinity;
|
||||
this.privateFlags = privateFlags;
|
||||
this.permission = permission;
|
||||
this.mKnownActivityEmbeddingCerts = knownActivityEmbeddingCerts;
|
||||
this.launchMode = launchMode;
|
||||
this.documentLaunchMode = documentLaunchMode;
|
||||
this.maxRecents = maxRecents;
|
||||
@@ -645,10 +677,10 @@ public class ParsedActivityImpl extends ParsedMainComponentImpl implements Parse
|
||||
}
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1641431949361L,
|
||||
time = 1644372875433L,
|
||||
codegenVersion = "1.0.23",
|
||||
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedActivityImpl.java",
|
||||
inputSignatures = "private int theme\nprivate int uiOptions\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetActivity\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String parentActivityName\nprivate @android.annotation.Nullable java.lang.String taskAffinity\nprivate int privateFlags\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\nprivate int launchMode\nprivate int documentLaunchMode\nprivate int maxRecents\nprivate int configChanges\nprivate int softInputMode\nprivate int persistableMode\nprivate int lockTaskLaunchMode\nprivate int screenOrientation\nprivate int resizeMode\nprivate float maxAspectRatio\nprivate float minAspectRatio\nprivate boolean supportsSizeChanges\nprivate @android.annotation.Nullable java.lang.String requestedVrComponent\nprivate int rotationAnimation\nprivate int colorMode\nprivate @android.annotation.Nullable android.content.pm.ActivityInfo.WindowLayout windowLayout\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.parsing.component.ParsedActivityImpl> CREATOR\nstatic @android.annotation.NonNull android.content.pm.parsing.component.ParsedActivityImpl makeAppDetailsActivity(java.lang.String,java.lang.String,int,java.lang.String,boolean)\nstatic @android.annotation.NonNull android.content.pm.parsing.component.ParsedActivityImpl makeAlias(java.lang.String,android.content.pm.parsing.component.ParsedActivity)\npublic android.content.pm.parsing.component.ParsedActivityImpl setMaxAspectRatio(int,float)\npublic android.content.pm.parsing.component.ParsedActivityImpl setMinAspectRatio(int,float)\npublic android.content.pm.parsing.component.ParsedActivityImpl setTargetActivity(java.lang.String)\npublic android.content.pm.parsing.component.ParsedActivityImpl setPermission(java.lang.String)\npublic java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedActivityImpl extends android.content.pm.parsing.component.ParsedMainComponentImpl implements [android.content.pm.parsing.component.ParsedActivity, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
|
||||
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java",
|
||||
inputSignatures = "private int theme\nprivate int uiOptions\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetActivity\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String parentActivityName\nprivate @android.annotation.Nullable java.lang.String taskAffinity\nprivate int privateFlags\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> mKnownActivityEmbeddingCerts\nprivate int launchMode\nprivate int documentLaunchMode\nprivate int maxRecents\nprivate int configChanges\nprivate int softInputMode\nprivate int persistableMode\nprivate int lockTaskLaunchMode\nprivate int screenOrientation\nprivate int resizeMode\nprivate float maxAspectRatio\nprivate float minAspectRatio\nprivate boolean supportsSizeChanges\nprivate @android.annotation.Nullable java.lang.String requestedVrComponent\nprivate int rotationAnimation\nprivate int colorMode\nprivate @android.annotation.Nullable android.content.pm.ActivityInfo.WindowLayout windowLayout\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.server.pm.pkg.component.ParsedActivityImpl> CREATOR\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAppDetailsActivity(java.lang.String,java.lang.String,int,java.lang.String,boolean)\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAlias(java.lang.String,com.android.server.pm.pkg.component.ParsedActivity)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setMaxAspectRatio(int,float)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setMinAspectRatio(int,float)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setTargetActivity(java.lang.String)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setPermission(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override java.util.Set<java.lang.String> getKnownActivityEmbeddingCerts()\npublic void setKnownActivityEmbeddingCerts(java.util.Set<java.lang.String>)\npublic java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedActivityImpl extends com.android.server.pm.pkg.component.ParsedMainComponentImpl implements [com.android.server.pm.pkg.component.ParsedActivity, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
|
||||
import static com.android.server.pm.pkg.component.ComponentParseUtils.flag;
|
||||
import static com.android.server.pm.pkg.parsing.ParsingUtils.NOT_SET;
|
||||
import static com.android.server.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -151,7 +152,8 @@ public class ParsedActivityUtils {
|
||||
| flag(ActivityInfo.FLAG_SHOW_WHEN_LOCKED, R.styleable.AndroidManifestActivity_showWhenLocked, sa)
|
||||
| flag(ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE, R.styleable.AndroidManifestActivity_supportsPictureInPicture, sa)
|
||||
| flag(ActivityInfo.FLAG_TURN_SCREEN_ON, R.styleable.AndroidManifestActivity_turnScreenOn, sa)
|
||||
| flag(ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING, R.styleable.AndroidManifestActivity_preferMinimalPostProcessing, sa)));
|
||||
| flag(ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING, R.styleable.AndroidManifestActivity_preferMinimalPostProcessing, sa))
|
||||
| flag(ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING, R.styleable.AndroidManifestActivity_allowUntrustedActivityEmbedding, sa));
|
||||
|
||||
activity.setPrivateFlags(activity.getPrivateFlags() | (flag(ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED,
|
||||
R.styleable.AndroidManifestActivity_inheritShowWhenLocked, sa)
|
||||
@@ -338,6 +340,20 @@ public class ParsedActivityUtils {
|
||||
activity.setPermission(permission != null ? permission : pkg.getPermission());
|
||||
}
|
||||
|
||||
final ParseResult<Set<String>> knownActivityEmbeddingCertsResult =
|
||||
parseKnownActivityEmbeddingCerts(array, resources, isAlias
|
||||
? R.styleable.AndroidManifestActivityAlias_knownActivityEmbeddingCerts
|
||||
: R.styleable.AndroidManifestActivity_knownActivityEmbeddingCerts, input);
|
||||
if (knownActivityEmbeddingCertsResult.isError()) {
|
||||
return input.error(knownActivityEmbeddingCertsResult);
|
||||
} else {
|
||||
final Set<String> knownActivityEmbeddingCerts = knownActivityEmbeddingCertsResult
|
||||
.getResult();
|
||||
if (knownActivityEmbeddingCerts != null) {
|
||||
activity.setKnownActivityEmbeddingCerts(knownActivityEmbeddingCerts);
|
||||
}
|
||||
}
|
||||
|
||||
final boolean setExported = array.hasValue(exportedAttr);
|
||||
if (setExported) {
|
||||
activity.setExported(array.getBoolean(exportedAttr, false));
|
||||
|
||||
@@ -549,6 +549,7 @@ public class PackageInfoWithoutStateUtils {
|
||||
ai.metaData = a.getMetaData();
|
||||
}
|
||||
ai.applicationInfo = applicationInfo;
|
||||
ai.setKnownActivityEmbeddingCerts(a.getKnownActivityEmbeddingCerts());
|
||||
return ai;
|
||||
}
|
||||
|
||||
|
||||
@@ -381,6 +381,12 @@ public interface ParsingPackage extends ParsingPackageRead {
|
||||
|
||||
ParsingPackage setLocaleConfigRes(int localeConfigRes);
|
||||
|
||||
/**
|
||||
* Sets the trusted host certificates of apps that are allowed to embed activities of this
|
||||
* application.
|
||||
*/
|
||||
ParsingPackage setKnownActivityEmbeddingCerts(Set<String> knownActivityEmbeddingCerts);
|
||||
|
||||
// TODO(b/135203078): This class no longer has access to ParsedPackage, find a replacement
|
||||
// for moving to the next step
|
||||
@CallSuper
|
||||
|
||||
@@ -563,6 +563,9 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
|
||||
return (mBooleans & flag) != 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Set<String> mKnownActivityEmbeddingCerts;
|
||||
|
||||
// Derived fields
|
||||
@NonNull
|
||||
private UUID mStorageUuid;
|
||||
@@ -1150,6 +1153,9 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
|
||||
appInfo.setVersionCode(mLongVersionCode);
|
||||
appInfo.setAppClassNamesByProcess(buildAppClassNamesByProcess());
|
||||
appInfo.setLocaleConfigRes(mLocaleConfigRes);
|
||||
if (mKnownActivityEmbeddingCerts != null) {
|
||||
appInfo.setKnownActivityEmbeddingCerts(mKnownActivityEmbeddingCerts);
|
||||
}
|
||||
|
||||
return appInfo;
|
||||
}
|
||||
@@ -1329,6 +1335,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
|
||||
dest.writeInt(this.nativeHeapZeroInitialized);
|
||||
sForBoolean.parcel(this.requestRawExternalStorageAccess, dest, flags);
|
||||
dest.writeInt(this.mLocaleConfigRes);
|
||||
sForStringSet.parcel(mKnownActivityEmbeddingCerts, dest, flags);
|
||||
}
|
||||
|
||||
public ParsingPackageImpl(Parcel in) {
|
||||
@@ -1477,6 +1484,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
|
||||
this.nativeHeapZeroInitialized = in.readInt();
|
||||
this.requestRawExternalStorageAccess = sForBoolean.unparcel(in);
|
||||
this.mLocaleConfigRes = in.readInt();
|
||||
this.mKnownActivityEmbeddingCerts = sForStringSet.unparcel(in);
|
||||
assignDerivedFields();
|
||||
}
|
||||
|
||||
@@ -2376,6 +2384,13 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
|
||||
return getBoolean(Booleans.RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Set<String> getKnownActivityEmbeddingCerts() {
|
||||
return mKnownActivityEmbeddingCerts == null ? Collections.emptySet()
|
||||
: mKnownActivityEmbeddingCerts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldInheritKeyStoreKeys() {
|
||||
return getBoolean(Booleans.INHERIT_KEYSTORE_KEYS);
|
||||
@@ -2973,4 +2988,11 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
|
||||
mLocaleConfigRes = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParsingPackage setKnownActivityEmbeddingCerts(
|
||||
@Nullable Set<String> knownEmbeddingCerts) {
|
||||
mKnownActivityEmbeddingCerts = knownEmbeddingCerts;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import static android.os.Build.VERSION_CODES.DONUT;
|
||||
import static android.os.Build.VERSION_CODES.O;
|
||||
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
|
||||
|
||||
import static com.android.server.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
|
||||
|
||||
import android.annotation.AnyRes;
|
||||
import android.annotation.CheckResult;
|
||||
import android.annotation.IntDef;
|
||||
@@ -2009,6 +2011,19 @@ public class ParsingPackageUtils {
|
||||
.AndroidManifestApplication_requestForegroundServiceExemption,
|
||||
false));
|
||||
}
|
||||
final ParseResult<Set<String>> knownActivityEmbeddingCertsResult =
|
||||
parseKnownActivityEmbeddingCerts(sa, res,
|
||||
R.styleable.AndroidManifestApplication_knownActivityEmbeddingCerts,
|
||||
input);
|
||||
if (knownActivityEmbeddingCertsResult.isError()) {
|
||||
return input.error(knownActivityEmbeddingCertsResult);
|
||||
} else {
|
||||
final Set<String> knownActivityEmbeddingCerts = knownActivityEmbeddingCertsResult
|
||||
.getResult();
|
||||
if (knownActivityEmbeddingCerts != null) {
|
||||
pkg.setKnownActivityEmbeddingCerts(knownActivityEmbeddingCerts);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
sa.recycle();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.parsing.result.ParseInput;
|
||||
import android.content.pm.parsing.result.ParseResult;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
@@ -38,6 +40,7 @@ import org.xmlpull.v1.XmlPullParserException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/** @hide **/
|
||||
public class ParsingUtils {
|
||||
@@ -168,4 +171,50 @@ public class ParsingUtils {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the {@link android.R.attr#knownActivityEmbeddingCerts} attribute, if available.
|
||||
*/
|
||||
@NonNull
|
||||
public static ParseResult<Set<String>> parseKnownActivityEmbeddingCerts(@NonNull TypedArray sa,
|
||||
@NonNull Resources res, int resourceId, @NonNull ParseInput input) {
|
||||
if (!sa.hasValue(resourceId)) {
|
||||
return input.success(null);
|
||||
}
|
||||
|
||||
final int knownActivityEmbeddingCertsResource = sa.getResourceId(resourceId, 0);
|
||||
if (knownActivityEmbeddingCertsResource != 0) {
|
||||
// The knownCerts attribute supports both a string array resource as well as a
|
||||
// string resource for the case where the permission should only be granted to a
|
||||
// single known signer.
|
||||
Set<String> knownEmbeddingCertificates = null;
|
||||
final String resourceType = res.getResourceTypeName(
|
||||
knownActivityEmbeddingCertsResource);
|
||||
if (resourceType.equals("array")) {
|
||||
final String[] knownCerts = res.getStringArray(knownActivityEmbeddingCertsResource);
|
||||
if (knownCerts != null) {
|
||||
knownEmbeddingCertificates = Set.of(knownCerts);
|
||||
}
|
||||
} else {
|
||||
final String knownCert = res.getString(knownActivityEmbeddingCertsResource);
|
||||
if (knownCert != null) {
|
||||
knownEmbeddingCertificates = Set.of(knownCert);
|
||||
}
|
||||
}
|
||||
if (knownEmbeddingCertificates == null || knownEmbeddingCertificates.isEmpty()) {
|
||||
return input.error("Defined a knownActivityEmbeddingCerts attribute but the "
|
||||
+ "provided resource is null");
|
||||
}
|
||||
return input.success(knownEmbeddingCertificates);
|
||||
}
|
||||
|
||||
// If the knownCerts resource ID is null - the app specified a string value for the
|
||||
// attribute representing a single trusted signer.
|
||||
final String knownCert = sa.getString(resourceId);
|
||||
if (knownCert == null || knownCert.isEmpty()) {
|
||||
return input.error("Defined a knownActivityEmbeddingCerts attribute but the provided "
|
||||
+ "string is empty");
|
||||
}
|
||||
return input.success(Set.of(knownCert));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.annotation.Nullable;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Container for fields that are eventually exposed through {@link ApplicationInfo}.
|
||||
* <p>
|
||||
@@ -284,6 +286,13 @@ public interface PkgWithoutStateAppInfo {
|
||||
@Nullable
|
||||
String getPermission();
|
||||
|
||||
/**
|
||||
* @see ApplicationInfo#knownActivityEmbeddingCerts
|
||||
* @see R.styleable#AndroidManifestApplication_knownActivityEmbeddingCerts
|
||||
*/
|
||||
@NonNull
|
||||
Set<String> getKnownActivityEmbeddingCerts();
|
||||
|
||||
/**
|
||||
* @see ApplicationInfo#processName
|
||||
* @see R.styleable#AndroidManifestApplication_process
|
||||
|
||||
@@ -508,7 +508,8 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag
|
||||
AndroidPackage::shouldInheritKeyStoreKeys,
|
||||
ParsingPackage::setInheritKeyStoreKeys,
|
||||
true
|
||||
)
|
||||
),
|
||||
getter(AndroidPackage::getKnownActivityEmbeddingCerts, setOf("TESTEMBEDDINGCERT"))
|
||||
)
|
||||
|
||||
override fun initialObject() = PackageImpl.forParsing(
|
||||
|
||||
@@ -53,7 +53,7 @@ class ParsedActivityTest : ParsedMainComponentTest(
|
||||
ParsedActivity::getTaskAffinity,
|
||||
ParsedActivity::getTheme,
|
||||
ParsedActivity::getUiOptions,
|
||||
ParsedActivity::isSupportsSizeChanges,
|
||||
ParsedActivity::isSupportsSizeChanges
|
||||
)
|
||||
|
||||
override fun mainComponentSubclassExtraParams() = listOf(
|
||||
@@ -73,6 +73,7 @@ class ParsedActivityTest : ParsedMainComponentTest(
|
||||
ActivityInfo.WindowLayout::minHeight
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
getter(ParsedActivity::getKnownActivityEmbeddingCerts, setOf("TESTEMBEDDINGCERT"))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -895,6 +895,7 @@ public class PackageParserTest {
|
||||
assertEquals(a.networkSecurityConfigRes, that.networkSecurityConfigRes);
|
||||
assertEquals(a.taskAffinity, that.taskAffinity);
|
||||
assertEquals(a.permission, that.permission);
|
||||
assertEquals(a.getKnownActivityEmbeddingCerts(), that.getKnownActivityEmbeddingCerts());
|
||||
assertEquals(a.processName, that.processName);
|
||||
assertEquals(a.className, that.className);
|
||||
assertEquals(a.manageSpaceActivityName, that.manageSpaceActivityName);
|
||||
|
||||
Reference in New Issue
Block a user