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

Commit a0ac8d3a authored by Winson Chiu's avatar Winson Chiu Committed by Android (Google) Code Review
Browse files

Merge changes I8d5a10c3,I3d629722,I35072d6e,I6cc270fb,I19b88fb5, ... into sc-dev

* changes:
  Remove app links caller BROWSABLE requirement
  Fix DomainVerificationShell user/allowed bugs
  Remove pending/restored domain state when attaching
  Check user ID for domain verification setters
  Expose error codes for domain verification setters
  Move domain state ints to DomainVerificationInfo
  Migrate approved/denied domain states and add tests
parents a481a433 1122021b
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -2837,21 +2837,29 @@ package android.content.pm.verify.domain {
    method @NonNull public String getPackageName();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.verify.domain.DomainVerificationInfo> CREATOR;
    field public static final int STATE_FIRST_VERIFIER_DEFINED = 1024; // 0x400
    field public static final int STATE_MODIFIABLE_UNVERIFIED = 3; // 0x3
    field public static final int STATE_MODIFIABLE_VERIFIED = 4; // 0x4
    field public static final int STATE_NO_RESPONSE = 0; // 0x0
    field public static final int STATE_SUCCESS = 1; // 0x1
    field public static final int STATE_UNMODIFIABLE = 2; // 0x2
  }
  public final class DomainVerificationManager {
    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.DOMAIN_VERIFICATION_AGENT, android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION}) public android.content.pm.verify.domain.DomainVerificationInfo getDomainVerificationInfo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
    method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public java.util.List<android.content.pm.verify.domain.DomainOwner> getOwnersForDomain(@NonNull String);
    method public static boolean isStateModifiable(int);
    method public static boolean isStateVerified(int);
    method @NonNull @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public java.util.List<java.lang.String> queryValidVerificationPackageNames();
    method @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public void setDomainVerificationLinkHandlingAllowed(@NonNull String, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
    method @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public void setDomainVerificationStatus(@NonNull java.util.UUID, @NonNull java.util.Set<java.lang.String>, int) throws android.content.pm.PackageManager.NameNotFoundException;
    method @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public void setDomainVerificationUserSelection(@NonNull java.util.UUID, @NonNull java.util.Set<java.lang.String>, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
    method @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public int setDomainVerificationStatus(@NonNull java.util.UUID, @NonNull java.util.Set<java.lang.String>, int) throws android.content.pm.PackageManager.NameNotFoundException;
    method @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public int setDomainVerificationUserSelection(@NonNull java.util.UUID, @NonNull java.util.Set<java.lang.String>, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
    field public static final int ERROR_DOMAIN_SET_ID_INVALID = 1; // 0x1
    field public static final int ERROR_DOMAIN_SET_ID_NULL = 2; // 0x2
    field public static final int ERROR_DOMAIN_SET_NULL_OR_EMPTY = 3; // 0x3
    field public static final int ERROR_INVALID_STATE_CODE = 6; // 0x6
    field public static final int ERROR_UNABLE_TO_APPROVE = 5; // 0x5
    field public static final int ERROR_UNKNOWN_DOMAIN = 4; // 0x4
    field public static final String EXTRA_VERIFICATION_REQUEST = "android.content.pm.verify.domain.extra.VERIFICATION_REQUEST";
    field public static final int STATE_FIRST_VERIFIER_DEFINED = 1024; // 0x400
    field public static final int STATE_NO_RESPONSE = 0; // 0x0
    field public static final int STATE_SUCCESS = 1; // 0x1
    field public static final int STATUS_OK = 0; // 0x0
  }
  public final class DomainVerificationRequest implements android.os.Parcelable {
+33 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.content.pm;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -183,6 +184,17 @@ public class ResolveInfo implements Parcelable {
    @SystemApi
    public boolean handleAllWebDataURI;

    /**
     * Whether the resolved {@link IntentFilter} declares {@link Intent#CATEGORY_BROWSABLE} and is
     * thus allowed to automatically resolve an {@link Intent} as it's assumed the action is safe
     * for the user.
     *
     * Note that the above doesn't apply when this is the only result is returned in the candidate
     * set, as the system will not prompt before opening the result. It only applies when there are
     * multiple candidates.
     */
    private final boolean mAutoResolutionAllowed;

    /** {@hide} */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public ComponentInfo getComponentInfo() {
@@ -364,8 +376,26 @@ public class ResolveInfo implements Parcelable {
                && INTENT_FORWARDER_ACTIVITY.equals(activityInfo.targetActivity);
    }

    /**
     * @see #mAutoResolutionAllowed
     * @hide
     */
    public boolean isAutoResolutionAllowed() {
        return mAutoResolutionAllowed;
    }

    public ResolveInfo() {
        targetUserId = UserHandle.USER_CURRENT;

        // It's safer to assume that an unaware caller that constructs a ResolveInfo doesn't
        // accidentally mark a result as auto resolveable.
        mAutoResolutionAllowed = false;
    }

    /** @hide */
    public ResolveInfo(boolean autoResolutionAllowed) {
        targetUserId = UserHandle.USER_CURRENT;
        mAutoResolutionAllowed = autoResolutionAllowed;
    }

    public ResolveInfo(ResolveInfo orig) {
@@ -386,6 +416,7 @@ public class ResolveInfo implements Parcelable {
        system = orig.system;
        targetUserId = orig.targetUserId;
        handleAllWebDataURI = orig.handleAllWebDataURI;
        mAutoResolutionAllowed = orig.mAutoResolutionAllowed;
        isInstantAppAvailable = orig.isInstantAppAvailable;
    }

@@ -450,6 +481,7 @@ public class ResolveInfo implements Parcelable {
        dest.writeInt(noResourceId ? 1 : 0);
        dest.writeInt(iconResourceId);
        dest.writeInt(handleAllWebDataURI ? 1 : 0);
        dest.writeInt(mAutoResolutionAllowed ? 1 : 0);
        dest.writeInt(isInstantAppAvailable ? 1 : 0);
    }

@@ -498,6 +530,7 @@ public class ResolveInfo implements Parcelable {
        noResourceId = source.readInt() != 0;
        iconResourceId = source.readInt();
        handleAllWebDataURI = source.readInt() != 0;
        mAutoResolutionAllowed = source.readInt() != 0;
        isInstantAppAvailable = source.readInt() != 0;
    }

+92 −30
Original line number Diff line number Diff line
@@ -43,9 +43,50 @@ import java.util.UUID;
 */
@SystemApi
@DataClass(genAidl = true, genHiddenConstructor = true, genParcelable = true, genToString = true,
        genEqualsHashCode = true)
        genEqualsHashCode = true, genHiddenConstDefs = true)
public final class DomainVerificationInfo implements Parcelable {

    // Implementation note: the following states are OUTPUT only. Any value that is synonymous with
    // a value in DomainVerificationState must be the EXACT same integer, so that state
    // transformation does not have to occur when sending input into the system, assuming that the
    // system only accepts those synonymous values. The public API values declared here are only
    // used when exiting the system server to prepare this data object for consumption by the
    // verification agent. These constants should only be referenced inside public API classes.
    // The server must use DomainVerificationState.

    /**
     * No response has been recorded by either the system or any verification agent.
     */
    public static final int STATE_NO_RESPONSE = DomainVerificationState.STATE_NO_RESPONSE;

    /**
     * The domain has been explicitly verified.
     */
    public static final int STATE_SUCCESS = DomainVerificationState.STATE_SUCCESS;

    /**
     * Indicates the host cannot be modified by the verification agent.
     */
    public static final int STATE_UNMODIFIABLE = 2;

    /**
     * Indicates the host can be modified by the verification agent and is not considered verified.
     */
    public static final int STATE_MODIFIABLE_UNVERIFIED = 3;

    /**
     * Indicates the host can be modified by the verification agent and is considered verified.
     */
    public static final int STATE_MODIFIABLE_VERIFIED = 4;

    /**
     * The first available custom response code. This and any greater integer, along with {@link
     * #STATE_SUCCESS} are the only values settable by the verification agent. All custom values
     * will be treated as if the domain is unverified.
     */
    public static final int STATE_FIRST_VERIFIER_DEFINED =
            DomainVerificationState.STATE_FIRST_VERIFIER_DEFINED;

    /**
     * A domain verification ID for use in later API calls. This represents the snapshot of the
     * domains for a package on device, and will be invalidated whenever the package changes.
@@ -74,16 +115,12 @@ public final class DomainVerificationInfo implements Parcelable {

    /**
     * Map of host names to their current state. State is an integer, which defaults to {@link
     * DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the domain
     * verification agent (the intended consumer of this API), which can be equal to {@link
     * DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or greater than {@link
     * DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
     * #STATE_NO_RESPONSE}. State can be modified by the domain verification agent (the intended
     * consumer of this API), which can be equal to {@link #STATE_SUCCESS} when verified, or equal
     * to or greater than {@link #STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
     * <p>
     * Any value non-inclusive between those 2 values are reserved for use by the system. The domain
     * verification agent may be able to act on these reserved values, and this ability can be
     * queried using {@link DomainVerificationManager#isStateModifiable(int)}. It is expected that
     * the agent attempt to verify all domains that it can modify the state of, even if it does not
     * understand the meaning of those values.
     * Hosts which cannot be edited will be assigned {@link #STATE_UNMODIFIABLE}. It is expected
     * that the agent attempt to verify all domains that it can modify the state of.
     */
    @NonNull
    private final Map<String, Integer> mHostToStateMap;
@@ -112,6 +149,39 @@ public final class DomainVerificationInfo implements Parcelable {
    //@formatter:off


    /** @hide */
    @android.annotation.IntDef(prefix = "STATE_", value = {
        STATE_NO_RESPONSE,
        STATE_SUCCESS,
        STATE_UNMODIFIABLE,
        STATE_MODIFIABLE_UNVERIFIED,
        STATE_MODIFIABLE_VERIFIED,
        STATE_FIRST_VERIFIER_DEFINED
    })
    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
    @DataClass.Generated.Member
    public @interface State {}

    /** @hide */
    @DataClass.Generated.Member
    public static String stateToString(@State int value) {
        switch (value) {
            case STATE_NO_RESPONSE:
                    return "STATE_NO_RESPONSE";
            case STATE_SUCCESS:
                    return "STATE_SUCCESS";
            case STATE_UNMODIFIABLE:
                    return "STATE_UNMODIFIABLE";
            case STATE_MODIFIABLE_UNVERIFIED:
                    return "STATE_MODIFIABLE_UNVERIFIED";
            case STATE_MODIFIABLE_VERIFIED:
                    return "STATE_MODIFIABLE_VERIFIED";
            case STATE_FIRST_VERIFIER_DEFINED:
                    return "STATE_FIRST_VERIFIER_DEFINED";
            default: return Integer.toHexString(value);
        }
    }

    /**
     * Creates a new DomainVerificationInfo.
     *
@@ -134,16 +204,12 @@ public final class DomainVerificationInfo implements Parcelable {
     *   The package name that this data corresponds to.
     * @param hostToStateMap
     *   Map of host names to their current state. State is an integer, which defaults to {@link
     *   DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the domain
     *   verification agent (the intended consumer of this API), which can be equal to {@link
     *   DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or greater than {@link
     *   DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
     *   #STATE_NO_RESPONSE}. State can be modified by the domain verification agent (the intended
     *   consumer of this API), which can be equal to {@link #STATE_SUCCESS} when verified, or equal
     *   to or greater than {@link #STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
     *   <p>
     *   Any value non-inclusive between those 2 values are reserved for use by the system. The domain
     *   verification agent may be able to act on these reserved values, and this ability can be
     *   queried using {@link DomainVerificationManager#isStateModifiable(int)}. It is expected that
     *   the agent attempt to verify all domains that it can modify the state of, even if it does not
     *   understand the meaning of those values.
     *   Hosts which cannot be edited will be assigned {@link #STATE_UNMODIFIABLE}. It is expected
     *   that the agent attempt to verify all domains that it can modify the state of.
     * @hide
     */
    @DataClass.Generated.Member
@@ -195,16 +261,12 @@ public final class DomainVerificationInfo implements Parcelable {

    /**
     * Map of host names to their current state. State is an integer, which defaults to {@link
     * DomainVerificationManager#STATE_NO_RESPONSE}. State can be modified by the domain
     * verification agent (the intended consumer of this API), which can be equal to {@link
     * DomainVerificationManager#STATE_SUCCESS} when verified, or equal to or greater than {@link
     * DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
     * #STATE_NO_RESPONSE}. State can be modified by the domain verification agent (the intended
     * consumer of this API), which can be equal to {@link #STATE_SUCCESS} when verified, or equal
     * to or greater than {@link #STATE_FIRST_VERIFIER_DEFINED} for any unsuccessful response.
     * <p>
     * Any value non-inclusive between those 2 values are reserved for use by the system. The domain
     * verification agent may be able to act on these reserved values, and this ability can be
     * queried using {@link DomainVerificationManager#isStateModifiable(int)}. It is expected that
     * the agent attempt to verify all domains that it can modify the state of, even if it does not
     * understand the meaning of those values.
     * Hosts which cannot be edited will be assigned {@link #STATE_UNMODIFIABLE}. It is expected
     * that the agent attempt to verify all domains that it can modify the state of.
     */
    @DataClass.Generated.Member
    public @NonNull Map<String,Integer> getHostToStateMap() {
@@ -320,10 +382,10 @@ public final class DomainVerificationInfo implements Parcelable {
    };

    @DataClass.Generated(
            time = 1614721812023L,
            time = 1615317187669L,
            codegenVersion = "1.0.22",
            sourceFile = "frameworks/base/core/java/android/content/pm/verify/domain/DomainVerificationInfo.java",
            inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForUUID.class) java.util.UUID mIdentifier\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.Integer> mHostToStateMap\nprivate  void parcelHostToStateMap(android.os.Parcel,int)\nprivate  java.util.Map<java.lang.String,java.lang.Integer> unparcelHostToStateMap(android.os.Parcel)\nclass DomainVerificationInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=true, genHiddenConstructor=true, genParcelable=true, genToString=true, genEqualsHashCode=true)")
            inputSignatures = "public static final  int STATE_NO_RESPONSE\npublic static final  int STATE_SUCCESS\npublic static final  int STATE_UNMODIFIABLE\npublic static final  int STATE_MODIFIABLE_UNVERIFIED\npublic static final  int STATE_MODIFIABLE_VERIFIED\npublic static final  int STATE_FIRST_VERIFIER_DEFINED\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForUUID.class) java.util.UUID mIdentifier\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.Integer> mHostToStateMap\nprivate  void parcelHostToStateMap(android.os.Parcel,int)\nprivate  java.util.Map<java.lang.String,java.lang.Integer> unparcelHostToStateMap(android.os.Parcel)\nclass DomainVerificationInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=true, genHiddenConstructor=true, genParcelable=true, genToString=true, genEqualsHashCode=true, genHiddenConstDefs=true)")
    @Deprecated
    private void __metadata() {}

+56 −217

File changed.

Preview size limit exceeded, changes collapsed.

+129 −6
Original line number Diff line number Diff line
@@ -17,15 +17,13 @@
package android.content.pm.verify.domain;

import android.annotation.IntDef;
import android.annotation.NonNull;

/**
 * @hide
 */
public interface DomainVerificationState {

    /**
     * @hide
     */
    @IntDef({
            STATE_NO_RESPONSE,
            STATE_SUCCESS,
@@ -42,12 +40,12 @@ public interface DomainVerificationState {

    // TODO(b/159952358): Document all the places that states need to be updated when one is added
    /**
     * @see DomainVerificationManager#STATE_NO_RESPONSE
     * @see DomainVerificationInfo#STATE_NO_RESPONSE
     */
    int STATE_NO_RESPONSE = 0;

    /**
     * @see DomainVerificationManager#STATE_SUCCESS
     * @see DomainVerificationInfo#STATE_SUCCESS
     */
    int STATE_SUCCESS = 1;

@@ -94,7 +92,132 @@ public interface DomainVerificationState {
    int STATE_SYS_CONFIG = 7;

    /**
     * @see DomainVerificationManager#STATE_FIRST_VERIFIER_DEFINED
     * @see DomainVerificationInfo#STATE_FIRST_VERIFIER_DEFINED
     */
    int STATE_FIRST_VERIFIER_DEFINED = 0b10000000000;

    @NonNull
    static String stateToDebugString(@DomainVerificationState.State int state) {
        switch (state) {
            case DomainVerificationState.STATE_NO_RESPONSE:
                return "none";
            case DomainVerificationState.STATE_SUCCESS:
                return "verified";
            case DomainVerificationState.STATE_APPROVED:
                return "approved";
            case DomainVerificationState.STATE_DENIED:
                return "denied";
            case DomainVerificationState.STATE_MIGRATED:
                return "migrated";
            case DomainVerificationState.STATE_RESTORED:
                return "restored";
            case DomainVerificationState.STATE_LEGACY_FAILURE:
                return "legacy_failure";
            case DomainVerificationState.STATE_SYS_CONFIG:
                return "system_configured";
            default:
                return String.valueOf(state);
        }
    }

    /**
     * For determining re-verify policy. This is hidden from the domain verification agent so that
     * no behavior is made based on the result.
     */
    static boolean isDefault(@State int state) {
        switch (state) {
            case STATE_NO_RESPONSE:
            case STATE_MIGRATED:
            case STATE_RESTORED:
                return true;
            case STATE_SUCCESS:
            case STATE_APPROVED:
            case STATE_DENIED:
            case STATE_LEGACY_FAILURE:
            case STATE_SYS_CONFIG:
            default:
                return false;
        }
    }

    /**
     * Checks if a state considers the corresponding domain to be successfully verified. The domain
     * verification agent may use this to determine whether or not to re-verify a domain.
     */
    static boolean isVerified(@DomainVerificationState.State int state) {
        switch (state) {
            case DomainVerificationState.STATE_SUCCESS:
            case DomainVerificationState.STATE_APPROVED:
            case DomainVerificationState.STATE_MIGRATED:
            case DomainVerificationState.STATE_RESTORED:
            case DomainVerificationState.STATE_SYS_CONFIG:
                return true;
            case DomainVerificationState.STATE_NO_RESPONSE:
            case DomainVerificationState.STATE_DENIED:
            case DomainVerificationState.STATE_LEGACY_FAILURE:
            default:
                return false;
        }
    }

    /**
     * Checks if a state is modifiable by the domain verification agent. This is useful as the
     * platform may add new state codes in newer versions, and older verification agents can use
     * this method to determine if a state can be changed without having to be aware of what the new
     * state means.
     */
    static boolean isModifiable(@DomainVerificationState.State int state) {
        switch (state) {
            case DomainVerificationState.STATE_NO_RESPONSE:
            case DomainVerificationState.STATE_SUCCESS:
            case DomainVerificationState.STATE_MIGRATED:
            case DomainVerificationState.STATE_RESTORED:
            case DomainVerificationState.STATE_LEGACY_FAILURE:
                return true;
            case DomainVerificationState.STATE_APPROVED:
            case DomainVerificationState.STATE_DENIED:
            case DomainVerificationState.STATE_SYS_CONFIG:
                return false;
            default:
                return state >= DomainVerificationState.STATE_FIRST_VERIFIER_DEFINED;
        }
    }

    /**
     * Whether the state is migrated when updating a package. Generally this is only for states
     * that maintain verification state or were set by an explicit user or developer action.
     */
    static boolean shouldMigrate(@State int state) {
        switch (state) {
            case STATE_SUCCESS:
            case STATE_MIGRATED:
            case STATE_RESTORED:
            case STATE_APPROVED:
            case STATE_DENIED:
                return true;
            case STATE_NO_RESPONSE:
            case STATE_LEGACY_FAILURE:
            case STATE_SYS_CONFIG:
            case STATE_FIRST_VERIFIER_DEFINED:
            default:
                return false;
        }
    }

    @DomainVerificationInfo.State
    static int convertToInfoState(@State int internalState) {
        if (internalState >= STATE_FIRST_VERIFIER_DEFINED) {
            return internalState;
        } else if (internalState == STATE_NO_RESPONSE) {
            return DomainVerificationInfo.STATE_NO_RESPONSE;
        } else if (internalState == STATE_SUCCESS) {
            return DomainVerificationInfo.STATE_SUCCESS;
        } else if (!isModifiable(internalState)) {
            return DomainVerificationInfo.STATE_UNMODIFIABLE;
        } else if (isVerified(internalState)) {
            return DomainVerificationInfo.STATE_MODIFIABLE_VERIFIED;
        } else {
            return DomainVerificationInfo.STATE_MODIFIABLE_UNVERIFIED;
        }
    }
}
Loading