diff options
author | 2022-11-10 22:57:43 +0000 | |
---|---|---|
committer | 2023-03-09 21:28:19 +0000 | |
commit | 3b2b0e7f7dc7c4c767ac2094ed7b88e37e0e4acc (patch) | |
tree | ede15c4cce31621f418180bc0b5ac9984d088c0c | |
parent | 29c4d9c49b9e5feeca639d206fc3ad344975b385 (diff) |
Clean up proguard.flags.
Splits the file between "proguard_common.flags" that other
variants should include, and "proguard.flags" that is used
for AOSP.
Remove reflection from FragmentService. This helps proguard, and
generally makes the code more pleasant to work with.
Bug: 257631899
Test: manually built and run
Change-Id: I014039a8187057bb85b526d3cdfb5ea1324a916b
9 files changed, 252 insertions, 296 deletions
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md index 9b4c21efb27f..4a6240b56081 100644 --- a/packages/SystemUI/docs/dagger.md +++ b/packages/SystemUI/docs/dagger.md @@ -108,20 +108,13 @@ You can then include your module in one of three places: ### Using injection with Fragments -Fragments are created as part of the FragmentManager, so they need to be -setup so the manager knows how to create them. To do that, add a method -to com.android.systemui.fragments.FragmentService$FragmentCreator that -returns your fragment class. That is all that is required, once the method -exists, FragmentService will automatically pick it up and use injection -whenever your fragment needs to be created. +Fragments are created as part of the FragmentManager, so injectable Fragments need to be registered +so the manager knows how to create them. This is done via +[FragmentService#addFragmentInstantiationProvider](../src/com/android/systemui/fragments/FragmentService.java). +Pass it the class of your fragment and a `Provider` for your fragment at some time before your +Fragment is accessed. -```java -public interface FragmentCreator { - NavigationBarFragment createNavigationBar(); -} -``` - -If you need to create your fragment (i.e. for the add or replace transaction), +When you need to create your fragment (i.e. for the add or replace transaction), then the FragmentHostManager can do this for you. ```java diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags index 10bb00cad1a0..65f5a14e13e2 100644 --- a/packages/SystemUI/proguard.flags +++ b/packages/SystemUI/proguard.flags @@ -1,156 +1,13 @@ -# Preserve line number information for debugging stack traces. --keepattributes SourceFile,LineNumberTable +-include proguard_common.flags -# Preserve relationship information that can impact simple class naming. --keepattributes EnclosingMethod,InnerClasses - --keep class com.android.systemui.recents.OverviewProxyRecentsImpl --keep class com.android.systemui.statusbar.car.CarStatusBar --keep class com.android.systemui.statusbar.phone.CentralSurfaces -keep class com.android.systemui.statusbar.tv.TvStatusBar --keep class ** extends com.android.systemui.SystemUIInitializer { +-keep class com.android.systemui.SystemUIInitializerImpl { *; } --keep class * extends com.android.systemui.CoreStartable --keep class * implements com.android.systemui.CoreStartable$Injector - -# Needed for builds to properly initialize KeyFrames from xml scene --keepclassmembers class * extends androidx.constraintlayout.motion.widget.Key { - public <init>(); -} -# Needed to ensure callback field references are kept in their respective -# owning classes when the downstream callback registrars only store weak refs. -# TODO(b/264686688): Handle these cases with more targeted annotations. --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - private com.android.keyguard.KeyguardUpdateMonitorCallback *; - private com.android.systemui.privacy.PrivacyConfig$Callback *; - private com.android.systemui.privacy.PrivacyItemController$Callback *; - private com.android.systemui.settings.UserTracker$Callback *; - private com.android.systemui.statusbar.phone.StatusBarWindowCallback *; - private com.android.systemui.util.service.Observer$Callback *; - private com.android.systemui.util.service.ObservableServiceConnection$Callback *; -} -# Note that these rules are temporary companions to the above rules, required -# for cases like Kotlin where fields with anonymous types use the anonymous type -# rather than the supertype. --if class * extends com.android.keyguard.KeyguardUpdateMonitorCallback --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - <1> *; -} --if class * extends com.android.systemui.privacy.PrivacyConfig$Callback --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - <1> *; -} --if class * extends com.android.systemui.privacy.PrivacyItemController$Callback --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - <1> *; -} --if class * extends com.android.systemui.settings.UserTracker$Callback --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - <1> *; -} --if class * extends com.android.systemui.statusbar.phone.StatusBarWindowCallback --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - <1> *; -} --if class * extends com.android.systemui.util.service.Observer$Callback --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - <1> *; -} --if class * extends com.android.systemui.util.service.ObservableServiceConnection$Callback --keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { - <1> *; -} - --keepclasseswithmembers class * { - public <init>(android.content.Context, android.util.AttributeSet); -} - --keep class ** extends androidx.preference.PreferenceFragment --keep class com.android.systemui.tuner.* - -# The plugins subpackage acts as a shared library that might be referenced in -# dynamically-loaded plugin APKs. --keep class com.android.systemui.plugins.** { - *; -} --keep class com.android.systemui.fragments.FragmentService$FragmentCreator { +-keep class com.android.systemui.TVSystemUIInitializer { *; } --keep class androidx.core.app.CoreComponentFactory --keep public class * extends com.android.systemui.CoreStartable { - public <init>(android.content.Context); -} - -# Keep the wm shell lib --keep class com.android.wm.shell.* -# Keep the protolog group methods that are called by the generated code --keepclassmembers class com.android.wm.shell.protolog.ShellProtoLogGroup { - *; -} - --keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.GlobalRootComponent { !synthetic *; } --keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.GlobalRootComponent$SysUIComponentImpl { !synthetic *; } --keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.Dagger** { !synthetic *; } --keep,allowoptimization,allowaccessmodification class com.android.systemui.tv.Dagger** { !synthetic *; } - -# Prevent optimization or access modification of any referenced code that may -# conflict with code in the bootclasspath. -# TODO(b/222468116): Resolve such collisions in the build system. --keepnames class android.**.nano.** { *; } --keepnames class com.android.**.nano.** { *; } --keepnames class com.android.internal.protolog.** { *; } --keepnames class android.hardware.common.** { *; } - -# Allows proguard to make private and protected methods and fields public as -# part of optimization. This lets proguard inline trivial getter/setter methods. --allowaccessmodification - -# Removes runtime checks added through Kotlin to JVM code genereration to -# avoid linear growth as more Kotlin code is converted / added to the codebase. -# These checks are generally applied to Java platform types (values returned -# from Java code that don't have nullness annotations), but we remove them to -# avoid code size increases. -# -# See also https://kotlinlang.org/docs/reference/java-interop.html -# -# TODO(b/199941987): Consider standardizing these rules in a central place as -# Kotlin gains adoption with other platform targets. --assumenosideeffects class kotlin.jvm.internal.Intrinsics { - # Remove check for method parameters being null - static void checkParameterIsNotNull(java.lang.Object, java.lang.String); - - # When a Java platform type is returned and passed to Kotlin NonNull method, - # remove the null check - static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String); - static void checkNotNullExpressionValue(java.lang.Object, java.lang.String); - - # Remove check that final value returned from method is null, if passing - # back Java platform type. - static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String, java.lang.String); - static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String); - - # Null check for accessing a field from a parent class written in Java. - static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String); - static void checkFieldIsNotNull(java.lang.Object, java.lang.String); - - # Removes code generated from !! operator which converts Nullable type to - # NonNull type. These would throw an NPE immediate after on access. - static void checkNotNull(java.lang.Object, java.lang.String); - static void checkNotNullParameter(java.lang.Object, java.lang.String); - - # Removes lateinit var check being used before being set. Check is applied - # on every field access without this. - static void throwUninitializedPropertyAccessException(java.lang.String); -} -# Strip verbose logs. --assumenosideeffects class android.util.Log { - static *** v(...); - static *** isLoggable(...); -} --assumenosideeffects class android.util.Slog { - static *** v(...); -} --maximumremovedandroidloglevel 2 +-keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.DaggerReferenceGlobalRootComponent** { !synthetic *; } +-keep,allowoptimization,allowaccessmodification class com.android.systemui.tv.DaggerTvGlobalRootComponent** { !synthetic *; }
\ No newline at end of file diff --git a/packages/SystemUI/proguard_common.flags b/packages/SystemUI/proguard_common.flags new file mode 100644 index 000000000000..1d008cf57ea7 --- /dev/null +++ b/packages/SystemUI/proguard_common.flags @@ -0,0 +1,141 @@ +# Preserve line number information for debugging stack traces. +-keepattributes SourceFile,LineNumberTable + +-keep class com.android.systemui.VendorServices + +# the `#inject` methods are accessed via reflection to work on ContentProviders +-keepclassmembers class * extends com.android.systemui.dagger.SysUIComponent { void inject(***); } + +# Needed for builds to properly initialize KeyFrames from xml scene +-keepclassmembers class * extends androidx.constraintlayout.motion.widget.Key { + public <init>(); +} + +# Needed to ensure callback field references are kept in their respective +# owning classes when the downstream callback registrars only store weak refs. +# TODO(b/264686688): Handle these cases with more targeted annotations. +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + private com.android.keyguard.KeyguardUpdateMonitorCallback *; + private com.android.systemui.privacy.PrivacyConfig$Callback *; + private com.android.systemui.privacy.PrivacyItemController$Callback *; + private com.android.systemui.settings.UserTracker$Callback *; + private com.android.systemui.statusbar.phone.StatusBarWindowCallback *; + private com.android.systemui.util.service.Observer$Callback *; + private com.android.systemui.util.service.ObservableServiceConnection$Callback *; +} +# Note that these rules are temporary companions to the above rules, required +# for cases like Kotlin where fields with anonymous types use the anonymous type +# rather than the supertype. +-if class * extends com.android.keyguard.KeyguardUpdateMonitorCallback +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + <1> *; +} +-if class * extends com.android.systemui.privacy.PrivacyConfig$Callback +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + <1> *; +} +-if class * extends com.android.systemui.privacy.PrivacyItemController$Callback +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + <1> *; +} +-if class * extends com.android.systemui.settings.UserTracker$Callback +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + <1> *; +} +-if class * extends com.android.systemui.statusbar.phone.StatusBarWindowCallback +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + <1> *; +} +-if class * extends com.android.systemui.util.service.Observer$Callback +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + <1> *; +} +-if class * extends com.android.systemui.util.service.ObservableServiceConnection$Callback +-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** { + <1> *; +} + +-keepclasseswithmembers class * { + public <init>(android.content.Context, android.util.AttributeSet); +} + +-keep class ** extends androidx.preference.PreferenceFragment +-keep class com.android.systemui.tuner.* + +# The plugins subpackage acts as a shared library that might be referenced in +# dynamically-loaded plugin APKs. +-keep class com.android.systemui.plugins.** { + *; +} +-keep class com.android.systemui.fragments.FragmentService$FragmentCreator { + *; +} +-keep class androidx.core.app.CoreComponentFactory + +# Keep the wm shell lib +-keep class com.android.wm.shell.* +# Keep the protolog group methods that are called by the generated code +-keepclassmembers class com.android.wm.shell.protolog.ShellProtoLogGroup { + *; +} + +# Prevent optimization or access modification of any referenced code that may +# conflict with code in the bootclasspath. +# TODO(b/222468116): Resolve such collisions in the build system. +-keepnames class android.**.nano.** { *; } +-keepnames class com.android.**.nano.** { *; } +-keepnames class com.android.internal.protolog.** { *; } +-keepnames class android.hardware.common.** { *; } + +# Allows proguard to make private and protected methods and fields public as +# part of optimization. This lets proguard inline trivial getter/setter methods. +-allowaccessmodification + +# Removes runtime checks added through Kotlin to JVM code genereration to +# avoid linear growth as more Kotlin code is converted / added to the codebase. +# These checks are generally applied to Java platform types (values returned +# from Java code that don't have nullness annotations), but we remove them to +# avoid code size increases. +# +# See also https://kotlinlang.org/docs/reference/java-interop.html +# +# TODO(b/199941987): Consider standardizing these rules in a central place as +# Kotlin gains adoption with other platform targets. +-assumenosideeffects class kotlin.jvm.internal.Intrinsics { + # Remove check for method parameters being null + static void checkParameterIsNotNull(java.lang.Object, java.lang.String); + + # When a Java platform type is returned and passed to Kotlin NonNull method, + # remove the null check + static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String); + static void checkNotNullExpressionValue(java.lang.Object, java.lang.String); + + # Remove check that final value returned from method is null, if passing + # back Java platform type. + static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String, java.lang.String); + static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String); + + # Null check for accessing a field from a parent class written in Java. + static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String); + static void checkFieldIsNotNull(java.lang.Object, java.lang.String); + + # Removes code generated from !! operator which converts Nullable type to + # NonNull type. These would throw an NPE immediate after on access. + static void checkNotNull(java.lang.Object, java.lang.String); + static void checkNotNullParameter(java.lang.Object, java.lang.String); + + # Removes lateinit var check being used before being set. Check is applied + # on every field access without this. + static void throwUninitializedPropertyAccessException(java.lang.String); +} + + +# Strip verbose logs. +-assumenosideeffects class android.util.Log { + static *** v(...); + static *** isLoggable(...); +} +-assumenosideeffects class android.util.Slog { + static *** v(...); +} +-maximumremovedandroidloglevel 2 diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 7a1abf46bd93..90994afcd1ae 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -47,7 +47,6 @@ import com.android.systemui.dreams.dagger.DreamModule; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FlagsModule; -import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyboard.KeyboardModule; import com.android.systemui.keyguard.data.BouncerViewModule; import com.android.systemui.log.dagger.LogModule; @@ -63,6 +62,7 @@ import com.android.systemui.privacy.PrivacyModule; import com.android.systemui.qrcodescanner.dagger.QRCodeScannerModule; import com.android.systemui.qs.FgsManagerController; import com.android.systemui.qs.FgsManagerControllerImpl; +import com.android.systemui.qs.QSFragmentStartableModule; import com.android.systemui.qs.footer.dagger.FooterActionsModule; import com.android.systemui.recents.Recents; import com.android.systemui.screenrecord.ScreenRecordModule; @@ -114,16 +114,16 @@ import com.android.systemui.wallet.dagger.WalletModule; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; -import java.util.Optional; -import java.util.concurrent.Executor; - -import javax.inject.Named; - import dagger.Binds; import dagger.BindsOptionalOf; import dagger.Module; import dagger.Provides; +import java.util.Optional; +import java.util.concurrent.Executor; + +import javax.inject.Named; + /** * A dagger module for injecting components of System UI that are required by System UI. * @@ -163,6 +163,7 @@ import dagger.Provides; PolicyModule.class, PrivacyModule.class, QRCodeScannerModule.class, + QSFragmentStartableModule.class, ScreenshotModule.class, SensorModule.class, SecurityRepositoryModule.class, @@ -192,8 +193,7 @@ import dagger.Provides; DozeComponent.class, ExpandableNotificationRowComponent.class, KeyguardBouncerComponent.class, - NotificationShelfComponent.class, - FragmentService.FragmentCreator.class + NotificationShelfComponent.class }) public abstract class SystemUIModule { diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java index 6a27ee7c0c89..81a520661cfe 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java @@ -39,15 +39,16 @@ import com.android.settingslib.applications.InterestingConfigChanges; import com.android.systemui.plugins.Plugin; import com.android.systemui.util.leak.LeakDetector; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; + import java.io.FileDescriptor; import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; -import dagger.assisted.Assisted; -import dagger.assisted.AssistedFactory; -import dagger.assisted.AssistedInject; +import javax.inject.Provider; public class FragmentHostManager { @@ -322,25 +323,17 @@ public class FragmentHostManager { return instantiateWithInjections(context, className, arguments); } - private Fragment instantiateWithInjections( - Context context, String className, Bundle args) { - FragmentService.FragmentInstantiationInfo fragmentInstantiationInfo = + private Fragment instantiateWithInjections(Context context, String className, Bundle args) { + Provider<? extends Fragment> fragmentProvider = mManager.getInjectionMap().get(className); - if (fragmentInstantiationInfo != null) { - try { - Fragment f = (Fragment) fragmentInstantiationInfo - .mMethod - .invoke(fragmentInstantiationInfo.mDaggerComponent); - // Setup the args, taken from Fragment#instantiate. - if (args != null) { - args.setClassLoader(f.getClass().getClassLoader()); - f.setArguments(args); - } - return f; - } catch (IllegalAccessException | InvocationTargetException e) { - throw new Fragment.InstantiationException("Unable to instantiate " + className, - e); + if (fragmentProvider != null) { + Fragment f = fragmentProvider.get(); + // Setup the args, taken from Fragment#instantiate. + if (args != null) { + args.setClassLoader(f.getClass().getClassLoader()); + f.setArguments(args); } + return f; } return Fragment.instantiate(context, className, args); } diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java index d302b13a68b6..a75c056c5c71 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java @@ -24,16 +24,12 @@ import android.view.View; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; -import com.android.systemui.qs.QSFragment; import com.android.systemui.statusbar.policy.ConfigurationController; import java.io.PrintWriter; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import javax.inject.Inject; - -import dagger.Subcomponent; +import javax.inject.Provider; /** * Holds a map of root views to FragmentHostStates and generates them as needed. @@ -49,9 +45,9 @@ public class FragmentService implements Dumpable { * A map with the means to create fragments via Dagger injection. * * key: the fragment class name. - * value: see {@link FragmentInstantiationInfo}. + * value: A {@link Provider} for the Fragment */ - private final ArrayMap<String, FragmentInstantiationInfo> mInjectionMap = new ArrayMap<>(); + private final ArrayMap<String, Provider<? extends Fragment>> mInjectionMap = new ArrayMap<>(); private final Handler mHandler = new Handler(); private final FragmentHostManager.Factory mFragmentHostManagerFactory; @@ -67,38 +63,31 @@ public class FragmentService implements Dumpable { @Inject public FragmentService( - FragmentCreator.Factory fragmentCreatorFactory, FragmentHostManager.Factory fragmentHostManagerFactory, ConfigurationController configurationController, DumpManager dumpManager) { mFragmentHostManagerFactory = fragmentHostManagerFactory; - addFragmentInstantiationProvider(fragmentCreatorFactory.build()); configurationController.addCallback(mConfigurationListener); - dumpManager.registerDumpable(getClass().getSimpleName(), this); + dumpManager.registerNormalDumpable(this); } - ArrayMap<String, FragmentInstantiationInfo> getInjectionMap() { + ArrayMap<String, Provider<? extends Fragment>> getInjectionMap() { return mInjectionMap; } /** * Adds a new Dagger component object that provides method(s) to create fragments via injection. */ - public void addFragmentInstantiationProvider(Object daggerComponent) { - for (Method method : daggerComponent.getClass().getDeclaredMethods()) { - if (Fragment.class.isAssignableFrom(method.getReturnType()) - && (method.getModifiers() & Modifier.PUBLIC) != 0) { - String fragmentName = method.getReturnType().getName(); - if (mInjectionMap.containsKey(fragmentName)) { - Log.w(TAG, "Fragment " + fragmentName + " is already provided by different" - + " Dagger component; Not adding method"); - continue; - } - mInjectionMap.put( - fragmentName, new FragmentInstantiationInfo(method, daggerComponent)); - } + public void addFragmentInstantiationProvider( + Class<?> fragmentCls, Provider<? extends Fragment> provider) { + String fragmentName = fragmentCls.getName(); + if (mInjectionMap.containsKey(fragmentName)) { + Log.w(TAG, "Fragment " + fragmentName + " is already provided by different" + + " Dagger component; Not adding method"); + return; } + mInjectionMap.put(fragmentName, provider); } public FragmentHostManager getFragmentHostManager(View view) { @@ -132,22 +121,6 @@ public class FragmentService implements Dumpable { } } - /** - * The subcomponent of dagger that holds all fragments that need injection. - */ - @Subcomponent - public interface FragmentCreator { - /** Factory for creating a FragmentCreator. */ - @Subcomponent.Factory - interface Factory { - FragmentCreator build(); - } - /** - * Inject a QSFragment. - */ - QSFragment createQSFragment(); - } - private class FragmentHostState { private final View mView; @@ -170,16 +143,4 @@ public class FragmentService implements Dumpable { mFragmentHostManager.onConfigurationChanged(newConfig); } } - - /** An object containing the information needed to instantiate a fragment. */ - static class FragmentInstantiationInfo { - /** The method that returns a newly-created fragment of the given class. */ - final Method mMethod; - /** The Dagger component that the method should be invoked on. */ - final Object mDaggerComponent; - FragmentInstantiationInfo(Method method, Object daggerComponent) { - this.mMethod = method; - this.mDaggerComponent = daggerComponent; - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt new file mode 100644 index 000000000000..253560b93f1a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 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.qs + +import com.android.systemui.CoreStartable +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.fragments.FragmentService +import dagger.Binds +import dagger.Module +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap +import javax.inject.Inject +import javax.inject.Provider + +@SysUISingleton +class QSFragmentStartable +@Inject +constructor( + private val fragmentService: FragmentService, + private val qsFragmentProvider: Provider<QSFragment> +) : CoreStartable { + override fun start() { + fragmentService.addFragmentInstantiationProvider(QSFragment::class.java, qsFragmentProvider) + } +} + +@Module +interface QSFragmentStartableModule { + @Binds + @IntoMap + @ClassKey(QSFragmentStartable::class) + fun bindsQSFragmentStartable(startable: QSFragmentStartable): CoreStartable +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 664d61acf7cc..73a3ca889ee3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -228,6 +228,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BrightnessMirrorController; @@ -1613,7 +1614,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { } } mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create(); - mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent); + mFragmentService.addFragmentInstantiationProvider( + CollapsedStatusBarFragment.class, + mCentralSurfacesComponent::createCollapsedStatusBarFragment); mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView(); mNotificationShadeWindowViewController = mCentralSurfacesComponent diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt index a2dc1eb606ed..4ba1bc6dfbbb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt @@ -5,7 +5,6 @@ import android.os.Looper import android.test.suitebuilder.annotation.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager -import com.android.systemui.qs.QSFragment import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -13,9 +12,7 @@ import org.junit.Test @SmallTest class FragmentServiceTest : SysuiTestCase() { - private val fragmentCreator = TestFragmentCreator() - private val fragmenetHostManagerFactory: FragmentHostManager.Factory = mock() - private val fragmentCreatorFactory = FragmentService.FragmentCreator.Factory { fragmentCreator } + private val fragmentHostManagerFactory: FragmentHostManager.Factory = mock() private lateinit var fragmentService: FragmentService @@ -25,65 +22,29 @@ class FragmentServiceTest : SysuiTestCase() { Looper.prepare() } - fragmentService = - FragmentService( - fragmentCreatorFactory, - fragmenetHostManagerFactory, - mock(), - DumpManager() - ) - } - - @Test - fun constructor_addsFragmentCreatorMethodsToMap() { - val map = fragmentService.injectionMap - assertThat(map).hasSize(2) - assertThat(map.keys).contains(QSFragment::class.java.name) - assertThat(map.keys).contains(TestFragmentInCreator::class.java.name) + fragmentService = FragmentService(fragmentHostManagerFactory, mock(), DumpManager()) } @Test fun addFragmentInstantiationProvider_objectHasNoFragmentMethods_nothingAdded() { - fragmentService.addFragmentInstantiationProvider(Object()) - - assertThat(fragmentService.injectionMap).hasSize(2) - } - - @Test - fun addFragmentInstantiationProvider_objectHasFragmentMethods_methodsAdded() { - fragmentService.addFragmentInstantiationProvider( - @Suppress("unused") - object : Any() { - fun createTestFragment2() = TestFragment2() - fun createTestFragment3() = TestFragment3() - } - ) + fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) { + TestFragment() + } - val map = fragmentService.injectionMap - assertThat(map).hasSize(4) - assertThat(map.keys).contains(TestFragment2::class.java.name) - assertThat(map.keys).contains(TestFragment3::class.java.name) + assertThat(fragmentService.injectionMap).hasSize(1) } @Test fun addFragmentInstantiationProvider_objectFragmentMethodsAlreadyProvided_nothingAdded() { - fragmentService.addFragmentInstantiationProvider( - @Suppress("unused") - object : Any() { - fun createTestFragment() = TestFragmentInCreator() - } - ) - - assertThat(fragmentService.injectionMap).hasSize(2) - } + fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) { + TestFragment() + } + fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) { + TestFragment() + } - class TestFragmentCreator : FragmentService.FragmentCreator { - override fun createQSFragment(): QSFragment = mock() - @Suppress("unused") - fun createTestFragment(): TestFragmentInCreator = TestFragmentInCreator() + assertThat(fragmentService.injectionMap).hasSize(1) } - class TestFragmentInCreator : Fragment() - class TestFragment2 : Fragment() - class TestFragment3 : Fragment() + class TestFragment : Fragment() } |