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 package com.android.settings.bluetooth;
18 
19 import android.app.Dialog;
20 import android.app.settings.SettingsEnums;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.os.Bundle;
25 import android.text.TextUtils;
26 import android.util.Log;
27 import android.view.View;
28 import android.widget.Button;
29 import android.widget.TextView;
30 
31 import androidx.annotation.NonNull;
32 import androidx.appcompat.app.AlertDialog;
33 
34 import com.android.settings.R;
35 import com.android.settings.core.SubSettingLauncher;
36 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
37 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
38 import com.android.settingslib.bluetooth.LocalBluetoothManager;
39 import com.android.settingslib.media.MediaOutputConstants;
40 
41 /**
42  * This Dialog allowed users to do some actions for broadcast media or find the
43  * nearby broadcast sources.
44  */
45 public class BluetoothBroadcastDialog extends InstrumentedDialogFragment {
46 
47     public static final String KEY_APP_LABEL = "app_label";
48     public static final String KEY_DEVICE_ADDRESS =
49             BluetoothFindBroadcastsFragment.KEY_DEVICE_ADDRESS;
50     public static final String KEY_MEDIA_STREAMING = "media_streaming";
51 
52     private static final String TAG = "BTBroadcastsDialog";
53     private static final CharSequence UNKNOWN_APP_LABEL = "unknown";
54     private Context mContext;
55     private CharSequence mCurrentAppLabel = UNKNOWN_APP_LABEL;
56     private String mDeviceAddress;
57     private boolean mIsMediaStreaming;
58     private LocalBluetoothManager mLocalBluetoothManager;
59     private AlertDialog mAlertDialog;
60 
61     @Override
onCreate(Bundle savedInstanceState)62     public void onCreate(Bundle savedInstanceState) {
63         super.onCreate(savedInstanceState);
64         mContext = getActivity();
65         mCurrentAppLabel = getActivity().getIntent().getCharSequenceExtra(KEY_APP_LABEL);
66         mDeviceAddress = getActivity().getIntent().getStringExtra(KEY_DEVICE_ADDRESS);
67         mIsMediaStreaming = getActivity().getIntent().getBooleanExtra(KEY_MEDIA_STREAMING, false);
68         mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
69         setShowsDialog(true);
70     }
71 
72     @Override
onCreateDialog(Bundle savedInstanceState)73     public Dialog onCreateDialog(Bundle savedInstanceState) {
74         View layout = View.inflate(mContext,
75                 com.android.settingslib.R.layout.broadcast_dialog, null);
76 
77         TextView title = layout.findViewById(com.android.settingslib.R.id.dialog_title);
78         TextView subTitle = layout.findViewById(com.android.settingslib.R.id.dialog_subtitle);
79 
80         Button broadcastBtn = layout.findViewById(com.android.settingslib.R.id.positive_btn);
81         if (isBroadcastSupported() && mIsMediaStreaming) {
82             title.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
83             subTitle.setText(
84                     mContext.getString(R.string.bluetooth_broadcast_dialog_broadcast_message));
85             broadcastBtn.setVisibility(View.VISIBLE);
86             if (TextUtils.isEmpty(mCurrentAppLabel)) {
87                 broadcastBtn.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
88             } else {
89                 broadcastBtn.setText(mContext.getString(
90                     R.string.bluetooth_broadcast_dialog_broadcast_app,
91                     String.valueOf(mCurrentAppLabel)));
92             }
93             broadcastBtn.setOnClickListener((view) -> {
94                 launchMediaOutputBroadcastDialog();
95             });
96         } else {
97             title.setText(mContext.getString(R.string.bluetooth_find_broadcast));
98             subTitle.setText(
99                     mContext.getString(R.string.bluetooth_broadcast_dialog_find_message));
100             broadcastBtn.setVisibility(View.GONE);
101         }
102 
103         Button findBroadcastBtn = layout.findViewById(com.android.settingslib.R.id.negative_btn);
104         findBroadcastBtn.setText(mContext.getString(R.string.bluetooth_find_broadcast));
105         findBroadcastBtn.setOnClickListener((view) -> {
106             launchFindBroadcastsActivity();
107         });
108 
109         Button cancelBtn = layout.findViewById(com.android.settingslib.R.id.neutral_btn);
110         cancelBtn.setOnClickListener((view) -> {
111             dismiss();
112             getActivity().finish();
113         });
114 
115         mAlertDialog = new AlertDialog.Builder(mContext,
116                 com.android.settingslib.widget.theme.R.style.Theme_AlertDialog_SettingsLib)
117             .setView(layout)
118             .create();
119 
120         return mAlertDialog;
121     }
122 
123     @Override
onStart()124     public void onStart() {
125         super.onStart();
126     }
127 
128     @Override
getMetricsCategory()129     public int getMetricsCategory() {
130         return SettingsEnums.DIALOG_LE_AUDIO_BROADCAST;
131     }
132 
133     @Override
onCancel(@onNull DialogInterface dialog)134     public void onCancel(@NonNull DialogInterface dialog) {
135         dismiss();
136         getActivity().finish();
137     }
138 
launchFindBroadcastsActivity()139     private void launchFindBroadcastsActivity() {
140         Bundle bundle = new Bundle();
141         bundle.putString(KEY_DEVICE_ADDRESS, mDeviceAddress);
142 
143         new SubSettingLauncher(mContext)
144                 .setTitleRes(R.string.bluetooth_find_broadcast_title)
145                 .setDestination(BluetoothFindBroadcastsFragment.class.getName())
146                 .setArguments(bundle)
147                 .setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN)
148                 .launch();
149         dismissVolumePanel();
150     }
151 
launchMediaOutputBroadcastDialog()152     private void launchMediaOutputBroadcastDialog() {
153         if (startBroadcast()) {
154             mContext.sendBroadcast(new Intent()
155                     .setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME)
156                     .setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG)
157                     .putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME,
158                             getActivity().getPackageName()));
159             dismissVolumePanel();
160         }
161     }
162 
getLEAudioBroadcastProfile()163     private LocalBluetoothLeBroadcast getLEAudioBroadcastProfile() {
164         if (mLocalBluetoothManager != null && mLocalBluetoothManager.getProfileManager() != null) {
165             LocalBluetoothLeBroadcast bluetoothLeBroadcast =
166                     mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
167             if (bluetoothLeBroadcast != null) {
168                 return bluetoothLeBroadcast;
169             }
170         }
171         Log.d(TAG, "Can not get LE Audio Broadcast Profile");
172         return null;
173     }
174 
startBroadcast()175     private boolean startBroadcast() {
176         LocalBluetoothLeBroadcast btLeBroadcast = getLEAudioBroadcastProfile();
177         if (btLeBroadcast != null) {
178             btLeBroadcast.startBroadcast(String.valueOf(mCurrentAppLabel), null);
179             return true;
180         }
181         Log.d(TAG, "Can not broadcast successfully");
182         return false;
183     }
184 
dismissVolumePanel()185     private void dismissVolumePanel() {
186         // Dismiss volume panel
187         mContext.sendBroadcast(new Intent()
188                 .setPackage(MediaOutputConstants.SETTINGS_PACKAGE_NAME)
189                 .setAction(MediaOutputConstants.ACTION_CLOSE_PANEL));
190     }
191 
isBroadcastSupported()192     boolean isBroadcastSupported() {
193         LocalBluetoothLeBroadcast broadcast =
194                 mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
195         return broadcast != null;
196     }
197 }
198