Loading packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt +101 −54 Original line number Diff line number Diff line Loading @@ -68,11 +68,11 @@ private val KNOWN_PLUGINS = private fun <TKey, TVal> ConcurrentHashMap<TKey, TVal>.concurrentGetOrPut( key: TKey, value: TVal, onNew: () -> Unit onNew: (TVal) -> Unit ): TVal { val result = this.putIfAbsent(key, value) if (result == null) { onNew() onNew(value) } return result ?: value } Loading Loading @@ -148,6 +148,8 @@ open class ClockRegistry( override fun onPluginAttached( manager: PluginLifecycleManager<ClockProviderPlugin> ): Boolean { manager.isDebug = true if (keepAllLoaded) { // Always load new plugins if requested return true Loading Loading @@ -177,15 +179,22 @@ open class ClockRegistry( val info = availableClocks.concurrentGetOrPut(id, ClockInfo(metadata, null, manager)) { isClockListChanged = true onConnected(id) onConnected(it) } if (manager != info.manager) { logger.tryLog( TAG, LogLevel.ERROR, { str1 = id }, { "Clock Id conflict on known attach: $str1 is double registered" } { str1 = id str2 = info.manager.toString() str3 = manager.toString() }, { "Clock Id conflict on attach: " + "$str1 is double registered by $str2 and $str3" } ) continue } Loading Loading @@ -217,22 +226,29 @@ open class ClockRegistry( val info = availableClocks.concurrentGetOrPut(id, ClockInfo(clock, plugin, manager)) { isClockListChanged = true onConnected(id) onConnected(it) } if (manager != info.manager) { logger.tryLog( TAG, LogLevel.ERROR, { str1 = id }, { "Clock Id conflict on load: $str1 is double registered" } { str1 = id str2 = info.manager.toString() str3 = manager.toString() }, { "Clock Id conflict on load: " + "$str1 is double registered by $str2 and $str3" } ) manager.unloadPlugin() continue } info.provider = plugin onLoaded(id) onLoaded(info) } if (isClockListChanged) { Loading @@ -252,26 +268,33 @@ open class ClockRegistry( logger.tryLog( TAG, LogLevel.ERROR, { str1 = id }, { "Clock Id conflict on unload: $str1 is double registered" } { str1 = id str2 = info?.manager.toString() str3 = manager.toString() }, { "Clock Id conflict on unload: " + "$str1 is double registered by $str2 and $str3" } ) continue } info.provider = null onUnloaded(id) onUnloaded(info) } verifyLoadedProviders() } override fun onPluginDetached(manager: PluginLifecycleManager<ClockProviderPlugin>) { val removed = mutableListOf<ClockId>() val removed = mutableListOf<ClockInfo>() availableClocks.entries.removeAll { if (it.value.manager != manager) { return@removeAll false } removed.add(it.key) removed.add(it.value) return@removeAll true } Loading Loading @@ -493,6 +516,12 @@ open class ClockRegistry( scope.launch(bgDispatcher) { if (keepAllLoaded) { logger.tryLog( TAG, LogLevel.INFO, {}, { "verifyLoadedProviders: keepAllLoaded=true" } ) // Enforce that all plugins are loaded if requested for ((_, info) in availableClocks) { info.manager?.loadPlugin() Loading @@ -503,6 +532,12 @@ open class ClockRegistry( val currentClock = availableClocks[currentClockId] if (currentClock == null) { logger.tryLog( TAG, LogLevel.INFO, {}, { "verifyLoadedProviders: currentClock=null" } ) // Current Clock missing, load no plugins and use default for ((_, info) in availableClocks) { info.manager?.unloadPlugin() Loading @@ -511,12 +546,13 @@ open class ClockRegistry( return@launch } logger.tryLog(TAG, LogLevel.INFO, {}, { "verifyLoadedProviders: load currentClock" }) val currentManager = currentClock.manager currentManager?.loadPlugin() for ((_, info) in availableClocks) { val manager = info.manager if (manager != null && manager.isLoaded && currentManager != manager) { if (manager != null && currentManager != manager) { manager.unloadPlugin() } } Loading @@ -524,58 +560,69 @@ open class ClockRegistry( } } private fun onConnected(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Connected $str1" }) if (currentClockId == clockId) { private fun onConnected(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.INFO, { str1 = clockId }, { "Current clock ($str1) was connected" } if (isCurrent) LogLevel.INFO else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Connected $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) } } private fun onLoaded(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Loaded $str1" }) if (currentClockId == clockId) { private fun onLoaded(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.INFO, { str1 = clockId }, { "Current clock ($str1) was loaded" } if (isCurrent) LogLevel.INFO else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Loaded $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) if (isCurrent) { triggerOnCurrentClockChanged() } } private fun onUnloaded(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Unloaded $str1" }) if (currentClockId == clockId) { private fun onUnloaded(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.WARNING, { str1 = clockId }, { "Current clock ($str1) was unloaded" } if (isCurrent) LogLevel.WARNING else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Unloaded $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) if (isCurrent) { triggerOnCurrentClockChanged() } } private fun onDisconnected(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Disconnected $str1" }) if (currentClockId == clockId) { private fun onDisconnected(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.WARNING, { str1 = clockId }, { "Current clock ($str1) was disconnected" } if (isCurrent) LogLevel.INFO else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Disconnected $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) } } fun getClocks(): List<ClockMetadata> { if (!isEnabled) { Loading packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginLifecycleManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,12 @@ public interface PluginLifecycleManager<T extends Plugin> { /** Returns the currently loaded plugin instance (if plugin is loaded) */ T getPlugin(); /** Returns true if the lifecycle manager should log debug messages */ boolean getIsDebug(); /** Sets whether or not hte lifecycle manager should log debug messages */ void setIsDebug(boolean debug); /** returns true if the plugin is currently loaded */ default boolean isLoaded() { return getPlugin() != null; Loading packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java +32 −0 Original line number Diff line number Diff line Loading @@ -55,7 +55,9 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager private final PluginListener<T> mListener; private final ComponentName mComponentName; private final PluginFactory<T> mPluginFactory; private final String mTag; private boolean mIsDebug = false; private Context mPluginContext; private T mPlugin; Loading @@ -71,27 +73,51 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager mComponentName = componentName; mPluginFactory = pluginFactory; mPlugin = plugin; mTag = TAG + mComponentName.toShortString() + '@' + Integer.toHexString(hashCode()); if (mPlugin != null) { mPluginContext = mPluginFactory.createPluginContext(); } } @Override public String toString() { return mTag; } public boolean getIsDebug() { return mIsDebug; } public void setIsDebug(boolean debug) { mIsDebug = debug; } private void logDebug(String message) { if (mIsDebug) { Log.i(mTag, message); } } /** Alerts listener and plugin that the plugin has been created. */ public void onCreate() { boolean loadPlugin = mListener.onPluginAttached(this); if (!loadPlugin) { if (mPlugin != null) { logDebug("onCreate: auto-unload"); unloadPlugin(); } return; } if (mPlugin == null) { logDebug("onCreate auto-load"); loadPlugin(); return; } logDebug("onCreate: load callbacks"); mPluginFactory.checkVersion(mPlugin); if (!(mPlugin instanceof PluginFragment)) { // Only call onCreate for plugins that aren't fragments, as fragments Loading @@ -103,6 +129,7 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager /** Alerts listener and plugin that the plugin is being shutdown. */ public void onDestroy() { logDebug("onDestroy"); unloadPlugin(); mListener.onPluginDetached(this); } Loading @@ -118,15 +145,18 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager */ public void loadPlugin() { if (mPlugin != null) { logDebug("Load request when already loaded"); return; } mPlugin = mPluginFactory.createPlugin(); mPluginContext = mPluginFactory.createPluginContext(); if (mPlugin == null || mPluginContext == null) { Log.e(mTag, "Requested load, but failed"); return; } logDebug("Loaded plugin; running callbacks"); mPluginFactory.checkVersion(mPlugin); if (!(mPlugin instanceof PluginFragment)) { // Only call onCreate for plugins that aren't fragments, as fragments Loading @@ -143,9 +173,11 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager */ public void unloadPlugin() { if (mPlugin == null) { logDebug("Unload request when already unloaded"); return; } logDebug("Unloading plugin, running callbacks"); mListener.onPluginUnloaded(mPlugin, this); if (!(mPlugin instanceof PluginFragment)) { // Only call onDestroy for plugins that aren't fragments, as fragments Loading Loading
packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt +101 −54 Original line number Diff line number Diff line Loading @@ -68,11 +68,11 @@ private val KNOWN_PLUGINS = private fun <TKey, TVal> ConcurrentHashMap<TKey, TVal>.concurrentGetOrPut( key: TKey, value: TVal, onNew: () -> Unit onNew: (TVal) -> Unit ): TVal { val result = this.putIfAbsent(key, value) if (result == null) { onNew() onNew(value) } return result ?: value } Loading Loading @@ -148,6 +148,8 @@ open class ClockRegistry( override fun onPluginAttached( manager: PluginLifecycleManager<ClockProviderPlugin> ): Boolean { manager.isDebug = true if (keepAllLoaded) { // Always load new plugins if requested return true Loading Loading @@ -177,15 +179,22 @@ open class ClockRegistry( val info = availableClocks.concurrentGetOrPut(id, ClockInfo(metadata, null, manager)) { isClockListChanged = true onConnected(id) onConnected(it) } if (manager != info.manager) { logger.tryLog( TAG, LogLevel.ERROR, { str1 = id }, { "Clock Id conflict on known attach: $str1 is double registered" } { str1 = id str2 = info.manager.toString() str3 = manager.toString() }, { "Clock Id conflict on attach: " + "$str1 is double registered by $str2 and $str3" } ) continue } Loading Loading @@ -217,22 +226,29 @@ open class ClockRegistry( val info = availableClocks.concurrentGetOrPut(id, ClockInfo(clock, plugin, manager)) { isClockListChanged = true onConnected(id) onConnected(it) } if (manager != info.manager) { logger.tryLog( TAG, LogLevel.ERROR, { str1 = id }, { "Clock Id conflict on load: $str1 is double registered" } { str1 = id str2 = info.manager.toString() str3 = manager.toString() }, { "Clock Id conflict on load: " + "$str1 is double registered by $str2 and $str3" } ) manager.unloadPlugin() continue } info.provider = plugin onLoaded(id) onLoaded(info) } if (isClockListChanged) { Loading @@ -252,26 +268,33 @@ open class ClockRegistry( logger.tryLog( TAG, LogLevel.ERROR, { str1 = id }, { "Clock Id conflict on unload: $str1 is double registered" } { str1 = id str2 = info?.manager.toString() str3 = manager.toString() }, { "Clock Id conflict on unload: " + "$str1 is double registered by $str2 and $str3" } ) continue } info.provider = null onUnloaded(id) onUnloaded(info) } verifyLoadedProviders() } override fun onPluginDetached(manager: PluginLifecycleManager<ClockProviderPlugin>) { val removed = mutableListOf<ClockId>() val removed = mutableListOf<ClockInfo>() availableClocks.entries.removeAll { if (it.value.manager != manager) { return@removeAll false } removed.add(it.key) removed.add(it.value) return@removeAll true } Loading Loading @@ -493,6 +516,12 @@ open class ClockRegistry( scope.launch(bgDispatcher) { if (keepAllLoaded) { logger.tryLog( TAG, LogLevel.INFO, {}, { "verifyLoadedProviders: keepAllLoaded=true" } ) // Enforce that all plugins are loaded if requested for ((_, info) in availableClocks) { info.manager?.loadPlugin() Loading @@ -503,6 +532,12 @@ open class ClockRegistry( val currentClock = availableClocks[currentClockId] if (currentClock == null) { logger.tryLog( TAG, LogLevel.INFO, {}, { "verifyLoadedProviders: currentClock=null" } ) // Current Clock missing, load no plugins and use default for ((_, info) in availableClocks) { info.manager?.unloadPlugin() Loading @@ -511,12 +546,13 @@ open class ClockRegistry( return@launch } logger.tryLog(TAG, LogLevel.INFO, {}, { "verifyLoadedProviders: load currentClock" }) val currentManager = currentClock.manager currentManager?.loadPlugin() for ((_, info) in availableClocks) { val manager = info.manager if (manager != null && manager.isLoaded && currentManager != manager) { if (manager != null && currentManager != manager) { manager.unloadPlugin() } } Loading @@ -524,58 +560,69 @@ open class ClockRegistry( } } private fun onConnected(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Connected $str1" }) if (currentClockId == clockId) { private fun onConnected(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.INFO, { str1 = clockId }, { "Current clock ($str1) was connected" } if (isCurrent) LogLevel.INFO else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Connected $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) } } private fun onLoaded(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Loaded $str1" }) if (currentClockId == clockId) { private fun onLoaded(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.INFO, { str1 = clockId }, { "Current clock ($str1) was loaded" } if (isCurrent) LogLevel.INFO else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Loaded $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) if (isCurrent) { triggerOnCurrentClockChanged() } } private fun onUnloaded(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Unloaded $str1" }) if (currentClockId == clockId) { private fun onUnloaded(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.WARNING, { str1 = clockId }, { "Current clock ($str1) was unloaded" } if (isCurrent) LogLevel.WARNING else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Unloaded $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) if (isCurrent) { triggerOnCurrentClockChanged() } } private fun onDisconnected(clockId: ClockId) { logger.tryLog(TAG, LogLevel.DEBUG, { str1 = clockId }, { "Disconnected $str1" }) if (currentClockId == clockId) { private fun onDisconnected(info: ClockInfo) { val isCurrent = currentClockId == info.metadata.clockId logger.tryLog( TAG, LogLevel.WARNING, { str1 = clockId }, { "Current clock ($str1) was disconnected" } if (isCurrent) LogLevel.INFO else LogLevel.DEBUG, { str1 = info.metadata.clockId str2 = info.manager.toString() bool1 = isCurrent }, { "Disconnected $str1 @$str2" + if (bool1) " (Current Clock)" else "" } ) } } fun getClocks(): List<ClockMetadata> { if (!isEnabled) { Loading
packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginLifecycleManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,12 @@ public interface PluginLifecycleManager<T extends Plugin> { /** Returns the currently loaded plugin instance (if plugin is loaded) */ T getPlugin(); /** Returns true if the lifecycle manager should log debug messages */ boolean getIsDebug(); /** Sets whether or not hte lifecycle manager should log debug messages */ void setIsDebug(boolean debug); /** returns true if the plugin is currently loaded */ default boolean isLoaded() { return getPlugin() != null; Loading
packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java +32 −0 Original line number Diff line number Diff line Loading @@ -55,7 +55,9 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager private final PluginListener<T> mListener; private final ComponentName mComponentName; private final PluginFactory<T> mPluginFactory; private final String mTag; private boolean mIsDebug = false; private Context mPluginContext; private T mPlugin; Loading @@ -71,27 +73,51 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager mComponentName = componentName; mPluginFactory = pluginFactory; mPlugin = plugin; mTag = TAG + mComponentName.toShortString() + '@' + Integer.toHexString(hashCode()); if (mPlugin != null) { mPluginContext = mPluginFactory.createPluginContext(); } } @Override public String toString() { return mTag; } public boolean getIsDebug() { return mIsDebug; } public void setIsDebug(boolean debug) { mIsDebug = debug; } private void logDebug(String message) { if (mIsDebug) { Log.i(mTag, message); } } /** Alerts listener and plugin that the plugin has been created. */ public void onCreate() { boolean loadPlugin = mListener.onPluginAttached(this); if (!loadPlugin) { if (mPlugin != null) { logDebug("onCreate: auto-unload"); unloadPlugin(); } return; } if (mPlugin == null) { logDebug("onCreate auto-load"); loadPlugin(); return; } logDebug("onCreate: load callbacks"); mPluginFactory.checkVersion(mPlugin); if (!(mPlugin instanceof PluginFragment)) { // Only call onCreate for plugins that aren't fragments, as fragments Loading @@ -103,6 +129,7 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager /** Alerts listener and plugin that the plugin is being shutdown. */ public void onDestroy() { logDebug("onDestroy"); unloadPlugin(); mListener.onPluginDetached(this); } Loading @@ -118,15 +145,18 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager */ public void loadPlugin() { if (mPlugin != null) { logDebug("Load request when already loaded"); return; } mPlugin = mPluginFactory.createPlugin(); mPluginContext = mPluginFactory.createPluginContext(); if (mPlugin == null || mPluginContext == null) { Log.e(mTag, "Requested load, but failed"); return; } logDebug("Loaded plugin; running callbacks"); mPluginFactory.checkVersion(mPlugin); if (!(mPlugin instanceof PluginFragment)) { // Only call onCreate for plugins that aren't fragments, as fragments Loading @@ -143,9 +173,11 @@ public class PluginInstance<T extends Plugin> implements PluginLifecycleManager */ public void unloadPlugin() { if (mPlugin == null) { logDebug("Unload request when already unloaded"); return; } logDebug("Unloading plugin, running callbacks"); mListener.onPluginUnloaded(mPlugin, this); if (!(mPlugin instanceof PluginFragment)) { // Only call onDestroy for plugins that aren't fragments, as fragments Loading