Merge "Clean up proguard.flags." into udc-dev

This commit is contained in:
Dave Mankoff
2023-04-17 18:50:39 +00:00
committed by Android (Google) Code Review
9 changed files with 251 additions and 295 deletions

View File

@@ -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

View File

@@ -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 *; }

View 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

View File

@@ -48,7 +48,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;
@@ -64,6 +63,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;
@@ -169,6 +169,7 @@ import javax.inject.Named;
PolicyModule.class,
PrivacyModule.class,
QRCodeScannerModule.class,
QSFragmentStartableModule.class,
ScreenshotModule.class,
SensorModule.class,
SecurityRepositoryModule.class,
@@ -198,8 +199,7 @@ import javax.inject.Named;
DozeComponent.class,
ExpandableNotificationRowComponent.class,
KeyguardBouncerComponent.class,
NotificationShelfComponent.class,
FragmentService.FragmentCreator.class
NotificationShelfComponent.class
})
public abstract class SystemUIModule {

View File

@@ -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);
}

View File

@@ -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;
}
}
}

View File

@@ -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
}

View File

@@ -232,6 +232,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;
@@ -1632,7 +1633,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
}
mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent);
mFragmentService.addFragmentInstantiationProvider(
CollapsedStatusBarFragment.class,
mCentralSurfacesComponent::createCollapsedStatusBarFragment);
mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView();
mNotificationShadeWindowViewController = mCentralSurfacesComponent

View File

@@ -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()
}