1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.plugins;
16 
17 import android.content.ComponentName;
18 import android.media.AudioManager;
19 import android.media.AudioSystem;
20 import android.os.Handler;
21 import android.os.VibrationEffect;
22 import android.util.SparseArray;
23 
24 import androidx.annotation.StringRes;
25 
26 import com.android.systemui.plugins.VolumeDialogController.Callbacks;
27 import com.android.systemui.plugins.VolumeDialogController.State;
28 import com.android.systemui.plugins.VolumeDialogController.StreamState;
29 import com.android.systemui.plugins.annotations.DependsOn;
30 import com.android.systemui.plugins.annotations.ProvidesInterface;
31 
32 /**
33  * Manages the VolumeDialog.
34  *
35  * Accessible through {@link PluginDependency}
36  */
37 @ProvidesInterface(version = VolumeDialogController.VERSION)
38 @DependsOn(target = StreamState.class)
39 @DependsOn(target = State.class)
40 @DependsOn(target = Callbacks.class)
41 public interface VolumeDialogController {
42     int VERSION = 1;
43 
setActiveStream(int stream)44     void setActiveStream(int stream);
setStreamVolume(int stream, int userLevel)45     void setStreamVolume(int stream, int userLevel);
setRingerMode(int ringerModeNormal, boolean external)46     void setRingerMode(int ringerModeNormal, boolean external);
47 
hasVibrator()48     boolean hasVibrator();
vibrate(VibrationEffect effect)49     void vibrate(VibrationEffect effect);
scheduleTouchFeedback()50     void scheduleTouchFeedback();
51 
getAudioManager()52     AudioManager getAudioManager();
53 
notifyVisible(boolean visible)54     void notifyVisible(boolean visible);
55 
addCallback(Callbacks callbacks, Handler handler)56     void addCallback(Callbacks callbacks, Handler handler);
removeCallback(Callbacks callbacks)57     void removeCallback(Callbacks callbacks);
58 
userActivity()59     void userActivity();
getState()60     void getState();
61 
62     /**
63      * Get Captions enabled state
64      *
65      * @param checkForSwitchState set true when we'd like to switch captions enabled state after
66      *                            getting the latest captions state.
67      */
getCaptionsEnabledState(boolean checkForSwitchState)68     void getCaptionsEnabledState(boolean checkForSwitchState);
69 
70     /**
71      * Set Captions enabled state
72      *
73      * @param enabled the captions enabled state we'd like to update.
74      */
setCaptionsEnabledState(boolean enabled)75     void setCaptionsEnabledState(boolean enabled);
76 
77     /**
78      * Get Captions component state
79      *
80      * @param fromTooltip if it's triggered from tooltip.
81      */
getCaptionsComponentState(boolean fromTooltip)82     void getCaptionsComponentState(boolean fromTooltip);
83 
84     @ProvidesInterface(version = StreamState.VERSION)
85     public static final class StreamState {
86         public static final int VERSION = 1;
87 
88         public boolean dynamic;
89         public int level;
90         public int levelMin;
91         public int levelMax;
92         public boolean muted;
93         public boolean muteSupported;
94         public @StringRes int name;
95         public String remoteLabel;
96         public boolean routedToBluetooth;
97 
copy()98         public StreamState copy() {
99             final StreamState rt = new StreamState();
100             rt.dynamic = dynamic;
101             rt.level = level;
102             rt.levelMin = levelMin;
103             rt.levelMax = levelMax;
104             rt.muted = muted;
105             rt.muteSupported = muteSupported;
106             rt.name = name;
107             rt.remoteLabel = remoteLabel;
108             rt.routedToBluetooth = routedToBluetooth;
109             return rt;
110         }
111     }
112 
113     @ProvidesInterface(version = State.VERSION)
114     public static final class State {
115         public static final int VERSION = 1;
116 
117         public static int NO_ACTIVE_STREAM = -1;
118 
119         public final SparseArray<StreamState> states = new SparseArray<>();
120 
121         public int ringerModeInternal;
122         public int ringerModeExternal;
123         public int zenMode;
124         public ComponentName effectsSuppressor;
125         public String effectsSuppressorName;
126         public int activeStream = NO_ACTIVE_STREAM;
127         public boolean disallowAlarms;
128         public boolean disallowMedia;
129         public boolean disallowSystem;
130         public boolean disallowRinger;
131 
copy()132         public State copy() {
133             final State rt = new State();
134             for (int i = 0; i < states.size(); i++) {
135                 rt.states.put(states.keyAt(i), states.valueAt(i).copy());
136             }
137             rt.ringerModeExternal = ringerModeExternal;
138             rt.ringerModeInternal = ringerModeInternal;
139             rt.zenMode = zenMode;
140             if (effectsSuppressor != null) {
141                 rt.effectsSuppressor = effectsSuppressor.clone();
142             }
143             rt.effectsSuppressorName = effectsSuppressorName;
144             rt.activeStream = activeStream;
145             rt.disallowAlarms = disallowAlarms;
146             rt.disallowMedia = disallowMedia;
147             rt.disallowSystem = disallowSystem;
148             rt.disallowRinger = disallowRinger;
149             return rt;
150         }
151 
152         @Override
toString()153         public String toString() {
154             return toString(0);
155         }
156 
toString(int indent)157         public String toString(int indent) {
158             final StringBuilder sb = new StringBuilder("{");
159             if (indent > 0) sep(sb, indent);
160             for (int i = 0; i < states.size(); i++) {
161                 if (i > 0) {
162                     sep(sb, indent);
163                 }
164                 final int stream = states.keyAt(i);
165                 final StreamState ss = states.valueAt(i);
166                 sb.append(AudioSystem.streamToString(stream)).append(":").append(ss.level)
167                         .append('[').append(ss.levelMin).append("..").append(ss.levelMax)
168                         .append(']');
169                 if (ss.muted) sb.append(" [MUTED]");
170                 if (ss.dynamic) sb.append(" [DYNAMIC]");
171             }
172             sep(sb, indent); sb.append("ringerModeExternal:").append(ringerModeExternal);
173             sep(sb, indent); sb.append("ringerModeInternal:").append(ringerModeInternal);
174             sep(sb, indent); sb.append("zenMode:").append(zenMode);
175             sep(sb, indent); sb.append("effectsSuppressor:").append(effectsSuppressor);
176             sep(sb, indent); sb.append("effectsSuppressorName:").append(effectsSuppressorName);
177             sep(sb, indent); sb.append("activeStream:").append(activeStream);
178             sep(sb, indent); sb.append("disallowAlarms:").append(disallowAlarms);
179             sep(sb, indent); sb.append("disallowMedia:").append(disallowMedia);
180             sep(sb, indent); sb.append("disallowSystem:").append(disallowSystem);
181             sep(sb, indent); sb.append("disallowRinger:").append(disallowRinger);
182             if (indent > 0) sep(sb, indent);
183             return sb.append('}').toString();
184         }
185 
sep(StringBuilder sb, int indent)186         private static void sep(StringBuilder sb, int indent) {
187             if (indent > 0) {
188                 sb.append('\n');
189                 for (int i = 0; i < indent; i++) {
190                     sb.append(' ');
191                 }
192             } else {
193                 sb.append(',');
194             }
195         }
196     }
197 
198     @ProvidesInterface(version = Callbacks.VERSION)
199     public interface Callbacks {
200         int VERSION = 2;
201 
202         // requires version 1
onShowRequested(int reason, boolean keyguardLocked, int lockTaskModeState)203         void onShowRequested(int reason, boolean keyguardLocked, int lockTaskModeState);
onDismissRequested(int reason)204         void onDismissRequested(int reason);
onStateChanged(State state)205         void onStateChanged(State state);
onLayoutDirectionChanged(int layoutDirection)206         void onLayoutDirectionChanged(int layoutDirection);
onConfigurationChanged()207         void onConfigurationChanged();
onShowVibrateHint()208         void onShowVibrateHint();
onShowSilentHint()209         void onShowSilentHint();
onScreenOff()210         void onScreenOff();
onShowSafetyWarning(int flags)211         void onShowSafetyWarning(int flags);
onAccessibilityModeChanged(Boolean showA11yStream)212         void onAccessibilityModeChanged(Boolean showA11yStream);
213 
214         /**
215          * Callback function for captions component state changed event
216          *
217          * @param isComponentEnabled the lateset captions component state.
218          * @param fromTooltip if it's triggered from tooltip.
219          */
onCaptionComponentStateChanged(Boolean isComponentEnabled, Boolean fromTooltip)220         void onCaptionComponentStateChanged(Boolean isComponentEnabled, Boolean fromTooltip);
221 
222         /**
223          * Callback function for captions enabled state changed event
224          *
225          * @param isEnabled the lateset captions enabled state.
226          * @param checkBeforeSwitch intend to switch captions enabled state after the callback.
227          */
onCaptionEnabledStateChanged(Boolean isEnabled, Boolean checkBeforeSwitch)228         void onCaptionEnabledStateChanged(Boolean isEnabled, Boolean checkBeforeSwitch);
229         // requires version 2
onShowCsdWarning(@udioManager.CsdWarning int csdWarning, int durationMs)230         void onShowCsdWarning(@AudioManager.CsdWarning int csdWarning, int durationMs);
231 
232         /**
233          * Callback function for when the volume changed due to a physical key press.
234          */
onVolumeChangedFromKey()235         void onVolumeChangedFromKey();
236     }
237 }
238