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
15package com.android.systemui.plugins;
16
17import android.annotation.IntegerRes;
18import android.content.ComponentName;
19import android.media.AudioManager;
20import android.media.AudioSystem;
21import android.os.Handler;
22import android.os.VibrationEffect;
23import android.util.SparseArray;
24
25import com.android.systemui.plugins.VolumeDialogController.Callbacks;
26import com.android.systemui.plugins.VolumeDialogController.State;
27import com.android.systemui.plugins.VolumeDialogController.StreamState;
28import com.android.systemui.plugins.annotations.DependsOn;
29import com.android.systemui.plugins.annotations.ProvidesInterface;
30
31/**
32 * Manages the VolumeDialog.
33 *
34 * Accessible through {@link PluginDependency}
35 */
36@ProvidesInterface(version = VolumeDialogController.VERSION)
37@DependsOn(target = StreamState.class)
38@DependsOn(target = State.class)
39@DependsOn(target = Callbacks.class)
40public interface VolumeDialogController {
41    int VERSION = 1;
42
43    void setActiveStream(int stream);
44    void setStreamVolume(int stream, int userLevel);
45    void setRingerMode(int ringerModeNormal, boolean external);
46
47    boolean hasVibrator();
48    void vibrate(VibrationEffect effect);
49    void scheduleTouchFeedback();
50
51    AudioManager getAudioManager();
52
53    void notifyVisible(boolean visible);
54
55    void addCallback(Callbacks callbacks, Handler handler);
56    void removeCallback(Callbacks callbacks);
57
58    void userActivity();
59    void getState();
60
61    @ProvidesInterface(version = StreamState.VERSION)
62    public static final class StreamState {
63        public static final int VERSION = 1;
64
65        public boolean dynamic;
66        public int level;
67        public int levelMin;
68        public int levelMax;
69        public boolean muted;
70        public boolean muteSupported;
71        public @IntegerRes int name;
72        public String remoteLabel;
73        public boolean routedToBluetooth;
74
75        public StreamState copy() {
76            final StreamState rt = new StreamState();
77            rt.dynamic = dynamic;
78            rt.level = level;
79            rt.levelMin = levelMin;
80            rt.levelMax = levelMax;
81            rt.muted = muted;
82            rt.muteSupported = muteSupported;
83            rt.name = name;
84            rt.remoteLabel = remoteLabel;
85            rt.routedToBluetooth = routedToBluetooth;
86            return rt;
87        }
88    }
89
90    @ProvidesInterface(version = State.VERSION)
91    public static final class State {
92        public static final int VERSION = 1;
93
94        public static int NO_ACTIVE_STREAM = -1;
95
96        public final SparseArray<StreamState> states = new SparseArray<>();
97
98        public int ringerModeInternal;
99        public int ringerModeExternal;
100        public int zenMode;
101        public ComponentName effectsSuppressor;
102        public String effectsSuppressorName;
103        public int activeStream = NO_ACTIVE_STREAM;
104        public boolean disallowAlarms;
105        public boolean disallowMedia;
106        public boolean disallowSystem;
107        public boolean disallowRinger;
108
109        public State copy() {
110            final State rt = new State();
111            for (int i = 0; i < states.size(); i++) {
112                rt.states.put(states.keyAt(i), states.valueAt(i).copy());
113            }
114            rt.ringerModeExternal = ringerModeExternal;
115            rt.ringerModeInternal = ringerModeInternal;
116            rt.zenMode = zenMode;
117            if (effectsSuppressor != null) {
118                rt.effectsSuppressor = effectsSuppressor.clone();
119            }
120            rt.effectsSuppressorName = effectsSuppressorName;
121            rt.activeStream = activeStream;
122            rt.disallowAlarms = disallowAlarms;
123            rt.disallowMedia = disallowMedia;
124            rt.disallowSystem = disallowSystem;
125            rt.disallowRinger = disallowRinger;
126            return rt;
127        }
128
129        @Override
130        public String toString() {
131            return toString(0);
132        }
133
134        public String toString(int indent) {
135            final StringBuilder sb = new StringBuilder("{");
136            if (indent > 0) sep(sb, indent);
137            for (int i = 0; i < states.size(); i++) {
138                if (i > 0) {
139                    sep(sb, indent);
140                }
141                final int stream = states.keyAt(i);
142                final StreamState ss = states.valueAt(i);
143                sb.append(AudioSystem.streamToString(stream)).append(":").append(ss.level)
144                        .append('[').append(ss.levelMin).append("..").append(ss.levelMax)
145                        .append(']');
146                if (ss.muted) sb.append(" [MUTED]");
147                if (ss.dynamic) sb.append(" [DYNAMIC]");
148            }
149            sep(sb, indent); sb.append("ringerModeExternal:").append(ringerModeExternal);
150            sep(sb, indent); sb.append("ringerModeInternal:").append(ringerModeInternal);
151            sep(sb, indent); sb.append("zenMode:").append(zenMode);
152            sep(sb, indent); sb.append("effectsSuppressor:").append(effectsSuppressor);
153            sep(sb, indent); sb.append("effectsSuppressorName:").append(effectsSuppressorName);
154            sep(sb, indent); sb.append("activeStream:").append(activeStream);
155            sep(sb, indent); sb.append("disallowAlarms:").append(disallowAlarms);
156            sep(sb, indent); sb.append("disallowMedia:").append(disallowMedia);
157            sep(sb, indent); sb.append("disallowSystem:").append(disallowSystem);
158            sep(sb, indent); sb.append("disallowRinger:").append(disallowRinger);
159            if (indent > 0) sep(sb, indent);
160            return sb.append('}').toString();
161        }
162
163        private static void sep(StringBuilder sb, int indent) {
164            if (indent > 0) {
165                sb.append('\n');
166                for (int i = 0; i < indent; i++) {
167                    sb.append(' ');
168                }
169            } else {
170                sb.append(',');
171            }
172        }
173    }
174
175    @ProvidesInterface(version = Callbacks.VERSION)
176    public interface Callbacks {
177        int VERSION = 1;
178
179        void onShowRequested(int reason);
180        void onDismissRequested(int reason);
181        void onStateChanged(State state);
182        void onLayoutDirectionChanged(int layoutDirection);
183        void onConfigurationChanged();
184        void onShowVibrateHint();
185        void onShowSilentHint();
186        void onScreenOff();
187        void onShowSafetyWarning(int flags);
188        void onAccessibilityModeChanged(Boolean showA11yStream);
189    }
190}
191