summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java22
-rw-r--r--core/java/com/android/internal/app/IntentForwarderActivity.java82
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java34
3 files changed, 104 insertions, 34 deletions
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 3fc3f3e65d37..c4e25b137c0d 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -171,17 +171,6 @@ public class ChooserActivity extends ResolverActivity implements
public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
= "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
- /**
- * Integer extra to indicate which profile should be automatically selected.
- * <p>Can only be used if there is a work profile.
- * <p>Possible values can be either {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}.
- */
- static final String EXTRA_SELECTED_PROFILE =
- "com.android.internal.app.ChooserActivity.EXTRA_SELECTED_PROFILE";
-
- static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
- static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK;
-
private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
@@ -923,15 +912,8 @@ public class ChooserActivity extends ResolverActivity implements
}
private int findSelectedProfile() {
- int selectedProfile;
- if (getIntent().hasExtra(EXTRA_SELECTED_PROFILE)) {
- selectedProfile = getIntent().getIntExtra(EXTRA_SELECTED_PROFILE, /* defValue = */ -1);
- if (selectedProfile != PROFILE_PERSONAL && selectedProfile != PROFILE_WORK) {
- throw new IllegalArgumentException(EXTRA_SELECTED_PROFILE + " has invalid value "
- + selectedProfile + ". Must be either ChooserActivity.PROFILE_PERSONAL or "
- + "ChooserActivity.PROFILE_WORK.");
- }
- } else {
+ int selectedProfile = getSelectedProfileExtra();
+ if (selectedProfile == -1) {
selectedProfile = getProfileForUser(getUser());
}
return selectedProfile;
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index fca156a97a83..e65d1fe9ce53 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -18,6 +18,8 @@ package com.android.internal.app;
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
+import static com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE;
+
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Activity;
@@ -26,6 +28,7 @@ import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -74,6 +77,9 @@ public class IntentForwarderActivity extends Activity {
private static final String TEL_SCHEME = "tel";
+ private static final ComponentName RESOLVER_COMPONENT_NAME =
+ new ComponentName("android", ResolverActivity.class.getName());
+
private Injector mInjector;
private MetricsLogger mMetricsLogger;
@@ -136,21 +142,50 @@ public class IntentForwarderActivity extends Activity {
}
newIntent.prepareToLeaveUser(callingUserId);
- maybeShowDisclosureAsync(intentReceived, newIntent, targetUserId, userMessageId);
- CompletableFuture.runAsync(() ->
- startActivityAsCaller(newIntent, targetUserId), mExecutorService)
- .thenAcceptAsync(result -> finish(), getApplicationContext().getMainExecutor());
+ final CompletableFuture<ResolveInfo> targetResolveInfoFuture =
+ mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, targetUserId);
+ targetResolveInfoFuture
+ .thenApplyAsync(targetResolveInfo -> {
+ if (isResolverActivityResolveInfo(targetResolveInfo)) {
+ launchResolverActivityWithCorrectTab(intentReceived, className, newIntent,
+ callingUserId, targetUserId);
+ return targetResolveInfo;
+ }
+ startActivityAsCaller(newIntent, targetUserId);
+ return targetResolveInfo;
+ }, mExecutorService)
+ .thenAcceptAsync(result -> {
+ maybeShowDisclosure(intentReceived, result, userMessageId);
+ finish();
+ }, getApplicationContext().getMainExecutor());
}
- private void maybeShowDisclosureAsync(
- Intent intentReceived, Intent newIntent, int userId, int messageId) {
- final CompletableFuture<ResolveInfo> resolveInfoFuture =
- mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, userId);
- resolveInfoFuture.thenAcceptAsync(ri -> {
- if (shouldShowDisclosure(ri, intentReceived)) {
- mInjector.showToast(messageId, Toast.LENGTH_LONG);
- }
- }, getApplicationContext().getMainExecutor());
+ private boolean isIntentForwarderResolveInfo(ResolveInfo resolveInfo) {
+ if (resolveInfo == null) {
+ return false;
+ }
+ ActivityInfo activityInfo = resolveInfo.activityInfo;
+ if (activityInfo == null) {
+ return false;
+ }
+ if (!"android".equals(activityInfo.packageName)) {
+ return false;
+ }
+ return activityInfo.name.equals(FORWARD_INTENT_TO_PARENT)
+ || activityInfo.name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE);
+ }
+
+ private boolean isResolverActivityResolveInfo(@Nullable ResolveInfo resolveInfo) {
+ return resolveInfo != null
+ && resolveInfo.activityInfo != null
+ && RESOLVER_COMPONENT_NAME.equals(resolveInfo.activityInfo.getComponentName());
+ }
+
+ private void maybeShowDisclosure(
+ Intent intentReceived, ResolveInfo resolveInfo, int messageId) {
+ if (shouldShowDisclosure(resolveInfo, intentReceived)) {
+ mInjector.showToast(messageId, Toast.LENGTH_LONG);
+ }
}
private void startActivityAsCaller(Intent newIntent, int userId) {
@@ -185,7 +220,7 @@ public class IntentForwarderActivity extends Activity {
// when cross-profile intents are disabled.
int selectedProfile = findSelectedProfile(className);
sanitizeIntent(intentReceived);
- intentReceived.putExtra(ChooserActivity.EXTRA_SELECTED_PROFILE, selectedProfile);
+ intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
Intent innerIntent = intentReceived.getParcelableExtra(Intent.EXTRA_INTENT);
if (innerIntent == null) {
Slog.wtf(TAG, "Cannot start a chooser intent with no extra " + Intent.EXTRA_INTENT);
@@ -196,6 +231,25 @@ public class IntentForwarderActivity extends Activity {
finish();
}
+ private void launchResolverActivityWithCorrectTab(Intent intentReceived, String className,
+ Intent newIntent, int callingUserId, int targetUserId) {
+ // When showing the intent resolver, instead of forwarding to the other profile,
+ // we launch it in the current user and select the other tab. This fixes b/155874820.
+ //
+ // In the case when there are 0 targets in the current profile and >1 apps in the other
+ // profile, the package manager launches the intent resolver in the other profile.
+ // If that's the case, we launch the resolver in the target user instead (other profile).
+ ResolveInfo callingResolveInfo = mInjector.resolveActivityAsUser(
+ newIntent, MATCH_DEFAULT_ONLY, callingUserId).join();
+ int userId = isIntentForwarderResolveInfo(callingResolveInfo)
+ ? targetUserId : callingUserId;
+ int selectedProfile = findSelectedProfile(className);
+ sanitizeIntent(intentReceived);
+ intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
+ startActivityAsCaller(intentReceived, null, null, false, userId);
+ finish();
+ }
+
private int findSelectedProfile(String className) {
if (className.equals(FORWARD_INTENT_TO_PARENT)) {
return ChooserActivity.PROFILE_PERSONAL;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 9c2df131d11a..08ae6c227316 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -179,6 +179,17 @@ public class ResolverActivity extends Activity implements
// Intent extra for connected audio devices
public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device";
+ /**
+ * Integer extra to indicate which profile should be automatically selected.
+ * <p>Can only be used if there is a work profile.
+ * <p>Possible values can be either {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}.
+ */
+ static final String EXTRA_SELECTED_PROFILE =
+ "com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE";
+
+ static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
+ static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK;
+
private BroadcastReceiver mWorkProfileStateReceiver;
private UserHandle mHeaderCreatorUser;
@@ -475,6 +486,10 @@ public class ResolverActivity extends Activity implements
selectedProfile = PROFILE_WORK;
}
}
+ int selectedProfileExtra = getSelectedProfileExtra();
+ if (selectedProfileExtra != -1) {
+ selectedProfile = selectedProfileExtra;
+ }
// We only show the default app for the profile of the current user. The filterLastUsed
// flag determines whether to show a default app and that app is not shown in the
// resolver list. So filterLastUsed should be false for the other profile.
@@ -508,6 +523,25 @@ public class ResolverActivity extends Activity implements
}
/**
+ * Returns {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK} if the {@link
+ * #EXTRA_SELECTED_PROFILE} extra was supplied, or {@code -1} if no extra was supplied.
+ * @throws IllegalArgumentException if the value passed to the {@link #EXTRA_SELECTED_PROFILE}
+ * extra is not {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}
+ */
+ int getSelectedProfileExtra() {
+ int selectedProfile = -1;
+ if (getIntent().hasExtra(EXTRA_SELECTED_PROFILE)) {
+ selectedProfile = getIntent().getIntExtra(EXTRA_SELECTED_PROFILE, /* defValue = */ -1);
+ if (selectedProfile != PROFILE_PERSONAL && selectedProfile != PROFILE_WORK) {
+ throw new IllegalArgumentException(EXTRA_SELECTED_PROFILE + " has invalid value "
+ + selectedProfile + ". Must be either ResolverActivity.PROFILE_PERSONAL or "
+ + "ResolverActivity.PROFILE_WORK.");
+ }
+ }
+ return selectedProfile;
+ }
+
+ /**
* Returns the user id of the user that the starting intent originated from.
* <p>This is not necessarily equal to {@link #getUserId()} or {@link UserHandle#myUserId()},
* as there are edge cases when the intent resolver is launched in the other profile.