From 15142270fe17845890d147aca8720a32b8c73ecf Mon Sep 17 00:00:00 2001 From: Cyan Hsieh Date: Fri, 8 Jul 2022 05:57:24 +0000 Subject: [PATCH] Revert "Change SysemUIFactory to SystemUIInitializer." Revert submission 18917521-b235624311-app-component Reason for revert: Broken test b/238359875 and b/238372209 Reverted Changes: I7029fb296:Change SysemUIFactory to SystemUIInitializer. I082787983:Conform to new SystemUIInitializer pattern. I923e5bbbc:Conform to new SystemUIInitializer pattern. I7af1a39b2:Conform to new SystemUIInitializer pattern. Iba9a5ba24:Conform to new SystemUIInitializer pattern. I4fe83e292:Conform to new SystemUIInitializer pattern. I7f54204ae:Conform to new SystemUIInitializer pattern. I6246c6eb4:Conform to new SystemUIInitializer pattern. Bug: 238359875 Bug: 238372209 Change-Id: I833ec524c4f6072d64eba55e22f0b37341d38f4f --- packages/SystemUI/proguard.flags | 4 +- .../SystemUI/res/values-television/config.xml | 2 +- packages/SystemUI/res/values/config.xml | 2 +- .../systemui/SystemUIAppComponentFactory.java | 158 ++++++++++++++- .../SystemUIAppComponentFactoryBase.kt | 183 ------------------ .../android/systemui/SystemUIApplication.java | 23 +-- ...IInitializer.java => SystemUIFactory.java} | 103 +++++++--- .../systemui/SystemUIInitializerFactory.kt | 72 ------- .../systemui/SystemUIInitializerImpl.kt | 30 --- .../systemui/dagger/SysUIComponent.java | 4 +- .../systemui/dagger/SystemUIModule.java | 6 + .../android/systemui/dagger/WMComponent.java | 4 +- .../systemui/people/PeopleProvider.java | 9 +- ...nitializer.java => TvSystemUIFactory.java} | 12 +- .../com/android/systemui/DependencyTest.java | 10 +- .../systemui/SysuiBaseFragmentTest.java | 12 +- .../com/android/systemui/SysuiTestCase.java | 7 +- .../keyguard/KeyguardSliceProviderTest.java | 3 +- .../CollapsedStatusBarFragmentTest.java | 2 - 19 files changed, 269 insertions(+), 377 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt rename packages/SystemUI/src/com/android/systemui/{SystemUIInitializer.java => SystemUIFactory.java} (76%) delete mode 100644 packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt delete mode 100644 packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt rename packages/SystemUI/src/com/android/systemui/tv/{TvSystemUIInitializer.java => TvSystemUIFactory.java} (73%) diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags index ed01494a911ba..6ffd661636539 100644 --- a/packages/SystemUI/proguard.flags +++ b/packages/SystemUI/proguard.flags @@ -9,8 +9,8 @@ -keep class com.android.systemui.statusbar.phone.CentralSurfaces -keep class com.android.systemui.statusbar.tv.TvStatusBar -keep class com.android.systemui.car.CarSystemUIFactory --keep class com.android.systemui.SystemUIInitializer --keep class com.android.systemui.tv.TvSystemUIInitializer +-keep class com.android.systemui.SystemUIFactory +-keep class com.android.systemui.tv.TvSystemUIFactory -keep class * extends com.android.systemui.CoreStartable -keep class * implements com.android.systemui.CoreStartable$Injector diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml index 375bd394bb4ce..94f6c3952e06d 100644 --- a/packages/SystemUI/res/values-television/config.xml +++ b/packages/SystemUI/res/values-television/config.xml @@ -22,7 +22,7 @@ - com.android.systemui.tv.TvSystemUIInitializer + com.android.systemui.tv.TvSystemUIFactory diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 82a3b58a51555..771973c36053e 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -286,7 +286,7 @@ false - com.android.systemui.SystemUIInitializerImpl + com.android.systemui.SystemUIFactory -1dp diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java index 527ce127820e8..714d267bb07de 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java @@ -16,22 +16,160 @@ package com.android.systemui; +import android.app.Activity; +import android.app.Application; +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.ContentProvider; import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.AppComponentFactory; + +import com.android.systemui.dagger.ContextComponentHelper; +import com.android.systemui.dagger.SysUIComponent; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.inject.Inject; /** - * Starts up SystemUI using the AOSP {@link SystemUIInitializerImpl}. + * Implementation of AppComponentFactory that injects into constructors. * - * This initializer relies on reflection to start everything up and should be considered deprecated. - * Instead, create your own {@link SystemUIAppComponentFactoryBase}, specify it in your - * AndroidManifest.xml and construct your own {@link SystemUIInitializer} directly. + * This class sets up dependency injection when creating our application. * - * @deprecated Define your own SystemUIAppComponentFactoryBase implementation and use that. This - * implementation may be changed or removed in future releases. + * Services support dependency injection into their constructors. + * + * ContentProviders support injection into member variables - _not_ constructors. */ -@Deprecated -public class SystemUIAppComponentFactory extends SystemUIAppComponentFactoryBase { +public class SystemUIAppComponentFactory extends AppComponentFactory { + + private static final String TAG = "AppComponentFactory"; + @Inject + public ContextComponentHelper mComponentHelper; + + public SystemUIAppComponentFactory() { + super(); + } + + @NonNull @Override - protected SystemUIInitializer createSystemUIInitializer(Context context) { - return SystemUIInitializerFactory.createWithContext(context); + public Application instantiateApplicationCompat( + @NonNull ClassLoader cl, @NonNull String className) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + Application app = super.instantiateApplicationCompat(cl, className); + if (app instanceof ContextInitializer) { + ((ContextInitializer) app).setContextAvailableCallback( + context -> { + SystemUIFactory.createFromConfig(context); + SystemUIFactory.getInstance().getSysUIComponent().inject( + SystemUIAppComponentFactory.this); + } + ); + } + + return app; + } + + @NonNull + @Override + public ContentProvider instantiateProviderCompat( + @NonNull ClassLoader cl, @NonNull String className) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + + ContentProvider contentProvider = super.instantiateProviderCompat(cl, className); + if (contentProvider instanceof ContextInitializer) { + ((ContextInitializer) contentProvider).setContextAvailableCallback( + context -> { + SystemUIFactory.createFromConfig(context); + SysUIComponent rootComponent = + SystemUIFactory.getInstance().getSysUIComponent(); + try { + Method injectMethod = rootComponent.getClass() + .getMethod("inject", contentProvider.getClass()); + injectMethod.invoke(rootComponent, contentProvider); + } catch (NoSuchMethodException + | IllegalAccessException + | InvocationTargetException e) { + Log.w(TAG, "No injector for class: " + contentProvider.getClass(), e); + } + } + ); + } + + return contentProvider; + } + + @NonNull + @Override + public Activity instantiateActivityCompat(@NonNull ClassLoader cl, @NonNull String className, + @Nullable Intent intent) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + if (mComponentHelper == null) { + // This shouldn't happen, but is seen on occasion. + // Bug filed against framework to take a look: http://b/141008541 + SystemUIFactory.getInstance().getSysUIComponent().inject( + SystemUIAppComponentFactory.this); + } + Activity activity = mComponentHelper.resolveActivity(className); + if (activity != null) { + return activity; + } + return super.instantiateActivityCompat(cl, className, intent); + } + + @NonNull + @Override + public Service instantiateServiceCompat( + @NonNull ClassLoader cl, @NonNull String className, Intent intent) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + if (mComponentHelper == null) { + // This shouldn't happen, but does when a device is freshly formatted. + // Bug filed against framework to take a look: http://b/141008541 + SystemUIFactory.getInstance().getSysUIComponent().inject( + SystemUIAppComponentFactory.this); + } + Service service = mComponentHelper.resolveService(className); + if (service != null) { + return service; + } + return super.instantiateServiceCompat(cl, className, intent); + } + + @NonNull + @Override + public BroadcastReceiver instantiateReceiverCompat(@NonNull ClassLoader cl, + @NonNull String className, @Nullable Intent intent) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + if (mComponentHelper == null) { + // This shouldn't happen, but does when a device is freshly formatted. + // Bug filed against framework to take a look: http://b/141008541 + SystemUIFactory.getInstance().getSysUIComponent().inject( + SystemUIAppComponentFactory.this); + } + BroadcastReceiver receiver = mComponentHelper.resolveBroadcastReceiver(className); + if (receiver != null) { + return receiver; + } + + return super.instantiateReceiverCompat(cl, className, intent); + } + + /** + * A callback that receives a Context when one is ready. + */ + public interface ContextAvailableCallback { + void onContextAvailable(Context context); + } + + /** + * Implemented in classes that get started by the system before a context is available. + */ + public interface ContextInitializer { + void setContextAvailableCallback(ContextAvailableCallback callback); } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt deleted file mode 100644 index 12108b01ab28e..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui - -import android.app.Activity -import android.app.Application -import android.app.Service -import android.content.BroadcastReceiver -import android.content.ContentProvider -import android.content.Context -import android.content.Intent -import android.util.Log -import androidx.core.app.AppComponentFactory -import com.android.systemui.dagger.ContextComponentHelper -import java.lang.reflect.InvocationTargetException -import java.util.concurrent.ExecutionException -import javax.inject.Inject - -/** - * Implementation of AppComponentFactory that injects into constructors. - * - * This class sets up dependency injection when creating our application. - * - * Activities, Services, and BroadcastReceivers support dependency injection into - * their constructors. - * - * ContentProviders support injection into member variables - _not_ constructors. - */ -abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() { - companion object { - private const val TAG = "AppComponentFactory" - // Must be static due to http://b/141008541. - var systemUIInitializer: SystemUIInitializer? = null - } - - @set:Inject - lateinit var componentHelper: ContextComponentHelper - - /** - * Returns a new [SystemUIInitializer]. - * - * The returned implementation should be specific to your build. - */ - protected abstract fun createSystemUIInitializer(context: Context): SystemUIInitializer - - private fun createSystemUIInitializerInternal(context: Context): SystemUIInitializer { - return systemUIInitializer ?: run { - val initializer = createSystemUIInitializer(context.applicationContext) - try { - initializer.init(false) - } catch (exception: ExecutionException) { - throw RuntimeException("Failed to initialize SysUI", exception) - } catch (exception: InterruptedException) { - throw RuntimeException("Failed to initialize SysUI", exception) - } - initializer.sysUIComponent.inject( - this@SystemUIAppComponentFactoryBase - ) - - systemUIInitializer = initializer - return initializer - } - } - - override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application { - val app = super.instantiateApplicationCompat(cl, className) - if (app !is ContextInitializer) { - throw RuntimeException("App must implement ContextInitializer") - } else { - app.setContextAvailableCallback { context -> - createSystemUIInitializerInternal(context) - } - } - - return app - } - - override fun instantiateProviderCompat(cl: ClassLoader, className: String): ContentProvider { - val contentProvider = super.instantiateProviderCompat(cl, className) - if (contentProvider is ContextInitializer) { - contentProvider.setContextAvailableCallback { context -> - val initializer = createSystemUIInitializerInternal(context) - val rootComponent = initializer.sysUIComponent - try { - val injectMethod = rootComponent.javaClass - .getMethod("inject", contentProvider.javaClass) - injectMethod.invoke(rootComponent, contentProvider) - } catch (e: NoSuchMethodException) { - Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e) - } catch (e: IllegalAccessException) { - Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e) - } catch (e: InvocationTargetException) { - Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e) - } - initializer - } - } - return contentProvider - } - - override fun instantiateActivityCompat( - cl: ClassLoader, - className: String, - intent: Intent? - ): Activity { - if (!this::componentHelper.isInitialized) { - // This shouldn't happen, but is seen on occasion. - // Bug filed against framework to take a look: http://b/141008541 - systemUIInitializer?.sysUIComponent?.inject(this@SystemUIAppComponentFactoryBase) - } - return componentHelper.resolveActivity(className) - ?: super.instantiateActivityCompat(cl, className, intent) - } - - override fun instantiateServiceCompat( - cl: ClassLoader, - className: String, - intent: Intent? - ): Service { - if (!this::componentHelper.isInitialized) { - // This shouldn't happen, but does when a device is freshly formatted. - // Bug filed against framework to take a look: http://b/141008541 - systemUIInitializer?.sysUIComponent?.inject(this@SystemUIAppComponentFactoryBase) - } - return componentHelper.resolveService(className) - ?: super.instantiateServiceCompat(cl, className, intent) - } - - override fun instantiateReceiverCompat( - cl: ClassLoader, - className: String, - intent: Intent? - ): BroadcastReceiver { - if (!this::componentHelper.isInitialized) { - // This shouldn't happen, but does when a device is freshly formatted. - // Bug filed against framework to take a look: http://b/141008541 - systemUIInitializer?.sysUIComponent?.inject(this@SystemUIAppComponentFactoryBase) - } - return componentHelper.resolveBroadcastReceiver(className) - ?: super.instantiateReceiverCompat(cl, className, intent) - } - - /** - * An Interface for classes that can be notified when an Application Context becomes available. - * - * An instance of this will be passed to implementers of [ContextInitializer]. - */ - fun interface ContextAvailableCallback { - /** Notifies when the Application Context is available. */ - fun onContextAvailable(context: Context): SystemUIInitializer - } - - /** - * Interface for classes that can be constructed by the system before a context is available. - * - * This is intended for [Application] and [ContentProvider] implementations that - * either may not have a Context until some point after construction or are themselves - * a [Context]. - * - * Implementers will be passed a [ContextAvailableCallback] that they should call as soon - * as an Application Context is ready. - */ - interface ContextInitializer { - /** - * Called to supply the [ContextAvailableCallback] that should be called when an - * Application [Context] is available. - */ - fun setContextAvailableCallback(callback: ContextAvailableCallback) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 9138b2346ab81..6d3fd503dff6e 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -42,6 +42,7 @@ import android.view.SurfaceControl; import android.view.ThreadedRenderer; import com.android.internal.protolog.common.ProtoLog; +import com.android.systemui.dagger.ContextComponentHelper; import com.android.systemui.dagger.GlobalRootComponent; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dump.DumpManager; @@ -64,6 +65,7 @@ public class SystemUIApplication extends Application implements public static final String TAG = "SystemUIService"; private static final boolean DEBUG = false; + private ContextComponentHelper mComponentHelper; private BootCompleteCacheImpl mBootCompleteCache; private DumpManager mDumpManager; @@ -78,8 +80,8 @@ public class SystemUIApplication extends Application implements private CoreStartable[] mServices; private boolean mServicesStarted; private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback; + private GlobalRootComponent mRootComponent; private SysUIComponent mSysUIComponent; - private SystemUIInitializer mInitializer; public SystemUIApplication() { super(); @@ -88,10 +90,6 @@ public class SystemUIApplication extends Application implements ProtoLog.REQUIRE_PROTOLOGTOOL = false; } - protected GlobalRootComponent getRootComponent() { - return mInitializer.getRootComponent(); - } - @Override public void onCreate() { super.onCreate(); @@ -101,8 +99,10 @@ public class SystemUIApplication extends Application implements TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming", Trace.TRACE_TAG_APP); log.traceBegin("DependencyInjection"); - mInitializer = mContextAvailableCallback.onContextAvailable(this); - mSysUIComponent = mInitializer.getSysUIComponent(); + mContextAvailableCallback.onContextAvailable(this); + mRootComponent = SystemUIFactory.getInstance().getRootComponent(); + mSysUIComponent = SystemUIFactory.getInstance().getSysUIComponent(); + mComponentHelper = mSysUIComponent.getContextComponentHelper(); mBootCompleteCache = mSysUIComponent.provideBootCacheImpl(); log.traceEnd(); @@ -189,14 +189,15 @@ public class SystemUIApplication extends Application implements */ public void startServicesIfNeeded() { - final String vendorComponent = mInitializer.getVendorComponent(getResources()); + final String vendorComponent = SystemUIFactory.getInstance() + .getVendorComponent(getResources()); // Sort the startables so that we get a deterministic ordering. // TODO: make #start idempotent and require users of CoreStartable to call it. Map, Provider> sortedStartables = new TreeMap<>( Comparator.comparing(Class::getName)); - sortedStartables.putAll(mSysUIComponent.getStartables()); - sortedStartables.putAll(mSysUIComponent.getPerUserStartables()); + sortedStartables.putAll(SystemUIFactory.getInstance().getStartableComponents()); + sortedStartables.putAll(SystemUIFactory.getInstance().getStartableComponentsPerUser()); startServicesIfNeeded( sortedStartables, "StartServices", vendorComponent); } @@ -211,7 +212,7 @@ public class SystemUIApplication extends Application implements // Sort the startables so that we get a deterministic ordering. Map, Provider> sortedStartables = new TreeMap<>( Comparator.comparing(Class::getName)); - sortedStartables.putAll(mSysUIComponent.getPerUserStartables()); + sortedStartables.putAll(SystemUIFactory.getInstance().getStartableComponentsPerUser()); startServicesIfNeeded( sortedStartables, "StartSecondaryServices", null); } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java similarity index 76% rename from packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java rename to packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 5100c09912c8d..ca94b8cd05b74 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -11,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License */ package com.android.systemui; @@ -22,6 +22,8 @@ import android.os.Handler; import android.os.HandlerThread; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.DaggerGlobalRootComponent; import com.android.systemui.dagger.GlobalRootComponent; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.WMComponent; @@ -29,47 +31,66 @@ import com.android.systemui.util.InitializationChecker; import com.android.wm.shell.dagger.WMShellConcurrencyModule; import com.android.wm.shell.transition.ShellTransitions; +import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutionException; +import javax.inject.Provider; + /** - * Initializer that stands up SystemUI. - * - * Implementations should override {@link #getGlobalRootComponentBuilder()} to fill in their own - * Dagger root component. + * Class factory to provide customizable SystemUI components. */ -public abstract class SystemUIInitializer { +public class SystemUIFactory { private static final String TAG = "SystemUIFactory"; - private final Context mContext; - + static SystemUIFactory mFactory; private GlobalRootComponent mRootComponent; private WMComponent mWMComponent; private SysUIComponent mSysUIComponent; private InitializationChecker mInitializationChecker; - public SystemUIInitializer(Context context) { - mContext = context; + public static T getInstance() { + return (T) mFactory; } - protected abstract GlobalRootComponent.Builder getGlobalRootComponentBuilder(); - - /** - * Prepares the SysUIComponent builder before it is built. - * @param sysUIBuilder the builder provided by the root component's getSysUIComponent() method - * @param wm the built WMComponent from the root component's getWMComponent() method - */ - protected SysUIComponent.Builder prepareSysUIComponentBuilder( - SysUIComponent.Builder sysUIBuilder, WMComponent wm) { - return sysUIBuilder; + public static void createFromConfig(Context context) { + createFromConfig(context, false); } - /** - * Starts the initialization process. This stands up the Dagger graph. - */ - public void init(boolean fromTest) throws ExecutionException, InterruptedException { + @VisibleForTesting + public static void createFromConfig(Context context, boolean fromTest) { + if (mFactory != null) { + return; + } + + final String clsName = context.getString(R.string.config_systemUIFactoryComponent); + if (clsName == null || clsName.length() == 0) { + throw new RuntimeException("No SystemUIFactory component configured"); + } + + try { + Class cls = null; + cls = context.getClassLoader().loadClass(clsName); + mFactory = (SystemUIFactory) cls.newInstance(); + mFactory.init(context, fromTest); + } catch (Throwable t) { + Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t); + throw new RuntimeException(t); + } + } + + @VisibleForTesting + static void cleanup() { + mFactory = null; + } + + public SystemUIFactory() {} + + @VisibleForTesting + public void init(Context context, boolean fromTest) + throws ExecutionException, InterruptedException { mRootComponent = getGlobalRootComponentBuilder() - .context(mContext) + .context(context) .instrumentationTest(fromTest) .build(); @@ -77,7 +98,7 @@ public abstract class SystemUIInitializer { boolean initializeComponents = mInitializationChecker.initializeComponents(); // Stand up WMComponent - setupWmComponent(mContext); + setupWmComponent(context); if (initializeComponents) { // Only initialize when not starting from tests since this currently initializes some // components that shouldn't be run in the test environment @@ -167,6 +188,20 @@ public abstract class SystemUIInitializer { } } + /** + * Prepares the SysUIComponent builder before it is built. + * @param sysUIBuilder the builder provided by the root component's getSysUIComponent() method + * @param wm the built WMComponent from the root component's getWMComponent() method + */ + protected SysUIComponent.Builder prepareSysUIComponentBuilder( + SysUIComponent.Builder sysUIBuilder, WMComponent wm) { + return sysUIBuilder; + } + + protected GlobalRootComponent.Builder getGlobalRootComponentBuilder() { + return DaggerGlobalRootComponent.builder(); + } + public GlobalRootComponent getRootComponent() { return mRootComponent; } @@ -179,10 +214,24 @@ public abstract class SystemUIInitializer { return mSysUIComponent; } + /** + * Returns the list of {@link CoreStartable} components that should be started at startup. + */ + public Map, Provider> getStartableComponents() { + return mSysUIComponent.getStartables(); + } + /** * Returns the list of additional system UI components that should be started. */ public String getVendorComponent(Resources resources) { return resources.getString(R.string.config_systemUIVendorServiceComponent); } + + /** + * Returns the list of {@link CoreStartable} components that should be started per user. + */ + public Map, Provider> getStartableComponentsPerUser() { + return mSysUIComponent.getPerUserStartables(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt b/packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt deleted file mode 100644 index b9454e8c3be86..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui - -import android.annotation.SuppressLint -import android.content.Context -import android.util.Log -import com.android.internal.annotations.VisibleForTesting -import com.android.systemui.util.Assert - -/** - * Factory to reflectively lookup a [SystemUIInitializer] to start SystemUI with. - */ -@Deprecated("Provide your own {@link SystemUIAppComponentFactoryBase} that doesn't need this.") -object SystemUIInitializerFactory { - private const val TAG = "SysUIInitializerFactory" - @SuppressLint("StaticFieldLeak") - private var initializer: SystemUIInitializer? = null - - /** - * Instantiate a [SystemUIInitializer] reflectively. - */ - @JvmStatic - fun createWithContext(context: Context): SystemUIInitializer { - return createFromConfig(context) - } - - /** - * Instantiate a [SystemUIInitializer] reflectively. - */ - @JvmStatic - private fun createFromConfig(context: Context): SystemUIInitializer { - Assert.isMainThread() - - return createFromConfigNoAssert(context) - } - - @JvmStatic - @VisibleForTesting - fun createFromConfigNoAssert(context: Context): SystemUIInitializer { - - return initializer ?: run { - val className = context.getString(R.string.config_systemUIFactoryComponent) - if (className.isEmpty()) { - throw RuntimeException("No SystemUIFactory component configured") - } - try { - val cls = context.classLoader.loadClass(className) - val constructor = cls.getConstructor(Context::class.java) - (constructor.newInstance(context) as SystemUIInitializer).apply { - initializer = this - } - } catch (t: Throwable) { - Log.w(TAG, "Error creating SystemUIInitializer component: $className", t) - throw t - } - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt b/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt deleted file mode 100644 index 8920c928da09a..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui - -import android.content.Context -import com.android.systemui.dagger.DaggerGlobalRootComponent -import com.android.systemui.dagger.GlobalRootComponent - -/** - * {@link SystemUIInitializer} that stands up AOSP SystemUI. - */ -class SystemUIInitializerImpl(context: Context) : SystemUIInitializer(context) { - override fun getGlobalRootComponentBuilder(): GlobalRootComponent.Builder { - return DaggerGlobalRootComponent.builder() - } -} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 550af7cafc751..3a1b12955647c 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -21,7 +21,7 @@ import com.android.systemui.BootCompleteCacheImpl; import com.android.systemui.CoreStartable; import com.android.systemui.Dependency; import com.android.systemui.InitController; -import com.android.systemui.SystemUIAppComponentFactoryBase; +import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.dagger.qualifiers.PerUser; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardSliceProvider; @@ -241,7 +241,7 @@ public interface SysUIComponent { /** * Member injection into the supplied argument. */ - void inject(SystemUIAppComponentFactoryBase factory); + void inject(SystemUIAppComponentFactory factory); /** * Member injection into the supplied argument. diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 8cc952df47ed8..137e288887281 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -26,6 +26,7 @@ import com.android.keyguard.clock.ClockModule; import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.BootCompleteCache; import com.android.systemui.BootCompleteCacheImpl; +import com.android.systemui.SystemUIFactory; import com.android.systemui.appops.dagger.AppOpsModule; import com.android.systemui.assist.AssistModule; import com.android.systemui.biometrics.AlternateUdfpsTouchProvider; @@ -197,6 +198,11 @@ public abstract class SystemUIModule { @Binds abstract SystemClock bindSystemClock(SystemClockImpl systemClock); + @Provides + static SystemUIFactory getSystemUIFactory() { + return SystemUIFactory.getInstance(); + } + // TODO: This should provided by the WM component /** Provides Optional of BubbleManager */ @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index f2f1798c94f66..1570a7ebc0c4f 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -21,7 +21,7 @@ import android.os.HandlerThread; import androidx.annotation.Nullable; -import com.android.systemui.SystemUIInitializerFactory; +import com.android.systemui.SystemUIFactory; import com.android.systemui.tv.TvWMComponent; import com.android.wm.shell.ShellCommandHandler; import com.android.wm.shell.ShellInit; @@ -52,7 +52,7 @@ import dagger.Subcomponent; /** * Dagger Subcomponent for WindowManager. This class explicitly describes the interfaces exported * from the WM component into the SysUI component (in - * {@link SystemUIInitializerFactory#init(Context, boolean)}), and references the specific dependencies + * {@link SystemUIFactory#init(Context, boolean)}), and references the specific dependencies * provided by its particular device/form-factor SystemUI implementation. * * ie. {@link WMComponent} includes {@link WMShellModule} diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java b/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java index 0ba077eb09127..b55d86e8fb1c2 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java @@ -29,8 +29,7 @@ import android.os.UserHandle; import android.util.Log; import android.widget.RemoteViews; -import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCallback; -import com.android.systemui.SystemUIAppComponentFactoryBase.ContextInitializer; +import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.people.widget.PeopleSpaceWidgetManager; import com.android.systemui.shared.system.PeopleProviderUtils; @@ -38,11 +37,11 @@ import javax.inject.Inject; /** API that returns a People Tile preview. */ public class PeopleProvider extends ContentProvider implements - ContextInitializer { + SystemUIAppComponentFactory.ContextInitializer { private static final String TAG = "PeopleProvider"; private static final boolean DEBUG = PeopleSpaceUtils.DEBUG; private static final String EMPTY_STRING = ""; - private ContextAvailableCallback mCallback; + private SystemUIAppComponentFactory.ContextAvailableCallback mCallback; @Inject PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; @@ -145,7 +144,7 @@ public class PeopleProvider extends ContentProvider implements @Override public void setContextAvailableCallback( - ContextAvailableCallback callback) { + SystemUIAppComponentFactory.ContextAvailableCallback callback) { mCallback = callback; } } diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIInitializer.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java similarity index 73% rename from packages/SystemUI/src/com/android/systemui/tv/TvSystemUIInitializer.java rename to packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java index fabbb2c1f44d4..0b5594b14d0ec 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIInitializer.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java @@ -16,20 +16,14 @@ package com.android.systemui.tv; -import android.content.Context; - -import com.android.systemui.SystemUIInitializer; +import com.android.systemui.SystemUIFactory; import com.android.systemui.dagger.GlobalRootComponent; /** - * TV variant {@link SystemUIInitializer}, that substitutes default {@link GlobalRootComponent} for + * TV variant {@link SystemUIFactory}, that substitutes default {@link GlobalRootComponent} for * {@link TvGlobalRootComponent} */ -public class TvSystemUIInitializer extends SystemUIInitializer { - public TvSystemUIInitializer(Context context) { - super(context); - } - +public class TvSystemUIFactory extends SystemUIFactory { @Override protected GlobalRootComponent.Builder getGlobalRootComponentBuilder() { return DaggerTvGlobalRootComponent.builder(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java index a0fdc8f1555e3..5d8e4351cfd9b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java @@ -26,8 +26,6 @@ import com.android.systemui.statusbar.policy.FlashlightController; import org.junit.Assert; import org.junit.Test; -import java.util.concurrent.ExecutionException; - @SmallTest public class DependencyTest extends SysuiTestCase { @@ -46,12 +44,10 @@ public class DependencyTest extends SysuiTestCase { } @Test - public void testInitDependency() throws ExecutionException, InterruptedException { + public void testInitDependency() { Dependency.clearDependencies(); - SystemUIInitializer initializer = - SystemUIInitializerFactory.createFromConfigNoAssert(mContext); - initializer.init(true); - Dependency dependency = initializer.getSysUIComponent().createDependency(); + Dependency dependency = + SystemUIFactory.getInstance().getSysUIComponent().createDependency(); dependency.start(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java index 9179efc9f39f5..8c20b248d02c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java @@ -34,8 +34,6 @@ import org.junit.Before; import org.junit.Rule; import org.mockito.Mockito; -import java.util.concurrent.ExecutionException; - public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { public static final Class[] ALL_SUPPORTED_CLASSES = LeakCheckedTest.ALL_SUPPORTED_CLASSES; @@ -56,11 +54,10 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { } @Before - public void sysuiSetup() throws ExecutionException, InterruptedException { - SystemUIInitializer initializer = - SystemUIInitializerFactory.createFromConfigNoAssert(mContext); - initializer.init(true); - mDependency = new TestableDependency(initializer.getSysUIComponent().createDependency()); + public void SysuiSetup() { + SystemUIFactory.createFromConfig(mContext, true); + mDependency = new TestableDependency( + SystemUIFactory.getInstance().getSysUIComponent().createDependency()); Dependency.setInstance(mDependency); // TODO: Figure out another way to give reference to a SysuiTestableContext. @@ -80,6 +77,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { public void SysuiTeardown() { InstrumentationRegistry.registerInstance(mRealInstrumentation, InstrumentationRegistry.getArguments()); + SystemUIFactory.cleanup(); } @AfterClass diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index c52ea60f0bfc6..8c7927782d2d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -76,10 +76,9 @@ public abstract class SysuiTestCase { @Before public void SysuiSetup() throws Exception { - SystemUIInitializer initializer = - SystemUIInitializerFactory.createFromConfigNoAssert(mContext); - initializer.init(true); - mDependency = new TestableDependency(initializer.getSysUIComponent().createDependency()); + SystemUIFactory.createFromConfig(mContext, true); + mDependency = new TestableDependency( + SystemUIFactory.getInstance().getSysUIComponent().createDependency()); Dependency.setInstance(mDependency); mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Looper.class), mock(Executor.class), mock(DumpManager.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java index 23516c94d8519..51c2580554653 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java @@ -45,7 +45,6 @@ import androidx.slice.core.SliceQuery; import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.SystemUIInitializerImpl; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; @@ -101,7 +100,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mIsZenMode = false; mProvider = new TestableKeyguardSliceProvider(); - mProvider.setContextAvailableCallback(context -> new SystemUIInitializerImpl(mContext)); + mProvider.setContextAvailableCallback(context -> { }); mProvider.attachInfo(getContext(), null); reset(mContentResolver); SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST))); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 6f9e60fc5d69a..3d03c4750869d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -44,7 +44,6 @@ import com.android.systemui.SysuiBaseFragmentTest; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.log.LogBuffer; import com.android.systemui.log.LogcatEchoTracker; -import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DisableFlagsLogger; @@ -113,7 +112,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { @Before public void setup() { injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); - mDependency.injectMockDependency(DarkIconDispatcher.class); } @Test