Fix bug with split screen not recognizing user differences
This patch fixes a bug where split screen did not fully support launching intents with different users.
The bug arose because SplitSelectStateController only had one place to store user information about the staged intent, mUser, but this disregarded the fact that the secondary app could also be passed in as an intent, and could belong to a different user from that of the initial app and the existing context. We need to support this case now since we now allow second-app selection from Taskbar.
Fixed by splitting the field into mInitialUser and mSecondUser, which will be tightly bound with mInitialTaskIntent and mSecondTaskIntent to make sure that Intents are always launched with the correct UserHandle.
Fixes: 275410160
Test: Manual
Change-Id: Ic904672769be8fd116180d457b36eb567c5ee304
Merged-In: Ic904672769be8fd116180d457b36eb567c5ee304
Merged-In: I1ec49c75d562e4309a41d98010f0eff113c81e9d
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index b9242b2..1435cb0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -244,7 +244,8 @@
taskAttributes.getIconView().getDrawable(),
taskAttributes.getThumbnailView(),
taskAttributes.getThumbnailView().getThumbnail(),
- null /* intent */);
+ null /* intent */,
+ null /* user */);
return;
}
}
@@ -256,7 +257,8 @@
new BitmapDrawable(info.bitmap.icon),
startingView,
null /* thumbnail */,
- intent);
+ intent,
+ info.user);
}
);
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 1f4085f..5a883bf 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -88,11 +88,17 @@
private final StateManager mStateManager;
@Nullable
private DepthController mDepthController;
- private @StagePosition int mStagePosition;
+ private @StagePosition int mInitialStagePosition;
private ItemInfo mItemInfo;
+ /** {@link #mInitialTaskIntent} and {@link #mInitialUser} (the user of the Intent) are set
+ * together when split is initiated from an Intent. */
private Intent mInitialTaskIntent;
+ private UserHandle mInitialUser;
private int mInitialTaskId = INVALID_TASK_ID;
+ /** {@link #mSecondTaskIntent} and {@link #mSecondUser} (the user of the Intent) are set
+ * together when split is confirmed with an Intent. */
private Intent mSecondTaskIntent;
+ private UserHandle mSecondUser;
private int mSecondTaskId = INVALID_TASK_ID;
private boolean mRecentsAnimationRunning;
/** If {@code true}, animates the existing task view split placeholder view */
@@ -102,8 +108,6 @@
* split pair task view without wanting to animate current task dismissal overall
*/
private boolean mDismissingFromSplitPair;
- @Nullable
- private UserHandle mUser;
/** If not null, this is the TaskView we want to launch from */
@Nullable
private GroupedTaskView mLaunchingTaskView;
@@ -137,7 +141,7 @@
mInitialTaskId = alreadyRunningTask;
} else {
mInitialTaskIntent = intent;
- mUser = itemInfo.user;
+ mInitialUser = itemInfo.user;
}
setInitialData(stagePosition, splitEvent, itemInfo);
@@ -157,7 +161,7 @@
private void setInitialData(@StagePosition int stagePosition,
StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
mItemInfo = itemInfo;
- mStagePosition = stagePosition;
+ mInitialStagePosition = stagePosition;
mSplitEvent = splitEvent;
}
@@ -214,7 +218,7 @@
Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
LogUtils.getShellShareableInstanceId();
launchTasks(mInitialTaskId, mInitialTaskIntent, mSecondTaskId, mSecondTaskIntent,
- mStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
+ mInitialStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
instanceIds.first);
mStatsLogManager.logger()
@@ -231,8 +235,14 @@
mSecondTaskId = task.key.id;
}
- public void setSecondTask(Intent intent) {
+ /**
+ * To be called as soon as user selects the second app (even if animations aren't complete)
+ * @param intent The second intent that will be launched.
+ * @param user The user of that intent.
+ */
+ public void setSecondTask(Intent intent, UserHandle user) {
mSecondTaskIntent = intent;
+ mSecondUser = user;
}
/**
@@ -289,16 +299,17 @@
null /* options2 */, stagePosition, splitRatio, remoteTransition,
shellInstanceId);
} else if (intent2 == null) {
- launchIntentOrShortcut(intent1, options1, taskId2, stagePosition, splitRatio,
- remoteTransition, shellInstanceId);
+ launchIntentOrShortcut(intent1, mInitialUser, options1, taskId2, stagePosition,
+ splitRatio, remoteTransition, shellInstanceId);
} else if (intent1 == null) {
- launchIntentOrShortcut(intent2, options1, taskId1,
+ launchIntentOrShortcut(intent2, mSecondUser, options1, taskId1,
getOppositeStagePosition(stagePosition), splitRatio, remoteTransition,
shellInstanceId);
} else {
- mSystemUiProxy.startIntents(getPendingIntent(intent1), options1.toBundle(),
- getPendingIntent(intent2), null /* options2 */, stagePosition,
- splitRatio, remoteTransition, shellInstanceId);
+ mSystemUiProxy.startIntents(getPendingIntent(intent1, mInitialUser),
+ options1.toBundle(), getPendingIntent(intent2, mSecondUser),
+ null /* options2 */, stagePosition, splitRatio, remoteTransition,
+ shellInstanceId);
}
} else {
final RemoteSplitLaunchAnimationRunner animationRunner =
@@ -312,60 +323,63 @@
taskId2, null /* options2 */, stagePosition, splitRatio, adapter,
shellInstanceId);
} else if (intent2 == null) {
- launchIntentOrShortcutLegacy(intent1, options1, taskId2, stagePosition, splitRatio,
- adapter, shellInstanceId);
+ launchIntentOrShortcutLegacy(intent1, mInitialUser, options1, taskId2,
+ stagePosition, splitRatio, adapter, shellInstanceId);
} else if (intent1 == null) {
- launchIntentOrShortcutLegacy(intent2, options1, taskId1,
+ launchIntentOrShortcutLegacy(intent2, mSecondUser, options1, taskId1,
getOppositeStagePosition(stagePosition), splitRatio, adapter,
shellInstanceId);
} else {
mSystemUiProxy.startIntentsWithLegacyTransition(
- getPendingIntent(intent1), getShortcutInfo(intent1), options1.toBundle(),
- getPendingIntent(intent2), getShortcutInfo(intent2), null /* options2 */,
- stagePosition, splitRatio, adapter, shellInstanceId);
+ getPendingIntent(intent1, mInitialUser),
+ getShortcutInfo(intent1, mInitialUser), options1.toBundle(),
+ getPendingIntent(intent2, mSecondUser),
+ getShortcutInfo(intent2, mSecondUser), null /* options2 */, stagePosition,
+ splitRatio, adapter, shellInstanceId);
}
}
}
- private void launchIntentOrShortcut(Intent intent, ActivityOptions options1, int taskId,
- @StagePosition int stagePosition, float splitRatio, RemoteTransition remoteTransition,
- @Nullable InstanceId shellInstanceId) {
- final ShortcutInfo shortcutInfo = getShortcutInfo(intent);
+ private void launchIntentOrShortcut(Intent intent, UserHandle user, ActivityOptions options1,
+ int taskId, @StagePosition int stagePosition, float splitRatio,
+ RemoteTransition remoteTransition, @Nullable InstanceId shellInstanceId) {
+ final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
if (shortcutInfo != null) {
mSystemUiProxy.startShortcutAndTask(shortcutInfo,
options1.toBundle(), taskId, null /* options2 */, stagePosition,
splitRatio, remoteTransition, shellInstanceId);
} else {
- mSystemUiProxy.startIntentAndTask(getPendingIntent(intent), options1.toBundle(), taskId,
- null /* options2 */, stagePosition, splitRatio, remoteTransition,
- shellInstanceId);
+ mSystemUiProxy.startIntentAndTask(getPendingIntent(intent, user),
+ options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
+ remoteTransition, shellInstanceId);
}
}
- private void launchIntentOrShortcutLegacy(Intent intent, ActivityOptions options1, int taskId,
- @StagePosition int stagePosition, float splitRatio, RemoteAnimationAdapter adapter,
+ private void launchIntentOrShortcutLegacy(Intent intent, UserHandle user,
+ ActivityOptions options1, int taskId, @StagePosition int stagePosition,
+ float splitRatio, RemoteAnimationAdapter adapter,
@Nullable InstanceId shellInstanceId) {
- final ShortcutInfo shortcutInfo = getShortcutInfo(intent);
+ final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
if (shortcutInfo != null) {
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(shortcutInfo,
options1.toBundle(), taskId, null /* options2 */, stagePosition,
splitRatio, adapter, shellInstanceId);
} else {
- mSystemUiProxy.startIntentAndTaskWithLegacyTransition(getPendingIntent(intent),
- options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
- adapter, shellInstanceId);
+ mSystemUiProxy.startIntentAndTaskWithLegacyTransition(
+ getPendingIntent(intent, user), options1.toBundle(), taskId,
+ null /* options2 */, stagePosition, splitRatio, adapter, shellInstanceId);
}
}
- private PendingIntent getPendingIntent(Intent intent) {
- return intent == null ? null : (mUser != null
+ private PendingIntent getPendingIntent(Intent intent, UserHandle user) {
+ return intent == null ? null : (user != null
? PendingIntent.getActivityAsUser(mContext, 0, intent,
- FLAG_MUTABLE, null /* options */, mUser)
+ FLAG_MUTABLE, null /* options */, user)
: PendingIntent.getActivity(mContext, 0, intent, FLAG_MUTABLE));
}
public @StagePosition int getActiveSplitStagePosition() {
- return mStagePosition;
+ return mInitialStagePosition;
}
public StatsLogManager.EventEnum getSplitEvent() {
@@ -377,7 +391,7 @@
}
@Nullable
- private ShortcutInfo getShortcutInfo(Intent intent) {
+ private ShortcutInfo getShortcutInfo(Intent intent, UserHandle user) {
if (intent == null || intent.getPackage() == null) {
return null;
}
@@ -389,7 +403,7 @@
try {
final Context context = mContext.createPackageContextAsUser(
- intent.getPackage(), 0 /* flags */, mUser);
+ intent.getPackage(), 0 /* flags */, user);
return new ShortcutInfo.Builder(context, shortcutId).build();
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Failed to create a ShortcutInfo for " + intent.getPackage());
@@ -519,7 +533,9 @@
mInitialTaskIntent = null;
mSecondTaskId = INVALID_TASK_ID;
mSecondTaskIntent = null;
- mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
+ mInitialUser = null;
+ mSecondUser = null;
+ mInitialStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
mRecentsAnimationRunning = false;
mLaunchingTaskView = null;
mItemInfo = null;
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index e5c74dc..dd10c2d 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -24,6 +24,7 @@
import android.content.Intent;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.os.UserHandle;
import android.view.View;
import com.android.launcher3.DeviceProfile;
@@ -66,21 +67,24 @@
}
Object tag = view.getTag();
Intent intent;
+ UserHandle user;
BitmapInfo bitmapInfo;
if (tag instanceof WorkspaceItemInfo) {
final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
intent = workspaceItemInfo.intent;
+ user = workspaceItemInfo.user;
bitmapInfo = workspaceItemInfo.bitmap;
} else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
final com.android.launcher3.model.data.AppInfo appInfo =
(com.android.launcher3.model.data.AppInfo) tag;
intent = appInfo.intent;
+ user = appInfo.user;
bitmapInfo = appInfo.bitmap;
} else {
return false;
}
- mController.setSecondTask(intent);
+ mController.setSecondTask(intent, user);
boolean isTablet = mLauncher.getDeviceProfile().isTablet;
SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6899f9e..904537f 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -4575,11 +4575,13 @@
* is (either the ThumbnailView or the tapped icon).
* @param intent If we are launching a fresh instance of the app, this is the Intent for it. If
* the second app is already running in Recents, this will be null.
+ * @param user If we are launching a fresh instance of the app, this is the UserHandle for it.
+ * If the second app is already running in Recents, this will be null.
* @return true if waiting for confirmation of second app or if split animations are running,
* false otherwise
*/
public boolean confirmSplitSelect(TaskView containerTaskView, Task task, Drawable drawable,
- View secondView, @Nullable Bitmap thumbnail, Intent intent) {
+ View secondView, @Nullable Bitmap thumbnail, Intent intent, UserHandle user) {
if (canLaunchFullscreenTask()) {
return false;
}
@@ -4595,7 +4597,7 @@
}
mSplitSelectStateController.setSecondTask(task);
} else {
- mSplitSelectStateController.setSecondTask(intent);
+ mSplitSelectStateController.setSecondTask(intent, user);
}
RectF secondTaskStartingBounds = new RectF();
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index df90583..42589ce 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -761,7 +761,8 @@
if (container != null) {
return getRecentsView().confirmSplitSelect(this, container.getTask(),
container.getIconView().getDrawable(), container.getThumbnailView(),
- container.getThumbnailView().getThumbnail(), /* intent */ null);
+ container.getThumbnailView().getThumbnail(), /* intent */ null,
+ /* user */ null);
}
return false;
}