Merge "Refactor handling data launching split screen to separate class" into udc-dev
This commit is contained in:
@@ -1317,5 +1317,8 @@ public class QuickstepLauncher extends Launcher {
|
||||
writer.println("\nQuickstepLauncher:");
|
||||
writer.println(prefix + "\tmOrientationState: " + (recentsView == null ? "recentsNull" :
|
||||
recentsView.getPagedViewOrientedState()));
|
||||
if (recentsView != null) {
|
||||
recentsView.getSplitSelectController().dump(prefix, writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.quickstep.util
|
||||
|
||||
import android.annotation.IntDef
|
||||
import android.app.ActivityManager.RunningTaskInfo
|
||||
import android.app.ActivityTaskManager.INVALID_TASK_ID
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.os.UserHandle
|
||||
import android.util.Log
|
||||
import com.android.internal.annotations.VisibleForTesting
|
||||
import com.android.launcher3.logging.StatsLogManager.EventEnum
|
||||
import com.android.launcher3.model.data.ItemInfo
|
||||
import com.android.launcher3.shortcuts.ShortcutKey
|
||||
import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
|
||||
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
|
||||
import com.android.launcher3.util.SplitConfigurationOptions.getOppositeStagePosition
|
||||
import com.android.quickstep.util.SplitSelectDataHolder.Companion.SplitLaunchType
|
||||
import java.io.PrintWriter
|
||||
|
||||
/**
|
||||
* Holds/transforms/signs/seals/delivers information for the transient state of the user
|
||||
* selecting a first app to start split with and then choosing a second app.
|
||||
* This class DOES NOT associate itself with drag-and-drop split screen starts because they come
|
||||
* from the bad part of town.
|
||||
*
|
||||
* After setting the correct fields for initial/second.* variables, this converts them into the
|
||||
* correct [PendingIntent] and [ShortcutInfo] objects where applicable and sends the necessary
|
||||
* data back via [getSplitLaunchData].
|
||||
* [SplitLaunchType] indicates the type of tasks/apps/intents being launched given the provided
|
||||
* state
|
||||
*/
|
||||
class SplitSelectDataHolder(
|
||||
val context: Context
|
||||
) {
|
||||
val TAG = SplitSelectDataHolder::class.simpleName
|
||||
|
||||
/**
|
||||
* Order of the constant indicates the order of which task/app was selected.
|
||||
* Ex. SPLIT_TASK_SHORTCUT means primary split app identified by task, secondary is shortcut
|
||||
* SPLIT_SHORTCUT_TASK means primary split app is determined by shortcut, secondary is task
|
||||
*/
|
||||
companion object {
|
||||
@IntDef(SPLIT_TASK_TASK, SPLIT_TASK_PENDINGINTENT, SPLIT_TASK_SHORTCUT,
|
||||
SPLIT_PENDINGINTENT_TASK, SPLIT_PENDINGINTENT_PENDINGINTENT, SPLIT_SHORTCUT_TASK)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class SplitLaunchType
|
||||
|
||||
const val SPLIT_TASK_TASK = 0
|
||||
const val SPLIT_TASK_PENDINGINTENT = 1
|
||||
const val SPLIT_TASK_SHORTCUT = 2
|
||||
const val SPLIT_PENDINGINTENT_TASK = 3
|
||||
const val SPLIT_SHORTCUT_TASK = 4
|
||||
const val SPLIT_PENDINGINTENT_PENDINGINTENT = 5
|
||||
}
|
||||
|
||||
|
||||
@StagePosition
|
||||
private var initialStagePosition: Int = STAGE_POSITION_UNDEFINED
|
||||
private var initialTaskId: Int = INVALID_TASK_ID
|
||||
private var secondTaskId: Int = INVALID_TASK_ID
|
||||
private var initialUser: UserHandle? = null
|
||||
private var secondUser: UserHandle? = null
|
||||
private var initialIntent: Intent? = null
|
||||
private var secondIntent: Intent? = null
|
||||
private var secondPendingIntent: PendingIntent? = null
|
||||
private var itemInfo: ItemInfo? = null
|
||||
private var splitEvent: EventEnum? = null
|
||||
private var initialShortcut: ShortcutInfo? = null
|
||||
private var secondShortcut: ShortcutInfo? = null
|
||||
private var initialPendingIntent: PendingIntent? = null
|
||||
|
||||
/**
|
||||
* @param alreadyRunningTask if set to [android.app.ActivityTaskManager.INVALID_TASK_ID]
|
||||
* then @param intent will be used to launch the initial task
|
||||
* @param intent will be ignored if @param alreadyRunningTask is set
|
||||
*/
|
||||
fun setInitialTaskSelect(intent: Intent?, @StagePosition stagePosition: Int,
|
||||
itemInfo: ItemInfo?, splitEvent: EventEnum?,
|
||||
alreadyRunningTask: Int) {
|
||||
if (alreadyRunningTask != INVALID_TASK_ID) {
|
||||
initialTaskId = alreadyRunningTask
|
||||
} else {
|
||||
initialIntent = intent!!
|
||||
initialUser = itemInfo!!.user
|
||||
}
|
||||
setInitialData(stagePosition, splitEvent, itemInfo)
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called after first task selected from using a split shortcut from the fullscreen
|
||||
* running app.
|
||||
*/
|
||||
fun setInitialTaskSelect(info: RunningTaskInfo,
|
||||
@StagePosition stagePosition: Int, itemInfo: ItemInfo?,
|
||||
splitEvent: EventEnum?) {
|
||||
initialTaskId = info.taskId
|
||||
setInitialData(stagePosition, splitEvent, itemInfo)
|
||||
}
|
||||
|
||||
private fun setInitialData(@StagePosition stagePosition: Int,
|
||||
event: EventEnum?, item: ItemInfo?) {
|
||||
itemInfo = item
|
||||
initialStagePosition = stagePosition
|
||||
splitEvent = event
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called as soon as user selects the second task (even if animations aren't complete)
|
||||
* @param taskId The second task that will be launched.
|
||||
*/
|
||||
fun setSecondTask(taskId: Int) {
|
||||
secondTaskId = taskId
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
fun setSecondTask(intent: Intent, user: UserHandle) {
|
||||
secondIntent = intent
|
||||
secondUser = user
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called as soon as user selects the second app (even if animations aren't complete)
|
||||
* Sets [secondUser] from that of the pendingIntent
|
||||
* @param pendingIntent The second PendingIntent that will be launched.
|
||||
*/
|
||||
fun setSecondTask(pendingIntent: PendingIntent) {
|
||||
secondPendingIntent = pendingIntent
|
||||
secondUser = pendingIntent.creatorUserHandle!!
|
||||
}
|
||||
|
||||
private fun getShortcutInfo(intent: Intent?, user: UserHandle?): ShortcutInfo? {
|
||||
if (intent?.getPackage() == null) {
|
||||
return null
|
||||
}
|
||||
val shortcutId = intent.getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID)
|
||||
?: return null
|
||||
try {
|
||||
val context: Context = context.createPackageContextAsUser(
|
||||
intent.getPackage(), 0 /* flags */, user)
|
||||
return ShortcutInfo.Builder(context, shortcutId).build()
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
Log.w(TAG, "Failed to create a ShortcutInfo for " + intent.getPackage())
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts intents to pendingIntents, associating the [user] with the intent if provided
|
||||
*/
|
||||
private fun getPendingIntent(intent: Intent?, user: UserHandle?): PendingIntent? {
|
||||
if (intent != initialIntent && intent != secondIntent) {
|
||||
throw IllegalStateException("Invalid intent to convert to PendingIntent")
|
||||
}
|
||||
|
||||
return if (intent == null) {
|
||||
null
|
||||
} else if (user != null) {
|
||||
PendingIntent.getActivityAsUser(context, 0, intent,
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT,
|
||||
null /* options */, user)
|
||||
} else {
|
||||
PendingIntent.getActivity(context, 0, intent,
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return [SplitLaunchData] with the necessary fields populated as determined by
|
||||
* [SplitLaunchData.splitLaunchType]
|
||||
*/
|
||||
fun getSplitLaunchData() : SplitLaunchData {
|
||||
// Convert all intents to shortcut infos to see if determine if we launch shortcut or intent
|
||||
convertIntentsToFinalTypes()
|
||||
val splitLaunchType = getSplitLaunchType()
|
||||
if (splitLaunchType == SPLIT_TASK_PENDINGINTENT || splitLaunchType == SPLIT_TASK_SHORTCUT) {
|
||||
// need to get opposite stage position
|
||||
initialStagePosition = getOppositeStagePosition(initialStagePosition)
|
||||
}
|
||||
|
||||
return SplitLaunchData(
|
||||
splitLaunchType,
|
||||
initialTaskId,
|
||||
secondTaskId,
|
||||
initialPendingIntent,
|
||||
secondPendingIntent,
|
||||
initialShortcut,
|
||||
secondShortcut,
|
||||
itemInfo,
|
||||
splitEvent,
|
||||
initialStagePosition)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts our [initialIntent] and [secondIntent] into shortcuts and pendingIntents, if
|
||||
* possible.
|
||||
*
|
||||
* Note that both [initialIntent] and [secondIntent] will be nullified on method return
|
||||
*
|
||||
* One caveat is that if [secondPendingIntent] is set, we will use that and *not* attempt to
|
||||
* convert [secondIntent]
|
||||
*/
|
||||
private fun convertIntentsToFinalTypes() {
|
||||
initialShortcut = getShortcutInfo(initialIntent, initialUser)
|
||||
initialPendingIntent = getPendingIntent(initialIntent, initialUser)
|
||||
initialIntent = null
|
||||
|
||||
// Only one of the two is currently allowed (secondPendingIntent directly set for widgets)
|
||||
if (secondIntent != null && secondPendingIntent != null) {
|
||||
throw IllegalStateException("Both secondIntent and secondPendingIntent non-null")
|
||||
}
|
||||
// If secondPendingIntent already set, no need to convert. Prioritize using that
|
||||
if (secondPendingIntent != null) {
|
||||
secondIntent = null
|
||||
return
|
||||
}
|
||||
|
||||
secondShortcut = getShortcutInfo(secondIntent, secondUser)
|
||||
secondPendingIntent = getPendingIntent(secondIntent, secondUser)
|
||||
secondIntent = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Only valid data fields at this point should be tasks, shortcuts, or pendingIntents
|
||||
* Intents need to be converted in [convertIntentsToFinalTypes] prior to calling this method
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@SplitLaunchType
|
||||
fun getSplitLaunchType(): Int {
|
||||
if (initialIntent != null || secondIntent != null) {
|
||||
throw IllegalStateException("Intents need to be converted")
|
||||
}
|
||||
|
||||
// Prioritize task launches first
|
||||
if (initialTaskId != INVALID_TASK_ID) {
|
||||
if (secondTaskId != INVALID_TASK_ID) {
|
||||
return SPLIT_TASK_TASK
|
||||
}
|
||||
if (secondShortcut != null) {
|
||||
return SPLIT_TASK_SHORTCUT
|
||||
}
|
||||
if (secondPendingIntent != null) {
|
||||
return SPLIT_TASK_PENDINGINTENT
|
||||
}
|
||||
}
|
||||
|
||||
if (secondTaskId != INVALID_TASK_ID) {
|
||||
if (initialShortcut != null) {
|
||||
return SPLIT_SHORTCUT_TASK
|
||||
}
|
||||
if (initialPendingIntent != null) {
|
||||
return SPLIT_PENDINGINTENT_TASK
|
||||
}
|
||||
}
|
||||
|
||||
// All task+shortcut combinations are handled above, only launch left is with multiple
|
||||
// intents (and respective shortcut infos, if necessary)
|
||||
if (initialPendingIntent != null && secondPendingIntent != null) {
|
||||
return SPLIT_PENDINGINTENT_PENDINGINTENT
|
||||
}
|
||||
throw IllegalStateException("Unidentified split launch type")
|
||||
}
|
||||
|
||||
data class SplitLaunchData(
|
||||
@SplitLaunchType
|
||||
val splitLaunchType: Int,
|
||||
var initialTaskId: Int = INVALID_TASK_ID,
|
||||
var secondTaskId: Int = INVALID_TASK_ID,
|
||||
var initialPendingIntent: PendingIntent? = null,
|
||||
var secondPendingIntent: PendingIntent? = null,
|
||||
var initialShortcut: ShortcutInfo? = null,
|
||||
var secondShortcut: ShortcutInfo? = null,
|
||||
var itemInfo: ItemInfo? = null,
|
||||
var splitEvent: EventEnum? = null,
|
||||
val initialStagePosition: Int = STAGE_POSITION_UNDEFINED
|
||||
)
|
||||
|
||||
/**
|
||||
* @return `true` if first task has been selected and waiting for the second task to be
|
||||
* chosen
|
||||
*/
|
||||
fun isSplitSelectActive(): Boolean {
|
||||
return isInitialTaskIntentSet() && !isSecondTaskIntentSet()
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` if the first and second task have been chosen and split is waiting to
|
||||
* be launched
|
||||
*/
|
||||
fun isBothSplitAppsConfirmed(): Boolean {
|
||||
return isInitialTaskIntentSet() && isSecondTaskIntentSet()
|
||||
}
|
||||
|
||||
private fun isInitialTaskIntentSet(): Boolean {
|
||||
return initialTaskId != INVALID_TASK_ID || initialIntent != null
|
||||
}
|
||||
|
||||
fun getInitialTaskId(): Int {
|
||||
return initialTaskId
|
||||
}
|
||||
|
||||
fun getSecondTaskId(): Int {
|
||||
return secondTaskId
|
||||
}
|
||||
|
||||
private fun isSecondTaskIntentSet(): Boolean {
|
||||
return secondTaskId != INVALID_TASK_ID || secondIntent != null
|
||||
|| secondPendingIntent != null
|
||||
}
|
||||
|
||||
fun resetState() {
|
||||
initialStagePosition = STAGE_POSITION_UNDEFINED
|
||||
initialTaskId = INVALID_TASK_ID
|
||||
secondTaskId = INVALID_TASK_ID
|
||||
initialUser = null
|
||||
secondUser = null
|
||||
initialIntent = null
|
||||
secondIntent = null
|
||||
secondPendingIntent = null
|
||||
itemInfo = null
|
||||
splitEvent = null
|
||||
initialShortcut = null
|
||||
secondShortcut = null
|
||||
}
|
||||
|
||||
fun dump(prefix: String, writer: PrintWriter) {
|
||||
writer.println("$prefix ${javaClass.simpleName}")
|
||||
writer.println("$prefix\tinitialStagePosition= $initialStagePosition")
|
||||
writer.println("$prefix\tinitialTaskId= $initialTaskId")
|
||||
writer.println("$prefix\tsecondTaskId= $secondTaskId")
|
||||
writer.println("$prefix\tinitialUser= $initialUser")
|
||||
writer.println("$prefix\tsecondUser= $secondUser")
|
||||
writer.println("$prefix\tinitialIntent= $initialIntent")
|
||||
writer.println("$prefix\tsecondIntent= $secondIntent")
|
||||
writer.println("$prefix\tsecondPendingIntent= $secondPendingIntent")
|
||||
writer.println("$prefix\titemInfo= $itemInfo")
|
||||
writer.println("$prefix\tsplitEvent= $splitEvent")
|
||||
writer.println("$prefix\tinitialShortcut= $initialShortcut")
|
||||
writer.println("$prefix\tsecondShortcut= $secondShortcut")
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,12 @@ import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.getOppositeStagePosition;
|
||||
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_PENDINGINTENT;
|
||||
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_TASK;
|
||||
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SHORTCUT_TASK;
|
||||
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDINGINTENT;
|
||||
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
|
||||
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManager;
|
||||
@@ -34,6 +40,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -51,6 +58,7 @@ import android.window.TransitionInfo;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
@@ -71,6 +79,7 @@ import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -85,6 +94,7 @@ public class SplitSelectStateController {
|
||||
private final RecentsModel mRecentTasksModel;
|
||||
private final SplitAnimationController mSplitAnimationController;
|
||||
private final AppPairsController mAppPairsController;
|
||||
private final SplitSelectDataHolder mSplitSelectDataHolder;
|
||||
private StatsLogManager mStatsLogManager;
|
||||
private final SystemUiProxy mSystemUiProxy;
|
||||
private final StateManager mStateManager;
|
||||
@@ -137,6 +147,7 @@ public class SplitSelectStateController {
|
||||
mRecentTasksModel = recentsModel;
|
||||
mSplitAnimationController = new SplitAnimationController(this);
|
||||
mAppPairsController = new AppPairsController(context, this);
|
||||
mSplitSelectDataHolder = new SplitSelectDataHolder(mContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,6 +166,11 @@ public class SplitSelectStateController {
|
||||
}
|
||||
|
||||
setInitialData(stagePosition, splitEvent, itemInfo);
|
||||
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.setInitialTaskSelect(intent, stagePosition, itemInfo, splitEvent,
|
||||
alreadyRunningTask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,6 +182,10 @@ public class SplitSelectStateController {
|
||||
StatsLogManager.EventEnum splitEvent) {
|
||||
mInitialTaskId = info.taskId;
|
||||
setInitialData(stagePosition, splitEvent, itemInfo);
|
||||
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.setInitialTaskSelect(info, stagePosition, itemInfo, splitEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private void setInitialData(@StagePosition int stagePosition,
|
||||
@@ -243,6 +263,10 @@ public class SplitSelectStateController {
|
||||
*/
|
||||
public void setSecondTask(Task task) {
|
||||
mSecondTaskId = task.key.id;
|
||||
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.setSecondTask(task.key.id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,6 +277,10 @@ public class SplitSelectStateController {
|
||||
public void setSecondTask(Intent intent, UserHandle user) {
|
||||
mSecondTaskIntent = intent;
|
||||
mSecondUser = user;
|
||||
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.setSecondTask(intent, user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,6 +291,10 @@ public class SplitSelectStateController {
|
||||
public void setSecondTask(PendingIntent pendingIntent) {
|
||||
mSecondPendingIntent = pendingIntent;
|
||||
mSecondUser = pendingIntent.getCreatorUserHandle();
|
||||
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.setSecondTask(pendingIntent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,6 +317,12 @@ public class SplitSelectStateController {
|
||||
*/
|
||||
public void launchTasks(int taskId1, int taskId2, @StagePosition int stagePosition,
|
||||
Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.setInitialTaskSelect(null /*intent*/,
|
||||
stagePosition, null /*itemInfo*/, null /*splitEvent*/,
|
||||
taskId1);
|
||||
mSplitSelectDataHolder.setSecondTask(taskId2);
|
||||
}
|
||||
launchTasks(taskId1, null /* intent1 */, taskId2, null /* intent2 */, stagePosition,
|
||||
callback, freezeTaskList, splitRatio, null);
|
||||
}
|
||||
@@ -305,6 +343,11 @@ public class SplitSelectStateController {
|
||||
@Nullable InstanceId shellInstanceId) {
|
||||
TestLogging.recordEvent(
|
||||
TestProtocol.SEQUENCE_MAIN, "launchSplitTasks");
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
launchTasksRefactored(callback, freezeTaskList, splitRatio, shellInstanceId);
|
||||
return;
|
||||
}
|
||||
|
||||
final ActivityOptions options1 = ActivityOptions.makeBasic();
|
||||
if (freezeTaskList) {
|
||||
options1.setFreezeRecentTasksReordering();
|
||||
@@ -367,6 +410,101 @@ public class SplitSelectStateController {
|
||||
}
|
||||
}
|
||||
|
||||
private void launchTasksRefactored(Consumer<Boolean> callback, boolean freezeTaskList,
|
||||
float splitRatio, @Nullable InstanceId shellInstanceId) {
|
||||
final ActivityOptions options1 = ActivityOptions.makeBasic();
|
||||
if (freezeTaskList) {
|
||||
options1.setFreezeRecentTasksReordering();
|
||||
}
|
||||
|
||||
SplitSelectDataHolder.SplitLaunchData launchData =
|
||||
mSplitSelectDataHolder.getSplitLaunchData();
|
||||
int firstTaskId = launchData.getInitialTaskId();
|
||||
int secondTaskId = launchData.getSecondTaskId();
|
||||
ShortcutInfo firstShortcut = launchData.getInitialShortcut();
|
||||
ShortcutInfo secondShortcut = launchData.getSecondShortcut();
|
||||
PendingIntent firstPI = launchData.getInitialPendingIntent();
|
||||
PendingIntent secondPI = launchData.getSecondPendingIntent();
|
||||
int initialStagePosition = launchData.getInitialStagePosition();
|
||||
Bundle optionsBundle = options1.toBundle();
|
||||
|
||||
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
|
||||
final RemoteSplitLaunchTransitionRunner animationRunner =
|
||||
new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
|
||||
final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
|
||||
ActivityThread.currentActivityThread().getApplicationThread(),
|
||||
"LaunchSplitPair");
|
||||
switch (launchData.getSplitLaunchType()) {
|
||||
case SPLIT_TASK_TASK ->
|
||||
mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
|
||||
null /* options2 */, initialStagePosition, splitRatio,
|
||||
remoteTransition, shellInstanceId);
|
||||
|
||||
case SPLIT_TASK_PENDINGINTENT ->
|
||||
mSystemUiProxy.startIntentAndTask(secondPI, optionsBundle, firstTaskId,
|
||||
null /*options2*/, initialStagePosition, splitRatio,
|
||||
remoteTransition, shellInstanceId);
|
||||
|
||||
case SPLIT_TASK_SHORTCUT ->
|
||||
mSystemUiProxy.startShortcutAndTask(secondShortcut, optionsBundle,
|
||||
firstTaskId, null /*options2*/, initialStagePosition, splitRatio,
|
||||
remoteTransition, shellInstanceId);
|
||||
|
||||
case SPLIT_PENDINGINTENT_TASK ->
|
||||
mSystemUiProxy.startIntentAndTask(firstPI, optionsBundle, secondTaskId,
|
||||
null /*options2*/, initialStagePosition, splitRatio,
|
||||
remoteTransition, shellInstanceId);
|
||||
|
||||
case SPLIT_PENDINGINTENT_PENDINGINTENT ->
|
||||
mSystemUiProxy.startIntents(firstPI, firstShortcut, optionsBundle, secondPI,
|
||||
secondShortcut, null /*options2*/, initialStagePosition, splitRatio,
|
||||
remoteTransition, shellInstanceId);
|
||||
|
||||
case SPLIT_SHORTCUT_TASK ->
|
||||
mSystemUiProxy.startShortcutAndTask(firstShortcut, optionsBundle,
|
||||
secondTaskId, null /*options2*/, initialStagePosition, splitRatio,
|
||||
remoteTransition, shellInstanceId);
|
||||
}
|
||||
} else {
|
||||
final RemoteSplitLaunchAnimationRunner animationRunner =
|
||||
new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
|
||||
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
||||
animationRunner, 300, 150,
|
||||
ActivityThread.currentActivityThread().getApplicationThread());
|
||||
switch (launchData.getSplitLaunchType()) {
|
||||
case SPLIT_TASK_TASK ->
|
||||
mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
|
||||
secondTaskId, null /* options2 */, initialStagePosition,
|
||||
splitRatio, adapter, shellInstanceId);
|
||||
|
||||
case SPLIT_TASK_PENDINGINTENT ->
|
||||
mSystemUiProxy.startIntentAndTaskWithLegacyTransition(secondPI,
|
||||
optionsBundle, firstTaskId, null /*options2*/, initialStagePosition,
|
||||
splitRatio, adapter, shellInstanceId);
|
||||
|
||||
case SPLIT_TASK_SHORTCUT ->
|
||||
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(secondShortcut,
|
||||
optionsBundle, firstTaskId, null /*options2*/, initialStagePosition,
|
||||
splitRatio, adapter, shellInstanceId);
|
||||
|
||||
case SPLIT_PENDINGINTENT_TASK ->
|
||||
mSystemUiProxy.startIntentAndTaskWithLegacyTransition(firstPI,
|
||||
optionsBundle, secondTaskId, null /*options2*/,
|
||||
initialStagePosition, splitRatio, adapter, shellInstanceId);
|
||||
|
||||
case SPLIT_PENDINGINTENT_PENDINGINTENT ->
|
||||
mSystemUiProxy.startIntentsWithLegacyTransition(firstPI, firstShortcut,
|
||||
optionsBundle, secondPI, secondShortcut, null /*options2*/,
|
||||
initialStagePosition, splitRatio, adapter, shellInstanceId);
|
||||
|
||||
case SPLIT_SHORTCUT_TASK ->
|
||||
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(firstShortcut,
|
||||
optionsBundle, secondTaskId, null /*options2*/,
|
||||
initialStagePosition, splitRatio, adapter, shellInstanceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void launchIntentOrShortcut(Intent intent, UserHandle user, ActivityOptions options1,
|
||||
int taskId, @StagePosition int stagePosition, float splitRatio,
|
||||
RemoteTransition remoteTransition, @Nullable InstanceId shellInstanceId) {
|
||||
@@ -572,6 +710,9 @@ public class SplitSelectStateController {
|
||||
* To be called if split select was cancelled
|
||||
*/
|
||||
public void resetState() {
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
mSplitSelectDataHolder.resetState();
|
||||
}
|
||||
mInitialTaskId = INVALID_TASK_ID;
|
||||
mInitialTaskIntent = null;
|
||||
mSecondTaskId = INVALID_TASK_ID;
|
||||
@@ -593,7 +734,11 @@ public class SplitSelectStateController {
|
||||
* chosen
|
||||
*/
|
||||
public boolean isSplitSelectActive() {
|
||||
return isInitialTaskIntentSet() && !isSecondTaskIntentSet();
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
return mSplitSelectDataHolder.isSplitSelectActive();
|
||||
} else {
|
||||
return isInitialTaskIntentSet() && !isSecondTaskIntentSet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +746,11 @@ public class SplitSelectStateController {
|
||||
* be launched
|
||||
*/
|
||||
public boolean isBothSplitAppsConfirmed() {
|
||||
return isInitialTaskIntentSet() && isSecondTaskIntentSet();
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
return mSplitSelectDataHolder.isBothSplitAppsConfirmed();
|
||||
} else {
|
||||
return isInitialTaskIntentSet() && isSecondTaskIntentSet();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInitialTaskIntentSet() {
|
||||
@@ -609,11 +758,19 @@ public class SplitSelectStateController {
|
||||
}
|
||||
|
||||
public int getInitialTaskId() {
|
||||
return mInitialTaskId;
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
return mSplitSelectDataHolder.getInitialTaskId();
|
||||
} else {
|
||||
return mInitialTaskId;
|
||||
}
|
||||
}
|
||||
|
||||
public int getSecondTaskId() {
|
||||
return mSecondTaskId;
|
||||
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
|
||||
return mSplitSelectDataHolder.getSecondTaskId();
|
||||
} else {
|
||||
return mSecondTaskId;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSecondTaskIntentSet() {
|
||||
@@ -632,4 +789,10 @@ public class SplitSelectStateController {
|
||||
public AppPairsController getAppPairsController() {
|
||||
return mAppPairsController;
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter writer) {
|
||||
if (mSplitSelectDataHolder != null) {
|
||||
mSplitSelectDataHolder.dump(prefix, writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +407,12 @@ public final class FeatureFlags {
|
||||
"USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", DISABLED,
|
||||
"Use local overrides for search request timeout");
|
||||
|
||||
// TODO(Block 31): Empty block
|
||||
// TODO(Block 31)
|
||||
public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(279494325,
|
||||
"ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED,
|
||||
"Use refactored split launching code path");
|
||||
|
||||
// TODO(Block 32): Empty block
|
||||
|
||||
public static class BooleanFlag {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user