1 /*
2  * Copyright (C) 2024 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 
17 package com.android.wm.shell.bubbles
18 
19 import android.app.ActivityTaskManager
20 import android.app.ActivityTaskManager.INVALID_TASK_ID
21 import android.content.ComponentName
22 import android.os.RemoteException
23 import android.util.Log
24 import androidx.annotation.VisibleForTesting
25 import com.android.wm.shell.taskview.TaskView
26 import com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS
27 import java.util.concurrent.Executor
28 
29 /**
30  * A wrapper class around [TaskView] for bubble expanded views.
31  *
32  * [delegateListener] allows callers to change listeners after a task has been created.
33  */
34 class BubbleTaskView(val taskView: TaskView, executor: Executor) {
35 
36     /** Whether the task is already created. */
37     var isCreated = false
38       private set
39 
40     /** The task id. */
41     var taskId = INVALID_TASK_ID
42       private set
43 
44     /** The component name of the application running in the task. */
45     var componentName: ComponentName? = null
46       private set
47 
48     /** [TaskView.Listener] for users of this class. */
49     var delegateListener: TaskView.Listener? = null
50 
51     /** A [TaskView.Listener] that delegates to [delegateListener]. */
52     @get:VisibleForTesting
53     val listener = object : TaskView.Listener {
onInitializednull54         override fun onInitialized() {
55             delegateListener?.onInitialized()
56         }
57 
onReleasednull58         override fun onReleased() {
59             delegateListener?.onReleased()
60         }
61 
onTaskCreatednull62         override fun onTaskCreated(taskId: Int, name: ComponentName) {
63             delegateListener?.onTaskCreated(taskId, name)
64             this@BubbleTaskView.taskId = taskId
65             isCreated = true
66             componentName = name
67         }
68 
onTaskVisibilityChangednull69         override fun onTaskVisibilityChanged(taskId: Int, visible: Boolean) {
70             delegateListener?.onTaskVisibilityChanged(taskId, visible)
71         }
72 
onTaskRemovalStartednull73         override fun onTaskRemovalStarted(taskId: Int) {
74             delegateListener?.onTaskRemovalStarted(taskId)
75         }
76 
onBackPressedOnTaskRootnull77         override fun onBackPressedOnTaskRoot(taskId: Int) {
78             delegateListener?.onBackPressedOnTaskRoot(taskId)
79         }
80     }
81 
82     init {
83         taskView.setListener(executor, listener)
84     }
85 
86     /**
87      * Removes the [TaskView] from window manager.
88      *
89      * This should be called after all other cleanup animations have finished.
90      */
cleanupnull91     fun cleanup() {
92         if (taskId != INVALID_TASK_ID) {
93             // Ensure the task is removed from WM
94             if (ENABLE_SHELL_TRANSITIONS) {
95                 taskView.removeTask()
96             } else {
97                 try {
98                     ActivityTaskManager.getService().removeTask(taskId)
99                 } catch (e: RemoteException) {
100                     Log.w(TAG, e.message ?: "")
101                 }
102             }
103         }
104     }
105 
106     private companion object {
107         const val TAG = "BubbleTaskView"
108     }
109 }
110