ExtensionControllerImpl.java revision 1d9632df97bdd4879cff0328a46a8fab6fde441a
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.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}
237