Merge "Load splits on-demand"

This commit is contained in:
TreeHugger Robot
2017-02-23 21:25:04 +00:00
committed by Android (Google) Code Review
8 changed files with 187 additions and 132 deletions

View File

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

View File

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

View File

@@ -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);
/**

View File

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

View File

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

View File

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

View File

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

View File

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