1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.wm.shell.common
17 
18 import android.window.WindowContainerToken
19 import android.window.WindowContainerTransaction
20 import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG
21 import com.android.wm.shell.util.KtProtoLog
22 
23 /**
24  * Controller to manage behavior of activities launched with
25  * [android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT].
26  */
27 class LaunchAdjacentController(private val syncQueue: SyncTransactionQueue) {
28 
29     /** Allows to temporarily disable launch adjacent handling */
30     var launchAdjacentEnabled: Boolean = true
31         set(value) {
32             if (field != value) {
33                 KtProtoLog.d(WM_SHELL_TASK_ORG, "set launch adjacent flag root enabled=%b", value)
34                 field = value
35                 container?.let { c ->
36                     if (value) {
37                         enableContainer(c)
38                     } else {
39                         disableContainer((c))
40                     }
41                 }
42             }
43         }
44     private var container: WindowContainerToken? = null
45 
46     /**
47      * Set [container] as the new launch adjacent flag root container.
48      *
49      * If launch adjacent handling is disabled through [setLaunchAdjacentEnabled], won't set the
50      * container until after it is enabled again.
51      *
52      * @see WindowContainerTransaction.setLaunchAdjacentFlagRoot
53      */
54     fun setLaunchAdjacentRoot(container: WindowContainerToken) {
55         KtProtoLog.d(WM_SHELL_TASK_ORG, "set new launch adjacent flag root container")
56         this.container = container
57         if (launchAdjacentEnabled) {
58             enableContainer(container)
59         }
60     }
61 
62     /**
63      * Clear a container previously set through [setLaunchAdjacentRoot].
64      *
65      * Always clears the container, regardless of [launchAdjacentEnabled] value.
66      *
67      * @see WindowContainerTransaction.clearLaunchAdjacentFlagRoot
68      */
69     fun clearLaunchAdjacentRoot() {
70         KtProtoLog.d(WM_SHELL_TASK_ORG, "clear launch adjacent flag root container")
71         container?.let {
72             disableContainer(it)
73             container = null
74         }
75     }
76 
77     private fun enableContainer(container: WindowContainerToken) {
78         KtProtoLog.v(WM_SHELL_TASK_ORG, "enable launch adjacent flag root container")
79         val wct = WindowContainerTransaction()
80         wct.setLaunchAdjacentFlagRoot(container)
81         syncQueue.queue(wct)
82     }
83 
84     private fun disableContainer(container: WindowContainerToken) {
85         KtProtoLog.v(WM_SHELL_TASK_ORG, "disable launch adjacent flag root container")
86         val wct = WindowContainerTransaction()
87         wct.clearLaunchAdjacentFlagRoot(container)
88         syncQueue.queue(wct)
89     }
90 }
91