diff options
| author | 2017-02-23 21:25:04 +0000 | |
|---|---|---|
| committer | 2017-02-23 21:25:08 +0000 | |
| commit | 5feacbed43c73958b68e69acd894c75ce1f6cb4d (patch) | |
| tree | 5021ab4ca2020421aade865a52b577c8f5f2b2ed | |
| parent | d7ece194c79e9a959c0ec8380e17c960a1a98c9c (diff) | |
| parent | e991022423c2e5b4386553af7ef3b54da7c54be1 (diff) | |
Merge "Load splits on-demand"
| -rw-r--r-- | core/java/android/content/pm/AuxiliaryResolveInfo.java (renamed from core/java/android/content/pm/EphemeralResponse.java) | 33 | ||||
| -rw-r--r-- | core/java/android/content/pm/EphemeralRequest.java | 9 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManagerInternal.java | 5 | ||||
| -rw-r--r-- | core/java/android/content/pm/ResolveInfo.java | 7 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStarter.java | 37 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/EphemeralResolver.java | 71 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/EphemeralResolverConnection.java | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 156 |
8 files changed, 187 insertions, 132 deletions
diff --git a/core/java/android/content/pm/EphemeralResponse.java b/core/java/android/content/pm/AuxiliaryResolveInfo.java index 6e569f7d4667..7d7784a185bf 100644 --- a/core/java/android/content/pm/EphemeralResponse.java +++ b/core/java/android/content/pm/AuxiliaryResolveInfo.java @@ -18,13 +18,19 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Intent; import android.content.IntentFilter; /** - * Ephemeral application resolution response. + * Auxiliary application resolution response. + * <p> + * Used when resolution occurs, but, the target is not actually on the device. + * This happens resolving instant apps that haven't been installed yet or if + * the application consists of multiple feature splits and the needed split + * hasn't been installed. * @hide */ -public final class EphemeralResponse extends IntentFilter { +public final class AuxiliaryResolveInfo extends IntentFilter { /** Resolved information returned from the external ephemeral resolver */ public final EphemeralResolveInfo resolveInfo; /** The resolved package. Copied from {@link #resolveInfo}. */ @@ -32,11 +38,14 @@ public final class EphemeralResponse extends IntentFilter { /** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */ public final String splitName; /** Whether or not ephemeral resolution needs the second phase */ - public final boolean needsPhase2; + public final boolean needsPhaseTwo; /** Opaque token to track the ephemeral application resolution */ public final String token; + /** The version code of the package */ + public final int versionCode; - public EphemeralResponse(@NonNull EphemeralResolveInfo resolveInfo, + /** Create a response for installing an instant application. */ + public AuxiliaryResolveInfo(@NonNull EphemeralResolveInfo resolveInfo, @NonNull IntentFilter orig, @Nullable String splitName, @NonNull String token, @@ -46,6 +55,20 @@ public final class EphemeralResponse extends IntentFilter { this.packageName = resolveInfo.getPackageName(); this.splitName = splitName; this.token = token; - this.needsPhase2 = needsPhase2; + this.needsPhaseTwo = needsPhase2; + this.versionCode = resolveInfo.getVersionCode(); + } + + /** Create a response for installing a split on demand. */ + public AuxiliaryResolveInfo(@NonNull String packageName, + @Nullable String splitName, + int versionCode) { + super(); + this.packageName = packageName; + this.splitName = splitName; + this.versionCode = versionCode; + this.resolveInfo = null; + this.token = null; + this.needsPhaseTwo = false; } }
\ No newline at end of file diff --git a/core/java/android/content/pm/EphemeralRequest.java b/core/java/android/content/pm/EphemeralRequest.java index 7f2b3ee1245b..58099c2b9b6a 100644 --- a/core/java/android/content/pm/EphemeralRequest.java +++ b/core/java/android/content/pm/EphemeralRequest.java @@ -24,24 +24,21 @@ import android.content.Intent; */ public final class EphemeralRequest { /** Response from the first phase of ephemeral application resolution */ - public final EphemeralResponse responseObj; + public final AuxiliaryResolveInfo responseObj; /** The original intent that triggered ephemeral application resolution */ public final Intent origIntent; /** Resolved type of the intent */ public final String resolvedType; - /** The intent that would launch if there were no ephemeral applications */ - public final Intent launchIntent; /** The name of the package requesting the ephemeral application */ public final String callingPackage; /** ID of the user requesting the ephemeral application */ public final int userId; - public EphemeralRequest(EphemeralResponse responseObj, Intent origIntent, - String resolvedType, Intent launchIntent, String callingPackage, int userId) { + public EphemeralRequest(AuxiliaryResolveInfo responseObj, Intent origIntent, + String resolvedType, String callingPackage, int userId) { this.responseObj = responseObj; this.origIntent = origIntent; this.resolvedType = resolvedType; - this.launchIntent = launchIntent; this.callingPackage = callingPackage; this.userId = userId; } diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 7d59bd619498..94fe572360b5 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -213,12 +213,11 @@ 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 launchIntent The intent that would launch if there was no ephemeral application * @param callingPackage The name of the package requesting the ephemeral application * @param userId The ID of the user that triggered ephemeral resolution */ - public abstract void requestEphemeralResolutionPhaseTwo(EphemeralResponse responseObj, - Intent origIntent, String resolvedType, Intent launchIntent, String callingPackage, + public abstract void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, + Intent origIntent, String resolvedType, String callingPackage, int userId); /** diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index f8b4570be6cc..50f2d5371019 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -61,11 +61,12 @@ public class ResolveInfo implements Parcelable { public ProviderInfo providerInfo; /** - * The ephemeral application that corresponds to this resolution match. This will - * only be set in specific circumstances. + * An auxiliary response that may modify the resolved information. This is + * only set under certain circumstances; such as when resolving instant apps + * or components defined in un-installed splits. * @hide */ - public EphemeralResponse ephemeralResponse; + public AuxiliaryResolveInfo auxiliaryInfo; /** * The IntentFilter that was matched for this ResolveInfo. diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 7605a1e0ffc3..83d43db20671 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -82,6 +82,7 @@ import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS; import static com.android.server.am.EventLogTags.AM_NEW_INTENT; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AppGlobals; @@ -98,7 +99,9 @@ import android.content.Intent; import android.content.IntentSender; 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; @@ -456,22 +459,9 @@ 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.ephemeralResponse != null) { - final String packageName = - rInfo.ephemeralResponse.resolveInfo.getPackageName(); - final String splitName = rInfo.ephemeralResponse.splitName; - final boolean needsPhaseTwo = rInfo.ephemeralResponse.needsPhase2; - final String token = rInfo.ephemeralResponse.token; - final int versionCode = rInfo.ephemeralResponse.resolveInfo.getVersionCode(); - if (needsPhaseTwo) { - // request phase two resolution - mService.getPackageManagerInternalLocked().requestEphemeralResolutionPhaseTwo( - rInfo.ephemeralResponse, ephemeralIntent, resolvedType, intent, - callingPackage, userId); - } - intent = EphemeralResolver.buildEphemeralInstallerIntent(intent, ephemeralIntent, - callingPackage, resolvedType, userId, packageName, splitName, versionCode, - token, needsPhaseTwo); + if (rInfo != null && rInfo.auxiliaryInfo != null) { + intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent, + callingPackage, resolvedType, userId); resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; @@ -530,6 +520,21 @@ class ActivityStarter { return err; } + /** Creates a launch intent for the given auxiliary resolution data. */ + private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse, + Intent originalIntent, String callingPackage, + String resolvedType, int userId) { + if (auxiliaryResponse.needsPhaseTwo) { + // request phase two resolution + mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo( + auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId); + } + return EphemeralResolver.buildEphemeralInstallerIntent(originalIntent, + callingPackage, resolvedType, userId, auxiliaryResponse.packageName, + auxiliaryResponse.splitName, auxiliaryResponse.versionCode, + auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo); + } + void postStartActivityUncheckedProcessing( ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord, ActivityStack targetStack) { diff --git a/services/core/java/com/android/server/pm/EphemeralResolver.java b/services/core/java/com/android/server/pm/EphemeralResolver.java index d99a1b685da3..7bc65f91a7ab 100644 --- a/services/core/java/com/android/server/pm/EphemeralResolver.java +++ b/services/core/java/com/android/server/pm/EphemeralResolver.java @@ -16,8 +16,9 @@ package com.android.server.pm; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.ActivityManagerNative; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -29,7 +30,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.EphemeralIntentFilter; import android.content.pm.EphemeralRequest; import android.content.pm.EphemeralResolveInfo; -import android.content.pm.EphemeralResponse; +import android.content.pm.AuxiliaryResolveInfo; import android.content.pm.EphemeralResolveInfo.EphemeralDigest; import android.os.Binder; import android.os.Handler; @@ -46,7 +47,7 @@ import java.util.UUID; /** @hide */ public abstract class EphemeralResolver { - public static EphemeralResponse doEphemeralResolutionPhaseOne(Context context, + public static AuxiliaryResolveInfo doEphemeralResolutionPhaseOne(Context context, EphemeralResolverConnection connection, EphemeralRequest requestObj) { final Intent intent = requestObj.origIntent; final EphemeralDigest digest = @@ -83,7 +84,7 @@ public abstract class EphemeralResolver { final ArrayList<EphemeralResolveInfo> ephemeralResolveInfoList = new ArrayList<EphemeralResolveInfo>(1); ephemeralResolveInfoList.add(ephemeralResolveInfo); - final EphemeralResponse ephemeralIntentInfo = + final AuxiliaryResolveInfo ephemeralIntentInfo = EphemeralResolver.filterEphemeralIntent( ephemeralResolveInfoList, intent, null /*resolvedType*/, 0 /*userId*/, intent.getPackage(), digest, @@ -104,7 +105,6 @@ public abstract class EphemeralResolver { versionCode = -1; } final Intent installerIntent = buildEphemeralInstallerIntent( - requestObj.launchIntent, requestObj.origIntent, requestObj.callingPackage, requestObj.resolvedType, @@ -126,35 +126,41 @@ public abstract class EphemeralResolver { /** * Builds and returns an intent to launch the ephemeral installer. */ - public static Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent, - String callingPackage, String resolvedType, int userId, String ephemeralPackageName, - String ephemeralSplitName, int versionCode, String token, boolean needsPhaseTwo) { + public static Intent buildEphemeralInstallerIntent(@NonNull Intent origIntent, + @NonNull String callingPackage, + @NonNull String resolvedType, + int userId, + @NonNull String ephemeralPackageName, + @Nullable String ephemeralSplitName, + int versionCode, + @Nullable String token, + boolean needsPhaseTwo) { // Construct the intent that launches the ephemeral installer - int flags = launchIntent.getFlags(); + int flags = origIntent.getFlags(); final Intent intent = new Intent(); intent.setFlags(flags | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - // TODO: Remove when the platform has fully implemented ephemeral apps - intent.setData(origIntent.getData().buildUpon().clearQuery().build()); - intent.putExtra(Intent.EXTRA_EPHEMERAL_TOKEN, token); - intent.putExtra(Intent.EXTRA_EPHEMERAL_HOSTNAME, origIntent.getData().getHost()); + if (token != null) { + intent.putExtra(Intent.EXTRA_EPHEMERAL_TOKEN, token); + } + if (origIntent.getData() != null) { + intent.putExtra(Intent.EXTRA_EPHEMERAL_HOSTNAME, origIntent.getData().getHost()); + } + // We have all of the data we need; just start the installer without a second phase if (!needsPhaseTwo) { - // We have all of the data we need; just start the installer without a second phase - final Intent nonEphemeralIntent = new Intent(origIntent); - nonEphemeralIntent.setFlags( - nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL); - // Intent that is launched if the ephemeral package couldn't be installed - // for any reason. + // Intent that is launched if the package couldn't be installed for any reason. + final Intent failureIntent = new Intent(origIntent); + failureIntent.setFlags(failureIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL); try { - final IIntentSender failureIntentTarget = ActivityManagerNative.getDefault() + final IIntentSender failureIntentTarget = ActivityManager.getService() .getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, null /*token*/, null /*resultWho*/, 1 /*requestCode*/, - new Intent[] { nonEphemeralIntent }, + new Intent[] { failureIntent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, @@ -163,19 +169,14 @@ public abstract class EphemeralResolver { new IntentSender(failureIntentTarget)); } catch (RemoteException ignore) { /* ignore; same process */ } - // Success intent goes back to the installer - final Intent ephemeralIntent = new Intent(launchIntent) - .setComponent(null) - .setPackage(ephemeralPackageName); - // Intent that is eventually launched if the ephemeral package was - // installed successfully. This will actually be launched by a platform - // broadcast receiver. + // Intent that is launched if the package was installed successfully. + final Intent successIntent = new Intent(origIntent); try { - final IIntentSender successIntentTarget = ActivityManagerNative.getDefault() + final IIntentSender successIntentTarget = ActivityManager.getService() .getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, null /*token*/, null /*resultWho*/, 0 /*requestCode*/, - new Intent[] { ephemeralIntent }, + new Intent[] { successIntent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, @@ -192,7 +193,7 @@ public abstract class EphemeralResolver { return intent; } - private static EphemeralResponse filterEphemeralIntent( + private static AuxiliaryResolveInfo filterEphemeralIntent( List<EphemeralResolveInfo> ephemeralResolveInfoList, Intent intent, String resolvedType, int userId, String packageName, EphemeralDigest digest, String token) { @@ -212,7 +213,7 @@ public abstract class EphemeralResolver { ephemeralInfo.getIntentFilters(); // No filters; we need to start phase two if (ephemeralFilters == null || ephemeralFilters.isEmpty()) { - return new EphemeralResponse(ephemeralInfo, + return new AuxiliaryResolveInfo(ephemeralInfo, new IntentFilter(Intent.ACTION_VIEW) /*intentFilter*/, null /*splitName*/, token, true /*needsPhase2*/); } @@ -226,14 +227,14 @@ public abstract class EphemeralResolver { continue; } for (int k = splitFilters.size() - 1; k >= 0; --k) { - final EphemeralResponse intentInfo = - new EphemeralResponse(ephemeralInfo, + final AuxiliaryResolveInfo intentInfo = + new AuxiliaryResolveInfo(ephemeralInfo, splitFilters.get(k), ephemeralFilter.getSplitName(), token, false /*needsPhase2*/); ephemeralResolver.addFilter(intentInfo); } } - List<EphemeralResponse> matchedResolveInfoList = ephemeralResolver.queryIntent( + List<AuxiliaryResolveInfo> matchedResolveInfoList = ephemeralResolver.queryIntent( intent, resolvedType, false /*defaultOnly*/, userId); if (!matchedResolveInfoList.isEmpty()) { return matchedResolveInfoList.get(0); diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java index 2b6ce10741c4..7f5973e64283 100644 --- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java +++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java @@ -23,7 +23,6 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.EphemeralResolveInfo; -import android.content.pm.EphemeralResponse; import android.os.Build; import android.os.Bundle; import android.os.Handler; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 975ae0654626..fe2fb66822f1 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -131,7 +131,7 @@ import android.content.pm.ComponentInfo; import android.content.pm.InstantAppInfo; import android.content.pm.EphemeralRequest; import android.content.pm.EphemeralResolveInfo; -import android.content.pm.EphemeralResponse; +import android.content.pm.AuxiliaryResolveInfo; import android.content.pm.FallbackCategoryProvider; import android.content.pm.FeatureInfo; import android.content.pm.IOnPermissionsChangeListener; @@ -837,12 +837,12 @@ public class PackageManagerService extends IPackageManager.Stub { private int mIntentFilterVerificationToken = 0; /** The service connection to the ephemeral resolver */ - final EphemeralResolverConnection mEphemeralResolverConnection; + final EphemeralResolverConnection mInstantAppResolverConnection; /** Component used to install ephemeral applications */ - ComponentName mEphemeralInstallerComponent; - final ActivityInfo mEphemeralInstallerActivity = new ActivityInfo(); - final ResolveInfo mEphemeralInstallerInfo = new ResolveInfo(); + ComponentName mInstantAppInstallerComponent; + final ActivityInfo mInstantAppInstallerActivity = new ActivityInfo(); + final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo(); final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates = new SparseArray<IntentFilterVerificationState>(); @@ -1164,7 +1164,7 @@ public class PackageManagerService extends IPackageManager.Stub { static final int START_INTENT_FILTER_VERIFICATIONS = 17; static final int INTENT_FILTER_VERIFIED = 18; static final int WRITE_PACKAGE_LIST = 19; - static final int EPHEMERAL_RESOLUTION_PHASE_TWO = 20; + static final int INSTANT_APP_RESOLUTION_PHASE_TWO = 20; static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds @@ -1735,11 +1735,11 @@ public class PackageManagerService extends IPackageManager.Stub { break; } - case EPHEMERAL_RESOLUTION_PHASE_TWO: { + case INSTANT_APP_RESOLUTION_PHASE_TWO: { EphemeralResolver.doEphemeralResolutionPhaseTwo(mContext, - mEphemeralResolverConnection, + mInstantAppResolverConnection, (EphemeralRequest) msg.obj, - mEphemeralInstallerActivity, + mInstantAppInstallerActivity, mHandler); } } @@ -2890,17 +2890,17 @@ public class PackageManagerService extends IPackageManager.Stub { if (DEBUG_EPHEMERAL) { Slog.i(TAG, "Ephemeral resolver: " + ephemeralResolverComponent); } - mEphemeralResolverConnection = + mInstantAppResolverConnection = new EphemeralResolverConnection(mContext, ephemeralResolverComponent); } else { - mEphemeralResolverConnection = null; + mInstantAppResolverConnection = null; } - mEphemeralInstallerComponent = getEphemeralInstallerLPr(); - if (mEphemeralInstallerComponent != null) { + mInstantAppInstallerComponent = getEphemeralInstallerLPr(); + if (mInstantAppInstallerComponent != null) { if (DEBUG_EPHEMERAL) { - Slog.i(TAG, "Ephemeral installer: " + mEphemeralInstallerComponent); + Slog.i(TAG, "Ephemeral installer: " + mInstantAppInstallerComponent); } - setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent); + setUpInstantAppInstallerActivityLP(mInstantAppInstallerComponent); } // Read and update the usage of dex files. @@ -4026,7 +4026,9 @@ public class PackageManagerService extends IPackageManager.Stub { } else { // Otherwise, prevent leaking ephemeral components flags &= ~PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY; - if (callingUid != Process.SYSTEM_UID && callingUid != 0) { + if (callingUid != Process.SYSTEM_UID + && callingUid != Process.SHELL_UID + && callingUid != 0) { // Unless called from the system process flags &= ~PackageManager.MATCH_INSTANT; } @@ -5659,10 +5661,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (callingUser != UserHandle.USER_SYSTEM) { return false; } - if (mEphemeralResolverConnection == null) { + if (mInstantAppResolverConnection == null) { return false; } - if (mEphemeralInstallerComponent == null) { + if (mInstantAppInstallerComponent == null) { return false; } if (intent.getComponent() != null) { @@ -5679,6 +5681,7 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution. + // Or if there's already an ephemeral app installed that handles the action synchronized (mPackages) { final int count = (resolvedActivities == null ? 0 : resolvedActivities.size()); for (int n = 0; n < count; n++) { @@ -5697,6 +5700,9 @@ public class PackageManagerService extends IPackageManager.Stub { } return false; } + if (ps.getInstantApp(userId)) { + return false; + } } } } @@ -5704,11 +5710,11 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } - private void requestEphemeralResolutionPhaseTwo(EphemeralResponse responseObj, - Intent origIntent, String resolvedType, Intent launchIntent, String callingPackage, + private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, + Intent origIntent, String resolvedType, String callingPackage, int userId) { - final Message msg = mHandler.obtainMessage(EPHEMERAL_RESOLUTION_PHASE_TWO, - new EphemeralRequest(responseObj, origIntent, resolvedType, launchIntent, + final Message msg = mHandler.obtainMessage(INSTANT_APP_RESOLUTION_PHASE_TWO, + new EphemeralRequest(responseObj, origIntent, resolvedType, callingPackage, userId)); mHandler.sendMessage(msg); } @@ -6134,7 +6140,7 @@ public class PackageManagerService extends IPackageManager.Stub { list.add(ri); } } - return list; + return applyPostResolutionFilter(list, instantAppPkgName); } // reader @@ -6152,7 +6158,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (xpResolveInfo != null) { List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1); xpResult.add(xpResolveInfo); - return filterForEphemeral( + return applyPostResolutionFilter( filterIfNotSystemUser(xpResult, userId), instantAppPkgName); } @@ -6193,13 +6199,13 @@ public class PackageManagerService extends IPackageManager.Stub { // And we are not going to add emphemeral app, so we can return the // result straight away. result.add(xpDomainInfo.resolveInfo); - return filterForEphemeral(result, instantAppPkgName); + return applyPostResolutionFilter(result, instantAppPkgName); } } else if (result.size() <= 1 && !addEphemeral) { // No result in parent user and <= 1 result in current profile, and we // are not going to add emphemeral app, so we can return the result without // further processing. - return filterForEphemeral(result, instantAppPkgName); + return applyPostResolutionFilter(result, instantAppPkgName); } // We have more than one candidate (combining results from current and parent // profile), so we need filtering and sorting. @@ -6210,7 +6216,7 @@ public class PackageManagerService extends IPackageManager.Stub { } else { final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { - result = filterForEphemeral(filterIfNotSystemUser( + result = applyPostResolutionFilter(filterIfNotSystemUser( mActivities.queryIntentForPackage( intent, resolvedType, flags, pkg.activities, userId), userId), instantAppPkgName); @@ -6227,15 +6233,16 @@ public class PackageManagerService extends IPackageManager.Stub { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final EphemeralRequest requestObject = new EphemeralRequest( null /*responseObj*/, intent /*origIntent*/, resolvedType, - null /*launchIntent*/, null /*callingPackage*/, userId); - final EphemeralResponse intentInfo = EphemeralResolver.doEphemeralResolutionPhaseOne( - mContext, mEphemeralResolverConnection, requestObject); - if (intentInfo != null) { + null /*callingPackage*/, userId); + final AuxiliaryResolveInfo auxiliaryResponse = + EphemeralResolver.doEphemeralResolutionPhaseOne( + mContext, mInstantAppResolverConnection, requestObject); + if (auxiliaryResponse != null) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); } - final ResolveInfo ephemeralInstaller = new ResolveInfo(mEphemeralInstallerInfo); - ephemeralInstaller.ephemeralResponse = intentInfo; + final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo); + ephemeralInstaller.auxiliaryInfo = auxiliaryResponse; // make sure this resolver is the default ephemeralInstaller.isDefault = true; ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART @@ -6251,7 +6258,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (sortResult) { Collections.sort(result, mResolvePrioritySorter); } - return filterForEphemeral(result, instantAppPkgName); + return applyPostResolutionFilter(result, instantAppPkgName); } private static class CrossProfileDomainInfo { @@ -6359,16 +6366,40 @@ public class PackageManagerService extends IPackageManager.Stub { * is performed. * @return A filtered list of resolved activities. */ - private List<ResolveInfo> filterForEphemeral(List<ResolveInfo> resolveInfos, + private List<ResolveInfo> applyPostResolutionFilter(List<ResolveInfo> resolveInfos, String ephemeralPkgName) { + // TODO: When adding on-demand split support for non-instant apps, remove this check + // and always apply post filtering if (ephemeralPkgName == null) { return resolveInfos; } for (int i = resolveInfos.size() - 1; i >= 0; i--) { - ResolveInfo info = resolveInfos.get(i); + final ResolveInfo info = resolveInfos.get(i); final boolean isEphemeralApp = info.activityInfo.applicationInfo.isInstantApp(); // allow activities that are defined in the provided package if (isEphemeralApp && ephemeralPkgName.equals(info.activityInfo.packageName)) { + if (info.activityInfo.splitName != null + && !ArrayUtils.contains(info.activityInfo.applicationInfo.splitNames, + info.activityInfo.splitName)) { + // requested activity is defined in a split that hasn't been installed yet. + // add the installer to the resolve list + if (DEBUG_EPHEMERAL) { + Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); + } + final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo); + installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo( + info.activityInfo.packageName, info.activityInfo.splitName, + info.activityInfo.applicationInfo.versionCode); + // make sure this resolver is the default + installerInfo.isDefault = true; + installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART + | IntentFilter.MATCH_ADJUSTMENT_NORMAL; + // add a non-generic filter + installerInfo.filter = new IntentFilter(); + // load resources from the correct package + installerInfo.resolvePackageName = info.getComponentInfo().packageName; + resolveInfos.set(i, installerInfo); + } continue; } // allow activities that have been explicitly exposed to ephemeral apps @@ -10699,12 +10730,12 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private void setUpEphemeralInstallerActivityLP(ComponentName installerComponent) { + private void setUpInstantAppInstallerActivityLP(ComponentName installerComponent) { if (installerComponent == null) { if (DEBUG_EPHEMERAL) { Slog.d(TAG, "Clear ephemeral installer activity"); } - mEphemeralInstallerActivity.applicationInfo = null; + mInstantAppInstallerActivity.applicationInfo = null; return; } @@ -10713,21 +10744,21 @@ public class PackageManagerService extends IPackageManager.Stub { } final PackageParser.Package pkg = mPackages.get(installerComponent.getPackageName()); // Set up information for ephemeral installer activity - mEphemeralInstallerActivity.applicationInfo = pkg.applicationInfo; - mEphemeralInstallerActivity.name = installerComponent.getClassName(); - mEphemeralInstallerActivity.packageName = pkg.applicationInfo.packageName; - mEphemeralInstallerActivity.processName = pkg.applicationInfo.packageName; - mEphemeralInstallerActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; - mEphemeralInstallerActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS + mInstantAppInstallerActivity.applicationInfo = pkg.applicationInfo; + mInstantAppInstallerActivity.name = installerComponent.getClassName(); + mInstantAppInstallerActivity.packageName = pkg.applicationInfo.packageName; + mInstantAppInstallerActivity.processName = pkg.applicationInfo.packageName; + mInstantAppInstallerActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; + mInstantAppInstallerActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS | ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; - mEphemeralInstallerActivity.theme = 0; - mEphemeralInstallerActivity.exported = true; - mEphemeralInstallerActivity.enabled = true; - mEphemeralInstallerInfo.activityInfo = mEphemeralInstallerActivity; - mEphemeralInstallerInfo.priority = 0; - mEphemeralInstallerInfo.preferredOrder = 1; - mEphemeralInstallerInfo.isDefault = true; - mEphemeralInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART + mInstantAppInstallerActivity.theme = 0; + mInstantAppInstallerActivity.exported = true; + mInstantAppInstallerActivity.enabled = true; + mInstantAppInstallerInfo.activityInfo = mInstantAppInstallerActivity; + mInstantAppInstallerInfo.priority = 0; + mInstantAppInstallerInfo.preferredOrder = 1; + mInstantAppInstallerInfo.isDefault = true; + mInstantAppInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART | IntentFilter.MATCH_ADJUSTMENT_NORMAL; } @@ -12769,7 +12800,7 @@ public class PackageManagerService extends IPackageManager.Stub { } static final class EphemeralIntentResolver - extends IntentResolver<EphemeralResponse, EphemeralResponse> { + 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 @@ -12784,17 +12815,17 @@ public class PackageManagerService extends IPackageManager.Stub { final ArrayMap<String, Pair<Integer, EphemeralResolveInfo>> mOrderResult = new ArrayMap<>(); @Override - protected EphemeralResponse[] newArray(int size) { - return new EphemeralResponse[size]; + protected AuxiliaryResolveInfo[] newArray(int size) { + return new AuxiliaryResolveInfo[size]; } @Override - protected boolean isPackageForFilter(String packageName, EphemeralResponse responseObj) { + protected boolean isPackageForFilter(String packageName, AuxiliaryResolveInfo responseObj) { return true; } @Override - protected EphemeralResponse newResult(EphemeralResponse responseObj, int match, + protected AuxiliaryResolveInfo newResult(AuxiliaryResolveInfo responseObj, int match, int userId) { if (!sUserManager.exists(userId)) { return null; @@ -12816,7 +12847,7 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - protected void filterResults(List<EphemeralResponse> 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; @@ -22898,11 +22929,10 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } @Override - public void requestEphemeralResolutionPhaseTwo(EphemeralResponse responseObj, - Intent origIntent, String resolvedType, Intent launchIntent, - String callingPackage, int userId) { - PackageManagerService.this.requestEphemeralResolutionPhaseTwo( - responseObj, origIntent, resolvedType, launchIntent, callingPackage, userId); + public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, + Intent origIntent, String resolvedType, String callingPackage, int userId) { + PackageManagerService.this.requestInstantAppResolutionPhaseTwo( + responseObj, origIntent, resolvedType, callingPackage, userId); } @Override |