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.bluetooth.BluetoothLeBroadcastMetadata;
21 import android.util.Log;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.widget.EditText;
25 import android.widget.TextView;
26 
27 import androidx.annotation.Nullable;
28 import androidx.preference.Preference;
29 
30 import com.android.settings.R;
31 import com.android.settingslib.bluetooth.BluetoothUtils;
32 import com.android.settingslib.utils.ThreadUtils;
33 
34 import java.nio.charset.StandardCharsets;
35 
36 class SyncedState extends AudioStreamStateHandler {
37     private static final String TAG = "SyncedState";
38     private static final boolean DEBUG = BluetoothUtils.D;
39     @Nullable private static SyncedState sInstance = null;
40 
SyncedState()41     SyncedState() {}
42 
getInstance()43     static SyncedState getInstance() {
44         if (sInstance == null) {
45             sInstance = new SyncedState();
46         }
47         return sInstance;
48     }
49 
50     @Override
getOnClickListener( AudioStreamsProgressCategoryController controller)51     Preference.OnPreferenceClickListener getOnClickListener(
52             AudioStreamsProgressCategoryController controller) {
53         return p -> addSourceOrShowDialog(p, controller);
54     }
55 
56     @Override
getStateEnum()57     AudioStreamsProgressCategoryController.AudioStreamState getStateEnum() {
58         return AudioStreamsProgressCategoryController.AudioStreamState.SYNCED;
59     }
60 
addSourceOrShowDialog( Preference preference, AudioStreamsProgressCategoryController controller)61     private boolean addSourceOrShowDialog(
62             Preference preference, AudioStreamsProgressCategoryController controller) {
63         var p = (AudioStreamPreference) preference;
64         if (DEBUG) {
65             Log.d(
66                     TAG,
67                     "preferenceClicked(): attempt to join broadcast id : "
68                             + p.getAudioStreamBroadcastId());
69         }
70         var source = p.getAudioStreamMetadata();
71         if (source != null) {
72             if (source.isEncrypted()) {
73                 ThreadUtils.postOnMainThread(() -> launchPasswordDialog(source, p, controller));
74             } else {
75                 controller.handleSourceAddRequest(p, source);
76             }
77         }
78         return true;
79     }
80 
launchPasswordDialog( BluetoothLeBroadcastMetadata source, AudioStreamPreference preference, AudioStreamsProgressCategoryController controller)81     private void launchPasswordDialog(
82             BluetoothLeBroadcastMetadata source,
83             AudioStreamPreference preference,
84             AudioStreamsProgressCategoryController controller) {
85         View layout =
86                 LayoutInflater.from(preference.getContext())
87                         .inflate(R.layout.bluetooth_find_broadcast_password_dialog, null);
88         ((TextView) layout.requireViewById(R.id.broadcast_name_text))
89                 .setText(preference.getTitle());
90         AlertDialog alertDialog =
91                 new AlertDialog.Builder(preference.getContext())
92                         .setTitle(R.string.find_broadcast_password_dialog_title)
93                         .setView(layout)
94                         .setNeutralButton(android.R.string.cancel, null)
95                         .setPositiveButton(
96                                 R.string.bluetooth_connect_access_dialog_positive,
97                                 (dialog, which) -> {
98                                     var code =
99                                             ((EditText)
100                                                             layout.requireViewById(
101                                                                     R.id.broadcast_edit_text))
102                                                     .getText()
103                                                     .toString();
104                                     var metadata =
105                                             new BluetoothLeBroadcastMetadata.Builder(source)
106                                                     .setBroadcastCode(
107                                                             code.getBytes(StandardCharsets.UTF_8))
108                                                     .build();
109                                     controller.handleSourceAddRequest(preference, metadata);
110                                 })
111                         .create();
112         alertDialog.show();
113     }
114 }
115