Merge "Allow applications to define failure handlers" into oc-mr1-dev

am: e551d361ac

Change-Id: I5c325e4bef2274d35fec3a0653043745383c77b6
This commit is contained in:
Todd Kennedy
2017-08-09 15:05:44 +00:00
committed by android-build-merger
8 changed files with 114 additions and 36 deletions

View File

@@ -9370,6 +9370,7 @@ package android.content {
field public static final java.lang.String ACTION_INPUT_METHOD_CHANGED = "android.intent.action.INPUT_METHOD_CHANGED";
field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
field public static final java.lang.String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
@@ -9552,6 +9553,7 @@ package android.content {
field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";

View File

@@ -9908,6 +9908,7 @@ package android.content {
field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
field public static final deprecated java.lang.String ACTION_INSTALL_EPHEMERAL_PACKAGE = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
field public static final java.lang.String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";

View File

@@ -9405,6 +9405,7 @@ package android.content {
field public static final java.lang.String ACTION_INPUT_METHOD_CHANGED = "android.intent.action.INPUT_METHOD_CHANGED";
field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
field public static final java.lang.String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
@@ -9587,6 +9588,7 @@ package android.content {
field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";

View File

@@ -1534,6 +1534,22 @@ public class Intent implements Parcelable, Cloneable {
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
/**
* Activity Action: Activity to handle split installation failures.
* <p>Splits may be installed dynamically. This happens when an Activity is launched,
* but the split that contains the application isn't installed. When a split is
* installed in this manner, the containing package usually doesn't know this is
* happening. However, if an error occurs during installation, the containing
* package can define a single activity handling this action to deal with such
* failures.
* <p>The activity handling this action must be in the base package.
* <p>
* Input: {@link #EXTRA_INTENT} the original intent that started split installation.
* {@link #EXTRA_SPLIT_NAME} the name of the split that failed to be installed.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
/**
* @hide
* @deprecated Do not use. This will go away.
@@ -1823,9 +1839,7 @@ public class Intent implements Parcelable, Cloneable {
* <p>
* Type: String
* </p>
* @hide
*/
@SystemApi
public static final String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
/**

View File

@@ -18,6 +18,7 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -35,6 +36,8 @@ public final class AuxiliaryResolveInfo extends IntentFilter {
public final InstantAppResolveInfo resolveInfo;
/** The resolved package. Copied from {@link #resolveInfo}. */
public final String packageName;
/** The activity to launch if there's an installation failure. */
public final ComponentName installFailureActivity;
/** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */
public final String splitName;
/** Whether or not instant resolution needs the second phase */
@@ -61,15 +64,18 @@ public final class AuxiliaryResolveInfo extends IntentFilter {
this.needsPhaseTwo = needsPhase2;
this.versionCode = resolveInfo.getVersionCode();
this.failureIntent = failureIntent;
this.installFailureActivity = null;
}
/** Create a response for installing a split on demand. */
public AuxiliaryResolveInfo(@NonNull String packageName,
@Nullable String splitName,
@Nullable ComponentName failureActivity,
int versionCode,
@Nullable Intent failureIntent) {
super();
this.packageName = packageName;
this.installFailureActivity = failureActivity;
this.splitName = splitName;
this.versionCode = versionCode;
this.resolveInfo = null;

View File

@@ -581,8 +581,8 @@ class ActivityStarter {
Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
auxiliaryResponse.versionCode, auxiliaryResponse.token,
auxiliaryResponse.needsPhaseTwo);
auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode,
auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
}
void postStartActivityProcessing(

View File

@@ -194,6 +194,7 @@ public abstract class InstantAppResolver {
requestObj.userId,
packageName,
splitName,
requestObj.responseObj.installFailureActivity,
versionCode,
token,
false /*needsPhaseTwo*/);
@@ -239,6 +240,7 @@ public abstract class InstantAppResolver {
int userId,
@NonNull String instantAppPackageName,
@Nullable String instantAppSplitName,
@Nullable ComponentName installFailureActivity,
int versionCode,
@Nullable String token,
boolean needsPhaseTwo) {
@@ -260,15 +262,25 @@ public abstract class InstantAppResolver {
// We have all of the data we need; just start the installer without a second phase
if (!needsPhaseTwo) {
// Intent that is launched if the package couldn't be installed for any reason.
if (failureIntent != null) {
if (failureIntent != null || installFailureActivity != null) {
try {
final Intent onFailureIntent;
if (installFailureActivity != null) {
onFailureIntent = new Intent();
onFailureIntent.setComponent(installFailureActivity);
onFailureIntent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName);
onFailureIntent.putExtra(Intent.EXTRA_INTENT, origIntent);
} else {
onFailureIntent = failureIntent;
}
final IIntentSender failureIntentTarget = ActivityManager.getService()
.getIntentSender(
ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
null /*token*/, null /*resultWho*/, 1 /*requestCode*/,
new Intent[] { failureIntent },
new Intent[] { onFailureIntent },
new String[] { resolvedType },
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_IMMUTABLE,
null /*bOptions*/, userId);
intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE,

View File

@@ -3358,7 +3358,7 @@ public class PackageManagerService extends IPackageManager.Stub
final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
UserHandle.USER_SYSTEM);
UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
if (matches.size() == 1) {
return matches.get(0).getComponentInfo().packageName;
} else if (matches.size() == 0) {
@@ -3418,7 +3418,7 @@ public class PackageManagerService extends IPackageManager.Stub
final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
UserHandle.USER_SYSTEM);
UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
ResolveInfo best = null;
final int N = matches.size();
for (int i = 0; i < N; i++) {
@@ -6586,7 +6586,7 @@ public class PackageManagerService extends IPackageManager.Stub
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
flags, callingUid, userId, resolveForStart);
flags, callingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
@@ -7131,12 +7131,13 @@ public class PackageManagerService extends IPackageManager.Stub
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
return queryIntentActivitiesInternal(
intent, resolvedType, flags, Binder.getCallingUid(), userId, false);
intent, resolvedType, flags, Binder.getCallingUid(), userId,
false /*resolveForStart*/, true /*allowDynamicSplits*/);
}
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int filterCallingUid, int userId,
boolean resolveForStart) {
boolean resolveForStart, boolean allowDynamicSplits) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -7193,7 +7194,8 @@ public class PackageManagerService extends IPackageManager.Stub
list.add(ri);
}
}
return applyPostResolutionFilter(list, instantAppPkgName);
return applyPostResolutionFilter(
list, instantAppPkgName, allowDynamicSplits, filterCallingUid, userId);
}
// reader
@@ -7212,7 +7214,8 @@ public class PackageManagerService extends IPackageManager.Stub
List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1);
xpResult.add(xpResolveInfo);
return applyPostResolutionFilter(
filterIfNotSystemUser(xpResult, userId), instantAppPkgName);
filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
allowDynamicSplits, filterCallingUid, userId);
}
// Check for results in the current profile.
@@ -7251,13 +7254,15 @@ 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 applyPostResolutionFilter(result, instantAppPkgName);
return applyPostResolutionFilter(result, instantAppPkgName,
allowDynamicSplits, filterCallingUid, userId);
}
} 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 applyPostResolutionFilter(result, instantAppPkgName);
return applyPostResolutionFilter(result, instantAppPkgName,
allowDynamicSplits, filterCallingUid, userId);
}
// We have more than one candidate (combining results from current and parent
// profile), so we need filtering and sorting.
@@ -7292,7 +7297,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (sortResult) {
Collections.sort(result, mResolvePrioritySorter);
}
return applyPostResolutionFilter(result, instantAppPkgName);
return applyPostResolutionFilter(
result, instantAppPkgName, allowDynamicSplits, filterCallingUid, userId);
}
private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
@@ -7358,7 +7364,8 @@ public class PackageManagerService extends IPackageManager.Stub
// the instant application, we'll do the right thing.
final ApplicationInfo ai = localInstantApp.activityInfo.applicationInfo;
auxiliaryResponse = new AuxiliaryResolveInfo(
ai.packageName, null /*splitName*/, ai.versionCode, null /*failureIntent*/);
ai.packageName, null /*splitName*/, null /*failureActivity*/,
ai.versionCode, null /*failureIntent*/);
}
}
if (auxiliaryResponse != null) {
@@ -7494,13 +7501,12 @@ public class PackageManagerService extends IPackageManager.Stub
* @return A filtered list of resolved activities.
*/
private List<ResolveInfo> applyPostResolutionFilter(List<ResolveInfo> resolveInfos,
String ephemeralPkgName) {
String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid, int userId) {
for (int i = resolveInfos.size() - 1; i >= 0; i--) {
final ResolveInfo info = resolveInfos.get(i);
// TODO: When adding on-demand split support for non-instant apps, remove this check
// and always apply post filtering
// allow activities that are defined in the provided package
if (info.activityInfo.splitName != null
if (allowDynamicSplits
&& 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.
@@ -7509,9 +7515,13 @@ public class PackageManagerService extends IPackageManager.Stub
Slog.v(TAG, "Adding installer to the ResolveInfo list");
}
final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
final ComponentName installFailureActivity = findInstallFailureActivity(
info.activityInfo.packageName, filterCallingUid, userId);
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
info.activityInfo.packageName, info.activityInfo.splitName,
info.activityInfo.applicationInfo.versionCode, null /*failureIntent*/);
installFailureActivity,
info.activityInfo.applicationInfo.versionCode,
null /*failureIntent*/);
// make sure this resolver is the default
installerInfo.isDefault = true;
installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -7541,6 +7551,34 @@ public class PackageManagerService extends IPackageManager.Stub
return resolveInfos;
}
/**
* Returns the activity component that can handle install failures.
* <p>By default, the instant application installer handles failures. However, an
* application may want to handle failures on its own. Applications do this by
* creating an activity with an intent filter that handles the action
* {@link Intent#ACTION_INSTALL_FAILURE}.
*/
private @Nullable ComponentName findInstallFailureActivity(
String packageName, int filterCallingUid, int userId) {
final Intent failureActivityIntent = new Intent(Intent.ACTION_INSTALL_FAILURE);
failureActivityIntent.setPackage(packageName);
// IMPORTANT: disallow dynamic splits to avoid an infinite loop
final List<ResolveInfo> result = queryIntentActivitiesInternal(
failureActivityIntent, null /*resolvedType*/, 0 /*flags*/, filterCallingUid, userId,
false /*resolveForStart*/, false /*allowDynamicSplits*/);
final int NR = result.size();
if (NR > 0) {
for (int i = 0; i < NR; i++) {
final ResolveInfo info = result.get(i);
if (info.activityInfo.splitName != null) {
continue;
}
return new ComponentName(packageName, info.activityInfo.name);
}
}
return null;
}
/**
* @param resolveInfos list of resolve infos in descending priority order
* @return if the list contains a resolve info with non-negative priority
@@ -8028,11 +8066,12 @@ public class PackageManagerService extends IPackageManager.Stub
public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
String resolvedType, int flags, int userId) {
return new ParceledListSlice<>(
queryIntentReceiversInternal(intent, resolvedType, flags, userId));
queryIntentReceiversInternal(intent, resolvedType, flags, userId,
false /*allowDynamicSplits*/));
}
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
String resolvedType, int flags, int userId) {
String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
final int callingUid = Binder.getCallingUid();
enforceCrossUserPermission(callingUid, userId,
@@ -8088,7 +8127,8 @@ public class PackageManagerService extends IPackageManager.Stub
list.add(ri);
}
}
return applyPostResolutionFilter(list, instantAppPkgName);
return applyPostResolutionFilter(
list, instantAppPkgName, allowDynamicSplits, callingUid, userId);
}
// reader
@@ -8097,13 +8137,15 @@ public class PackageManagerService extends IPackageManager.Stub
if (pkgName == null) {
final List<ResolveInfo> result =
mReceivers.queryIntent(intent, resolvedType, flags, userId);
return applyPostResolutionFilter(result, instantAppPkgName);
return applyPostResolutionFilter(
result, instantAppPkgName, allowDynamicSplits, callingUid, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
final List<ResolveInfo> result = mReceivers.queryIntentForPackage(
intent, resolvedType, flags, pkg.receivers, userId);
return applyPostResolutionFilter(result, instantAppPkgName);
return applyPostResolutionFilter(
result, instantAppPkgName, allowDynamicSplits, callingUid, userId);
}
return Collections.emptyList();
}
@@ -8212,8 +8254,6 @@ public class PackageManagerService extends IPackageManager.Stub
private List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
String instantAppPkgName) {
// TODO: When adding on-demand split support for non-instant apps, remove this check
// and always apply post filtering
if (instantAppPkgName == null) {
return resolveInfos;
}
@@ -8233,7 +8273,8 @@ public class PackageManagerService extends IPackageManager.Stub
final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
info.serviceInfo.packageName, info.serviceInfo.splitName,
info.serviceInfo.applicationInfo.versionCode, null /*failureIntent*/);
null /*failureActivity*/, info.serviceInfo.applicationInfo.versionCode,
null /*failureIntent*/);
// make sure this resolver is the default
installerInfo.isDefault = true;
installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -8333,8 +8374,6 @@ public class PackageManagerService extends IPackageManager.Stub
private List<ResolveInfo> applyPostContentProviderResolutionFilter(
List<ResolveInfo> resolveInfos, String instantAppPkgName) {
// TODO: When adding on-demand split support for non-instant applications, remove
// this check and always apply post filtering
if (instantAppPkgName == null) {
return resolveInfos;
}
@@ -8354,7 +8393,8 @@ public class PackageManagerService extends IPackageManager.Stub
final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
info.providerInfo.packageName, info.providerInfo.splitName,
info.providerInfo.applicationInfo.versionCode, null /*failureIntent*/);
null /*failureActivity*/, info.providerInfo.applicationInfo.versionCode,
null /*failureIntent*/);
// make sure this resolver is the default
installerInfo.isDefault = true;
installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -16224,7 +16264,8 @@ public class PackageManagerService extends IPackageManager.Stub
// Query all live verifiers based on current user state
final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier());
PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
false /*allowDynamicSplits*/);
if (DEBUG_VERIFY) {
Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
@@ -24978,7 +25019,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
return PackageManagerService.this
.queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
userId, false /*resolveForStart*/);
userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
}
@Override