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.os.Bundle;
21 import android.util.FeatureFlagUtils;
22 import android.view.View;
23 import android.view.WindowManager;
24 
25 import androidx.core.graphics.drawable.IconCompat;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.internal.logging.UiEvent;
29 import com.android.internal.logging.UiEventLogger;
30 import com.android.systemui.R;
31 import com.android.systemui.animation.DialogLaunchAnimator;
32 import com.android.systemui.broadcast.BroadcastSender;
33 import com.android.systemui.dagger.SysUISingleton;
34 
35 /**
36  * Dialog for media output transferring.
37  */
38 @SysUISingleton
39 public class MediaOutputDialog extends MediaOutputBaseDialog {
40     private final DialogLaunchAnimator mDialogLaunchAnimator;
41     private final UiEventLogger mUiEventLogger;
42 
MediaOutputDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender, MediaOutputController mediaOutputController, DialogLaunchAnimator dialogLaunchAnimator, UiEventLogger uiEventLogger)43     MediaOutputDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender,
44             MediaOutputController mediaOutputController, DialogLaunchAnimator dialogLaunchAnimator,
45             UiEventLogger uiEventLogger) {
46         super(context, broadcastSender, mediaOutputController);
47         mDialogLaunchAnimator = dialogLaunchAnimator;
48         mUiEventLogger = uiEventLogger;
49         mAdapter = new MediaOutputAdapter(mMediaOutputController);
50         if (!aboveStatusbar) {
51             getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
52         }
53     }
54 
55     @Override
onCreate(Bundle savedInstanceState)56     public void onCreate(Bundle savedInstanceState) {
57         super.onCreate(savedInstanceState);
58         mUiEventLogger.log(MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW);
59     }
60 
61     @Override
getHeaderIconRes()62     int getHeaderIconRes() {
63         return 0;
64     }
65 
66     @Override
getHeaderIcon()67     IconCompat getHeaderIcon() {
68         return mMediaOutputController.getHeaderIcon();
69     }
70 
71     @Override
getHeaderIconSize()72     int getHeaderIconSize() {
73         return mContext.getResources().getDimensionPixelSize(
74                 R.dimen.media_output_dialog_header_album_icon_size);
75     }
76 
77     @Override
getHeaderText()78     CharSequence getHeaderText() {
79         return mMediaOutputController.getHeaderTitle();
80     }
81 
82     @Override
getHeaderSubtitle()83     CharSequence getHeaderSubtitle() {
84         return mMediaOutputController.getHeaderSubTitle();
85     }
86 
87     @Override
getAppSourceIcon()88     IconCompat getAppSourceIcon() {
89         return mMediaOutputController.getNotificationSmallIcon();
90     }
91 
92     @Override
getStopButtonVisibility()93     int getStopButtonVisibility() {
94         boolean isActiveRemoteDevice = false;
95         if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) {
96             isActiveRemoteDevice = mMediaOutputController.isActiveRemoteDevice(
97                     mMediaOutputController.getCurrentConnectedMediaDevice());
98         }
99         boolean showBroadcastButton = isBroadcastSupported() && mMediaOutputController.isPlaying();
100 
101         return (isActiveRemoteDevice || showBroadcastButton) ? View.VISIBLE : View.GONE;
102     }
103 
104     @Override
isBroadcastSupported()105     public boolean isBroadcastSupported() {
106         boolean isBluetoothLeDevice = false;
107         boolean isBroadcastEnabled = false;
108         if (FeatureFlagUtils.isEnabled(mContext,
109                 FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST)) {
110             if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) {
111                 isBluetoothLeDevice = mMediaOutputController.isBluetoothLeDevice(
112                     mMediaOutputController.getCurrentConnectedMediaDevice());
113                 // if broadcast is active, broadcast should be considered as supported
114                 // there could be a valid case that broadcast is ongoing
115                 // without active LEA device connected
116                 isBroadcastEnabled = mMediaOutputController.isBluetoothLeBroadcastEnabled();
117             }
118         } else {
119             // To decouple LE Audio Broadcast and Unicast, it always displays the button when there
120             // is no LE Audio device connected to the phone
121             isBluetoothLeDevice = true;
122         }
123 
124         return mMediaOutputController.isBroadcastSupported()
125                 && (isBluetoothLeDevice || isBroadcastEnabled);
126     }
127 
128     @Override
getStopButtonText()129     public CharSequence getStopButtonText() {
130         int resId = R.string.media_output_dialog_button_stop_casting;
131         if (isBroadcastSupported() && mMediaOutputController.isPlaying()
132                 && !mMediaOutputController.isBluetoothLeBroadcastEnabled()) {
133             resId = R.string.media_output_broadcast;
134         }
135         return mContext.getText(resId);
136     }
137 
138     @Override
onStopButtonClick()139     public void onStopButtonClick() {
140         if (isBroadcastSupported() && mMediaOutputController.isPlaying()) {
141             if (!mMediaOutputController.isBluetoothLeBroadcastEnabled()) {
142                 if (startLeBroadcastDialogForFirstTime()) {
143                     return;
144                 }
145                 startLeBroadcast();
146             } else {
147                 stopLeBroadcast();
148             }
149         } else {
150             mMediaOutputController.releaseSession();
151             mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
152             dismiss();
153         }
154     }
155 
156     @Override
getBroadcastIconVisibility()157     public int getBroadcastIconVisibility() {
158         return (isBroadcastSupported() && mMediaOutputController.isBluetoothLeBroadcastEnabled())
159                 ? View.VISIBLE : View.GONE;
160     }
161 
162     @Override
onBroadcastIconClick()163     public void onBroadcastIconClick() {
164         startLeBroadcastDialog();
165     }
166 
167     @VisibleForTesting
168     public enum MediaOutputEvent implements UiEventLogger.UiEventEnum {
169         @UiEvent(doc = "The MediaOutput dialog became visible on the screen.")
170         MEDIA_OUTPUT_DIALOG_SHOW(655);
171 
172         private final int mId;
173 
MediaOutputEvent(int id)174         MediaOutputEvent(int id) {
175             mId = id;
176         }
177 
178         @Override
getId()179         public int getId() {
180             return mId;
181         }
182     }
183 }
184