1 /* 2 * Copyright (C) 2020 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.systemui.media.dialog 18 19 import android.content.Context 20 import android.media.session.MediaSession 21 import android.os.UserHandle 22 import android.view.View 23 import com.android.internal.jank.InteractionJankMonitor 24 import com.android.internal.logging.UiEventLogger 25 import com.android.systemui.animation.DialogCuj 26 import com.android.systemui.animation.DialogTransitionAnimator 27 import com.android.systemui.broadcast.BroadcastSender 28 import javax.inject.Inject 29 30 /** Manager to create and show a [MediaOutputDialog]. */ 31 open class MediaOutputDialogManager 32 @Inject 33 constructor( 34 private val context: Context, 35 private val broadcastSender: BroadcastSender, 36 private val uiEventLogger: UiEventLogger, 37 private val dialogTransitionAnimator: DialogTransitionAnimator, 38 private val mediaOutputControllerFactory: MediaOutputController.Factory, 39 ) { 40 companion object { 41 const val INTERACTION_JANK_TAG = "media_output" 42 var mediaOutputDialog: MediaOutputDialog? = null 43 } 44 45 /** Creates a [MediaOutputDialog] for the given package. */ 46 // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the 47 // package name. The user handle is necessary to disambiguate the same package running on 48 // different users. createAndShownull49 open fun createAndShow( 50 packageName: String, 51 aboveStatusBar: Boolean, 52 view: View? = null, 53 userHandle: UserHandle? = null, 54 token: MediaSession.Token? = null 55 ) { 56 createAndShowWithController( 57 packageName, 58 aboveStatusBar, 59 controller = 60 view?.let { 61 DialogTransitionAnimator.Controller.fromView( 62 it, 63 DialogCuj( 64 InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, 65 INTERACTION_JANK_TAG 66 ) 67 ) 68 }, 69 userHandle = userHandle, 70 token = token, 71 ) 72 } 73 74 /** Creates a [MediaOutputDialog] for the given package. */ 75 // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the 76 // package name. The user handle is necessary to disambiguate the same package running on 77 // different users. createAndShowWithControllernull78 open fun createAndShowWithController( 79 packageName: String, 80 aboveStatusBar: Boolean, 81 controller: DialogTransitionAnimator.Controller?, 82 userHandle: UserHandle? = null, 83 token: MediaSession.Token? = null, 84 ) { 85 createAndShow( 86 packageName, 87 aboveStatusBar, 88 dialogTransitionAnimatorController = controller, 89 includePlaybackAndAppMetadata = true, 90 userHandle = userHandle, 91 token = token, 92 ) 93 } 94 createAndShowForSystemRoutingnull95 open fun createAndShowForSystemRouting( 96 controller: DialogTransitionAnimator.Controller? = null 97 ) { 98 createAndShow( 99 packageName = null, 100 aboveStatusBar = false, 101 dialogTransitionAnimatorController = null, 102 includePlaybackAndAppMetadata = false, 103 userHandle = null, 104 ) 105 } 106 107 // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the 108 // package name. The user handle is necessary to disambiguate the same package running on 109 // different users. createAndShownull110 private fun createAndShow( 111 packageName: String?, 112 aboveStatusBar: Boolean, 113 dialogTransitionAnimatorController: DialogTransitionAnimator.Controller?, 114 includePlaybackAndAppMetadata: Boolean = true, 115 userHandle: UserHandle? = null, 116 token: MediaSession.Token? = null, 117 ) { 118 // Dismiss the previous dialog, if any. 119 mediaOutputDialog?.dismiss() 120 121 val controller = mediaOutputControllerFactory.create(packageName, userHandle, token) 122 123 val mediaOutputDialog = 124 MediaOutputDialog( 125 context, 126 aboveStatusBar, 127 broadcastSender, 128 controller, 129 dialogTransitionAnimator, 130 uiEventLogger, 131 includePlaybackAndAppMetadata 132 ) 133 134 // Show the dialog. 135 if (dialogTransitionAnimatorController != null) { 136 dialogTransitionAnimator.show( 137 mediaOutputDialog, 138 dialogTransitionAnimatorController, 139 ) 140 } else { 141 mediaOutputDialog.show() 142 } 143 } 144 145 /** dismiss [MediaOutputDialog] if exist. */ dismissnull146 open fun dismiss() { 147 mediaOutputDialog?.dismiss() 148 mediaOutputDialog = null 149 } 150 } 151