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.settings.connecteddevice.audiosharing.audiostreams; 18 19 import android.app.AlertDialog; 20 import android.app.Dialog; 21 import android.app.settings.SettingsEnums; 22 import android.content.Context; 23 import android.os.Bundle; 24 import android.util.Log; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.widget.Button; 28 import android.widget.TextView; 29 30 import androidx.annotation.NonNull; 31 import androidx.annotation.Nullable; 32 import androidx.fragment.app.DialogFragment; 33 import androidx.fragment.app.Fragment; 34 import androidx.fragment.app.FragmentManager; 35 36 import com.android.settings.R; 37 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 38 39 import com.google.common.base.Strings; 40 41 import java.util.function.Consumer; 42 43 /** A dialog fragment for constructing and showing audio stream dialogs. */ 44 public class AudioStreamsDialogFragment extends InstrumentedDialogFragment { 45 private static final String TAG = "AudioStreamsDialogFragment"; 46 private final DialogBuilder mDialogBuilder; 47 private int mDialogId = SettingsEnums.PAGE_UNKNOWN; 48 AudioStreamsDialogFragment(DialogBuilder dialogBuilder, int dialogId)49 AudioStreamsDialogFragment(DialogBuilder dialogBuilder, int dialogId) { 50 mDialogBuilder = dialogBuilder; 51 mDialogId = dialogId; 52 } 53 54 @Override getMetricsCategory()55 public int getMetricsCategory() { 56 return mDialogId; 57 } 58 59 @Override onCreateDialog(Bundle savedInstanceState)60 public Dialog onCreateDialog(Bundle savedInstanceState) { 61 return mDialogBuilder.build(); 62 } 63 64 /** 65 * Displays the audio stream dialog on the specified host fragment. 66 * 67 * @param host The fragment to host the dialog. 68 * @param dialogBuilder The builder for constructing the dialog. 69 * @param dialogId The dialog settings enum for logging 70 */ show(Fragment host, DialogBuilder dialogBuilder, int dialogId)71 public static void show(Fragment host, DialogBuilder dialogBuilder, int dialogId) { 72 if (!host.isAdded()) { 73 Log.w(TAG, "The host fragment is not added to the activity!"); 74 return; 75 } 76 FragmentManager manager = host.getChildFragmentManager(); 77 (new AudioStreamsDialogFragment(dialogBuilder, dialogId)).show(manager, TAG); 78 } 79 dismissAll(Fragment host)80 static void dismissAll(Fragment host) { 81 if (!host.isAdded()) { 82 Log.w(TAG, "The host fragment is not added to the activity!"); 83 return; 84 } 85 FragmentManager manager = host.getChildFragmentManager(); 86 Fragment dialog = manager.findFragmentByTag(TAG); 87 if (dialog != null 88 && ((DialogFragment) dialog).getDialog() != null 89 && ((DialogFragment) dialog).getDialog().isShowing()) { 90 ((DialogFragment) dialog).dismiss(); 91 } 92 } 93 94 @Override show(@onNull FragmentManager manager, @Nullable String tag)95 public void show(@NonNull FragmentManager manager, @Nullable String tag) { 96 Fragment dialog = manager.findFragmentByTag(TAG); 97 if (dialog != null 98 && ((DialogFragment) dialog).getDialog() != null 99 && ((DialogFragment) dialog).getDialog().isShowing()) { 100 Log.w(TAG, "Dialog already showing, ignore"); 101 return; 102 } 103 super.show(manager, tag); 104 } 105 106 /** A builder class for constructing the audio stream dialog. */ 107 public static class DialogBuilder { 108 private final Context mContext; 109 private final AlertDialog.Builder mBuilder; 110 @Nullable private String mTitle; 111 @Nullable private String mSubTitle1; 112 @Nullable private String mSubTitle2; 113 @Nullable private String mLeftButtonText; 114 @Nullable private String mRightButtonText; 115 @Nullable private Consumer<AlertDialog> mLeftButtonOnClickListener; 116 @Nullable private Consumer<AlertDialog> mRightButtonOnClickListener; 117 118 /** 119 * Constructs a new instance of DialogBuilder. 120 * 121 * @param context The context used for building the dialog. 122 */ DialogBuilder(Context context)123 public DialogBuilder(Context context) { 124 mContext = context; 125 mBuilder = new AlertDialog.Builder(context); 126 } 127 128 /** 129 * Sets the title of the dialog. 130 * 131 * @param title The title text. 132 * @return This DialogBuilder instance. 133 */ setTitle(String title)134 public DialogBuilder setTitle(String title) { 135 mTitle = title; 136 return this; 137 } 138 139 /** 140 * Sets the first subtitle of the dialog. 141 * 142 * @param subTitle1 The text of the first subtitle. 143 * @return This DialogBuilder instance. 144 */ setSubTitle1(String subTitle1)145 public DialogBuilder setSubTitle1(String subTitle1) { 146 mSubTitle1 = subTitle1; 147 return this; 148 } 149 150 /** 151 * Sets the second subtitle of the dialog. 152 * 153 * @param subTitle2 The text of the second subtitle. 154 * @return This DialogBuilder instance. 155 */ setSubTitle2(String subTitle2)156 public DialogBuilder setSubTitle2(String subTitle2) { 157 mSubTitle2 = subTitle2; 158 return this; 159 } 160 161 /** 162 * Sets the text of the left button. 163 * 164 * @param text The text of the left button. 165 * @return This DialogBuilder instance. 166 */ setLeftButtonText(String text)167 public DialogBuilder setLeftButtonText(String text) { 168 mLeftButtonText = text; 169 return this; 170 } 171 172 /** 173 * Sets the click listener of the left button. 174 * 175 * @param listener The click listener for the left button. 176 * @return This DialogBuilder instance. 177 */ setLeftButtonOnClickListener(Consumer<AlertDialog> listener)178 public DialogBuilder setLeftButtonOnClickListener(Consumer<AlertDialog> listener) { 179 mLeftButtonOnClickListener = listener; 180 return this; 181 } 182 183 /** 184 * Sets the text of the right button. 185 * 186 * @param text The text of the right button. 187 * @return This DialogBuilder instance. 188 */ setRightButtonText(String text)189 public DialogBuilder setRightButtonText(String text) { 190 mRightButtonText = text; 191 return this; 192 } 193 194 /** 195 * Sets the click listener of the right button. 196 * 197 * @param listener The click listener for the right button. 198 * @return This DialogBuilder instance. 199 */ setRightButtonOnClickListener(Consumer<AlertDialog> listener)200 public DialogBuilder setRightButtonOnClickListener(Consumer<AlertDialog> listener) { 201 mRightButtonOnClickListener = listener; 202 return this; 203 } 204 build()205 AlertDialog build() { 206 View rootView = 207 LayoutInflater.from(mContext) 208 .inflate(R.xml.bluetooth_audio_streams_dialog, /* parent= */ null); 209 210 AlertDialog dialog = mBuilder.setView(rootView).setCancelable(false).create(); 211 dialog.setCanceledOnTouchOutside(false); 212 213 TextView title = rootView.requireViewById(R.id.dialog_title); 214 title.setText(mTitle); 215 216 if (!Strings.isNullOrEmpty(mSubTitle1)) { 217 TextView subTitle1 = rootView.requireViewById(R.id.dialog_subtitle); 218 subTitle1.setText(mSubTitle1); 219 subTitle1.setVisibility(View.VISIBLE); 220 } 221 if (!Strings.isNullOrEmpty(mSubTitle2)) { 222 TextView subTitle2 = rootView.requireViewById(R.id.dialog_subtitle_2); 223 subTitle2.setText(mSubTitle2); 224 subTitle2.setVisibility(View.VISIBLE); 225 } 226 if (!Strings.isNullOrEmpty(mLeftButtonText)) { 227 Button leftButton = rootView.requireViewById(R.id.left_button); 228 leftButton.setText(mLeftButtonText); 229 leftButton.setVisibility(View.VISIBLE); 230 leftButton.setOnClickListener( 231 unused -> { 232 if (mLeftButtonOnClickListener != null) { 233 mLeftButtonOnClickListener.accept(dialog); 234 } 235 }); 236 } 237 if (!Strings.isNullOrEmpty(mRightButtonText)) { 238 Button rightButton = rootView.requireViewById(R.id.right_button); 239 rightButton.setText(mRightButtonText); 240 rightButton.setVisibility(View.VISIBLE); 241 rightButton.setOnClickListener( 242 unused -> { 243 if (mRightButtonOnClickListener != null) { 244 mRightButtonOnClickListener.accept(dialog); 245 } 246 }); 247 } 248 249 return dialog; 250 } 251 } 252 } 253