Merge "Launch intent resolver in same profile when used for sharing" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
66f1f9e2ce
@@ -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";
|
||||
@@ -928,15 +917,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
@@ -511,6 +526,25 @@ public class ResolverActivity extends Activity implements
|
||||
return R.style.Theme_DeviceDefault_Resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()},
|
||||
|
||||
Reference in New Issue
Block a user