Merge "Increase instant app privacy with dummy data"

This commit is contained in:
TreeHugger Robot
2018-02-06 23:18:13 +00:00
committed by Android (Google) Code Review
3 changed files with 65 additions and 18 deletions

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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) {