Loading core/java/android/content/pm/InstantAppRequest.java +10 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package android.content.pm; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; /** * Information needed to make an instant application resolution request. * @hide */ public final class InstantAppRequest { /** Response from the first phase of instant application resolution */ public final AuxiliaryResolveInfo responseObj; /** The original intent that triggered instant application resolution */ Loading @@ -40,6 +42,8 @@ public final class InstantAppRequest { public final Bundle verificationBundle; /** Whether resolution occurs because an application is starting */ public final boolean resolveForStart; /** The instant app digest for this request */ public final InstantAppResolveInfo.InstantAppDigest digest; public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, int userId, Bundle verificationBundle, Loading @@ -51,5 +55,11 @@ public final class InstantAppRequest { this.userId = userId; this.verificationBundle = verificationBundle; this.resolveForStart = resolveForStart; if (origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost())) { digest = new InstantAppResolveInfo.InstantAppDigest( origIntent.getData().getHost(), 5 /*maxDigests*/); } else { digest = InstantAppResolveInfo.InstantAppDigest.UNDEFINED; } } } core/java/android/content/pm/InstantAppResolveInfo.java +47 −3 Original line number Diff line number Diff line Loading @@ -26,10 +26,13 @@ import android.os.Parcelable; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Random; /** * Describes an externally resolvable instant application. There are three states that this class Loading Loading @@ -227,14 +230,25 @@ public final class InstantAppResolveInfo implements Parcelable { */ @SystemApi public static final class InstantAppDigest implements Parcelable { private static final int DIGEST_MASK = 0xfffff000; static final int DIGEST_MASK = 0xfffff000; public static final InstantAppDigest UNDEFINED = new InstantAppDigest(new byte[][]{}, new int[]{}); private static Random sRandom = null; static { try { sRandom = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e) { // oh well sRandom = new Random(); } } /** Full digest of the domain hashes */ private final byte[][] mDigestBytes; /** The first 4 bytes of the domain hashes */ /** The first 5 bytes of the domain hashes */ private final int[] mDigestPrefix; /** The first 5 bytes of the domain hashes interspersed with random data */ private int[] mDigestPrefixSecure; public InstantAppDigest(@NonNull String hostName) { this(hostName, -1 /*maxDigests*/); Loading Loading @@ -306,6 +320,7 @@ public final class InstantAppResolveInfo implements Parcelable { } } mDigestPrefix = in.createIntArray(); mDigestPrefixSecure = in.createIntArray(); } public byte[][] getDigestBytes() { Loading @@ -316,6 +331,26 @@ public final class InstantAppResolveInfo implements Parcelable { return mDigestPrefix; } /** * Returns a digest prefix with additional random prefixes interspersed. * @hide */ public int[] getDigestPrefixSecure() { if (this == InstantAppResolveInfo.InstantAppDigest.UNDEFINED) { return getDigestPrefix(); } else if (mDigestPrefixSecure == null) { // let's generate some random data to intersperse throughout the set of prefixes final int realSize = getDigestPrefix().length; final int manufacturedSize = realSize + 10 + sRandom.nextInt(10); mDigestPrefixSecure = Arrays.copyOf(getDigestPrefix(), manufacturedSize); for (int i = realSize; i < manufacturedSize; i++) { mDigestPrefixSecure[i] = sRandom.nextInt() & DIGEST_MASK; } Arrays.sort(mDigestPrefixSecure); } return mDigestPrefixSecure; } @Override public int describeContents() { return 0; Loading @@ -323,6 +358,11 @@ public final class InstantAppResolveInfo implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { final boolean isUndefined = this == UNDEFINED; out.writeBoolean(isUndefined); if (isUndefined) { return; } if (mDigestBytes == null) { out.writeInt(-1); } else { Loading @@ -332,6 +372,7 @@ public final class InstantAppResolveInfo implements Parcelable { } } out.writeIntArray(mDigestPrefix); out.writeIntArray(mDigestPrefixSecure); } @SuppressWarnings("hiding") Loading @@ -339,6 +380,9 @@ public final class InstantAppResolveInfo implements Parcelable { new Parcelable.Creator<InstantAppDigest>() { @Override public InstantAppDigest createFromParcel(Parcel in) { if (in.readBoolean() /* is undefined */) { return UNDEFINED; } return new InstantAppDigest(in); } @Override Loading services/core/java/com/android/server/pm/InstantAppResolver.java +8 −15 Original line number Diff line number Diff line Loading @@ -126,17 +126,16 @@ public abstract class InstantAppResolver { final Intent origIntent = requestObj.origIntent; final Intent sanitizedIntent = sanitizeIntent(origIntent); final InstantAppDigest digest = getInstantAppDigest(origIntent); final int[] shaPrefix = digest.getDigestPrefix(); AuxiliaryResolveInfo resolveInfo = null; @ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS; try { final List<InstantAppResolveInfo> instantAppResolveInfoList = connection.getInstantAppResolveInfoList(sanitizedIntent, shaPrefix, token); connection.getInstantAppResolveInfoList(sanitizedIntent, requestObj.digest.getDigestPrefixSecure(), token); if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { resolveInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, origIntent, requestObj.resolvedType, requestObj.userId, origIntent.getPackage(), digest, token); requestObj.userId, origIntent.getPackage(), requestObj.digest, token); } } catch (ConnectionException e) { if (e.failure == ConnectionException.FAILURE_BIND) { Loading Loading @@ -166,12 +165,6 @@ public abstract class InstantAppResolver { return resolveInfo; } private static InstantAppDigest getInstantAppDigest(Intent origIntent) { return origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost()) ? new InstantAppDigest(origIntent.getData().getHost(), 5 /*maxDigests*/) : InstantAppDigest.UNDEFINED; } public static void doInstantAppResolutionPhaseTwo(Context context, InstantAppResolverConnection connection, InstantAppRequest requestObj, ActivityInfo instantAppInstaller, Handler callbackHandler) { Loading @@ -182,8 +175,6 @@ public abstract class InstantAppResolver { } final Intent origIntent = requestObj.origIntent; final Intent sanitizedIntent = sanitizeIntent(origIntent); final InstantAppDigest digest = getInstantAppDigest(origIntent); final int[] shaPrefix = digest.getDigestPrefix(); final PhaseTwoCallback callback = new PhaseTwoCallback() { @Override Loading @@ -194,7 +185,8 @@ public abstract class InstantAppResolver { final AuxiliaryResolveInfo instantAppIntentInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, origIntent, null /*resolvedType*/, 0 /*userId*/, origIntent.getPackage(), digest, token); 0 /*userId*/, origIntent.getPackage(), requestObj.digest, token); if (instantAppIntentInfo != null) { failureIntent = instantAppIntentInfo.failureIntent; } else { Loading Loading @@ -225,8 +217,9 @@ public abstract class InstantAppResolver { } }; try { connection.getInstantAppIntentFilterList(sanitizedIntent, shaPrefix, token, callback, callbackHandler, startTime); connection.getInstantAppIntentFilterList(sanitizedIntent, requestObj.digest.getDigestPrefixSecure(), token, callback, callbackHandler, startTime); } catch (ConnectionException e) { @ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE; if (e.failure == ConnectionException.FAILURE_BIND) { Loading Loading
core/java/android/content/pm/InstantAppRequest.java +10 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package android.content.pm; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; /** * Information needed to make an instant application resolution request. * @hide */ public final class InstantAppRequest { /** Response from the first phase of instant application resolution */ public final AuxiliaryResolveInfo responseObj; /** The original intent that triggered instant application resolution */ Loading @@ -40,6 +42,8 @@ public final class InstantAppRequest { public final Bundle verificationBundle; /** Whether resolution occurs because an application is starting */ public final boolean resolveForStart; /** The instant app digest for this request */ public final InstantAppResolveInfo.InstantAppDigest digest; public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, int userId, Bundle verificationBundle, Loading @@ -51,5 +55,11 @@ public final class InstantAppRequest { this.userId = userId; this.verificationBundle = verificationBundle; this.resolveForStart = resolveForStart; if (origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost())) { digest = new InstantAppResolveInfo.InstantAppDigest( origIntent.getData().getHost(), 5 /*maxDigests*/); } else { digest = InstantAppResolveInfo.InstantAppDigest.UNDEFINED; } } }
core/java/android/content/pm/InstantAppResolveInfo.java +47 −3 Original line number Diff line number Diff line Loading @@ -26,10 +26,13 @@ import android.os.Parcelable; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Random; /** * Describes an externally resolvable instant application. There are three states that this class Loading Loading @@ -227,14 +230,25 @@ public final class InstantAppResolveInfo implements Parcelable { */ @SystemApi public static final class InstantAppDigest implements Parcelable { private static final int DIGEST_MASK = 0xfffff000; static final int DIGEST_MASK = 0xfffff000; public static final InstantAppDigest UNDEFINED = new InstantAppDigest(new byte[][]{}, new int[]{}); private static Random sRandom = null; static { try { sRandom = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e) { // oh well sRandom = new Random(); } } /** Full digest of the domain hashes */ private final byte[][] mDigestBytes; /** The first 4 bytes of the domain hashes */ /** The first 5 bytes of the domain hashes */ private final int[] mDigestPrefix; /** The first 5 bytes of the domain hashes interspersed with random data */ private int[] mDigestPrefixSecure; public InstantAppDigest(@NonNull String hostName) { this(hostName, -1 /*maxDigests*/); Loading Loading @@ -306,6 +320,7 @@ public final class InstantAppResolveInfo implements Parcelable { } } mDigestPrefix = in.createIntArray(); mDigestPrefixSecure = in.createIntArray(); } public byte[][] getDigestBytes() { Loading @@ -316,6 +331,26 @@ public final class InstantAppResolveInfo implements Parcelable { return mDigestPrefix; } /** * Returns a digest prefix with additional random prefixes interspersed. * @hide */ public int[] getDigestPrefixSecure() { if (this == InstantAppResolveInfo.InstantAppDigest.UNDEFINED) { return getDigestPrefix(); } else if (mDigestPrefixSecure == null) { // let's generate some random data to intersperse throughout the set of prefixes final int realSize = getDigestPrefix().length; final int manufacturedSize = realSize + 10 + sRandom.nextInt(10); mDigestPrefixSecure = Arrays.copyOf(getDigestPrefix(), manufacturedSize); for (int i = realSize; i < manufacturedSize; i++) { mDigestPrefixSecure[i] = sRandom.nextInt() & DIGEST_MASK; } Arrays.sort(mDigestPrefixSecure); } return mDigestPrefixSecure; } @Override public int describeContents() { return 0; Loading @@ -323,6 +358,11 @@ public final class InstantAppResolveInfo implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { final boolean isUndefined = this == UNDEFINED; out.writeBoolean(isUndefined); if (isUndefined) { return; } if (mDigestBytes == null) { out.writeInt(-1); } else { Loading @@ -332,6 +372,7 @@ public final class InstantAppResolveInfo implements Parcelable { } } out.writeIntArray(mDigestPrefix); out.writeIntArray(mDigestPrefixSecure); } @SuppressWarnings("hiding") Loading @@ -339,6 +380,9 @@ public final class InstantAppResolveInfo implements Parcelable { new Parcelable.Creator<InstantAppDigest>() { @Override public InstantAppDigest createFromParcel(Parcel in) { if (in.readBoolean() /* is undefined */) { return UNDEFINED; } return new InstantAppDigest(in); } @Override Loading
services/core/java/com/android/server/pm/InstantAppResolver.java +8 −15 Original line number Diff line number Diff line Loading @@ -126,17 +126,16 @@ public abstract class InstantAppResolver { final Intent origIntent = requestObj.origIntent; final Intent sanitizedIntent = sanitizeIntent(origIntent); final InstantAppDigest digest = getInstantAppDigest(origIntent); final int[] shaPrefix = digest.getDigestPrefix(); AuxiliaryResolveInfo resolveInfo = null; @ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS; try { final List<InstantAppResolveInfo> instantAppResolveInfoList = connection.getInstantAppResolveInfoList(sanitizedIntent, shaPrefix, token); connection.getInstantAppResolveInfoList(sanitizedIntent, requestObj.digest.getDigestPrefixSecure(), token); if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { resolveInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, origIntent, requestObj.resolvedType, requestObj.userId, origIntent.getPackage(), digest, token); requestObj.userId, origIntent.getPackage(), requestObj.digest, token); } } catch (ConnectionException e) { if (e.failure == ConnectionException.FAILURE_BIND) { Loading Loading @@ -166,12 +165,6 @@ public abstract class InstantAppResolver { return resolveInfo; } private static InstantAppDigest getInstantAppDigest(Intent origIntent) { return origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost()) ? new InstantAppDigest(origIntent.getData().getHost(), 5 /*maxDigests*/) : InstantAppDigest.UNDEFINED; } public static void doInstantAppResolutionPhaseTwo(Context context, InstantAppResolverConnection connection, InstantAppRequest requestObj, ActivityInfo instantAppInstaller, Handler callbackHandler) { Loading @@ -182,8 +175,6 @@ public abstract class InstantAppResolver { } final Intent origIntent = requestObj.origIntent; final Intent sanitizedIntent = sanitizeIntent(origIntent); final InstantAppDigest digest = getInstantAppDigest(origIntent); final int[] shaPrefix = digest.getDigestPrefix(); final PhaseTwoCallback callback = new PhaseTwoCallback() { @Override Loading @@ -194,7 +185,8 @@ public abstract class InstantAppResolver { final AuxiliaryResolveInfo instantAppIntentInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, origIntent, null /*resolvedType*/, 0 /*userId*/, origIntent.getPackage(), digest, token); 0 /*userId*/, origIntent.getPackage(), requestObj.digest, token); if (instantAppIntentInfo != null) { failureIntent = instantAppIntentInfo.failureIntent; } else { Loading Loading @@ -225,8 +217,9 @@ public abstract class InstantAppResolver { } }; try { connection.getInstantAppIntentFilterList(sanitizedIntent, shaPrefix, token, callback, callbackHandler, startTime); connection.getInstantAppIntentFilterList(sanitizedIntent, requestObj.digest.getDigestPrefixSecure(), token, callback, callbackHandler, startTime); } catch (ConnectionException e) { @ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE; if (e.failure == ConnectionException.FAILURE_BIND) { Loading