Merge "Load splits on-demand"
This commit is contained in:
committed by
Android (Google) Code Review
commit
5feacbed43
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user