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