summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt18
-rw-r--r--core/java/android/app/IInstantAppResolver.aidl10
-rw-r--r--core/java/android/app/InstantAppResolverService.java131
-rw-r--r--core/java/android/content/pm/AuxiliaryResolveInfo.java9
-rw-r--r--core/java/android/content/pm/InstantAppRequest.java33
-rw-r--r--core/java/android/content/pm/InstantAppRequestInfo.aidl19
-rw-r--r--core/java/android/content/pm/InstantAppRequestInfo.java188
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/pm/InstantAppResolver.java61
-rw-r--r--services/core/java/com/android/server/pm/InstantAppResolverConnection.java27
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java30
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java7
12 files changed, 425 insertions, 116 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index f74b74318180..dad0ac2c7e1a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -542,10 +542,12 @@ package android.app {
method public final android.os.IBinder onBind(android.content.Intent);
method @Deprecated public void onGetInstantAppIntentFilter(@Nullable int[], @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
method @Deprecated public void onGetInstantAppIntentFilter(@NonNull android.content.Intent, @Nullable int[], @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
- method public void onGetInstantAppIntentFilter(@NonNull android.content.Intent, @Nullable int[], @NonNull android.os.UserHandle, @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method @Deprecated public void onGetInstantAppIntentFilter(@NonNull android.content.Intent, @Nullable int[], @NonNull android.os.UserHandle, @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method public void onGetInstantAppIntentFilter(@NonNull android.content.pm.InstantAppRequestInfo, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
method @Deprecated public void onGetInstantAppResolveInfo(@Nullable int[], @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
method @Deprecated public void onGetInstantAppResolveInfo(@NonNull android.content.Intent, @Nullable int[], @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
- method public void onGetInstantAppResolveInfo(@NonNull android.content.Intent, @Nullable int[], @NonNull android.os.UserHandle, @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method @Deprecated public void onGetInstantAppResolveInfo(@NonNull android.content.Intent, @Nullable int[], @NonNull android.os.UserHandle, @NonNull String, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method public void onGetInstantAppResolveInfo(@NonNull android.content.pm.InstantAppRequestInfo, @NonNull android.app.InstantAppResolverService.InstantAppResolutionCallback);
}
public static final class InstantAppResolverService.InstantAppResolutionCallback {
@@ -1591,6 +1593,18 @@ package android.content.pm {
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstantAppIntentFilter> CREATOR;
}
+ public final class InstantAppRequestInfo implements android.os.Parcelable {
+ ctor public InstantAppRequestInfo(@NonNull android.content.Intent, @Nullable int[], @NonNull android.os.UserHandle, boolean, @NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstantAppRequestInfo> CREATOR;
+ field @Nullable public final int[] hostDigestPrefix;
+ field @NonNull public final android.content.Intent intent;
+ field public final boolean isRequesterInstantApp;
+ field @NonNull public final String token;
+ field @NonNull public final android.os.UserHandle userHandle;
+ }
+
public final class InstantAppResolveInfo implements android.os.Parcelable {
ctor public InstantAppResolveInfo(@NonNull android.content.pm.InstantAppResolveInfo.InstantAppDigest, @Nullable String, @Nullable java.util.List<android.content.pm.InstantAppIntentFilter>, int);
ctor public InstantAppResolveInfo(@NonNull android.content.pm.InstantAppResolveInfo.InstantAppDigest, @Nullable String, @Nullable java.util.List<android.content.pm.InstantAppIntentFilter>, long, @Nullable android.os.Bundle);
diff --git a/core/java/android/app/IInstantAppResolver.aidl b/core/java/android/app/IInstantAppResolver.aidl
index 7318762cfc63..8618fbb3bada 100644
--- a/core/java/android/app/IInstantAppResolver.aidl
+++ b/core/java/android/app/IInstantAppResolver.aidl
@@ -16,15 +16,13 @@
package android.app;
-import android.content.Intent;
+import android.content.pm.InstantAppRequestInfo;
import android.os.IRemoteCallback;
/** @hide */
oneway interface IInstantAppResolver {
- void getInstantAppResolveInfoList(in Intent sanitizedIntent, in int[] hostDigestPrefix,
- int userId, String token, int sequence, IRemoteCallback callback);
-
- void getInstantAppIntentFilterList(in Intent sanitizedIntent, in int[] hostDigestPrefix,
- int userId, String token, IRemoteCallback callback);
+ void getInstantAppResolveInfoList(in InstantAppRequestInfo request, int sequence,
+ IRemoteCallback callback);
+ void getInstantAppIntentFilterList(in InstantAppRequestInfo request, IRemoteCallback callback);
}
diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java
index a7be5421adb2..a413c606b76f 100644
--- a/core/java/android/app/InstantAppResolverService.java
+++ b/core/java/android/app/InstantAppResolverService.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.InstantAppRequestInfo;
import android.content.pm.InstantAppResolveInfo;
import android.os.Build;
import android.os.Bundle;
@@ -59,8 +60,9 @@ public abstract class InstantAppResolverService extends Service {
* Called to retrieve resolve info for instant applications immediately.
*
* @param digestPrefix The hash prefix of the instant app's domain.
- * @deprecated Should implement {@link #onGetInstantAppResolveInfo(Intent, int[], UserHandle,
- * String, InstantAppResolutionCallback)}.
+ *
+ * @deprecated Should implement {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo,
+ * InstantAppResolutionCallback)}
*/
@Deprecated
public void onGetInstantAppResolveInfo(@Nullable int[] digestPrefix, @NonNull String token,
@@ -73,8 +75,9 @@ public abstract class InstantAppResolverService extends Service {
* sources.
*
* @param digestPrefix The hash prefix of the instant app's domain.
- * @deprecated Should implement {@link #onGetInstantAppIntentFilter(Intent, int[], UserHandle,
- * String, InstantAppResolutionCallback)}.
+ *
+ * @deprecated Should implement {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
+ * InstantAppResolutionCallback)}
*/
@Deprecated
public void onGetInstantAppIntentFilter(@Nullable int[] digestPrefix, @NonNull String token,
@@ -103,8 +106,8 @@ public abstract class InstantAppResolverService extends Service {
*
* @see InstantAppResolveInfo
*
- * @deprecated Should implement {@link #onGetInstantAppResolveInfo(Intent, int[], UserHandle,
- * String, InstantAppResolutionCallback)}.
+ * @deprecated Should implement {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo,
+ * InstantAppResolutionCallback)}
*/
@Deprecated
public void onGetInstantAppResolveInfo(@NonNull Intent sanitizedIntent,
@@ -134,8 +137,8 @@ public abstract class InstantAppResolverService extends Service {
* {@link Intent#EXTRA_INSTANT_APP_TOKEN}.
* @param callback The {@link InstantAppResolutionCallback} to provide results to.
*
- * @deprecated Should implement {@link #onGetInstantAppIntentFilter(Intent, int[], UserHandle,
- * String, InstantAppResolutionCallback)}.
+ * @deprecated Should implement {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
+ * InstantAppResolutionCallback)}
*/
@Deprecated
public void onGetInstantAppIntentFilter(@NonNull Intent sanitizedIntent,
@@ -170,7 +173,11 @@ public abstract class InstantAppResolverService extends Service {
* @param callback The {@link InstantAppResolutionCallback} to provide results to.
*
* @see InstantAppResolveInfo
+ *
+ * @deprecated Should implement {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo,
+ * InstantAppResolutionCallback
*/
+ @Deprecated
public void onGetInstantAppResolveInfo(@NonNull Intent sanitizedIntent,
@Nullable int[] hostDigestPrefix, @NonNull UserHandle userHandle,
@NonNull String token, @NonNull InstantAppResolutionCallback callback) {
@@ -193,7 +200,11 @@ public abstract class InstantAppResolverService extends Service {
* Intent, int[], UserHandle, String, InstantAppResolutionCallback)} and provided
* to the currently visible installer via {@link Intent#EXTRA_INSTANT_APP_TOKEN}.
* @param callback The {@link InstantAppResolutionCallback} to provide results to.
+ *
+ * @deprecated Should implement {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
+ * InstantAppResolutionCallback)}
*/
+ @Deprecated
public void onGetInstantAppIntentFilter(@NonNull Intent sanitizedIntent,
@Nullable int[] hostDigestPrefix, @NonNull UserHandle userHandle,
@NonNull String token, @NonNull InstantAppResolutionCallback callback) {
@@ -202,6 +213,41 @@ public abstract class InstantAppResolverService extends Service {
}
/**
+ * Called to retrieve resolve info for instant applications immediately. The response will be
+ * ignored if not provided within a reasonable time. {@link InstantAppResolveInfo}s provided
+ * in response to this method may be partial to request a second phase of resolution which will
+ * result in a subsequent call to {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
+ * InstantAppResolutionCallback)}
+ *
+ * @param request The parameters for this resolution request
+ * @param callback The {@link InstantAppResolutionCallback} to provide results to.
+ *
+ * @see InstantAppResolveInfo
+ */
+ public void onGetInstantAppResolveInfo(@NonNull InstantAppRequestInfo request,
+ @NonNull InstantAppResolutionCallback callback) {
+ // If not overridden, forward to the old method.
+ onGetInstantAppResolveInfo(request.intent, request.hostDigestPrefix, request.userHandle,
+ request.token, callback);
+ }
+
+ /**
+ * Called to retrieve intent filters for potentially matching instant applications. Unlike
+ * {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo, InstantAppResolutionCallback)},
+ * the response may take as long as necessary to respond. All {@link InstantAppResolveInfo}s
+ * provided in response to this method must be completely populated.
+ *
+ * @param request The parameters for this resolution request
+ * @param callback The {@link InstantAppResolutionCallback} to provide results to.
+ */
+ public void onGetInstantAppIntentFilter(@NonNull InstantAppRequestInfo request,
+ @NonNull InstantAppResolutionCallback callback) {
+ // If not overridden, forward to the old method.
+ onGetInstantAppIntentFilter(request.intent, request.hostDigestPrefix, request.userHandle,
+ request.token, callback);
+ }
+
+ /**
* Returns a {@link Looper} to perform service operations on.
*/
Looper getLooper() {
@@ -218,35 +264,29 @@ public abstract class InstantAppResolverService extends Service {
public final IBinder onBind(Intent intent) {
return new IInstantAppResolver.Stub() {
@Override
- public void getInstantAppResolveInfoList(Intent sanitizedIntent, int[] digestPrefix,
- int userId, String token, int sequence, IRemoteCallback callback) {
+ public void getInstantAppResolveInfoList(InstantAppRequestInfo request, int sequence,
+ IRemoteCallback callback) {
if (DEBUG_INSTANT) {
- Slog.v(TAG, "[" + token + "] Phase1 called; posting");
+ Slog.v(TAG, "[" + request.token + "] Phase1 called; posting");
}
final SomeArgs args = SomeArgs.obtain();
- args.arg1 = callback;
- args.arg2 = digestPrefix;
- args.arg3 = userId;
- args.arg4 = token;
- args.arg5 = sanitizedIntent;
- mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO,
- sequence, 0, args).sendToTarget();
+ args.arg1 = request;
+ args.arg2 = callback;
+ mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, sequence,
+ 0, args).sendToTarget();
}
@Override
- public void getInstantAppIntentFilterList(Intent sanitizedIntent,
- int[] digestPrefix, int userId, String token, IRemoteCallback callback) {
+ public void getInstantAppIntentFilterList(InstantAppRequestInfo request,
+ IRemoteCallback callback) {
if (DEBUG_INSTANT) {
- Slog.v(TAG, "[" + token + "] Phase2 called; posting");
+ Slog.v(TAG, "[" + request.token + "] Phase2 called; posting");
}
final SomeArgs args = SomeArgs.obtain();
- args.arg1 = callback;
- args.arg2 = digestPrefix;
- args.arg3 = userId;
- args.arg4 = token;
- args.arg5 = sanitizedIntent;
- mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER,
- args).sendToTarget();
+ args.arg1 = request;
+ args.arg2 = callback;
+ mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, args)
+ .sendToTarget();
}
};
}
@@ -287,36 +327,33 @@ public abstract class InstantAppResolverService extends Service {
switch (action) {
case MSG_GET_INSTANT_APP_RESOLVE_INFO: {
final SomeArgs args = (SomeArgs) message.obj;
- final IRemoteCallback callback = (IRemoteCallback) args.arg1;
- final int[] digestPrefix = (int[]) args.arg2;
- final int userId = (int) args.arg3;
- final String token = (String) args.arg4;
- final Intent intent = (Intent) args.arg5;
+ final InstantAppRequestInfo request = (InstantAppRequestInfo) args.arg1;
+ final IRemoteCallback callback = (IRemoteCallback) args.arg2;
+ args.recycle();
final int sequence = message.arg1;
if (DEBUG_INSTANT) {
- Slog.d(TAG, "[" + token + "] Phase1 request;"
- + " prefix: " + Arrays.toString(digestPrefix)
- + ", userId: " + userId);
+ Slog.d(TAG, "[" + request.token + "] Phase1 request;"
+ + " prefix: " + Arrays.toString(request.hostDigestPrefix)
+ + ", userId: " + request.userHandle.getIdentifier());
}
- onGetInstantAppResolveInfo(intent, digestPrefix, UserHandle.of(userId), token,
+ onGetInstantAppResolveInfo(request,
new InstantAppResolutionCallback(sequence, callback));
} break;
case MSG_GET_INSTANT_APP_INTENT_FILTER: {
final SomeArgs args = (SomeArgs) message.obj;
- final IRemoteCallback callback = (IRemoteCallback) args.arg1;
- final int[] digestPrefix = (int[]) args.arg2;
- final int userId = (int) args.arg3;
- final String token = (String) args.arg4;
- final Intent intent = (Intent) args.arg5;
+ final InstantAppRequestInfo request = (InstantAppRequestInfo) args.arg1;
+ final IRemoteCallback callback = (IRemoteCallback) args.arg2;
+ args.recycle();
if (DEBUG_INSTANT) {
- Slog.d(TAG, "[" + token + "] Phase2 request;"
- + " prefix: " + Arrays.toString(digestPrefix)
- + ", userId: " + userId);
+ Slog.d(TAG, "[" + request.token + "] Phase2 request;"
+ + " prefix: " + Arrays.toString(request.hostDigestPrefix)
+ + ", userId: " + request.userHandle.getIdentifier());
}
- onGetInstantAppIntentFilter(intent, digestPrefix, UserHandle.of(userId), token,
+ onGetInstantAppIntentFilter(request,
new InstantAppResolutionCallback(-1 /*sequence*/, callback));
- } break;
+ }
+ break;
default: {
throw new IllegalArgumentException("Unknown message: " + action);
diff --git a/core/java/android/content/pm/AuxiliaryResolveInfo.java b/core/java/android/content/pm/AuxiliaryResolveInfo.java
index 202df50dda6f..7d07e1dc6361 100644
--- a/core/java/android/content/pm/AuxiliaryResolveInfo.java
+++ b/core/java/android/content/pm/AuxiliaryResolveInfo.java
@@ -46,17 +46,21 @@ public final class AuxiliaryResolveInfo {
public final Intent failureIntent;
/** The matching filters for this resolve info. */
public final List<AuxiliaryFilter> filters;
+ /** Stored {@link InstantAppRequest#hostDigestPrefixSecure} to prevent re-generation */
+ public final int[] hostDigestPrefixSecure;
/** Create a response for installing an instant application. */
public AuxiliaryResolveInfo(@NonNull String token,
boolean needsPhase2,
@Nullable Intent failureIntent,
- @Nullable List<AuxiliaryFilter> filters) {
+ @Nullable List<AuxiliaryFilter> filters,
+ @Nullable int[] hostDigestPrefix) {
this.token = token;
this.needsPhaseTwo = needsPhase2;
this.failureIntent = failureIntent;
this.filters = filters;
this.installFailureActivity = null;
+ this.hostDigestPrefixSecure = hostDigestPrefix;
}
/** Create a response for installing a split on demand. */
@@ -69,6 +73,7 @@ public final class AuxiliaryResolveInfo {
this.token = null;
this.needsPhaseTwo = false;
this.failureIntent = failureIntent;
+ this.hostDigestPrefixSecure = null;
}
/** Create a response for installing a split on demand. */
@@ -126,4 +131,4 @@ public final class AuxiliaryResolveInfo {
+ ", splitName='" + splitName + '\'' + '}';
}
}
-} \ No newline at end of file
+}
diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java
index 361d4e4acb3b..f692db1f0443 100644
--- a/core/java/android/content/pm/InstantAppRequest.java
+++ b/core/java/android/content/pm/InstantAppRequest.java
@@ -16,9 +16,10 @@
package android.content.pm;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Intent;
import android.os.Bundle;
-import android.text.TextUtils;
/**
* Information needed to make an instant application resolution request.
@@ -34,32 +35,40 @@ public final class InstantAppRequest {
public final String resolvedType;
/** The name of the package requesting the instant application */
public final String callingPackage;
+ /** Whether or not the requesting package was an instant app */
+ public final boolean isRequesterInstantApp;
/** ID of the user requesting the instant application */
public final int userId;
/**
* Optional extra bundle provided by the source application to the installer for additional
- * verification. */
+ * verification.
+ */
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;
+ /**
+ * The hash prefix of an instant app's domain or null if no host is defined.
+ * Secure version that should be carried through for external use.
+ */
+ @Nullable
+ public final int[] hostDigestPrefixSecure;
+ /** A unique identifier */
+ @NonNull
+ public final String token;
public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent,
- String resolvedType, String callingPackage, int userId, Bundle verificationBundle,
- boolean resolveForStart) {
+ String resolvedType, String callingPackage, boolean isRequesterInstantApp,
+ int userId, Bundle verificationBundle, boolean resolveForStart,
+ @Nullable int[] hostDigestPrefixSecure, @NonNull String token) {
this.responseObj = responseObj;
this.origIntent = origIntent;
this.resolvedType = resolvedType;
this.callingPackage = callingPackage;
+ this.isRequesterInstantApp = isRequesterInstantApp;
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;
- }
+ this.hostDigestPrefixSecure = hostDigestPrefixSecure;
+ this.token = token;
}
}
diff --git a/core/java/android/content/pm/InstantAppRequestInfo.aidl b/core/java/android/content/pm/InstantAppRequestInfo.aidl
new file mode 100644
index 000000000000..0f94220bc5da
--- /dev/null
+++ b/core/java/android/content/pm/InstantAppRequestInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+parcelable InstantAppRequestInfo;
diff --git a/core/java/android/content/pm/InstantAppRequestInfo.java b/core/java/android/content/pm/InstantAppRequestInfo.java
new file mode 100644
index 000000000000..83d55361ff2a
--- /dev/null
+++ b/core/java/android/content/pm/InstantAppRequestInfo.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Intent;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information exposed to {@link android.app.InstantAppResolverService} to complete
+ * an instant application resolution request.
+ * @hide
+ */
+@SystemApi
+@DataClass(genParcelable = true, genConstructor = true, genAidl = true)
+public final class InstantAppRequestInfo implements Parcelable {
+
+ /**
+ * The sanitized {@link Intent} used for resolution. A sanitized Intent is an intent with
+ * potential PII removed from the original intent. Fields removed include extras and the
+ * host + path of the data, if defined.
+ */
+ @NonNull
+ public final Intent intent;
+
+ /** The hash prefix of the instant app's domain or null if no host is defined. */
+ @Nullable
+ public final int[] hostDigestPrefix;
+
+ /** The user requesting the instant application */
+ @NonNull
+ public final UserHandle userHandle;
+
+ /** Whether or not the requesting package was an instant app itself */
+ public final boolean isRequesterInstantApp;
+
+ /** A unique identifier */
+ @NonNull
+ public final String token;
+
+
+
+ // Code below generated by codegen v1.0.13.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/InstantAppRequestInfo.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new InstantAppRequestInfo.
+ *
+ * @param intent
+ * The sanitized {@link Intent} used for resolution. A sanitized Intent is an intent with
+ * potential PII removed from the original intent. Fields removed include extras and the
+ * host + path of the data, if defined.
+ * @param hostDigestPrefix
+ * The hash prefix of the instant app's domain or null if no host is defined.
+ * @param userHandle
+ * The user requesting the instant application
+ * @param isRequesterInstantApp
+ * Whether or not the requesting package was an instant app itself
+ * @param token
+ * A unique identifier
+ */
+ @DataClass.Generated.Member
+ public InstantAppRequestInfo(
+ @NonNull Intent intent,
+ @Nullable int[] hostDigestPrefix,
+ @NonNull UserHandle userHandle,
+ boolean isRequesterInstantApp,
+ @NonNull String token) {
+ this.intent = intent;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, intent);
+ this.hostDigestPrefix = hostDigestPrefix;
+ this.userHandle = userHandle;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, userHandle);
+ this.isRequesterInstantApp = isRequesterInstantApp;
+ this.token = token;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, token);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (isRequesterInstantApp) flg |= 0x8;
+ if (hostDigestPrefix != null) flg |= 0x2;
+ dest.writeByte(flg);
+ dest.writeTypedObject(intent, flags);
+ if (hostDigestPrefix != null) dest.writeIntArray(hostDigestPrefix);
+ dest.writeTypedObject(userHandle, flags);
+ dest.writeString(token);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InstantAppRequestInfo(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ boolean _isRequesterInstantApp = (flg & 0x8) != 0;
+ Intent _intent = (Intent) in.readTypedObject(Intent.CREATOR);
+ int[] _hostDigestPrefix = (flg & 0x2) == 0 ? null : in.createIntArray();
+ UserHandle _userHandle = (UserHandle) in.readTypedObject(UserHandle.CREATOR);
+ String _token = in.readString();
+
+ this.intent = _intent;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, intent);
+ this.hostDigestPrefix = _hostDigestPrefix;
+ this.userHandle = _userHandle;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, userHandle);
+ this.isRequesterInstantApp = _isRequesterInstantApp;
+ this.token = _token;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, token);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InstantAppRequestInfo> CREATOR
+ = new Parcelable.Creator<InstantAppRequestInfo>() {
+ @Override
+ public InstantAppRequestInfo[] newArray(int size) {
+ return new InstantAppRequestInfo[size];
+ }
+
+ @Override
+ public InstantAppRequestInfo createFromParcel(@NonNull android.os.Parcel in) {
+ return new InstantAppRequestInfo(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1574373347443L,
+ codegenVersion = "1.0.13",
+ sourceFile = "frameworks/base/core/java/android/content/pm/InstantAppRequestInfo.java",
+ inputSignatures = "public final @android.annotation.NonNull android.content.Intent intent\npublic final @android.annotation.Nullable int[] hostDigestPrefix\npublic final @android.annotation.NonNull android.os.UserHandle userHandle\npublic final boolean isRequesterInstantApp\npublic final @android.annotation.NonNull java.lang.String token\nclass InstantAppRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=true, genAidl=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index dc24cffa54a4..5ec0fe76b5a2 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -331,14 +331,16 @@ public abstract class PackageManagerInternal {
* @param responseObj The response of the first phase of ephemeral resolution
* @param origIntent The original intent that triggered ephemeral resolution
* @param resolvedType The resolved type of the intent
- * @param callingPackage The name of the package requesting the ephemeral application
+ * @param callingPkg The app requesting the ephemeral application
+ * @param isRequesterInstantApp Whether or not the app requesting the ephemeral application
+ * is an instant app
* @param verificationBundle Optional bundle to pass to the installer for additional
* verification
* @param userId The ID of the user that triggered ephemeral resolution
*/
public abstract void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
- Intent origIntent, String resolvedType, String callingPackage,
- Bundle verificationBundle, int userId);
+ Intent origIntent, String resolvedType, String callingPkg,
+ boolean isRequesterInstantApp, Bundle verificationBundle, int userId);
/**
* Grants implicit access based on an interaction between two apps. This grants the target app
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 30b2c9d21a6a..8333ae5cbbad 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -39,6 +39,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.AuxiliaryResolveInfo;
import android.content.pm.InstantAppIntentFilter;
import android.content.pm.InstantAppRequest;
+import android.content.pm.InstantAppRequestInfo;
import android.content.pm.InstantAppResolveInfo;
import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
import android.metrics.LogMaker;
@@ -47,6 +48,8 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
@@ -63,7 +66,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import java.util.UUID;
/** @hide */
public abstract class InstantAppResolver {
@@ -117,26 +119,40 @@ public abstract class InstantAppResolver {
return sanitizedIntent;
}
+ /**
+ * Generate an {@link InstantAppDigest} from an {@link Intent} which contains hashes of the
+ * host. The object contains both secure and insecure hash array variants, and the secure
+ * version must be passed along to ensure the random data is consistent.
+ */
+ @NonNull
+ public static InstantAppDigest parseDigest(@NonNull Intent origIntent) {
+ if (origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost())) {
+ return new InstantAppResolveInfo.InstantAppDigest(origIntent.getData().getHost(),
+ 5 /*maxDigests*/);
+ } else {
+ return InstantAppResolveInfo.InstantAppDigest.UNDEFINED;
+ }
+ }
+
public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(
InstantAppResolverConnection connection, InstantAppRequest requestObj) {
final long startTime = System.currentTimeMillis();
- final String token = UUID.randomUUID().toString();
+ final String token = requestObj.token;
if (DEBUG_INSTANT) {
Log.d(TAG, "[" + token + "] Phase1; resolving");
}
- final Intent origIntent = requestObj.origIntent;
- final Intent sanitizedIntent = sanitizeIntent(origIntent);
AuxiliaryResolveInfo resolveInfo = null;
@ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS;
+ Intent origIntent = requestObj.origIntent;
try {
final List<InstantAppResolveInfo> instantAppResolveInfoList =
- connection.getInstantAppResolveInfoList(sanitizedIntent,
- requestObj.digest.getDigestPrefixSecure(), requestObj.userId, token);
+ connection.getInstantAppResolveInfoList(buildRequestInfo(requestObj));
if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) {
resolveInfo = InstantAppResolver.filterInstantAppIntent(
instantAppResolveInfoList, origIntent, requestObj.resolvedType,
- requestObj.userId, origIntent.getPackage(), requestObj.digest, token);
+ requestObj.userId, origIntent.getPackage(), token,
+ requestObj.hostDigestPrefixSecure);
}
} catch (ConnectionException e) {
if (e.failure == ConnectionException.FAILURE_BIND) {
@@ -166,7 +182,7 @@ public abstract class InstantAppResolver {
// if the match external flag is set, return an empty resolve info instead of a null result.
if (resolveInfo == null && (origIntent.getFlags() & FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
return new AuxiliaryResolveInfo(token, false, createFailureIntent(origIntent, token),
- null /* filters */);
+ null /* filters */, requestObj.hostDigestPrefixSecure);
}
return resolveInfo;
}
@@ -175,7 +191,7 @@ public abstract class InstantAppResolver {
InstantAppResolverConnection connection, InstantAppRequest requestObj,
ActivityInfo instantAppInstaller, Handler callbackHandler) {
final long startTime = System.currentTimeMillis();
- final String token = requestObj.responseObj.token;
+ final String token = requestObj.token;
if (DEBUG_INSTANT) {
Log.d(TAG, "[" + token + "] Phase2; resolving");
}
@@ -191,8 +207,8 @@ public abstract class InstantAppResolver {
final AuxiliaryResolveInfo instantAppIntentInfo =
InstantAppResolver.filterInstantAppIntent(
instantAppResolveInfoList, origIntent, null /*resolvedType*/,
- 0 /*userId*/, origIntent.getPackage(), requestObj.digest,
- token);
+ 0 /*userId*/, origIntent.getPackage(),
+ token, requestObj.hostDigestPrefixSecure);
if (instantAppIntentInfo != null) {
failureIntent = instantAppIntentInfo.failureIntent;
} else {
@@ -223,8 +239,7 @@ public abstract class InstantAppResolver {
}
};
try {
- connection.getInstantAppIntentFilterList(sanitizedIntent,
- requestObj.digest.getDigestPrefixSecure(), requestObj.userId, token, callback,
+ connection.getInstantAppIntentFilterList(buildRequestInfo(requestObj), callback,
callbackHandler, startTime);
} catch (ConnectionException e) {
@ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE;
@@ -356,10 +371,22 @@ public abstract class InstantAppResolver {
return intent;
}
+ private static InstantAppRequestInfo buildRequestInfo(InstantAppRequest request) {
+ return new InstantAppRequestInfo(
+ sanitizeIntent(request.origIntent),
+ // This must only expose the secured version of the host
+ request.hostDigestPrefixSecure,
+ UserHandle.getUserHandleForUid(request.userId),
+ request.isRequesterInstantApp,
+ request.token
+ );
+ }
+
private static AuxiliaryResolveInfo filterInstantAppIntent(
- List<InstantAppResolveInfo> instantAppResolveInfoList,
- Intent origIntent, String resolvedType, int userId, String packageName,
- InstantAppDigest digest, String token) {
+ List<InstantAppResolveInfo> instantAppResolveInfoList, Intent origIntent,
+ String resolvedType, int userId, String packageName, String token,
+ int[] hostDigestPrefixSecure) {
+ InstantAppDigest digest = InstantAppResolver.parseDigest(origIntent);
final int[] shaPrefix = digest.getDigestPrefix();
final byte[][] digestBytes = digest.getDigestBytes();
boolean requiresSecondPhase = false;
@@ -404,7 +431,7 @@ public abstract class InstantAppResolver {
}
if (filters != null && !filters.isEmpty()) {
return new AuxiliaryResolveInfo(token, requiresSecondPhase,
- createFailureIntent(origIntent, token), filters);
+ createFailureIntent(origIntent, token), filters, hostDigestPrefixSecure);
}
// Hash or filter mis-match; no instant apps for this domain.
return null;
diff --git a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
index c0e9f58f3b8e..0fe2eb1e6f4b 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
@@ -24,6 +24,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.InstantAppRequestInfo;
import android.content.pm.InstantAppResolveInfo;
import android.os.Binder;
import android.os.Build;
@@ -85,13 +86,13 @@ final class InstantAppResolverConnection implements DeathRecipient {
mBgHandler = BackgroundThread.getHandler();
}
- public List<InstantAppResolveInfo> getInstantAppResolveInfoList(Intent sanitizedIntent,
- int[] hashPrefix, int userId, String token) throws ConnectionException {
+ public List<InstantAppResolveInfo> getInstantAppResolveInfoList(InstantAppRequestInfo request)
+ throws ConnectionException {
throwIfCalledOnMainThread();
IInstantAppResolver target = null;
try {
try {
- target = getRemoteInstanceLazy(token);
+ target = getRemoteInstanceLazy(request.token);
} catch (TimeoutException e) {
throw new ConnectionException(ConnectionException.FAILURE_BIND);
} catch (InterruptedException e) {
@@ -99,8 +100,7 @@ final class InstantAppResolverConnection implements DeathRecipient {
}
try {
return mGetInstantAppResolveInfoCaller
- .getInstantAppResolveInfoList(target, sanitizedIntent, hashPrefix, userId,
- token);
+ .getInstantAppResolveInfoList(target, request);
} catch (TimeoutException e) {
throw new ConnectionException(ConnectionException.FAILURE_CALL);
} catch (RemoteException ignore) {
@@ -113,8 +113,8 @@ final class InstantAppResolverConnection implements DeathRecipient {
return null;
}
- public void getInstantAppIntentFilterList(Intent sanitizedIntent, int[] hashPrefix, int userId,
- String token, PhaseTwoCallback callback, Handler callbackHandler, final long startTime)
+ public void getInstantAppIntentFilterList(InstantAppRequestInfo request,
+ PhaseTwoCallback callback, Handler callbackHandler, final long startTime)
throws ConnectionException {
final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() {
@Override
@@ -126,9 +126,8 @@ final class InstantAppResolverConnection implements DeathRecipient {
}
};
try {
- getRemoteInstanceLazy(token)
- .getInstantAppIntentFilterList(sanitizedIntent, hashPrefix, userId, token,
- remoteCallback);
+ getRemoteInstanceLazy(request.token)
+ .getInstantAppIntentFilterList(request, remoteCallback);
} catch (TimeoutException e) {
throw new ConnectionException(ConnectionException.FAILURE_BIND);
} catch (InterruptedException e) {
@@ -352,12 +351,10 @@ final class InstantAppResolverConnection implements DeathRecipient {
};
}
- public List<InstantAppResolveInfo> getInstantAppResolveInfoList(
- IInstantAppResolver target, Intent sanitizedIntent, int[] hashPrefix, int userId,
- String token) throws RemoteException, TimeoutException {
+ public List<InstantAppResolveInfo> getInstantAppResolveInfoList(IInstantAppResolver target,
+ InstantAppRequestInfo request) throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
- target.getInstantAppResolveInfoList(sanitizedIntent, hashPrefix, userId, token,
- sequence, mCallback);
+ target.getInstantAppResolveInfoList(request, sequence, mCallback);
return getResultTimed(sequence);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fa98c962afbf..7b002f1f7929 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -154,6 +154,7 @@ import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstantAppInfo;
import android.content.pm.InstantAppRequest;
+import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
import android.content.pm.InstrumentationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.KeySet;
@@ -363,6 +364,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -6048,10 +6050,12 @@ public class PackageManagerService extends IPackageManager.Stub
private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
Intent origIntent, String resolvedType, String callingPackage,
- Bundle verificationBundle, int userId) {
+ boolean isRequesterInstantApp, Bundle verificationBundle, int userId) {
final Message msg = mHandler.obtainMessage(INSTANT_APP_RESOLUTION_PHASE_TWO,
new InstantAppRequest(responseObj, origIntent, resolvedType,
- callingPackage, userId, verificationBundle, false /*resolveForStart*/));
+ callingPackage, isRequesterInstantApp, userId, verificationBundle,
+ false /*resolveForStart*/, responseObj.hostDigestPrefixSecure,
+ responseObj.token));
mHandler.sendMessage(msg);
}
@@ -6668,8 +6672,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
if (addInstant) {
- result = maybeAddInstantAppInstaller(
- result, intent, resolvedType, flags, userId, resolveForStart);
+ String callingPkgName = getInstantAppPackageName(filterCallingUid);
+ boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
+ result = maybeAddInstantAppInstaller(result, intent, resolvedType, flags, userId,
+ resolveForStart, isRequesterInstantApp);
}
if (sortResult) {
Collections.sort(result, RESOLVE_PRIORITY_SORTER);
@@ -6680,7 +6686,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
- String resolvedType, int flags, int userId, boolean resolveForStart) {
+ String resolvedType, int flags, int userId, boolean resolveForStart,
+ boolean isRequesterInstantApp) {
// first, check to see if we've got an instant app already installed
final boolean alreadyResolvedLocally = (flags & PackageManager.MATCH_INSTANT) != 0;
ResolveInfo localInstantApp = null;
@@ -6728,10 +6735,13 @@ public class PackageManagerService extends IPackageManager.Stub
if (localInstantApp == null) {
// we don't have an instant app locally, resolve externally
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
+ String token = UUID.randomUUID().toString();
+ InstantAppDigest digest = InstantAppResolver.parseDigest(intent);
final InstantAppRequest requestObject = new InstantAppRequest(
null /*responseObj*/, intent /*origIntent*/, resolvedType,
- null /*callingPackage*/, userId, null /*verificationBundle*/,
- resolveForStart);
+ null /*callingPackage*/, isRequesterInstantApp,
+ userId, null /*verificationBundle*/, resolveForStart,
+ digest.getDigestPrefixSecure(), token);
auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne(
mInstantAppResolverConnection, requestObject);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -23167,10 +23177,10 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
Intent origIntent, String resolvedType, String callingPackage,
- Bundle verificationBundle, int userId) {
+ boolean isRequesterInstantApp, Bundle verificationBundle, int userId) {
PackageManagerService.this.requestInstantAppResolutionPhaseTwo(
- responseObj, origIntent, resolvedType, callingPackage, verificationBundle,
- userId);
+ responseObj, origIntent, resolvedType, callingPackage, isRequesterInstantApp,
+ verificationBundle, userId);
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index be7f88700d88..7aee19e9b766 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -99,6 +99,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.AuxiliaryResolveInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
@@ -1302,9 +1303,11 @@ class ActivityStarter {
String resolvedType, int userId) {
if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
// request phase two resolution
- mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
+ PackageManagerInternal packageManager = mService.getPackageManagerInternalLocked();
+ boolean isRequesterInstantApp = packageManager.isInstantApp(callingPackage, userId);
+ packageManager.requestInstantAppResolutionPhaseTwo(
auxiliaryResponse, originalIntent, resolvedType, callingPackage,
- verificationBundle, userId);
+ isRequesterInstantApp, verificationBundle, userId);
}
return InstantAppResolver.buildEphemeralInstallerIntent(
originalIntent,