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 @Override 130 public T reload() { 131 notifyChanged(); 132 return get(); 133 } 134 135 private void notifyChanged() { 136 for (int i = 0; i < mProducers.size(); i++) { 137 final T item = mProducers.get(i).get(); 138 if (item != null) { 139 mItem = item; 140 break; 141 } 142 } 143 for (int i = 0; i < mCallbacks.size(); i++) { 144 mCallbacks.get(i).accept(mItem); 145 } 146 } 147 148 public void addDefault(Supplier<T> def) { 149 mProducers.add(new Default(def)); 150 } 151 152 public <P> void addPlugin(String action, Class<P> cls, PluginConverter<T, P> converter) { 153 mProducers.add(new PluginItem(action, cls, converter)); 154 } 155 156 public void addTunerFactory(TunerFactory<T> factory, String[] keys) { 157 mProducers.add(new TunerItem(factory, factory.keys())); 158 } 159 160 private class PluginItem<P extends Plugin> implements Producer<T>, PluginListener<P> { 161 private final PluginConverter<T, P> mConverter; 162 private T mItem; 163 164 public PluginItem(String action, Class<P> cls, PluginConverter<T, P> converter) { 165 mConverter = converter; 166 Dependency.get(PluginManager.class).addPluginListener(action, this, cls); 167 } 168 169 @Override 170 public void onPluginConnected(P plugin, Context pluginContext) { 171 if (mConverter != null) { 172 mItem = mConverter.getInterfaceFromPlugin(plugin); 173 } else { 174 mItem = (T) plugin; 175 } 176 notifyChanged(); 177 } 178 179 @Override 180 public void onPluginDisconnected(P plugin) { 181 mItem = null; 182 notifyChanged(); 183 } 184 185 @Override 186 public T get() { 187 return mItem; 188 } 189 190 @Override 191 public void destroy() { 192 Dependency.get(PluginManager.class).removePluginListener(this); 193 } 194 } 195 196 private class TunerItem<T> implements Producer<T>, Tunable { 197 private final TunerFactory<T> mFactory; 198 private final ArrayMap<String, String> mSettings = new ArrayMap<>(); 199 private T mItem; 200 201 public TunerItem(TunerFactory<T> factory, String... setting) { 202 mFactory = factory; 203 Dependency.get(TunerService.class).addTunable(this, setting); 204 } 205 206 @Override 207 public T get() { 208 return mItem; 209 } 210 211 @Override 212 public void destroy() { 213 Dependency.get(TunerService.class).removeTunable(this); 214 } 215 216 @Override 217 public void onTuningChanged(String key, String newValue) { 218 mSettings.put(key, newValue); 219 mItem = mFactory.create(mSettings); 220 notifyChanged(); 221 } 222 } 223 224 private class Default<T> implements Producer<T> { 225 private final Supplier<T> mSupplier; 226 227 public Default(Supplier<T> supplier) { 228 mSupplier = supplier; 229 } 230 231 @Override 232 public T get() { 233 return mSupplier.get(); 234 } 235 236 @Override 237 public void destroy() { 238 239 } 240 } 241 } 242} 243