Merge "Increase instant app privacy with dummy data"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a54e69a116
@@ -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 */
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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*/);
|
||||
@@ -306,6 +320,7 @@ public final class InstantAppResolveInfo implements Parcelable {
|
||||
}
|
||||
}
|
||||
mDigestPrefix = in.createIntArray();
|
||||
mDigestPrefixSecure = in.createIntArray();
|
||||
}
|
||||
|
||||
public byte[][] getDigestBytes() {
|
||||
@@ -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;
|
||||
@@ -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 {
|
||||
@@ -332,6 +372,7 @@ public final class InstantAppResolveInfo implements Parcelable {
|
||||
}
|
||||
}
|
||||
out.writeIntArray(mDigestPrefix);
|
||||
out.writeIntArray(mDigestPrefixSecure);
|
||||
}
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user