Merge "Launch intent resolver in same profile when used for sharing" into rvc-dev am: 66f1f9e2ce
Change-Id: Ia9688f3afadb4146908f9cf7d557038801ba9dad
This commit is contained in:
@@ -171,17 +171,6 @@ public class ChooserActivity extends ResolverActivity implements
|
|||||||
public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
|
public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
|
||||||
= "com.android.internal.app.ChooserActivity.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 PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
|
||||||
|
|
||||||
private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
|
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() {
|
private int findSelectedProfile() {
|
||||||
int selectedProfile;
|
int selectedProfile = getSelectedProfileExtra();
|
||||||
if (getIntent().hasExtra(EXTRA_SELECTED_PROFILE)) {
|
if (selectedProfile == -1) {
|
||||||
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 {
|
|
||||||
selectedProfile = getProfileForUser(getUser());
|
selectedProfile = getProfileForUser(getUser());
|
||||||
}
|
}
|
||||||
return selectedProfile;
|
return selectedProfile;
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package com.android.internal.app;
|
|||||||
|
|
||||||
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
|
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.Nullable;
|
||||||
import android.annotation.StringRes;
|
import android.annotation.StringRes;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -26,6 +28,7 @@ import android.app.ActivityThread;
|
|||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
@@ -74,6 +77,9 @@ public class IntentForwarderActivity extends Activity {
|
|||||||
|
|
||||||
private static final String TEL_SCHEME = "tel";
|
private static final String TEL_SCHEME = "tel";
|
||||||
|
|
||||||
|
private static final ComponentName RESOLVER_COMPONENT_NAME =
|
||||||
|
new ComponentName("android", ResolverActivity.class.getName());
|
||||||
|
|
||||||
private Injector mInjector;
|
private Injector mInjector;
|
||||||
|
|
||||||
private MetricsLogger mMetricsLogger;
|
private MetricsLogger mMetricsLogger;
|
||||||
@@ -136,21 +142,50 @@ public class IntentForwarderActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newIntent.prepareToLeaveUser(callingUserId);
|
newIntent.prepareToLeaveUser(callingUserId);
|
||||||
maybeShowDisclosureAsync(intentReceived, newIntent, targetUserId, userMessageId);
|
final CompletableFuture<ResolveInfo> targetResolveInfoFuture =
|
||||||
CompletableFuture.runAsync(() ->
|
mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, targetUserId);
|
||||||
startActivityAsCaller(newIntent, targetUserId), mExecutorService)
|
targetResolveInfoFuture
|
||||||
.thenAcceptAsync(result -> finish(), getApplicationContext().getMainExecutor());
|
.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(
|
private boolean isIntentForwarderResolveInfo(ResolveInfo resolveInfo) {
|
||||||
Intent intentReceived, Intent newIntent, int userId, int messageId) {
|
if (resolveInfo == null) {
|
||||||
final CompletableFuture<ResolveInfo> resolveInfoFuture =
|
return false;
|
||||||
mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, userId);
|
}
|
||||||
resolveInfoFuture.thenAcceptAsync(ri -> {
|
ActivityInfo activityInfo = resolveInfo.activityInfo;
|
||||||
if (shouldShowDisclosure(ri, intentReceived)) {
|
if (activityInfo == null) {
|
||||||
mInjector.showToast(messageId, Toast.LENGTH_LONG);
|
return false;
|
||||||
}
|
}
|
||||||
}, getApplicationContext().getMainExecutor());
|
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) {
|
private void startActivityAsCaller(Intent newIntent, int userId) {
|
||||||
@@ -185,7 +220,7 @@ public class IntentForwarderActivity extends Activity {
|
|||||||
// when cross-profile intents are disabled.
|
// when cross-profile intents are disabled.
|
||||||
int selectedProfile = findSelectedProfile(className);
|
int selectedProfile = findSelectedProfile(className);
|
||||||
sanitizeIntent(intentReceived);
|
sanitizeIntent(intentReceived);
|
||||||
intentReceived.putExtra(ChooserActivity.EXTRA_SELECTED_PROFILE, selectedProfile);
|
intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
|
||||||
Intent innerIntent = intentReceived.getParcelableExtra(Intent.EXTRA_INTENT);
|
Intent innerIntent = intentReceived.getParcelableExtra(Intent.EXTRA_INTENT);
|
||||||
if (innerIntent == null) {
|
if (innerIntent == null) {
|
||||||
Slog.wtf(TAG, "Cannot start a chooser intent with no extra " + Intent.EXTRA_INTENT);
|
Slog.wtf(TAG, "Cannot start a chooser intent with no extra " + Intent.EXTRA_INTENT);
|
||||||
@@ -196,6 +231,25 @@ public class IntentForwarderActivity extends Activity {
|
|||||||
finish();
|
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) {
|
private int findSelectedProfile(String className) {
|
||||||
if (className.equals(FORWARD_INTENT_TO_PARENT)) {
|
if (className.equals(FORWARD_INTENT_TO_PARENT)) {
|
||||||
return ChooserActivity.PROFILE_PERSONAL;
|
return ChooserActivity.PROFILE_PERSONAL;
|
||||||
|
|||||||
@@ -179,6 +179,17 @@ public class ResolverActivity extends Activity implements
|
|||||||
// Intent extra for connected audio devices
|
// Intent extra for connected audio devices
|
||||||
public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device";
|
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 BroadcastReceiver mWorkProfileStateReceiver;
|
||||||
private UserHandle mHeaderCreatorUser;
|
private UserHandle mHeaderCreatorUser;
|
||||||
|
|
||||||
@@ -475,6 +486,10 @@ public class ResolverActivity extends Activity implements
|
|||||||
selectedProfile = PROFILE_WORK;
|
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
|
// 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
|
// 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.
|
// 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;
|
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.
|
* 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()},
|
* <p>This is not necessarily equal to {@link #getUserId()} or {@link UserHandle#myUserId()},
|
||||||
|
|||||||
Reference in New Issue
Block a user