• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
20 
21 import android.os.Handler;
22 import android.os.Looper;
23 import android.text.SpannableString;
24 import android.text.style.ForegroundColorSpan;
25 import android.util.Log;
26 
27 import androidx.annotation.Nullable;
28 import androidx.annotation.StringRes;
29 import androidx.annotation.VisibleForTesting;
30 import androidx.preference.Preference;
31 
32 import com.android.settings.overlay.FeatureFactory;
33 import com.android.settingslib.Utils;
34 import com.android.settingslib.bluetooth.BluetoothUtils;
35 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
36 import com.android.settingslib.utils.ThreadUtils;
37 
38 class AudioStreamStateHandler {
39     private static final String TAG = "AudioStreamStateHandler";
40     private static final boolean DEBUG = BluetoothUtils.D;
41     @VisibleForTesting static final int EMPTY_STRING_RES = 0;
42 
43     final Handler mHandler = new Handler(Looper.getMainLooper());
44     final MetricsFeatureProvider mMetricsFeatureProvider =
45             FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
46     AudioStreamsRepository mAudioStreamsRepository = AudioStreamsRepository.getInstance();
47 
AudioStreamStateHandler()48     AudioStreamStateHandler() {}
49 
handleStateChange( AudioStreamPreference preference, AudioStreamsProgressCategoryController controller, AudioStreamsHelper helper)50     void handleStateChange(
51             AudioStreamPreference preference,
52             AudioStreamsProgressCategoryController controller,
53             AudioStreamsHelper helper) {
54         var newState = getStateEnum();
55         if (preference.getAudioStreamState() == newState) {
56             return;
57         }
58         if (DEBUG) {
59             Log.d(
60                     TAG,
61                     "moveToState() : moving preference : ["
62                             + preference.getAudioStreamBroadcastId()
63                             + ", "
64                             + preference.getAudioStreamBroadcastName()
65                             + "] from state : "
66                             + preference.getAudioStreamState()
67                             + " to state : "
68                             + newState);
69         }
70         preference.setAudioStreamState(newState);
71 
72         performAction(preference, controller, helper);
73 
74         // Update UI
75         ThreadUtils.postOnMainThread(
76                 () -> {
77                     String summary =
78                             getSummary() != EMPTY_STRING_RES
79                                     ? preference.getContext().getString(getSummary())
80                                     : "";
81                     if (newState
82                             == AudioStreamsProgressCategoryController.AudioStreamState
83                                     .ADD_SOURCE_BAD_CODE) {
84                         SpannableString summarySpan = new SpannableString(summary);
85                         int colorError = Utils.getColorErrorDefaultColor(preference.getContext());
86                         summarySpan.setSpan(
87                                 new ForegroundColorSpan(colorError),
88                                 0,
89                                 summary.length(),
90                                 SPAN_EXCLUSIVE_INCLUSIVE);
91                         preference.setSummary(summarySpan);
92                     } else {
93                         preference.setSummary(summary);
94                     }
95                     preference.setIsConnected(
96                             newState
97                                             == AudioStreamsProgressCategoryController
98                                                     .AudioStreamState.SOURCE_ADDED
99                                     || (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
100                                                     preference.getContext())
101                                             && newState
102                                                     == AudioStreamsProgressCategoryController
103                                                             .AudioStreamState.SOURCE_PRESENT));
104                     preference.setOnPreferenceClickListener(getOnClickListener(controller));
105                 });
106     }
107 
108     /**
109      * Perform action related to the audio stream state (e.g, addSource) This method is intended to
110      * be optionally overridden by subclasses to provide custom behavior based on the audio stream
111      * state change.
112      */
performAction( AudioStreamPreference preference, AudioStreamsProgressCategoryController controller, AudioStreamsHelper helper)113     void performAction(
114             AudioStreamPreference preference,
115             AudioStreamsProgressCategoryController controller,
116             AudioStreamsHelper helper) {}
117 
118     /**
119      * The preference summary for the audio stream state (e.g, Scanning...) This method is intended
120      * to be optionally overridden.
121      */
122     @StringRes
getSummary()123     int getSummary() {
124         return EMPTY_STRING_RES;
125     }
126 
127     /**
128      * The preference on click event for the audio stream state (e.g, open up a dialog) This method
129      * is intended to be optionally overridden.
130      */
131     @Nullable
getOnClickListener( AudioStreamsProgressCategoryController controller)132     Preference.OnPreferenceClickListener getOnClickListener(
133             AudioStreamsProgressCategoryController controller) {
134         return null;
135     }
136 
137     /** Subclasses should always override. */
getStateEnum()138     AudioStreamsProgressCategoryController.AudioStreamState getStateEnum() {
139         return AudioStreamsProgressCategoryController.AudioStreamState.UNKNOWN;
140     }
141 
142     @VisibleForTesting
setAudioStreamsRepositoryForTesting(AudioStreamsRepository repository)143     void setAudioStreamsRepositoryForTesting(AudioStreamsRepository repository) {
144         mAudioStreamsRepository = repository;
145     }
146 }
147