• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.bluetooth.BluetoothLeBroadcastMetadata;
20 import android.bluetooth.BluetoothLeBroadcastReceiveState;
21 import android.content.Context;
22 import android.util.AttributeSet;
23 import android.view.View;
24 
25 import androidx.annotation.Nullable;
26 import androidx.annotation.VisibleForTesting;
27 import androidx.preference.PreferenceViewHolder;
28 
29 import com.android.settings.R;
30 import com.android.settingslib.utils.ThreadUtils;
31 import com.android.settingslib.widget.TwoTargetPreference;
32 
33 /**
34  * Custom preference class for managing audio stream preferences with an optional lock icon. Extends
35  * {@link TwoTargetPreference}.
36  */
37 class AudioStreamPreference extends TwoTargetPreference {
38     private boolean mIsConnected = false;
39     private boolean mIsEncrypted = true;
40     @Nullable private AudioStream mAudioStream;
41 
42     /**
43      * Update preference UI based on connection status
44      *
45      * @param isConnected Is this stream connected
46      */
setIsConnected(boolean isConnected)47     void setIsConnected(boolean isConnected) {
48         if (mIsConnected != isConnected) {
49             mIsConnected = isConnected;
50             notifyChanged();
51         }
52     }
53 
54     @VisibleForTesting
AudioStreamPreference(Context context, @Nullable AttributeSet attrs)55     AudioStreamPreference(Context context, @Nullable AttributeSet attrs) {
56         super(context, attrs);
57         setIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing);
58     }
59 
setAudioStreamState(AudioStreamsProgressCategoryController.AudioStreamState state)60     void setAudioStreamState(AudioStreamsProgressCategoryController.AudioStreamState state) {
61         if (mAudioStream != null) {
62             mAudioStream.setState(state);
63         }
64     }
65 
setAudioStreamMetadata(BluetoothLeBroadcastMetadata metadata)66     void setAudioStreamMetadata(BluetoothLeBroadcastMetadata metadata) {
67         if (mAudioStream != null) {
68             mAudioStream.setMetadata(metadata);
69             // Update title based on the metadata
70             String broadcastName = AudioStreamsHelper.getBroadcastName(metadata);
71             ThreadUtils.postOnMainThread(() -> setTitle(broadcastName));
72         }
73     }
74 
getAudioStreamBroadcastId()75     int getAudioStreamBroadcastId() {
76         return mAudioStream != null ? mAudioStream.getBroadcastId() : -1;
77     }
78 
79     @Nullable
getAudioStreamBroadcastName()80     String getAudioStreamBroadcastName() {
81         return mAudioStream != null ? mAudioStream.getBroadcastName() : null;
82     }
83 
getAudioStreamRssi()84     int getAudioStreamRssi() {
85         return mAudioStream != null ? mAudioStream.getRssi() : -1;
86     }
87 
88     @Nullable
getAudioStreamMetadata()89     BluetoothLeBroadcastMetadata getAudioStreamMetadata() {
90         return mAudioStream != null ? mAudioStream.getMetadata() : null;
91     }
92 
getAudioStreamState()93     AudioStreamsProgressCategoryController.AudioStreamState getAudioStreamState() {
94         return mAudioStream != null
95                 ? mAudioStream.getState()
96                 : AudioStreamsProgressCategoryController.AudioStreamState.UNKNOWN;
97     }
98 
getSourceOriginForLogging()99     SourceOriginForLogging getSourceOriginForLogging() {
100         return mAudioStream != null
101                 ? mAudioStream.getSourceOriginForLogging()
102                 : SourceOriginForLogging.UNKNOWN;
103     }
104 
105     @Override
shouldHideSecondTarget()106     protected boolean shouldHideSecondTarget() {
107         return mIsConnected || !mIsEncrypted;
108     }
109 
110     @Override
getSecondTargetResId()111     protected int getSecondTargetResId() {
112         return R.layout.preference_widget_lock;
113     }
114 
115     @Override
onBindViewHolder(PreferenceViewHolder holder)116     public void onBindViewHolder(PreferenceViewHolder holder) {
117         super.onBindViewHolder(holder);
118         View divider =
119                 holder.findViewById(
120                         com.android.settingslib.widget.preference.twotarget.R.id
121                                 .two_target_divider);
122         if (divider != null) {
123             divider.setVisibility(View.GONE);
124         }
125     }
126 
fromMetadata( Context context, BluetoothLeBroadcastMetadata source, SourceOriginForLogging sourceOriginForLogging)127     static AudioStreamPreference fromMetadata(
128             Context context,
129             BluetoothLeBroadcastMetadata source,
130             SourceOriginForLogging sourceOriginForLogging) {
131         AudioStreamPreference preference = new AudioStreamPreference(context, /* attrs= */ null);
132         preference.setIsEncrypted(source.isEncrypted());
133         preference.setTitle(AudioStreamsHelper.getBroadcastName(source));
134         preference.setAudioStream(new AudioStream(source, sourceOriginForLogging));
135         return preference;
136     }
137 
fromReceiveState( Context context, BluetoothLeBroadcastReceiveState receiveState)138     static AudioStreamPreference fromReceiveState(
139             Context context, BluetoothLeBroadcastReceiveState receiveState) {
140         AudioStreamPreference preference = new AudioStreamPreference(context, /* attrs= */ null);
141         preference.setTitle(AudioStreamsHelper.getBroadcastName(receiveState));
142         preference.setAudioStream(new AudioStream(receiveState));
143         return preference;
144     }
145 
setAudioStream(AudioStream audioStream)146     private void setAudioStream(AudioStream audioStream) {
147         mAudioStream = audioStream;
148     }
149 
setIsEncrypted(boolean isEncrypted)150     private void setIsEncrypted(boolean isEncrypted) {
151         mIsEncrypted = isEncrypted;
152     }
153 
154     private static final class AudioStream {
155         private static final int UNAVAILABLE = -1;
156         @Nullable private BluetoothLeBroadcastMetadata mMetadata;
157         @Nullable private BluetoothLeBroadcastReceiveState mReceiveState;
158         private SourceOriginForLogging mSourceOriginForLogging = SourceOriginForLogging.UNKNOWN;
159         private AudioStreamsProgressCategoryController.AudioStreamState mState =
160                 AudioStreamsProgressCategoryController.AudioStreamState.UNKNOWN;
161 
AudioStream( BluetoothLeBroadcastMetadata metadata, SourceOriginForLogging sourceOriginForLogging)162         private AudioStream(
163                 BluetoothLeBroadcastMetadata metadata,
164                 SourceOriginForLogging sourceOriginForLogging) {
165             mMetadata = metadata;
166             mSourceOriginForLogging = sourceOriginForLogging;
167         }
168 
AudioStream(BluetoothLeBroadcastReceiveState receiveState)169         private AudioStream(BluetoothLeBroadcastReceiveState receiveState) {
170             mReceiveState = receiveState;
171         }
172 
getBroadcastId()173         private int getBroadcastId() {
174             return mMetadata != null
175                     ? mMetadata.getBroadcastId()
176                     : mReceiveState != null ? mReceiveState.getBroadcastId() : UNAVAILABLE;
177         }
178 
getBroadcastName()179         private @Nullable String getBroadcastName() {
180             return mMetadata != null
181                     ? AudioStreamsHelper.getBroadcastName(mMetadata)
182                     : mReceiveState != null
183                             ? AudioStreamsHelper.getBroadcastName(mReceiveState)
184                             : null;
185         }
186 
getRssi()187         private int getRssi() {
188             return mMetadata != null ? mMetadata.getRssi() : Integer.MAX_VALUE;
189         }
190 
getState()191         private AudioStreamsProgressCategoryController.AudioStreamState getState() {
192             return mState;
193         }
194 
getSourceOriginForLogging()195         private SourceOriginForLogging getSourceOriginForLogging() {
196             return mSourceOriginForLogging;
197         }
198 
199         @Nullable
getMetadata()200         private BluetoothLeBroadcastMetadata getMetadata() {
201             return mMetadata;
202         }
203 
setState(AudioStreamsProgressCategoryController.AudioStreamState state)204         private void setState(AudioStreamsProgressCategoryController.AudioStreamState state) {
205             mState = state;
206         }
207 
setMetadata(BluetoothLeBroadcastMetadata metadata)208         private void setMetadata(BluetoothLeBroadcastMetadata metadata) {
209             mMetadata = metadata;
210         }
211     }
212 }
213