1 /*
2  * Copyright (C) 2022 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 
18 package com.android.systemui.controls.ui
19 
20 import android.app.ActivityOptions
21 import android.app.PendingIntent
22 import android.content.ComponentName
23 import android.content.Context
24 import android.content.Intent
25 import android.graphics.Color
26 import android.graphics.drawable.ShapeDrawable
27 import android.graphics.drawable.shapes.RoundRectShape
28 import android.os.Trace
29 import com.android.internal.annotations.VisibleForTesting
30 import com.android.systemui.res.R
31 import com.android.systemui.util.boundsOnScreen
32 import com.android.wm.shell.taskview.TaskView
33 import java.util.concurrent.Executor
34 
35 class PanelTaskViewController(
36     private val activityContext: Context,
37     private val uiExecutor: Executor,
38     private val pendingIntent: PendingIntent,
39     val taskView: TaskView,
<lambda>null40     private val hide: () -> Unit = {}
41 ) {
42 
43     init {
44         taskView.alpha = 0f
45     }
46 
47     private val fillInIntent =
<lambda>null48         Intent().apply {
49             // Apply flags to make behaviour match documentLaunchMode=always.
50             addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
51             addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
52         }
53 
54     private val stateCallback =
55         object : TaskView.Listener {
onInitializednull56             override fun onInitialized() {
57                 val options =
58                     ActivityOptions.makeCustomAnimation(
59                         activityContext,
60                         0 /* enterResId */,
61                         0 /* exitResId */
62                     )
63                 options.taskAlwaysOnTop = true
64 
65                 taskView.post {
66                     val roundedCorner =
67                         activityContext.resources.getDimensionPixelSize(
68                             R.dimen.controls_panel_corner_radius
69                         )
70                     val radii = FloatArray(8) { roundedCorner.toFloat() }
71                     taskView.background =
72                         ShapeDrawable(RoundRectShape(radii, null, null)).apply {
73                             setTint(Color.TRANSPARENT)
74                         }
75                     taskView.clipToOutline = true
76                     taskView.startActivity(
77                         pendingIntent,
78                         fillInIntent,
79                         options,
80                         taskView.boundsOnScreen
81                     )
82                     Trace.instant(Trace.TRACE_TAG_APP, "PanelTaskViewController - startActivity")
83                 }
84             }
85 
onTaskRemovalStartednull86             override fun onTaskRemovalStarted(taskId: Int) {
87                 release()
88             }
89 
onTaskCreatednull90             override fun onTaskCreated(taskId: Int, name: ComponentName?) {
91                 taskView.alpha = 1f
92             }
93 
onBackPressedOnTaskRootnull94             override fun onBackPressedOnTaskRoot(taskId: Int) {
95                 hide()
96             }
97         }
98 
refreshBoundsnull99     fun refreshBounds() {
100         taskView.onLocationChanged()
101     }
102 
103     /** Call when the taskView is no longer being used, shouldn't be called before removeTask. */
104     @VisibleForTesting
releasenull105     fun release() {
106         taskView.release()
107     }
108 
109     /** Call to explicitly remove the task from window manager. */
removeTasknull110     fun removeTask() {
111         taskView.removeTask()
112     }
113 
launchTaskViewnull114     fun launchTaskView() {
115         taskView.setListener(uiExecutor, stateCallback)
116     }
117 }
118