blob: fefbaa31af2aecad3a902064230d1d2ce3981fd8 [file] [log] [blame]
Jason Monk1d9632d2017-02-09 13:20:04 -08001/*
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.statusbar.policy;
16
17import com.android.systemui.Dependency;
18import com.android.systemui.plugins.Plugin;
19import com.android.systemui.plugins.PluginListener;
20import com.android.systemui.plugins.PluginManager;
21import com.android.systemui.tuner.TunerService;
22import com.android.systemui.tuner.TunerService.Tunable;
23
24import android.content.Context;
25import android.util.ArrayMap;
26
27import java.util.ArrayList;
28import java.util.Collections;
29import java.util.function.Consumer;
30import java.util.function.Supplier;
31
32public class ExtensionControllerImpl implements ExtensionController {
33
34 @Override
35 public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
36 return new ExtensionBuilder<>();
37 }
38
39 private interface Producer<T> {
40 T get();
41 void destroy();
42 }
43
44 private class ExtensionBuilder<T> implements ExtensionController.ExtensionBuilder<T> {
45
46 private ExtensionImpl<T> mExtension = new ExtensionImpl<>();
47
48 @Override
49 public ExtensionController.ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
50 mExtension.addTunerFactory(factory, factory.keys());
51 return this;
52 }
53
54 @Override
55 public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls) {
56 return withPlugin(cls, PluginManager.getAction(cls));
57 }
58
59 @Override
60 public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
61 String action) {
62 return withPlugin(cls, action, null);
63 }
64
65 @Override
66 public <P> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
67 String action, PluginConverter<T, P> converter) {
68 mExtension.addPlugin(action, cls, converter);
69 return this;
70 }
71
72 @Override
73 public ExtensionController.ExtensionBuilder<T> withDefault(Supplier<T> def) {
74 mExtension.addDefault(def);
75 return this;
76 }
77
78 @Override
79 public ExtensionController.ExtensionBuilder<T> withCallback(
80 Consumer<T> callback) {
81 mExtension.mCallbacks.add(callback);
82 return this;
83 }
84
85 @Override
86 public ExtensionController.Extension build() {
87 // Manually sort, plugins first, tuners second, defaults last.
88 Collections.sort(mExtension.mProducers, (o1, o2) -> {
89 if (o1 instanceof ExtensionImpl.PluginItem) {
90 if (o2 instanceof ExtensionImpl.PluginItem) {
91 return 0;
92 } else {
93 return -1;
94 }
95 }
96 if (o1 instanceof ExtensionImpl.TunerItem) {
97 if (o2 instanceof ExtensionImpl.PluginItem) {
98 return 1;
99 } else if (o2 instanceof ExtensionImpl.TunerItem) {
100 return 0;
101 } else {
102 return -1;
103 }
104 }
105 return 0;
106 });
107 mExtension.notifyChanged();
108 return mExtension;
109 }
110 }
111
112 private class ExtensionImpl<T> implements ExtensionController.Extension<T> {
113 private final ArrayList<Producer<T>> mProducers = new ArrayList<>();
114 private final ArrayList<Consumer<T>> mCallbacks = new ArrayList<>();
115 private T mItem;
116
117 @Override
118 public T get() {
119 return mItem;
120 }
121
122 @Override
123 public void destroy() {
124 for (int i = 0; i < mProducers.size(); i++) {
125 mProducers.get(i).destroy();
126 }
127 }
128
129 private void notifyChanged() {
130 for (int i = 0; i < mProducers.size(); i++) {
131 final T item = mProducers.get(i).get();
132 if (item != null) {
133 mItem = item;
134 break;
135 }
136 }
137 for (int i = 0; i < mCallbacks.size(); i++) {
138 mCallbacks.get(i).accept(mItem);
139 }
140 }
141
142 public void addDefault(Supplier<T> def) {
143 mProducers.add(new Default(def));
144 }
145
146 public <P> void addPlugin(String action, Class<P> cls, PluginConverter<T, P> converter) {
147 mProducers.add(new PluginItem(action, cls, converter));
148 }
149
150 public void addTunerFactory(TunerFactory<T> factory, String[] keys) {
151 mProducers.add(new TunerItem(factory, factory.keys()));
152 }
153
154 private class PluginItem<P extends Plugin> implements Producer<T>, PluginListener<P> {
155 private final PluginConverter<T, P> mConverter;
156 private T mItem;
157
158 public PluginItem(String action, Class<P> cls, PluginConverter<T, P> converter) {
159 mConverter = converter;
160 Dependency.get(PluginManager.class).addPluginListener(action, this, cls);
161 }
162
163 @Override
164 public void onPluginConnected(P plugin, Context pluginContext) {
165 if (mConverter != null) {
166 mItem = mConverter.getInterfaceFromPlugin(plugin);
167 } else {
168 mItem = (T) plugin;
169 }
170 notifyChanged();
171 }
172
173 @Override
174 public void onPluginDisconnected(P plugin) {
175 mItem = null;
176 notifyChanged();
177 }
178
179 @Override
180 public T get() {
181 return mItem;
182 }
183
184 @Override
185 public void destroy() {
186 Dependency.get(PluginManager.class).removePluginListener(this);
187 }
188 }
189
190 private class TunerItem<T> implements Producer<T>, Tunable {
191 private final TunerFactory<T> mFactory;
192 private final ArrayMap<String, String> mSettings = new ArrayMap<>();
193 private T mItem;
194
195 public TunerItem(TunerFactory<T> factory, String... setting) {
196 mFactory = factory;
197 Dependency.get(TunerService.class).addTunable(this, setting);
198 }
199
200 @Override
201 public T get() {
202 return mItem;
203 }
204
205 @Override
206 public void destroy() {
207 Dependency.get(TunerService.class).removeTunable(this);
208 }
209
210 @Override
211 public void onTuningChanged(String key, String newValue) {
212 mSettings.put(key, newValue);
213 mItem = mFactory.create(mSettings);
214 notifyChanged();
215 }
216 }
217
218 private class Default<T> implements Producer<T> {
219 private final Supplier<T> mSupplier;
220
221 public Default(Supplier<T> supplier) {
222 mSupplier = supplier;
223 }
224
225 @Override
226 public T get() {
227 return mSupplier.get();
228 }
229
230 @Override
231 public void destroy() {
232
233 }
234 }
235 }
236}