Loading quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +3 −0 Original line number Diff line number Diff line Loading @@ -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); } } } quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt 0 → 100644 +364 −0 Original line number Diff line number Diff line /* * 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") } } No newline at end of file quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +167 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes src/com/android/launcher3/config/FeatureFlags.java +6 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading
quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +3 −0 Original line number Diff line number Diff line Loading @@ -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); } } }
quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt 0 → 100644 +364 −0 Original line number Diff line number Diff line /* * 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") } } No newline at end of file
quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +167 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/com/android/launcher3/config/FeatureFlags.java +6 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading