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 Merged-In: I014039a8187057bb85b526d3cdfb5ea1324a916b
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 * 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 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 class com.android.systemui.SystemUIInitializerImpl {
|
||||
*;
|
||||
}
|
||||
|
||||
-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);
|
||||
-keep class com.android.systemui.tv.TvSystemUIInitializer {
|
||||
*;
|
||||
}
|
||||
# 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 *; }
|
||||
141
packages/SystemUI/proguard_common.flags
Normal file
141
packages/SystemUI/proguard_common.flags
Normal file
@@ -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
|
||||
@@ -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;
|
||||
@@ -116,16 +116,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.
|
||||
*
|
||||
@@ -165,6 +165,7 @@ import dagger.Provides;
|
||||
PolicyModule.class,
|
||||
PrivacyModule.class,
|
||||
QRCodeScannerModule.class,
|
||||
QSFragmentStartableModule.class,
|
||||
ScreenshotModule.class,
|
||||
SensorModule.class,
|
||||
SecurityRepositoryModule.class,
|
||||
@@ -194,8 +195,7 @@ import dagger.Provides;
|
||||
DozeComponent.class,
|
||||
ExpandableNotificationRowComponent.class,
|
||||
KeyguardBouncerComponent.class,
|
||||
NotificationShelfComponent.class,
|
||||
FragmentService.FragmentCreator.class
|
||||
NotificationShelfComponent.class
|
||||
})
|
||||
public abstract class SystemUIModule {
|
||||
|
||||
|
||||
@@ -39,16 +39,17 @@ import com.android.settingslib.applications.InterestingConfigChanges;
|
||||
import com.android.systemui.plugins.Plugin;
|
||||
import com.android.systemui.util.leak.LeakDetector;
|
||||
|
||||
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 java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
public class FragmentHostManager {
|
||||
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
|
||||
TestFragment()
|
||||
}
|
||||
|
||||
assertThat(fragmentService.injectionMap).hasSize(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addFragmentInstantiationProvider_objectHasFragmentMethods_methodsAdded() {
|
||||
fragmentService.addFragmentInstantiationProvider(
|
||||
@Suppress("unused")
|
||||
object : Any() {
|
||||
fun createTestFragment2() = TestFragment2()
|
||||
fun createTestFragment3() = TestFragment3()
|
||||
}
|
||||
)
|
||||
|
||||
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()
|
||||
}
|
||||
)
|
||||
fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
|
||||
TestFragment()
|
||||
}
|
||||
fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
|
||||
TestFragment()
|
||||
}
|
||||
|
||||
assertThat(fragmentService.injectionMap).hasSize(2)
|
||||
assertThat(fragmentService.injectionMap).hasSize(1)
|
||||
}
|
||||
|
||||
class TestFragmentCreator : FragmentService.FragmentCreator {
|
||||
override fun createQSFragment(): QSFragment = mock()
|
||||
@Suppress("unused")
|
||||
fun createTestFragment(): TestFragmentInCreator = TestFragmentInCreator()
|
||||
}
|
||||
|
||||
class TestFragmentInCreator : Fragment()
|
||||
class TestFragment2 : Fragment()
|
||||
class TestFragment3 : Fragment()
|
||||
class TestFragment : Fragment()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user