diff options
| author | 2018-01-31 09:57:26 +0000 | |
|---|---|---|
| committer | 2018-01-31 09:57:26 +0000 | |
| commit | 397c38d01711b1fb21882b41f5ced0ba98edab6e (patch) | |
| tree | 6e620d7efaeb1d26411ff58a9da5fddb00b54bdc | |
| parent | 4b4539b6b0e1e6c8986aa0127470d1ce8651c124 (diff) | |
| parent | 860b8ba71938e9860a31881c1d1431877f9d01a2 (diff) | |
Merge "Revert "Adds generic intent Instant App resolution""
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 11 | ||||
| -rw-r--r-- | core/java/android/app/EphemeralResolverService.java | 12 | ||||
| -rw-r--r-- | core/java/android/app/IInstantAppResolver.aidl | 8 | ||||
| -rw-r--r-- | core/java/android/app/InstantAppResolverService.java | 107 | ||||
| -rw-r--r-- | core/java/android/content/Intent.java | 50 | ||||
| -rw-r--r-- | core/java/android/content/pm/AuxiliaryResolveInfo.java | 99 | ||||
| -rw-r--r-- | core/java/android/content/pm/InstantAppResolveInfo.java | 96 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/ResolverListController.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStackSupervisor.java | 10 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStarter.java | 30 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/EphemeralResolverConnection.java | 28 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/InstantAppResolver.java | 322 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 182 |
14 files changed, 324 insertions, 645 deletions
diff --git a/api/current.txt b/api/current.txt index 7f07f810afa7..dda165f1fdc6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10050,7 +10050,6 @@ package android.content { field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000 field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000 field public static final int FLAG_ACTIVITY_LAUNCH_ADJACENT = 4096; // 0x1000 - field public static final int FLAG_ACTIVITY_MATCH_EXTERNAL = 2048; // 0x800 field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000 field public static final int FLAG_ACTIVITY_NEW_DOCUMENT = 524288; // 0x80000 field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000 diff --git a/api/system-current.txt b/api/system-current.txt index 08ac295c9361..034ee3090fc4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -311,10 +311,8 @@ package android.app { ctor public InstantAppResolverService(); method public final void attachBaseContext(android.content.Context); method public final android.os.IBinder onBind(android.content.Intent); - method public deprecated void onGetInstantAppIntentFilter(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback); - method public void onGetInstantAppIntentFilter(android.content.Intent, int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback); - method public deprecated void onGetInstantAppResolveInfo(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback); - method public void onGetInstantAppResolveInfo(android.content.Intent, int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback); + method public void onGetInstantAppIntentFilter(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback); + method public void onGetInstantAppResolveInfo(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback); } public static final class InstantAppResolverService.InstantAppResolutionCallback { @@ -823,14 +821,12 @@ package android.content { field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST"; field public static final java.lang.String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS"; field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET"; - field public static final java.lang.String EXTRA_INSTANT_APP_BUNDLES = "android.intent.extra.INSTANT_APP_BUNDLES"; field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID"; field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES"; field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME"; field public static final java.lang.String EXTRA_REASON = "android.intent.extra.REASON"; field public static final java.lang.String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK"; field public static final java.lang.String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED"; - field public static final java.lang.String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP"; } public class IntentFilter implements android.os.Parcelable { @@ -873,7 +869,6 @@ package android.content.pm { ctor public InstantAppResolveInfo(android.content.pm.InstantAppResolveInfo.InstantAppDigest, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>, int); ctor public InstantAppResolveInfo(android.content.pm.InstantAppResolveInfo.InstantAppDigest, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>, long, android.os.Bundle); ctor public InstantAppResolveInfo(java.lang.String, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>); - ctor public InstantAppResolveInfo(android.os.Bundle); method public int describeContents(); method public byte[] getDigestBytes(); method public int getDigestPrefix(); @@ -882,7 +877,6 @@ package android.content.pm { method public long getLongVersionCode(); method public java.lang.String getPackageName(); method public deprecated int getVersionCode(); - method public boolean shouldLetInstallerDecide(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppResolveInfo> CREATOR; } @@ -894,7 +888,6 @@ package android.content.pm { method public int[] getDigestPrefix(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppResolveInfo.InstantAppDigest> CREATOR; - field public static final android.content.pm.InstantAppResolveInfo.InstantAppDigest UNDEFINED; } public final class IntentFilterVerificationInfo implements android.os.Parcelable { diff --git a/core/java/android/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java index d1c244136ec9..427a0386e87c 100644 --- a/core/java/android/app/EphemeralResolverService.java +++ b/core/java/android/app/EphemeralResolverService.java @@ -17,10 +17,20 @@ package android.app; import android.annotation.SystemApi; +import android.app.Service; +import android.app.InstantAppResolverService.InstantAppResolutionCallback; +import android.content.Context; +import android.content.Intent; import android.content.pm.EphemeralResolveInfo; import android.content.pm.InstantAppResolveInfo; import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.IRemoteCallback; import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; import android.util.Log; import java.util.ArrayList; @@ -75,6 +85,7 @@ public abstract class EphemeralResolverService extends InstantAppResolverService return super.getLooper(); } + @Override void _onGetInstantAppResolveInfo(int[] digestPrefix, String token, InstantAppResolutionCallback callback) { if (DEBUG_EPHEMERAL) { @@ -90,6 +101,7 @@ public abstract class EphemeralResolverService extends InstantAppResolverService callback.onInstantAppResolveInfo(resultList); } + @Override void _onGetInstantAppIntentFilter(int[] digestPrefix, String token, String hostName, InstantAppResolutionCallback callback) { if (DEBUG_EPHEMERAL) { diff --git a/core/java/android/app/IInstantAppResolver.aidl b/core/java/android/app/IInstantAppResolver.aidl index ae200578d829..805d8c057d27 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.os.IRemoteCallback; /** @hide */ oneway interface IInstantAppResolver { - void getInstantAppResolveInfoList(in Intent sanitizedIntent, in int[] hostDigestPrefix, + void getInstantAppResolveInfoList(in int[] digestPrefix, String token, int sequence, IRemoteCallback callback); - void getInstantAppIntentFilterList(in Intent sanitizedIntent, in int[] hostDigestPrefix, - String token, IRemoteCallback callback); - + void getInstantAppIntentFilterList(in int[] digestPrefix, + String token, String hostName, IRemoteCallback callback); } diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java index 89aff36f883a..c5dc86c79ef9 100644 --- a/core/java/android/app/InstantAppResolverService.java +++ b/core/java/android/app/InstantAppResolverService.java @@ -17,6 +17,7 @@ package android.app; import android.annotation.SystemApi; +import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.pm.InstantAppResolveInfo; @@ -34,7 +35,6 @@ import android.util.Slog; import com.android.internal.os.SomeArgs; import java.util.Arrays; -import java.util.Collections; import java.util.List; /** @@ -53,65 +53,23 @@ public abstract class InstantAppResolverService extends Service { Handler mHandler; /** - * Called to retrieve resolve info for instant applications immediately. + * Called to retrieve resolve info for instant applications. * * @param digestPrefix The hash prefix of the instant app's domain. - * @deprecated should implement {@link #onGetInstantAppResolveInfo(Intent, int[], String, - * InstantAppResolutionCallback)} */ - @Deprecated public void onGetInstantAppResolveInfo( int digestPrefix[], String token, InstantAppResolutionCallback callback) { throw new IllegalStateException("Must define"); } /** - * Called to retrieve intent filters for instant applications from potentially expensive - * sources. + * Called to retrieve intent filters for instant applications. * * @param digestPrefix The hash prefix of the instant app's domain. - * @deprecated should implement {@link #onGetInstantAppIntentFilter(Intent, int[], String, - * InstantAppResolutionCallback)} */ - @Deprecated public void onGetInstantAppIntentFilter( int digestPrefix[], String token, InstantAppResolutionCallback callback) { - throw new IllegalStateException("Must define onGetInstantAppIntentFilter"); - } - - /** - * Called to retrieve resolve info for instant applications immediately. - * - * @param sanitizedIntent The sanitized {@link Intent} used for resolution. - * @param hostDigestPrefix The hash prefix of the instant app's domain. - */ - public void onGetInstantAppResolveInfo(Intent sanitizedIntent, int[] hostDigestPrefix, - String token, InstantAppResolutionCallback callback) { - // if not overridden, forward to old methods and filter out non-web intents - if (sanitizedIntent.isBrowsableWebIntent()) { - onGetInstantAppResolveInfo(hostDigestPrefix, token, callback); - } else { - callback.onInstantAppResolveInfo(Collections.emptyList()); - } - } - - /** - * Called to retrieve intent filters for instant applications from potentially expensive - * sources. - * - * @param sanitizedIntent The sanitized {@link Intent} used for resolution. - * @param hostDigestPrefix The hash prefix of the instant app's domain or null if no host is - * defined. - */ - public void onGetInstantAppIntentFilter(Intent sanitizedIntent, int[] hostDigestPrefix, - String token, InstantAppResolutionCallback callback) { - Log.e(TAG, "New onGetInstantAppIntentFilter is not overridden"); - // if not overridden, forward to old methods and filter out non-web intents - if (sanitizedIntent.isBrowsableWebIntent()) { - onGetInstantAppIntentFilter(hostDigestPrefix, token, callback); - } else { - callback.onInstantAppResolveInfo(Collections.emptyList()); - } + throw new IllegalStateException("Must define"); } /** @@ -131,8 +89,8 @@ public abstract class InstantAppResolverService extends Service { public final IBinder onBind(Intent intent) { return new IInstantAppResolver.Stub() { @Override - public void getInstantAppResolveInfoList(Intent sanitizedIntent, int[] digestPrefix, - String token, int sequence, IRemoteCallback callback) { + public void getInstantAppResolveInfoList( + int digestPrefix[], String token, int sequence, IRemoteCallback callback) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "[" + token + "] Phase1 called; posting"); } @@ -140,14 +98,14 @@ public abstract class InstantAppResolverService extends Service { args.arg1 = callback; args.arg2 = digestPrefix; args.arg3 = token; - args.arg4 = sanitizedIntent; - mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, - sequence, 0, args).sendToTarget(); + mHandler.obtainMessage( + ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, sequence, 0, args) + .sendToTarget(); } @Override - public void getInstantAppIntentFilterList(Intent sanitizedIntent, - int[] digestPrefix, String token, IRemoteCallback callback) { + public void getInstantAppIntentFilterList( + int digestPrefix[], String token, String hostName, IRemoteCallback callback) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "[" + token + "] Phase2 called; posting"); } @@ -155,9 +113,9 @@ public abstract class InstantAppResolverService extends Service { args.arg1 = callback; args.arg2 = digestPrefix; args.arg3 = token; - args.arg4 = sanitizedIntent; - mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, - callback).sendToTarget(); + args.arg4 = hostName; + mHandler.obtainMessage( + ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, callback).sendToTarget(); } }; } @@ -184,9 +142,29 @@ public abstract class InstantAppResolverService extends Service { } } + @Deprecated + void _onGetInstantAppResolveInfo(int[] digestPrefix, String token, + InstantAppResolutionCallback callback) { + if (DEBUG_EPHEMERAL) { + Slog.d(TAG, "[" + token + "] Phase1 request;" + + " prefix: " + Arrays.toString(digestPrefix)); + } + onGetInstantAppResolveInfo(digestPrefix, token, callback); + } + @Deprecated + void _onGetInstantAppIntentFilter(int digestPrefix[], String token, String hostName, + InstantAppResolutionCallback callback) { + if (DEBUG_EPHEMERAL) { + Slog.d(TAG, "[" + token + "] Phase2 request;" + + " prefix: " + Arrays.toString(digestPrefix)); + } + onGetInstantAppIntentFilter(digestPrefix, token, callback); + } + private final class ServiceHandler extends Handler { public static final int MSG_GET_INSTANT_APP_RESOLVE_INFO = 1; public static final int MSG_GET_INSTANT_APP_INTENT_FILTER = 2; + public ServiceHandler(Looper looper) { super(looper, null /*callback*/, true /*async*/); } @@ -201,13 +179,9 @@ public abstract class InstantAppResolverService extends Service { final IRemoteCallback callback = (IRemoteCallback) args.arg1; final int[] digestPrefix = (int[]) args.arg2; final String token = (String) args.arg3; - final Intent intent = (Intent) args.arg4; final int sequence = message.arg1; - if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "[" + token + "] Phase1 request;" - + " prefix: " + Arrays.toString(digestPrefix)); - } - onGetInstantAppResolveInfo(intent, digestPrefix, token, + _onGetInstantAppResolveInfo( + digestPrefix, token, new InstantAppResolutionCallback(sequence, callback)); } break; @@ -216,12 +190,9 @@ public abstract class InstantAppResolverService extends Service { final IRemoteCallback callback = (IRemoteCallback) args.arg1; final int[] digestPrefix = (int[]) args.arg2; final String token = (String) args.arg3; - final Intent intent = (Intent) args.arg4; - if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "[" + token + "] Phase2 request;" - + " prefix: " + Arrays.toString(digestPrefix)); - } - onGetInstantAppIntentFilter(intent, digestPrefix, token, + final String hostName = (String) args.arg4; + _onGetInstantAppIntentFilter( + digestPrefix, token, hostName, new InstantAppResolutionCallback(-1 /*sequence*/, callback)); } break; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index b3c8737a2831..e02a29494296 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -50,7 +50,6 @@ import android.provider.DocumentsContract; import android.provider.DocumentsProvider; import android.provider.MediaStore; import android.provider.OpenableColumns; -import android.text.TextUtils; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; @@ -4473,15 +4472,7 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_INSTANT_APP_ACTION = "android.intent.extra.INSTANT_APP_ACTION"; /** - * An array of {@link Bundle}s containing details about resolved instant apps.. - * @hide - */ - @SystemApi - public static final String EXTRA_INSTANT_APP_BUNDLES = - "android.intent.extra.INSTANT_APP_BUNDLES"; - - /** - * A {@link Bundle} of metadata that describes the instant application that needs to be + * A {@link Bundle} of metadata that describes the instanta application that needs to be * installed. This data is populated from the response to * {@link android.content.pm.InstantAppResolveInfo#getExtras()} as provided by the registered * instant application resolver. @@ -4491,16 +4482,6 @@ public class Intent implements Parcelable, Cloneable { "android.intent.extra.INSTANT_APP_EXTRAS"; /** - * A boolean value indicating that the instant app resolver was unable to state with certainty - * that it did or did not have an app for the sanitized {@link Intent} defined at - * {@link #EXTRA_INTENT}. - * @hide - */ - @SystemApi - public static final String EXTRA_UNKNOWN_INSTANT_APP = - "android.intent.extra.UNKNOWN_INSTANT_APP"; - - /** * The version code of the app to install components from. * @deprecated Use {@link #EXTRA_LONG_VERSION_CODE). * @hide @@ -5048,7 +5029,6 @@ public class Intent implements Parcelable, Cloneable { FLAG_GRANT_PREFIX_URI_PERMISSION, FLAG_DEBUG_TRIAGED_MISSING, FLAG_IGNORE_EPHEMERAL, - FLAG_ACTIVITY_MATCH_EXTERNAL, FLAG_ACTIVITY_NO_HISTORY, FLAG_ACTIVITY_SINGLE_TOP, FLAG_ACTIVITY_NEW_TASK, @@ -5092,7 +5072,6 @@ public class Intent implements Parcelable, Cloneable { FLAG_INCLUDE_STOPPED_PACKAGES, FLAG_DEBUG_TRIAGED_MISSING, FLAG_IGNORE_EPHEMERAL, - FLAG_ACTIVITY_MATCH_EXTERNAL, FLAG_ACTIVITY_NO_HISTORY, FLAG_ACTIVITY_SINGLE_TOP, FLAG_ACTIVITY_NEW_TASK, @@ -5496,14 +5475,6 @@ public class Intent implements Parcelable, Cloneable { */ public static final int FLAG_ACTIVITY_LAUNCH_ADJACENT = 0x00001000; - - /** - * If set, resolution of this intent may take place via an instant app not - * yet on the device if there does not yet exist an app on device to - * resolve it. - */ - public static final int FLAG_ACTIVITY_MATCH_EXTERNAL = 0x00000800; - /** * If set, when sending a broadcast only registered receivers will be * called -- no BroadcastReceiver components will be launched. @@ -10057,25 +10028,6 @@ public class Intent implements Parcelable, Cloneable { } } - /** @hide */ - public boolean hasWebURI() { - if (getData() == null) { - return false; - } - final String scheme = getScheme(); - if (TextUtils.isEmpty(scheme)) { - return false; - } - return scheme.equals(IntentFilter.SCHEME_HTTP) || scheme.equals(IntentFilter.SCHEME_HTTPS); - } - - /** @hide */ - public boolean isBrowsableWebIntent() { - return ACTION_VIEW.equals(mAction) - && hasCategory(CATEGORY_BROWSABLE) - && hasWebURI(); - } - /** * @hide */ diff --git a/core/java/android/content/pm/AuxiliaryResolveInfo.java b/core/java/android/content/pm/AuxiliaryResolveInfo.java index 202df50dda6f..6bdcefbe974e 100644 --- a/core/java/android/content/pm/AuxiliaryResolveInfo.java +++ b/core/java/android/content/pm/AuxiliaryResolveInfo.java @@ -21,10 +21,6 @@ import android.annotation.Nullable; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; -import android.os.Bundle; - -import java.util.Collections; -import java.util.List; /** * Auxiliary application resolution response. @@ -35,95 +31,56 @@ import java.util.List; * hasn't been installed. * @hide */ -public final class AuxiliaryResolveInfo { +public final class AuxiliaryResolveInfo extends IntentFilter { + /** Resolved information returned from the external instant resolver */ + public final InstantAppResolveInfo resolveInfo; + /** The resolved package. Copied from {@link #resolveInfo}. */ + public final String packageName; /** The activity to launch if there's an installation failure. */ public final ComponentName installFailureActivity; + /** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */ + public final String splitName; /** Whether or not instant resolution needs the second phase */ public final boolean needsPhaseTwo; /** Opaque token to track the instant application resolution */ public final String token; + /** The version code of the package */ + public final long versionCode; /** An intent to start upon failure to install */ public final Intent failureIntent; - /** The matching filters for this resolve info. */ - public final List<AuxiliaryFilter> filters; /** Create a response for installing an instant application. */ - public AuxiliaryResolveInfo(@NonNull String token, + public AuxiliaryResolveInfo(@NonNull InstantAppResolveInfo resolveInfo, + @NonNull IntentFilter orig, + @Nullable String splitName, + @NonNull String token, boolean needsPhase2, - @Nullable Intent failureIntent, - @Nullable List<AuxiliaryFilter> filters) { + @Nullable Intent failureIntent) { + super(orig); + this.resolveInfo = resolveInfo; + this.packageName = resolveInfo.getPackageName(); + this.splitName = splitName; this.token = token; this.needsPhaseTwo = needsPhase2; + this.versionCode = resolveInfo.getVersionCode(); this.failureIntent = failureIntent; - this.filters = filters; this.installFailureActivity = null; } /** Create a response for installing a split on demand. */ - public AuxiliaryResolveInfo(@Nullable ComponentName failureActivity, - @Nullable Intent failureIntent, - @Nullable List<AuxiliaryFilter> filters) { + public AuxiliaryResolveInfo(@NonNull String packageName, + @Nullable String splitName, + @Nullable ComponentName failureActivity, + long versionCode, + @Nullable Intent failureIntent) { super(); + this.packageName = packageName; this.installFailureActivity = failureActivity; - this.filters = filters; + this.splitName = splitName; + this.versionCode = versionCode; + this.resolveInfo = null; this.token = null; this.needsPhaseTwo = false; this.failureIntent = failureIntent; } - - /** Create a response for installing a split on demand. */ - public AuxiliaryResolveInfo(@Nullable ComponentName failureActivity, - String packageName, long versionCode, String splitName) { - this(failureActivity, null, Collections.singletonList( - new AuxiliaryResolveInfo.AuxiliaryFilter(packageName, versionCode, splitName))); - } - - /** @hide */ - public static final class AuxiliaryFilter extends IntentFilter { - /** Resolved information returned from the external instant resolver */ - public final InstantAppResolveInfo resolveInfo; - /** The resolved package. Copied from {@link #resolveInfo}. */ - public final String packageName; - /** The version code of the package */ - public final long versionCode; - /** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */ - public final String splitName; - /** The extras to pass on to the installer for this filter. */ - public final Bundle extras; - - public AuxiliaryFilter(IntentFilter orig, InstantAppResolveInfo resolveInfo, - String splitName, Bundle extras) { - super(orig); - this.resolveInfo = resolveInfo; - this.packageName = resolveInfo.getPackageName(); - this.versionCode = resolveInfo.getLongVersionCode(); - this.splitName = splitName; - this.extras = extras; - } - - public AuxiliaryFilter(InstantAppResolveInfo resolveInfo, - String splitName, Bundle extras) { - this.resolveInfo = resolveInfo; - this.packageName = resolveInfo.getPackageName(); - this.versionCode = resolveInfo.getLongVersionCode(); - this.splitName = splitName; - this.extras = extras; - } - - public AuxiliaryFilter(String packageName, long versionCode, String splitName) { - this.resolveInfo = null; - this.packageName = packageName; - this.versionCode = versionCode; - this.splitName = splitName; - this.extras = null; - } - - @Override - public String toString() { - return "AuxiliaryFilter{" - + "packageName='" + packageName + '\'' - + ", versionCode=" + versionCode - + ", splitName='" + splitName + '\'' + '}'; - } - } }
\ No newline at end of file diff --git a/core/java/android/content/pm/InstantAppResolveInfo.java b/core/java/android/content/pm/InstantAppResolveInfo.java index 112c5dae6731..19cb9323ba93 100644 --- a/core/java/android/content/pm/InstantAppResolveInfo.java +++ b/core/java/android/content/pm/InstantAppResolveInfo.java @@ -19,7 +19,6 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; -import android.content.Intent; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -27,35 +26,11 @@ import android.os.Parcelable; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Locale; /** - * Describes an externally resolvable instant application. There are three states that this class - * can represent: <p/> - * <ul> - * <li> - * The first, usable only for non http/s intents, implies that the resolver cannot - * immediately resolve this intent and would prefer that resolution be deferred to the - * instant app installer. Represent this state with {@link #InstantAppResolveInfo(Bundle)}. - * If the {@link android.content.Intent} has the scheme set to http/s and a set of digest - * prefixes were passed into one of the resolve methods in - * {@link android.app.InstantAppResolverService}, this state cannot be used. - * </li> - * <li> - * The second represents a partial match and is constructed with any of the other - * constructors. By setting one or more of the {@link Nullable}arguments to null, you - * communicate to the resolver in response to - * {@link android.app.InstantAppResolverService#onGetInstantAppResolveInfo(Intent, int[], - * String, InstantAppResolverService.InstantAppResolutionCallback)} - * that you need a 2nd round of resolution to complete the request. - * </li> - * <li> - * The third represents a complete match and is constructed with all @Nullable parameters - * populated. - * </li> - * </ul> + * Information about an instant application. * @hide */ @SystemApi @@ -63,8 +38,6 @@ public final class InstantAppResolveInfo implements Parcelable { /** Algorithm that will be used to generate the domain digest */ private static final String SHA_ALGORITHM = "SHA-256"; - private static final byte[] EMPTY_DIGEST = new byte[0]; - private final InstantAppDigest mDigest; private final String mPackageName; /** The filters used to match domain */ @@ -73,30 +46,15 @@ public final class InstantAppResolveInfo implements Parcelable { private final long mVersionCode; /** Data about the app that should be passed along to the Instant App installer on resolve */ private final Bundle mExtras; - /** - * A flag that indicates that the resolver is aware that an app may match, but would prefer - * that the installer get the sanitized intent to decide. This should not be used for - * resolutions that include a host and will be ignored in such cases. - */ - private final boolean mShouldLetInstallerDecide; - /** Constructor for intent-based InstantApp resolution results. */ public InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName, @Nullable List<InstantAppIntentFilter> filters, int versionCode) { this(digest, packageName, filters, (long) versionCode, null /* extras */); } - /** Constructor for intent-based InstantApp resolution results with extras. */ public InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName, @Nullable List<InstantAppIntentFilter> filters, long versionCode, @Nullable Bundle extras) { - this(digest, packageName, filters, versionCode, extras, false); - } - - /** Constructor for intent-based InstantApp resolution results with extras. */ - private InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName, - @Nullable List<InstantAppIntentFilter> filters, long versionCode, - @Nullable Bundle extras, boolean shouldLetInstallerDecide) { // validate arguments if ((packageName == null && (filters != null && filters.size() != 0)) || (packageName != null && (filters == null || filters.size() == 0))) { @@ -104,7 +62,7 @@ public final class InstantAppResolveInfo implements Parcelable { } mDigest = digest; if (filters != null) { - mFilters = new ArrayList<>(filters.size()); + mFilters = new ArrayList<InstantAppIntentFilter>(filters.size()); mFilters.addAll(filters); } else { mFilters = null; @@ -112,48 +70,25 @@ public final class InstantAppResolveInfo implements Parcelable { mPackageName = packageName; mVersionCode = versionCode; mExtras = extras; - mShouldLetInstallerDecide = shouldLetInstallerDecide; } - /** Constructor for intent-based InstantApp resolution results by hostname. */ public InstantAppResolveInfo(@NonNull String hostName, @Nullable String packageName, @Nullable List<InstantAppIntentFilter> filters) { this(new InstantAppDigest(hostName), packageName, filters, -1 /*versionCode*/, null /* extras */); } - /** - * Constructor that creates a "let the installer decide" response with optional included - * extras. - */ - public InstantAppResolveInfo(@Nullable Bundle extras) { - this(InstantAppDigest.UNDEFINED, null, null, -1, extras, true); - } - InstantAppResolveInfo(Parcel in) { - mShouldLetInstallerDecide = in.readBoolean(); + mDigest = in.readParcelable(null /*loader*/); + mPackageName = in.readString(); + mFilters = new ArrayList<InstantAppIntentFilter>(); + in.readList(mFilters, null /*loader*/); + mVersionCode = in.readLong(); mExtras = in.readBundle(); - if (mShouldLetInstallerDecide) { - mDigest = InstantAppDigest.UNDEFINED; - mPackageName = null; - mFilters = Collections.emptyList(); - mVersionCode = -1; - } else { - mDigest = in.readParcelable(null /*loader*/); - mPackageName = in.readString(); - mFilters = new ArrayList<>(); - in.readList(mFilters, null /*loader*/); - mVersionCode = in.readLong(); - } - } - - /** Returns true if the installer should be notified that it should query for packages. */ - public boolean shouldLetInstallerDecide() { - return mShouldLetInstallerDecide; } public byte[] getDigestBytes() { - return mDigest.mDigestBytes.length > 0 ? mDigest.getDigestBytes()[0] : EMPTY_DIGEST; + return mDigest.getDigestBytes()[0]; } public int getDigestPrefix() { @@ -192,15 +127,11 @@ public final class InstantAppResolveInfo implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - out.writeBoolean(mShouldLetInstallerDecide); - out.writeBundle(mExtras); - if (mShouldLetInstallerDecide) { - return; - } out.writeParcelable(mDigest, flags); out.writeString(mPackageName); out.writeList(mFilters); out.writeLong(mVersionCode); + out.writeBundle(mExtras); } public static final Parcelable.Creator<InstantAppResolveInfo> CREATOR @@ -228,9 +159,7 @@ public final class InstantAppResolveInfo implements Parcelable { @SystemApi public static final class InstantAppDigest implements Parcelable { private static final int DIGEST_MASK = 0xfffff000; - - public static final InstantAppDigest UNDEFINED = - new InstantAppDigest(new byte[][]{}, new int[]{}); + private static final int DIGEST_PREFIX_COUNT = 5; /** Full digest of the domain hashes */ private final byte[][] mDigestBytes; /** The first 4 bytes of the domain hashes */ @@ -257,11 +186,6 @@ public final class InstantAppResolveInfo implements Parcelable { } } - private InstantAppDigest(byte[][] digestBytes, int[] prefix) { - this.mDigestPrefix = prefix; - this.mDigestBytes = digestBytes; - } - private static byte[][] generateDigest(String hostName, int maxDigests) { ArrayList<byte[]> digests = new ArrayList<>(); try { diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index 1dfff5efcab5..2ab2d20ed20d 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -103,14 +103,11 @@ public class ResolverListController { List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null; for (int i = 0, N = intents.size(); i < N; i++) { final Intent intent = intents.get(i); - int flags = PackageManager.MATCH_DEFAULT_ONLY - | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0) - | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0); - if (intent.isBrowsableWebIntent() - || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) { - flags |= PackageManager.MATCH_INSTANT; - } - final List<ResolveInfo> infos = mpm.queryIntentActivities(intent, flags); + final List<ResolveInfo> infos = mpm.queryIntentActivities(intent, + PackageManager.MATCH_DEFAULT_ONLY + | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0) + | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0) + | PackageManager.MATCH_INSTANT); // Remove any activities that are not exported. int totalSize = infos.size(); for (int j = totalSize - 1; j >= 0 ; j--) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index bf3882587693..6beafcb94ead 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1251,14 +1251,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { try { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent"); - int modifiedFlags = flags - | PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS; - if (intent.isBrowsableWebIntent() - || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) { - modifiedFlags |= PackageManager.MATCH_INSTANT; - } return mService.getPackageManagerInternalLocked().resolveIntent( - intent, resolvedType, modifiedFlags, userId, true); + intent, resolvedType, PackageManager.MATCH_INSTANT + | PackageManager.MATCH_DEFAULT_ONLY | flags + | ActivityManagerService.STOCK_PM_FLAGS, userId, true); } finally { Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index eab88aa45e44..8fd754af1a0f 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -31,7 +31,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; -import static android.content.Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT; @@ -790,7 +789,7 @@ class ActivityStarter { // Instead, launch the ephemeral installer. Once the installer is finished, it // starts either the intent we resolved here [on install error] or the ephemeral // app [on install success]. - if (rInfo != null && rInfo.isInstantAppAvailable) { + if (rInfo != null && rInfo.auxiliaryInfo != null) { intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent, callingPackage, verificationBundle, resolvedType, userId); resolvedType = null; @@ -850,27 +849,22 @@ class ActivityStarter { /** * Creates a launch intent for the given auxiliary resolution data. */ - private @NonNull Intent createLaunchIntent(@Nullable AuxiliaryResolveInfo auxiliaryResponse, + private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse, Intent originalIntent, String callingPackage, Bundle verificationBundle, String resolvedType, int userId) { - if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) { + if (auxiliaryResponse.needsPhaseTwo) { // request phase two resolution mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo( auxiliaryResponse, originalIntent, resolvedType, callingPackage, verificationBundle, userId); } return InstantAppResolver.buildEphemeralInstallerIntent( - originalIntent, - InstantAppResolver.sanitizeIntent(originalIntent), - auxiliaryResponse == null ? null : auxiliaryResponse.failureIntent, - callingPackage, - verificationBundle, - resolvedType, - userId, - auxiliaryResponse == null ? null : auxiliaryResponse.installFailureActivity, - auxiliaryResponse == null ? null : auxiliaryResponse.token, - auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo, - auxiliaryResponse == null ? null : auxiliaryResponse.filters); + Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent, + auxiliaryResponse.failureIntent, callingPackage, verificationBundle, + resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName, + auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode, + auxiliaryResponse.token, auxiliaryResponse.resolveInfo.getExtras(), + auxiliaryResponse.needsPhaseTwo); } void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) { @@ -930,12 +924,12 @@ class ActivityStarter { // Don't modify the client's object! intent = new Intent(intent); if (componentSpecified - && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction()) - && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction()) + && intent.getData() != null + && Intent.ACTION_VIEW.equals(intent.getAction()) && mService.getPackageManagerInternalLocked() .isInstantAppInstallerComponent(intent.getComponent())) { // intercept intents targeted directly to the ephemeral installer the - // ephemeral installer should never be started with a raw Intent; instead + // ephemeral installer should never be started with a raw URL; instead // adjust the intent so it looks like a "normal" instant app launch intent.setComponent(null /*component*/); componentSpecified = false; diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java index 6d6c960eed7e..b5ddf8c511f1 100644 --- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java +++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java @@ -43,7 +43,6 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.TimeoutException; @@ -85,8 +84,8 @@ final class EphemeralResolverConnection implements DeathRecipient { mIntent = new Intent(action).setComponent(componentName); } - public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(Intent sanitizedIntent, - int hashPrefix[], String token) throws ConnectionException { + public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[], + String token) throws ConnectionException { throwIfCalledOnMainThread(); IInstantAppResolver target = null; try { @@ -99,7 +98,7 @@ final class EphemeralResolverConnection implements DeathRecipient { } try { return mGetEphemeralResolveInfoCaller - .getEphemeralResolveInfoList(target, sanitizedIntent, hashPrefix, token); + .getEphemeralResolveInfoList(target, hashPrefix, token); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_CALL); } catch (RemoteException ignore) { @@ -112,22 +111,26 @@ final class EphemeralResolverConnection implements DeathRecipient { return null; } - public final void getInstantAppIntentFilterList(Intent sanitizedIntent, int hashPrefix[], - String token, PhaseTwoCallback callback, Handler callbackHandler, final long startTime) - throws ConnectionException { + public final void getInstantAppIntentFilterList(int hashPrefix[], String token, + String hostName, PhaseTwoCallback callback, Handler callbackHandler, + final long startTime) throws ConnectionException { final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() { @Override public void sendResult(Bundle data) throws RemoteException { final ArrayList<InstantAppResolveInfo> resolveList = data.getParcelableArrayList( InstantAppResolverService.EXTRA_RESOLVE_INFO); - callbackHandler.post(() -> callback.onPhaseTwoResolved(resolveList, startTime)); + callbackHandler.post(new Runnable() { + @Override + public void run() { + callback.onPhaseTwoResolved(resolveList, startTime); + } + }); } }; try { getRemoteInstanceLazy(token) - .getInstantAppIntentFilterList(sanitizedIntent, hashPrefix, token, - remoteCallback); + .getInstantAppIntentFilterList(hashPrefix, token, hostName, remoteCallback); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_BIND); } catch (InterruptedException e) { @@ -334,11 +337,10 @@ final class EphemeralResolverConnection implements DeathRecipient { } public List<InstantAppResolveInfo> getEphemeralResolveInfoList( - IInstantAppResolver target, Intent sanitizedIntent, int hashPrefix[], String token) + IInstantAppResolver target, int hashPrefix[], String token) throws RemoteException, TimeoutException { final int sequence = onBeforeRemoteCall(); - target.getInstantAppResolveInfoList(sanitizedIntent, hashPrefix, token, sequence, - mCallback); + target.getInstantAppResolveInfoList(hashPrefix, token, sequence, mCallback); return getResultTimed(sequence); } } diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java index 55212cc6b3d8..30072d45ccab 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolver.java +++ b/services/core/java/com/android/server/pm/InstantAppResolver.java @@ -40,14 +40,11 @@ import android.content.pm.InstantAppIntentFilter; import android.content.pm.InstantAppResolveInfo; import android.content.pm.InstantAppResolveInfo.InstantAppDigest; import android.metrics.LogMaker; -import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; -import android.text.TextUtils; import android.util.Log; -import android.util.Slog; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; @@ -56,12 +53,8 @@ import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; import java.util.List; -import java.util.Set; import java.util.UUID; /** @hide */ @@ -86,7 +79,6 @@ public abstract class InstantAppResolver { public @interface ResolutionStatus {} private static MetricsLogger sMetricsLogger; - private static MetricsLogger getLogger() { if (sMetricsLogger == null) { sMetricsLogger = new MetricsLogger(); @@ -94,49 +86,26 @@ public abstract class InstantAppResolver { return sMetricsLogger; } - /** - * Returns an intent with potential PII removed from the original intent. Fields removed - * include extras and the host + path of the data, if defined. - */ - public static Intent sanitizeIntent(Intent origIntent) { - final Intent sanitizedIntent; - sanitizedIntent = new Intent(origIntent.getAction()); - Set<String> categories = origIntent.getCategories(); - if (categories != null) { - for (String category : categories) { - sanitizedIntent.addCategory(category); - } - } - Uri sanitizedUri = origIntent.getData() == null - ? null - : Uri.fromParts(origIntent.getScheme(), "", ""); - sanitizedIntent.setDataAndType(sanitizedUri, origIntent.getType()); - sanitizedIntent.addFlags(origIntent.getFlags()); - sanitizedIntent.setPackage(origIntent.getPackage()); - return sanitizedIntent; - } - - public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne( + public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(Context context, EphemeralResolverConnection connection, InstantAppRequest requestObj) { final long startTime = System.currentTimeMillis(); final String token = UUID.randomUUID().toString(); if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] Phase1; resolving"); } - final Intent origIntent = requestObj.origIntent; - final Intent sanitizedIntent = sanitizeIntent(origIntent); - - final InstantAppDigest digest = getInstantAppDigest(origIntent); + final Intent intent = requestObj.origIntent; + final InstantAppDigest digest = + new InstantAppDigest(intent.getData().getHost(), 5 /*maxDigests*/); 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(shaPrefix, token); if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { resolveInfo = InstantAppResolver.filterInstantAppIntent( - instantAppResolveInfoList, origIntent, requestObj.resolvedType, - requestObj.userId, origIntent.getPackage(), digest, token); + instantAppResolveInfoList, intent, requestObj.resolvedType, + requestObj.userId, intent.getPackage(), digest, token); } } catch (ConnectionException e) { if (e.failure == ConnectionException.FAILURE_BIND) { @@ -166,12 +135,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, EphemeralResolverConnection connection, InstantAppRequest requestObj, ActivityInfo instantAppInstaller, Handler callbackHandler) { @@ -180,53 +143,73 @@ public abstract class InstantAppResolver { if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] Phase2; resolving"); } - final Intent origIntent = requestObj.origIntent; - final Intent sanitizedIntent = sanitizeIntent(origIntent); - final InstantAppDigest digest = getInstantAppDigest(origIntent); + final Intent intent = requestObj.origIntent; + final String hostName = intent.getData().getHost(); + final InstantAppDigest digest = new InstantAppDigest(hostName, 5 /*maxDigests*/); final int[] shaPrefix = digest.getDigestPrefix(); final PhaseTwoCallback callback = new PhaseTwoCallback() { @Override void onPhaseTwoResolved(List<InstantAppResolveInfo> instantAppResolveInfoList, long startTime) { + final String packageName; + final String splitName; + final long versionCode; final Intent failureIntent; + final Bundle extras; if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { final AuxiliaryResolveInfo instantAppIntentInfo = InstantAppResolver.filterInstantAppIntent( - instantAppResolveInfoList, origIntent, null /*resolvedType*/, - 0 /*userId*/, origIntent.getPackage(), digest, token); - if (instantAppIntentInfo != null) { + instantAppResolveInfoList, intent, null /*resolvedType*/, + 0 /*userId*/, intent.getPackage(), digest, token); + if (instantAppIntentInfo != null + && instantAppIntentInfo.resolveInfo != null) { + packageName = instantAppIntentInfo.resolveInfo.getPackageName(); + splitName = instantAppIntentInfo.splitName; + versionCode = instantAppIntentInfo.resolveInfo.getVersionCode(); failureIntent = instantAppIntentInfo.failureIntent; + extras = instantAppIntentInfo.resolveInfo.getExtras(); } else { + packageName = null; + splitName = null; + versionCode = -1; failureIntent = null; + extras = null; } } else { + packageName = null; + splitName = null; + versionCode = -1; failureIntent = null; + extras = null; } final Intent installerIntent = buildEphemeralInstallerIntent( + Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE, requestObj.origIntent, - sanitizedIntent, failureIntent, requestObj.callingPackage, requestObj.verificationBundle, requestObj.resolvedType, requestObj.userId, + packageName, + splitName, requestObj.responseObj.installFailureActivity, + versionCode, token, - false /*needsPhaseTwo*/, - requestObj.responseObj.filters); + extras, + false /*needsPhaseTwo*/); installerIntent.setComponent(new ComponentName( instantAppInstaller.packageName, instantAppInstaller.name)); logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token, - requestObj.responseObj.filters != null ? RESOLUTION_SUCCESS : RESOLUTION_FAILURE); + packageName != null ? RESOLUTION_SUCCESS : RESOLUTION_FAILURE); context.startActivity(installerIntent); } }; try { - connection.getInstantAppIntentFilterList(sanitizedIntent, shaPrefix, token, callback, - callbackHandler, startTime); + connection.getInstantAppIntentFilterList( + shaPrefix, token, hostName, callback, callbackHandler, startTime); } catch (ConnectionException e) { @ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE; if (e.failure == ConnectionException.FAILURE_BIND) { @@ -248,20 +231,23 @@ public abstract class InstantAppResolver { * Builds and returns an intent to launch the instant installer. */ public static Intent buildEphemeralInstallerIntent( + @NonNull String action, @NonNull Intent origIntent, - @NonNull Intent sanitizedIntent, - @Nullable Intent failureIntent, + @NonNull Intent failureIntent, @NonNull String callingPackage, @Nullable Bundle verificationBundle, @NonNull String resolvedType, int userId, + @NonNull String instantAppPackageName, + @Nullable String instantAppSplitName, @Nullable ComponentName installFailureActivity, + long versionCode, @Nullable String token, - boolean needsPhaseTwo, - List<AuxiliaryResolveInfo.AuxiliaryFilter> filters) { + @Nullable Bundle extras, + boolean needsPhaseTwo) { // Construct the intent that launches the instant installer int flags = origIntent.getFlags(); - final Intent intent = new Intent(); + final Intent intent = new Intent(action); intent.setFlags(flags | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK @@ -274,23 +260,20 @@ public abstract class InstantAppResolver { intent.putExtra(Intent.EXTRA_EPHEMERAL_HOSTNAME, origIntent.getData().getHost()); } intent.putExtra(Intent.EXTRA_INSTANT_APP_ACTION, origIntent.getAction()); - intent.putExtra(Intent.EXTRA_INTENT, sanitizedIntent); + if (extras != null) { + intent.putExtra(Intent.EXTRA_INSTANT_APP_EXTRAS, extras); + } - if (needsPhaseTwo) { - intent.setAction(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE); - } else { - // We have all of the data we need; just start the installer without a second phase + // We have all of the data we need; just start the installer without a second phase + if (!needsPhaseTwo) { + // Intent that is launched if the package couldn't be installed for any reason. if (failureIntent != null || installFailureActivity != null) { - // Intent that is launched if the package couldn't be installed for any reason. try { final Intent onFailureIntent; if (installFailureActivity != null) { onFailureIntent = new Intent(); onFailureIntent.setComponent(installFailureActivity); - if (filters != null && filters.size() == 1) { - onFailureIntent.putExtra(Intent.EXTRA_SPLIT_NAME, - filters.get(0).splitName); - } + onFailureIntent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName); onFailureIntent.putExtra(Intent.EXTRA_INTENT, origIntent); } else { onFailureIntent = failureIntent; @@ -326,35 +309,17 @@ public abstract class InstantAppResolver { intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget)); } catch (RemoteException ignore) { /* ignore; same process */ } + + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, instantAppPackageName); + intent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName); + intent.putExtra(Intent.EXTRA_VERSION_CODE, (int) (versionCode & 0x7fffffff)); + intent.putExtra(Intent.EXTRA_LONG_VERSION_CODE, versionCode); + intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage); if (verificationBundle != null) { intent.putExtra(Intent.EXTRA_VERIFICATION_BUNDLE, verificationBundle); } - intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage); - - if (filters != null) { - Bundle resolvableFilters[] = new Bundle[filters.size()]; - for (int i = 0, max = filters.size(); i < max; i++) { - Bundle resolvableFilter = new Bundle(); - AuxiliaryResolveInfo.AuxiliaryFilter filter = filters.get(i); - resolvableFilter.putBoolean(Intent.EXTRA_UNKNOWN_INSTANT_APP, - filter.resolveInfo != null - && filter.resolveInfo.shouldLetInstallerDecide()); - resolvableFilter.putString(Intent.EXTRA_PACKAGE_NAME, filter.packageName); - resolvableFilter.putString(Intent.EXTRA_SPLIT_NAME, filter.splitName); - resolvableFilter.putLong(Intent.EXTRA_LONG_VERSION_CODE, filter.versionCode); - resolvableFilter.putBundle(Intent.EXTRA_INSTANT_APP_EXTRAS, filter.extras); - resolvableFilters[i] = resolvableFilter; - if (i == 0) { - // for backwards compat, always set the first result on the intent and add - // the int version code - intent.putExtras(resolvableFilter); - intent.putExtra(Intent.EXTRA_VERSION_CODE, (int) filter.versionCode); - } - } - intent.putExtra(Intent.EXTRA_INSTANT_APP_BUNDLES, resolvableFilters); - } - intent.setAction(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE); } + return intent; } @@ -365,131 +330,66 @@ public abstract class InstantAppResolver { final int[] shaPrefix = digest.getDigestPrefix(); final byte[][] digestBytes = digest.getDigestBytes(); final Intent failureIntent = new Intent(origIntent); - boolean requiresSecondPhase = false; failureIntent.setFlags(failureIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL); failureIntent.setLaunchToken(token); - ArrayList<AuxiliaryResolveInfo.AuxiliaryFilter> filters = null; - boolean isWebIntent = origIntent.isBrowsableWebIntent(); - for (InstantAppResolveInfo instantAppResolveInfo : instantAppResolveInfoList) { - if (shaPrefix.length > 0 && instantAppResolveInfo.shouldLetInstallerDecide()) { - Slog.e(TAG, "InstantAppResolveInfo with mShouldLetInstallerDecide=true when digest" - + " provided; ignoring"); - continue; - } - byte[] filterDigestBytes = instantAppResolveInfo.getDigestBytes(); - // Only include matching digests if we have a prefix and we're either dealing with a - // web intent or the resolveInfo specifies digest details. - if (shaPrefix.length > 0 && (isWebIntent || filterDigestBytes.length > 0)) { - boolean matchFound = false; - // Go in reverse order so we match the narrowest scope first. - for (int i = shaPrefix.length - 1; i >= 0; --i) { - if (Arrays.equals(digestBytes[i], filterDigestBytes)) { - matchFound = true; - break; - } - } - if (!matchFound) { + // Go in reverse order so we match the narrowest scope first. + for (int i = shaPrefix.length - 1; i >= 0 ; --i) { + for (InstantAppResolveInfo instantAppInfo : instantAppResolveInfoList) { + if (!Arrays.equals(digestBytes[i], instantAppInfo.getDigestBytes())) { continue; } - } - // We matched a resolve info; resolve the filters to see if anything matches completely. - List<AuxiliaryResolveInfo.AuxiliaryFilter> matchFilters = computeResolveFilters( - origIntent, resolvedType, userId, packageName, token, instantAppResolveInfo); - if (matchFilters != null) { - if (matchFilters.isEmpty()) { - requiresSecondPhase = true; + if (packageName != null + && !packageName.equals(instantAppInfo.getPackageName())) { + continue; } - if (filters == null) { - filters = new ArrayList<>(matchFilters); - } else { - filters.addAll(matchFilters); + final List<InstantAppIntentFilter> instantAppFilters = + instantAppInfo.getIntentFilters(); + // No filters; we need to start phase two + if (instantAppFilters == null || instantAppFilters.isEmpty()) { + if (DEBUG_EPHEMERAL) { + Log.d(TAG, "No app filters; go to phase 2"); + } + return new AuxiliaryResolveInfo(instantAppInfo, + new IntentFilter(Intent.ACTION_VIEW) /*intentFilter*/, + null /*splitName*/, token, true /*needsPhase2*/, + null /*failureIntent*/); } - } - } - if (filters != null && !filters.isEmpty()) { - return new AuxiliaryResolveInfo(token, requiresSecondPhase, failureIntent, filters); - } - // Hash or filter mis-match; no instant apps for this domain. - return null; - } - - /** - * Returns one of three states: <p/> - * <ul> - * <li>{@code null} if there are no matches will not be; resolution is unnecessary.</li> - * <li>An empty list signifying that a 2nd phase of resolution is required.</li> - * <li>A populated list meaning that matches were found and should be sent directly to the - * installer</li> - * </ul> - * - */ - private static List<AuxiliaryResolveInfo.AuxiliaryFilter> computeResolveFilters( - Intent origIntent, String resolvedType, int userId, String packageName, String token, - InstantAppResolveInfo instantAppInfo) { - if (instantAppInfo.shouldLetInstallerDecide()) { - return Collections.singletonList( - new AuxiliaryResolveInfo.AuxiliaryFilter( - instantAppInfo, null /* splitName */, - instantAppInfo.getExtras())); - } - if (packageName != null - && !packageName.equals(instantAppInfo.getPackageName())) { - return null; - } - final List<InstantAppIntentFilter> instantAppFilters = - instantAppInfo.getIntentFilters(); - if (instantAppFilters == null || instantAppFilters.isEmpty()) { - // No filters on web intent; no matches, 2nd phase unnecessary. - if (origIntent.isBrowsableWebIntent()) { - return null; - } - // No filters; we need to start phase two - if (DEBUG_EPHEMERAL) { - Log.d(TAG, "No app filters; go to phase 2"); - } - return Collections.emptyList(); - } - final PackageManagerService.EphemeralIntentResolver instantAppResolver = - new PackageManagerService.EphemeralIntentResolver(); - for (int j = instantAppFilters.size() - 1; j >= 0; --j) { - final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j); - final List<IntentFilter> splitFilters = instantAppFilter.getFilters(); - if (splitFilters == null || splitFilters.isEmpty()) { - continue; - } - for (int k = splitFilters.size() - 1; k >= 0; --k) { - IntentFilter filter = splitFilters.get(k); - Iterator<IntentFilter.AuthorityEntry> authorities = - filter.authoritiesIterator(); - // ignore http/s-only filters. - if ((authorities == null || !authorities.hasNext()) - && (filter.hasDataScheme("http") || filter.hasDataScheme("https")) - && filter.hasAction(Intent.ACTION_VIEW) - && filter.hasCategory(Intent.CATEGORY_BROWSABLE)) { - continue; + // We have a domain match; resolve the filters to see if anything matches. + final PackageManagerService.EphemeralIntentResolver instantAppResolver = + new PackageManagerService.EphemeralIntentResolver(); + for (int j = instantAppFilters.size() - 1; j >= 0; --j) { + final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j); + final List<IntentFilter> splitFilters = instantAppFilter.getFilters(); + if (splitFilters == null || splitFilters.isEmpty()) { + continue; + } + for (int k = splitFilters.size() - 1; k >= 0; --k) { + final AuxiliaryResolveInfo intentInfo = + new AuxiliaryResolveInfo(instantAppInfo, + splitFilters.get(k), instantAppFilter.getSplitName(), + token, false /*needsPhase2*/, failureIntent); + instantAppResolver.addFilter(intentInfo); + } } - instantAppResolver.addFilter( - new AuxiliaryResolveInfo.AuxiliaryFilter( - filter, - instantAppInfo, - instantAppFilter.getSplitName(), - instantAppInfo.getExtras() - )); - } - } - List<AuxiliaryResolveInfo.AuxiliaryFilter> matchedResolveInfoList = - instantAppResolver.queryIntent( + List<AuxiliaryResolveInfo> matchedResolveInfoList = instantAppResolver.queryIntent( origIntent, resolvedType, false /*defaultOnly*/, userId); - if (!matchedResolveInfoList.isEmpty()) { - if (DEBUG_EPHEMERAL) { - Log.d(TAG, "[" + token + "] Found match(es); " + matchedResolveInfoList); + if (!matchedResolveInfoList.isEmpty()) { + if (DEBUG_EPHEMERAL) { + final AuxiliaryResolveInfo info = matchedResolveInfoList.get(0); + Log.d(TAG, "[" + token + "] Found match;" + + " package: " + info.packageName + + ", split: " + info.splitName + + ", versionCode: " + info.versionCode); + } + return matchedResolveInfoList.get(0); + } else if (DEBUG_EPHEMERAL) { + Log.d(TAG, "[" + token + "] No matches found" + + " package: " + instantAppInfo.getPackageName() + + ", versionCode: " + instantAppInfo.getVersionCode()); + } } - return matchedResolveInfoList; - } else if (DEBUG_EPHEMERAL) { - Log.d(TAG, "[" + token + "] No matches found" - + " package: " + instantAppInfo.getPackageName() - + ", versionCode: " + instantAppInfo.getVersionCode()); } + // Hash or filter mis-match; no instant apps for this domain. return null; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 18c5ffdc2ff5..c6b55cc1d555 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3595,35 +3595,24 @@ Slog.e("TODD", } private @Nullable ActivityInfo getInstantAppInstallerLPr() { - String[] orderedActions = Build.IS_ENG - ? new String[]{ - Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE + "_TEST", - Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, - Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE} - : new String[]{ - Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, - Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE}; + final Intent intent = new Intent(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); final int resolveFlags = MATCH_DIRECT_BOOT_AWARE - | MATCH_DIRECT_BOOT_UNAWARE - | Intent.FLAG_IGNORE_EPHEMERAL - | (!Build.IS_ENG ? MATCH_SYSTEM_ONLY : 0); - final Intent intent = new Intent(); - intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); - List<ResolveInfo> matches = null; - for (String action : orderedActions) { - intent.setAction(action); + | MATCH_DIRECT_BOOT_UNAWARE + | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0); + List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE, + resolveFlags, UserHandle.USER_SYSTEM); + // temporarily look for the old action + if (matches.isEmpty()) { + if (DEBUG_EPHEMERAL) { + Slog.d(TAG, "Ephemeral installer not found with new action; try old one"); + } + intent.setAction(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE); matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE, resolveFlags, UserHandle.USER_SYSTEM); - if (matches.isEmpty()) { - if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Instant App installer not found with " + action); - } - } else { - break; - } } Iterator<ResolveInfo> iter = matches.iterator(); while (iter.hasNext()) { @@ -3631,8 +3620,7 @@ Slog.e("TODD", final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName); if (ps != null) { final PermissionsState permissionsState = ps.getPermissionsState(); - if (permissionsState.hasPermission(Manifest.permission.INSTALL_PACKAGES, 0) - || Build.IS_ENG) { + if (permissionsState.hasPermission(Manifest.permission.INSTALL_PACKAGES, 0)) { continue; } } @@ -4791,7 +4779,10 @@ Slog.e("TODD", flags |= PackageManager.MATCH_INSTANT; } else { final boolean wantMatchInstant = (flags & PackageManager.MATCH_INSTANT) != 0; - final boolean allowMatchInstant = wantInstantApps + final boolean allowMatchInstant = + (wantInstantApps + && Intent.ACTION_VIEW.equals(intent.getAction()) + && hasWebURI(intent)) || (wantMatchInstant && canViewInstantApps(callingUid, userId)); flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY | PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY); @@ -5981,14 +5972,8 @@ Slog.e("TODD", if (!skipPackageCheck && intent.getPackage() != null) { return false; } - if (!intent.isBrowsableWebIntent()) { - // for non web intents, we should not resolve externally if an app already exists to - // handle it or if the caller didn't explicitly request it. - if ((resolvedActivities != null && resolvedActivities.size() != 0) - || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) == 0) { - return false; - } - } else if (intent.getData() == null) { + final boolean isWebUri = hasWebURI(intent); + if (!isWebUri || intent.getData().getHost() == null) { return false; } // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution. @@ -6386,7 +6371,7 @@ Slog.e("TODD", if (matches.get(i).getTargetUserId() == targetUserId) return true; } } - if (intent.hasWebURI()) { + if (hasWebURI(intent)) { // cross-profile app linking works only towards the parent. final int callingUid = Binder.getCallingUid(); final UserInfo parent = getProfileParent(sourceUserId); @@ -6561,7 +6546,7 @@ Slog.e("TODD", sortResult = true; } } - if (intent.hasWebURI()) { + if (hasWebURI(intent)) { CrossProfileDomainInfo xpDomainInfo = null; final UserInfo parent = getProfileParent(userId); if (parent != null) { @@ -6647,6 +6632,7 @@ Slog.e("TODD", if (ps.getInstantApp(userId)) { final long packedStatus = getDomainVerificationStatusLPr(ps, userId); final int status = (int)(packedStatus >> 32); + final int linkGeneration = (int)(packedStatus & 0xFFFFFFFF); if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { // there's a local instant application installed, but, the user has // chosen to never use it; skip resolution and don't acknowledge @@ -6678,8 +6664,9 @@ Slog.e("TODD", null /*responseObj*/, intent /*origIntent*/, resolvedType, null /*callingPackage*/, userId, null /*verificationBundle*/, resolveForStart); - auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne( - mInstantAppResolverConnection, requestObject); + auxiliaryResponse = + InstantAppResolver.doInstantAppResolutionPhaseOne( + mContext, mInstantAppResolverConnection, requestObject); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } else { // we have an instant application locally, but, we can't admit that since @@ -6688,40 +6675,35 @@ Slog.e("TODD", // instant application available externally. when it comes time to start // the instant application, we'll do the right thing. final ApplicationInfo ai = localInstantApp.activityInfo.applicationInfo; - auxiliaryResponse = new AuxiliaryResolveInfo(null /* failureActivity */, - ai.packageName, ai.versionCode, null /* splitName */); + auxiliaryResponse = new AuxiliaryResolveInfo( + ai.packageName, null /*splitName*/, null /*failureActivity*/, + ai.versionCode, null /*failureIntent*/); } } - if (intent.isBrowsableWebIntent() && auxiliaryResponse == null) { - return result; - } - final PackageSetting ps = mSettings.mPackages.get(mInstantAppInstallerActivity.packageName); - if (ps == null) { - return result; - } - final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo); - ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo( - mInstantAppInstallerActivity, 0, ps.readUserState(userId), userId); - ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART - | IntentFilter.MATCH_ADJUSTMENT_NORMAL; - // add a non-generic filter - ephemeralInstaller.filter = new IntentFilter(); - if (intent.getAction() != null) { - ephemeralInstaller.filter.addAction(intent.getAction()); - } - if (intent.getData() != null && intent.getData().getPath() != null) { - ephemeralInstaller.filter.addDataPath( - intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL); - } - ephemeralInstaller.isInstantAppAvailable = true; - // make sure this resolver is the default - ephemeralInstaller.isDefault = true; - ephemeralInstaller.auxiliaryInfo = auxiliaryResponse; - if (DEBUG_EPHEMERAL) { - Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); + if (auxiliaryResponse != null) { + if (DEBUG_EPHEMERAL) { + Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); + } + final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo); + final PackageSetting ps = + mSettings.mPackages.get(mInstantAppInstallerActivity.packageName); + if (ps != null) { + ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo( + mInstantAppInstallerActivity, 0, ps.readUserState(userId), userId); + ephemeralInstaller.activityInfo.launchToken = auxiliaryResponse.token; + ephemeralInstaller.auxiliaryInfo = auxiliaryResponse; + // make sure this resolver is the default + ephemeralInstaller.isDefault = true; + ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART + | IntentFilter.MATCH_ADJUSTMENT_NORMAL; + // add a non-generic filter + ephemeralInstaller.filter = new IntentFilter(intent.getAction()); + ephemeralInstaller.filter.addDataPath( + intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL); + ephemeralInstaller.isInstantAppAvailable = true; + result.add(ephemeralInstaller); + } } - - result.add(ephemeralInstaller); return result; } @@ -6836,11 +6818,10 @@ Slog.e("TODD", final ResolveInfo info = resolveInfos.get(i); // allow activities that are defined in the provided package if (allowDynamicSplits - && info.activityInfo != null && info.activityInfo.splitName != null && !ArrayUtils.contains(info.activityInfo.applicationInfo.splitNames, info.activityInfo.splitName)) { - if (mInstantAppInstallerActivity == null) { + if (mInstantAppInstallerInfo == null) { if (DEBUG_INSTALL) { Slog.v(TAG, "No installer - not adding it to the ResolveInfo list"); } @@ -6852,15 +6833,14 @@ Slog.e("TODD", if (DEBUG_INSTALL) { Slog.v(TAG, "Adding installer to the ResolveInfo list"); } - final ResolveInfo installerInfo = new ResolveInfo( - mInstantAppInstallerInfo); + final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo); final ComponentName installFailureActivity = findInstallFailureActivity( info.activityInfo.packageName, filterCallingUid, userId); installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo( + info.activityInfo.packageName, info.activityInfo.splitName, installFailureActivity, - info.activityInfo.packageName, info.activityInfo.applicationInfo.versionCode, - info.activityInfo.splitName); + null /*failureIntent*/); installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART | IntentFilter.MATCH_ADJUSTMENT_NORMAL; // add a non-generic filter @@ -6877,7 +6857,6 @@ Slog.e("TODD", installerInfo.priority = info.priority; installerInfo.preferredOrder = info.preferredOrder; installerInfo.isDefault = info.isDefault; - installerInfo.isInstantAppAvailable = true; resolveInfos.set(i, installerInfo); continue; } @@ -6935,6 +6914,17 @@ Slog.e("TODD", return resolveInfos.size() > 0 && resolveInfos.get(0).priority >= 0; } + private static boolean hasWebURI(Intent intent) { + if (intent.getData() == null) { + return false; + } + final String scheme = intent.getScheme(); + if (TextUtils.isEmpty(scheme)) { + return false; + } + return scheme.equals(IntentFilter.SCHEME_HTTP) || scheme.equals(IntentFilter.SCHEME_HTTPS); + } + private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Intent intent, int matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo, int userId) { @@ -7607,13 +7597,11 @@ Slog.e("TODD", if (DEBUG_EPHEMERAL) { Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); } - final ResolveInfo installerInfo = new ResolveInfo( - mInstantAppInstallerInfo); + final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo); installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo( - null /* installFailureActivity */, - info.serviceInfo.packageName, - info.serviceInfo.applicationInfo.versionCode, - info.serviceInfo.splitName); + info.serviceInfo.packageName, info.serviceInfo.splitName, + null /*failureActivity*/, info.serviceInfo.applicationInfo.versionCode, + null /*failureIntent*/); // make sure this resolver is the default installerInfo.isDefault = true; installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART @@ -7729,13 +7717,11 @@ Slog.e("TODD", if (DEBUG_EPHEMERAL) { Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); } - final ResolveInfo installerInfo = new ResolveInfo( - mInstantAppInstallerInfo); + final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo); installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo( - null /*failureActivity*/, - info.providerInfo.packageName, - info.providerInfo.applicationInfo.versionCode, - info.providerInfo.splitName); + info.providerInfo.packageName, info.providerInfo.splitName, + null /*failureActivity*/, info.providerInfo.applicationInfo.versionCode, + null /*failureIntent*/); // make sure this resolver is the default installerInfo.isDefault = true; installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART @@ -11777,7 +11763,7 @@ Slog.e("TODD", mInstantAppInstallerActivity.exported = true; mInstantAppInstallerActivity.enabled = true; mInstantAppInstallerInfo.activityInfo = mInstantAppInstallerActivity; - mInstantAppInstallerInfo.priority = 1; + mInstantAppInstallerInfo.priority = 0; mInstantAppInstallerInfo.preferredOrder = 1; mInstantAppInstallerInfo.isDefault = true; mInstantAppInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART @@ -13227,8 +13213,7 @@ Slog.e("TODD", } static final class EphemeralIntentResolver - extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter, - AuxiliaryResolveInfo.AuxiliaryFilter> { + extends IntentResolver<AuxiliaryResolveInfo, AuxiliaryResolveInfo> { /** * The result that has the highest defined order. Ordering applies on a * per-package basis. Mapping is from package name to Pair of order and @@ -13243,19 +13228,18 @@ Slog.e("TODD", final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult = new ArrayMap<>(); @Override - protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) { - return new AuxiliaryResolveInfo.AuxiliaryFilter[size]; + protected AuxiliaryResolveInfo[] newArray(int size) { + return new AuxiliaryResolveInfo[size]; } @Override - protected boolean isPackageForFilter(String packageName, - AuxiliaryResolveInfo.AuxiliaryFilter responseObj) { + protected boolean isPackageForFilter(String packageName, AuxiliaryResolveInfo responseObj) { return true; } @Override - protected AuxiliaryResolveInfo.AuxiliaryFilter newResult( - AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) { + protected AuxiliaryResolveInfo newResult(AuxiliaryResolveInfo responseObj, int match, + int userId) { if (!sUserManager.exists(userId)) { return null; } @@ -13276,7 +13260,7 @@ Slog.e("TODD", } @Override - protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) { + protected void filterResults(List<AuxiliaryResolveInfo> results) { // only do work if ordering is enabled [most of the time it won't be] if (mOrderResult.size() == 0) { return; |