Loading core/java/android/content/Intent.java +8 −0 Original line number Diff line number Diff line Loading @@ -4313,6 +4313,14 @@ public class Intent implements Parcelable, Cloneable { */ public static final int FLAG_DEBUG_TRIAGED_MISSING = 0x00000100; /** * Internal flag used to indicate ephemeral applications should not be * considered when resolving the intent. * * @hide */ public static final int FLAG_IGNORE_EPHEMERAL = 0x00000200; /** * If set, the new activity is not kept in the history stack. As soon as * the user navigates away from it, the activity is finished. This may also Loading core/java/android/content/pm/ResolveInfo.java +0 −6 Original line number Diff line number Diff line Loading @@ -67,12 +67,6 @@ public class ResolveInfo implements Parcelable { */ public EphemeralResolveInfo ephemeralResolveInfo; /** * A ResolveInfo that points at the ephemeral installer. * @hide */ public ResolveInfo ephemeralInstaller; /** * The IntentFilter that was matched for this ResolveInfo. */ Loading services/core/java/com/android/server/am/ActivityStarter.java +61 −29 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; Loading Loading @@ -132,6 +133,9 @@ class ActivityStarter { private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; // TODO b/30204367 remove when the platform fully supports ephemeral applications private static final boolean USE_DEFAULT_EPHEMERAL_LAUNCHER = false; private final ActivityManagerService mService; private final ActivityStackSupervisor mSupervisor; private ActivityStartInterceptor mInterceptor; Loading Loading @@ -456,39 +460,13 @@ class ActivityStarter { // starts either the intent we resolved here [on install error] or the ephemeral // app [on install success]. if (rInfo != null && rInfo.ephemeralResolveInfo != null) { // Create a pending intent to start the intent resolved here. final IIntentSender failureTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null); // Create a pending intent to start the ephemeral application; force it to be // directed to the ephemeral package. ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName()); final IIntentSender ephemeralTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null); int flags = intent.getFlags(); intent = new Intent(); intent.setFlags(flags | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, rInfo.ephemeralResolveInfo.getPackageName()); intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget)); intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget)); intent = buildEphemeralInstallerIntent(intent, ephemeralIntent, rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType, userId); resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; rInfo = rInfo.ephemeralInstaller; aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); } Loading Loading @@ -543,6 +521,60 @@ class ActivityStarter { return err; } /** * Builds and returns an intent to launch the ephemeral installer. */ private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent, String ephemeralPackage, String callingPackage, String resolvedType, int userId) { 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. final IIntentSender failureIntentTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1, new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/); final Intent ephemeralIntent; if (USE_DEFAULT_EPHEMERAL_LAUNCHER) { // Force the intent to be directed to the ephemeral package ephemeralIntent = new Intent(origIntent); ephemeralIntent.setPackage(ephemeralPackage); } else { // Success intent goes back to the installer // TODO; do we need any extras for the installer? ephemeralIntent = new Intent(launchIntent); ephemeralIntent.setData(null); } // Intent that is eventually launched if the ephemeral package was // installed successfully. This will actually be launched by a platform // broadcast receiver. final IIntentSender successIntentTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0, new Intent[]{ ephemeralIntent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/); // Finally build the actual intent to launch the ephemeral installer int flags = launchIntent.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); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage); intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget)); intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget)); // TODO: Remove when the platform has fully implemented ephemeral apps intent.setData(origIntent.getData()); return intent; } void postStartActivityUncheckedProcessing( ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord, ActivityStack targetStack) { Loading services/core/java/com/android/server/pm/PackageManagerService.java +86 −52 Original line number Diff line number Diff line Loading @@ -177,6 +177,7 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PatternMatcher; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; Loading Loading @@ -4725,20 +4726,6 @@ public class PackageManagerService extends IPackageManager.Stub { final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId); if (isEphemeralAllowed(intent, query, userId)) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final EphemeralResolveInfo ai = getEphemeralResolveInfo(intent, resolvedType, userId); if (ai != null) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "Returning an EphemeralResolveInfo"); } bestChoice.ephemeralInstaller = mEphemeralInstallerInfo; bestChoice.ephemeralResolveInfo = ai; } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } return bestChoice; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Loading Loading @@ -4779,9 +4766,9 @@ public class PackageManagerService extends IPackageManager.Stub { false, false, false, userId); } private boolean isEphemeralAllowed( Intent intent, List<ResolveInfo> resolvedActivites, int userId) { Intent intent, List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck) { // Short circuit and return early if possible. if (DISABLE_EPHEMERAL_APPS) { return false; Loading @@ -4796,18 +4783,21 @@ public class PackageManagerService extends IPackageManager.Stub { if (intent.getComponent() != null) { return false; } if (intent.getPackage() != null) { if ((intent.getFlags() & Intent.FLAG_IGNORE_EPHEMERAL) != 0) { return false; } if (!skipPackageCheck && intent.getPackage() != null) { return false; } final boolean isWebUri = hasWebURI(intent); if (!isWebUri) { if (!isWebUri || intent.getData().getHost() == null) { return false; } // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution. synchronized (mPackages) { final int count = resolvedActivites.size(); final int count = (resolvedActivities == null ? 0 : resolvedActivities.size()); for (int n = 0; n < count; n++) { ResolveInfo info = resolvedActivites.get(n); ResolveInfo info = resolvedActivities.get(n); String packageName = info.activityInfo.packageName; PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { Loading @@ -4829,19 +4819,19 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } private EphemeralResolveInfo getEphemeralResolveInfo(Intent intent, String resolvedType, int userId) { final int ephemeralPrefixMask = Global.getInt(mContext.getContentResolver(), private static EphemeralResolveInfo getEphemeralResolveInfo( Context context, EphemeralResolverConnection resolverConnection, Intent intent, String resolvedType, int userId, String packageName) { final int ephemeralPrefixMask = Global.getInt(context.getContentResolver(), Global.EPHEMERAL_HASH_PREFIX_MASK, DEFAULT_EPHEMERAL_HASH_PREFIX_MASK); final int ephemeralPrefixCount = Global.getInt(mContext.getContentResolver(), final int ephemeralPrefixCount = Global.getInt(context.getContentResolver(), Global.EPHEMERAL_HASH_PREFIX_COUNT, DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT); final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixMask, ephemeralPrefixCount); final int[] shaPrefix = digest.getDigestPrefix(); final byte[][] digestBytes = digest.getDigestBytes(); final List<EphemeralResolveInfo> ephemeralResolveInfoList = mEphemeralResolverConnection.getEphemeralResolveInfoList( shaPrefix, ephemeralPrefixMask); resolverConnection.getEphemeralResolveInfoList(shaPrefix, ephemeralPrefixMask); if (ephemeralResolveInfoList == null || ephemeralResolveInfoList.size() == 0) { // No hash prefix match; there are no ephemeral apps for this domain. return null; Loading @@ -4858,6 +4848,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (filters.isEmpty()) { continue; } if (packageName != null && !packageName.equals(ephemeralApplication.getPackageName())) { continue; } // We have a domain match; resolve the filters to see if anything matches. final EphemeralIntentResolver ephemeralResolver = new EphemeralIntentResolver(); for (int j = filters.size() - 1; j >= 0; --j) { Loading Loading @@ -5261,8 +5255,12 @@ public class PackageManagerService extends IPackageManager.Stub { } // reader synchronized (mPackages) { boolean sortResult = false; boolean addEphemeral = false; boolean matchEphemeralPackage = false; List<ResolveInfo> result; final String pkgName = intent.getPackage(); synchronized (mPackages) { if (pkgName == null) { List<CrossProfileIntentFilter> matchingFilters = getMatchingCrossProfileIntentFilters(intent, resolvedType, userId); Loading @@ -5270,15 +5268,16 @@ public class PackageManagerService extends IPackageManager.Stub { ResolveInfo xpResolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent, resolvedType, flags, userId); if (xpResolveInfo != null) { List<ResolveInfo> result = new ArrayList<ResolveInfo>(1); result.add(xpResolveInfo); return filterIfNotSystemUser(result, userId); List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1); xpResult.add(xpResolveInfo); return filterIfNotSystemUser(xpResult, userId); } // Check for results in the current profile. List<ResolveInfo> result = mActivities.queryIntent( intent, resolvedType, flags, userId); result = filterIfNotSystemUser(result, userId); result = filterIfNotSystemUser(mActivities.queryIntent( intent, resolvedType, flags, userId), userId); addEphemeral = isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/); // Check for cross profile results. boolean hasNonNegativePriorityResult = hasNonNegativePriority(result); Loading @@ -5290,7 +5289,7 @@ public class PackageManagerService extends IPackageManager.Stub { Collections.singletonList(xpResolveInfo), userId).size() > 0; if (isVisibleToUser) { result.add(xpResolveInfo); Collections.sort(result, mResolvePrioritySorter); sortResult = true; } } if (hasWebURI(intent)) { Loading @@ -5306,29 +5305,62 @@ public class PackageManagerService extends IPackageManager.Stub { // in the result. result.remove(xpResolveInfo); } if (result.size() == 0) { if (result.size() == 0 && !addEphemeral) { result.add(xpDomainInfo.resolveInfo); return result; } } else if (result.size() <= 1) { return result; } result = filterCandidatesWithDomainPreferredActivitiesLPr(intent, flags, result, xpDomainInfo, userId); Collections.sort(result, mResolvePrioritySorter); if (result.size() > 1 || addEphemeral) { result = filterCandidatesWithDomainPreferredActivitiesLPr( intent, flags, result, xpDomainInfo, userId); sortResult = true; } return result; } } else { final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { return filterIfNotSystemUser( result = filterIfNotSystemUser( mActivities.queryIntentForPackage( intent, resolvedType, flags, pkg.activities, userId), userId); } else { // the caller wants to resolve for a particular package; however, there // were no installed results, so, try to find an ephemeral result addEphemeral = isEphemeralAllowed( intent, null /*result*/, userId, true /*skipPackageCheck*/); matchEphemeralPackage = true; result = new ArrayList<ResolveInfo>(); } return new ArrayList<ResolveInfo>(); } } if (addEphemeral) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final EphemeralResolveInfo ai = getEphemeralResolveInfo( mContext, mEphemeralResolverConnection, intent, resolvedType, userId, matchEphemeralPackage ? pkgName : null); if (ai != null) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); } final ResolveInfo ephemeralInstaller = new ResolveInfo(mEphemeralInstallerInfo); ephemeralInstaller.ephemeralResolveInfo = ai; // make sure this resolver is the default ephemeralInstaller.isDefault = true; ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART | IntentFilter.MATCH_ADJUSTMENT_NORMAL; // add a non-generic filter ephemeralInstaller.filter = new IntentFilter(intent.getAction()); ephemeralInstaller.filter.addDataPath( intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL); result.add(ephemeralInstaller); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } if (sortResult) { Collections.sort(result, mResolvePrioritySorter); } return result; } private static class CrossProfileDomainInfo { /* ResolveInfo for IntentForwarderActivity to send the intent to the other profile */ Loading Loading @@ -9205,15 +9237,17 @@ public class PackageManagerService extends IPackageManager.Stub { mEphemeralInstallerActivity.packageName = pkg.applicationInfo.packageName; mEphemeralInstallerActivity.processName = pkg.applicationInfo.packageName; mEphemeralInstallerActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; mEphemeralInstallerActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS | ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; mEphemeralInstallerActivity.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 = 0; mEphemeralInstallerInfo.match = 0; mEphemeralInstallerInfo.preferredOrder = 1; mEphemeralInstallerInfo.isDefault = true; mEphemeralInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART | IntentFilter.MATCH_ADJUSTMENT_NORMAL; if (DEBUG_EPHEMERAL) { Slog.d(TAG, "Set ephemeral installer activity: " + mEphemeralInstallerComponent); Loading Loading
core/java/android/content/Intent.java +8 −0 Original line number Diff line number Diff line Loading @@ -4313,6 +4313,14 @@ public class Intent implements Parcelable, Cloneable { */ public static final int FLAG_DEBUG_TRIAGED_MISSING = 0x00000100; /** * Internal flag used to indicate ephemeral applications should not be * considered when resolving the intent. * * @hide */ public static final int FLAG_IGNORE_EPHEMERAL = 0x00000200; /** * If set, the new activity is not kept in the history stack. As soon as * the user navigates away from it, the activity is finished. This may also Loading
core/java/android/content/pm/ResolveInfo.java +0 −6 Original line number Diff line number Diff line Loading @@ -67,12 +67,6 @@ public class ResolveInfo implements Parcelable { */ public EphemeralResolveInfo ephemeralResolveInfo; /** * A ResolveInfo that points at the ephemeral installer. * @hide */ public ResolveInfo ephemeralInstaller; /** * The IntentFilter that was matched for this ResolveInfo. */ Loading
services/core/java/com/android/server/am/ActivityStarter.java +61 −29 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; Loading Loading @@ -132,6 +133,9 @@ class ActivityStarter { private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; // TODO b/30204367 remove when the platform fully supports ephemeral applications private static final boolean USE_DEFAULT_EPHEMERAL_LAUNCHER = false; private final ActivityManagerService mService; private final ActivityStackSupervisor mSupervisor; private ActivityStartInterceptor mInterceptor; Loading Loading @@ -456,39 +460,13 @@ class ActivityStarter { // starts either the intent we resolved here [on install error] or the ephemeral // app [on install success]. if (rInfo != null && rInfo.ephemeralResolveInfo != null) { // Create a pending intent to start the intent resolved here. final IIntentSender failureTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null); // Create a pending intent to start the ephemeral application; force it to be // directed to the ephemeral package. ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName()); final IIntentSender ephemeralTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null); int flags = intent.getFlags(); intent = new Intent(); intent.setFlags(flags | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, rInfo.ephemeralResolveInfo.getPackageName()); intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget)); intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget)); intent = buildEphemeralInstallerIntent(intent, ephemeralIntent, rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType, userId); resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; rInfo = rInfo.ephemeralInstaller; aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); } Loading Loading @@ -543,6 +521,60 @@ class ActivityStarter { return err; } /** * Builds and returns an intent to launch the ephemeral installer. */ private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent, String ephemeralPackage, String callingPackage, String resolvedType, int userId) { 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. final IIntentSender failureIntentTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1, new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/); final Intent ephemeralIntent; if (USE_DEFAULT_EPHEMERAL_LAUNCHER) { // Force the intent to be directed to the ephemeral package ephemeralIntent = new Intent(origIntent); ephemeralIntent.setPackage(ephemeralPackage); } else { // Success intent goes back to the installer // TODO; do we need any extras for the installer? ephemeralIntent = new Intent(launchIntent); ephemeralIntent.setData(null); } // Intent that is eventually launched if the ephemeral package was // installed successfully. This will actually be launched by a platform // broadcast receiver. final IIntentSender successIntentTarget = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0, new Intent[]{ ephemeralIntent }, new String[]{ resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/); // Finally build the actual intent to launch the ephemeral installer int flags = launchIntent.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); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage); intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget)); intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget)); // TODO: Remove when the platform has fully implemented ephemeral apps intent.setData(origIntent.getData()); return intent; } void postStartActivityUncheckedProcessing( ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord, ActivityStack targetStack) { Loading
services/core/java/com/android/server/pm/PackageManagerService.java +86 −52 Original line number Diff line number Diff line Loading @@ -177,6 +177,7 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PatternMatcher; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; Loading Loading @@ -4725,20 +4726,6 @@ public class PackageManagerService extends IPackageManager.Stub { final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId); if (isEphemeralAllowed(intent, query, userId)) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final EphemeralResolveInfo ai = getEphemeralResolveInfo(intent, resolvedType, userId); if (ai != null) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "Returning an EphemeralResolveInfo"); } bestChoice.ephemeralInstaller = mEphemeralInstallerInfo; bestChoice.ephemeralResolveInfo = ai; } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } return bestChoice; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Loading Loading @@ -4779,9 +4766,9 @@ public class PackageManagerService extends IPackageManager.Stub { false, false, false, userId); } private boolean isEphemeralAllowed( Intent intent, List<ResolveInfo> resolvedActivites, int userId) { Intent intent, List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck) { // Short circuit and return early if possible. if (DISABLE_EPHEMERAL_APPS) { return false; Loading @@ -4796,18 +4783,21 @@ public class PackageManagerService extends IPackageManager.Stub { if (intent.getComponent() != null) { return false; } if (intent.getPackage() != null) { if ((intent.getFlags() & Intent.FLAG_IGNORE_EPHEMERAL) != 0) { return false; } if (!skipPackageCheck && intent.getPackage() != null) { return false; } final boolean isWebUri = hasWebURI(intent); if (!isWebUri) { if (!isWebUri || intent.getData().getHost() == null) { return false; } // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution. synchronized (mPackages) { final int count = resolvedActivites.size(); final int count = (resolvedActivities == null ? 0 : resolvedActivities.size()); for (int n = 0; n < count; n++) { ResolveInfo info = resolvedActivites.get(n); ResolveInfo info = resolvedActivities.get(n); String packageName = info.activityInfo.packageName; PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { Loading @@ -4829,19 +4819,19 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } private EphemeralResolveInfo getEphemeralResolveInfo(Intent intent, String resolvedType, int userId) { final int ephemeralPrefixMask = Global.getInt(mContext.getContentResolver(), private static EphemeralResolveInfo getEphemeralResolveInfo( Context context, EphemeralResolverConnection resolverConnection, Intent intent, String resolvedType, int userId, String packageName) { final int ephemeralPrefixMask = Global.getInt(context.getContentResolver(), Global.EPHEMERAL_HASH_PREFIX_MASK, DEFAULT_EPHEMERAL_HASH_PREFIX_MASK); final int ephemeralPrefixCount = Global.getInt(mContext.getContentResolver(), final int ephemeralPrefixCount = Global.getInt(context.getContentResolver(), Global.EPHEMERAL_HASH_PREFIX_COUNT, DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT); final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixMask, ephemeralPrefixCount); final int[] shaPrefix = digest.getDigestPrefix(); final byte[][] digestBytes = digest.getDigestBytes(); final List<EphemeralResolveInfo> ephemeralResolveInfoList = mEphemeralResolverConnection.getEphemeralResolveInfoList( shaPrefix, ephemeralPrefixMask); resolverConnection.getEphemeralResolveInfoList(shaPrefix, ephemeralPrefixMask); if (ephemeralResolveInfoList == null || ephemeralResolveInfoList.size() == 0) { // No hash prefix match; there are no ephemeral apps for this domain. return null; Loading @@ -4858,6 +4848,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (filters.isEmpty()) { continue; } if (packageName != null && !packageName.equals(ephemeralApplication.getPackageName())) { continue; } // We have a domain match; resolve the filters to see if anything matches. final EphemeralIntentResolver ephemeralResolver = new EphemeralIntentResolver(); for (int j = filters.size() - 1; j >= 0; --j) { Loading Loading @@ -5261,8 +5255,12 @@ public class PackageManagerService extends IPackageManager.Stub { } // reader synchronized (mPackages) { boolean sortResult = false; boolean addEphemeral = false; boolean matchEphemeralPackage = false; List<ResolveInfo> result; final String pkgName = intent.getPackage(); synchronized (mPackages) { if (pkgName == null) { List<CrossProfileIntentFilter> matchingFilters = getMatchingCrossProfileIntentFilters(intent, resolvedType, userId); Loading @@ -5270,15 +5268,16 @@ public class PackageManagerService extends IPackageManager.Stub { ResolveInfo xpResolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent, resolvedType, flags, userId); if (xpResolveInfo != null) { List<ResolveInfo> result = new ArrayList<ResolveInfo>(1); result.add(xpResolveInfo); return filterIfNotSystemUser(result, userId); List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1); xpResult.add(xpResolveInfo); return filterIfNotSystemUser(xpResult, userId); } // Check for results in the current profile. List<ResolveInfo> result = mActivities.queryIntent( intent, resolvedType, flags, userId); result = filterIfNotSystemUser(result, userId); result = filterIfNotSystemUser(mActivities.queryIntent( intent, resolvedType, flags, userId), userId); addEphemeral = isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/); // Check for cross profile results. boolean hasNonNegativePriorityResult = hasNonNegativePriority(result); Loading @@ -5290,7 +5289,7 @@ public class PackageManagerService extends IPackageManager.Stub { Collections.singletonList(xpResolveInfo), userId).size() > 0; if (isVisibleToUser) { result.add(xpResolveInfo); Collections.sort(result, mResolvePrioritySorter); sortResult = true; } } if (hasWebURI(intent)) { Loading @@ -5306,29 +5305,62 @@ public class PackageManagerService extends IPackageManager.Stub { // in the result. result.remove(xpResolveInfo); } if (result.size() == 0) { if (result.size() == 0 && !addEphemeral) { result.add(xpDomainInfo.resolveInfo); return result; } } else if (result.size() <= 1) { return result; } result = filterCandidatesWithDomainPreferredActivitiesLPr(intent, flags, result, xpDomainInfo, userId); Collections.sort(result, mResolvePrioritySorter); if (result.size() > 1 || addEphemeral) { result = filterCandidatesWithDomainPreferredActivitiesLPr( intent, flags, result, xpDomainInfo, userId); sortResult = true; } return result; } } else { final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { return filterIfNotSystemUser( result = filterIfNotSystemUser( mActivities.queryIntentForPackage( intent, resolvedType, flags, pkg.activities, userId), userId); } else { // the caller wants to resolve for a particular package; however, there // were no installed results, so, try to find an ephemeral result addEphemeral = isEphemeralAllowed( intent, null /*result*/, userId, true /*skipPackageCheck*/); matchEphemeralPackage = true; result = new ArrayList<ResolveInfo>(); } return new ArrayList<ResolveInfo>(); } } if (addEphemeral) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final EphemeralResolveInfo ai = getEphemeralResolveInfo( mContext, mEphemeralResolverConnection, intent, resolvedType, userId, matchEphemeralPackage ? pkgName : null); if (ai != null) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); } final ResolveInfo ephemeralInstaller = new ResolveInfo(mEphemeralInstallerInfo); ephemeralInstaller.ephemeralResolveInfo = ai; // make sure this resolver is the default ephemeralInstaller.isDefault = true; ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART | IntentFilter.MATCH_ADJUSTMENT_NORMAL; // add a non-generic filter ephemeralInstaller.filter = new IntentFilter(intent.getAction()); ephemeralInstaller.filter.addDataPath( intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL); result.add(ephemeralInstaller); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } if (sortResult) { Collections.sort(result, mResolvePrioritySorter); } return result; } private static class CrossProfileDomainInfo { /* ResolveInfo for IntentForwarderActivity to send the intent to the other profile */ Loading Loading @@ -9205,15 +9237,17 @@ public class PackageManagerService extends IPackageManager.Stub { mEphemeralInstallerActivity.packageName = pkg.applicationInfo.packageName; mEphemeralInstallerActivity.processName = pkg.applicationInfo.packageName; mEphemeralInstallerActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; mEphemeralInstallerActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS | ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; mEphemeralInstallerActivity.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 = 0; mEphemeralInstallerInfo.match = 0; mEphemeralInstallerInfo.preferredOrder = 1; mEphemeralInstallerInfo.isDefault = true; mEphemeralInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART | IntentFilter.MATCH_ADJUSTMENT_NORMAL; if (DEBUG_EPHEMERAL) { Slog.d(TAG, "Set ephemeral installer activity: " + mEphemeralInstallerComponent); Loading