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