diff options
11 files changed, 278 insertions, 73 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java index b45dc52585ad..10878dcc2474 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java @@ -42,7 +42,6 @@ import com.android.systemui.util.leak.LeakDetector; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; @@ -308,22 +307,22 @@ public class FragmentHostManager { return instantiateWithInjections(context, className, arguments); } - private Fragment instantiateWithInjections(Context context, String className, - Bundle args) { - Method method = mManager.getInjectionMap().get(className); - if (method != null) { + private Fragment instantiateWithInjections( + Context context, String className, Bundle args) { + FragmentService.FragmentInstantiationInfo fragmentInstantiationInfo = + mManager.getInjectionMap().get(className); + if (fragmentInstantiationInfo != null) { try { - Fragment f = (Fragment) method.invoke(mManager.getFragmentCreator()); + 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 e) { - throw new Fragment.InstantiationException("Unable to instantiate " + className, - e); - } catch (InvocationTargetException e) { + } catch (IllegalAccessException | InvocationTargetException e) { throw new Fragment.InstantiationException("Unable to instantiate " + className, e); } diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java index 7f57fcc56117..2a5e653dd051 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java @@ -18,13 +18,13 @@ import android.app.Fragment; import android.content.res.Configuration; import android.os.Handler; import android.util.ArrayMap; +import android.util.Log; 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.phone.fragment.CollapsedStatusBarFragment; import com.android.systemui.statusbar.policy.ConfigurationController; import java.io.FileDescriptor; @@ -46,9 +46,14 @@ public class FragmentService implements Dumpable { private static final String TAG = "FragmentService"; private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>(); - private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>(); + /** + * A map with the means to create fragments via Dagger injection. + * + * key: the fragment class name. + * value: see {@link FragmentInstantiationInfo}. + */ + private final ArrayMap<String, FragmentInstantiationInfo> mInjectionMap = new ArrayMap<>(); private final Handler mHandler = new Handler(); - private final FragmentCreator mFragmentCreator; private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @@ -65,26 +70,31 @@ public class FragmentService implements Dumpable { FragmentCreator.Factory fragmentCreatorFactory, ConfigurationController configurationController, DumpManager dumpManager) { - mFragmentCreator = fragmentCreatorFactory.build(); - initInjectionMap(); + addFragmentInstantiationProvider(fragmentCreatorFactory.build()); configurationController.addCallback(mConfigurationListener); dumpManager.registerDumpable(getClass().getSimpleName(), this); } - ArrayMap<String, Method> getInjectionMap() { + ArrayMap<String, FragmentInstantiationInfo> getInjectionMap() { return mInjectionMap; } - FragmentCreator getFragmentCreator() { - return mFragmentCreator; - } - - private void initInjectionMap() { - for (Method method : FragmentCreator.class.getDeclaredMethods()) { + /** + * 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) { - mInjectionMap.put(method.getReturnType().getName(), method); + 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)); } } } @@ -134,9 +144,6 @@ public class FragmentService implements Dumpable { * Inject a QSFragment. */ QSFragment createQSFragment(); - - /** Inject a CollapsedStatusBarFragment. */ - CollapsedStatusBarFragment createCollapsedStatusBarFragment(); } private class FragmentHostState { @@ -161,4 +168,16 @@ 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/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt index c814622ff074..a4feeab48e6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt @@ -25,6 +25,7 @@ import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.flags.FeatureFlags import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope +import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_HEADER import javax.inject.Inject import javax.inject.Named @@ -35,7 +36,7 @@ class SplitShadeHeaderController @Inject constructor( private val statusBarIconController: StatusBarIconController, qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder, featureFlags: FeatureFlags, - batteryMeterViewController: BatteryMeterViewController + @Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController ) { companion object { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index e033c4725999..7b6cdbecc640 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -150,6 +150,7 @@ import com.android.systemui.emergency.EmergencyGesture; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; +import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardService; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -489,7 +490,6 @@ public class StatusBar extends SystemUI implements private final DozeParameters mDozeParameters; private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy; private final StatusBarComponent.Factory mStatusBarComponentFactory; - private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; private final PluginManager mPluginManager; private final Optional<LegacySplitScreen> mSplitScreenOptional; private final StatusBarNotificationActivityStarter.Builder @@ -538,7 +538,7 @@ public class StatusBar extends SystemUI implements protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider; private final BrightnessSliderController.Factory mBrightnessSliderFactory; private final FeatureFlags mFeatureFlags; - + private final FragmentService mFragmentService; private final WallpaperController mWallpaperController; private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private final MessageRouter mMessageRouter; @@ -546,6 +546,8 @@ public class StatusBar extends SystemUI implements private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private final TunerService mTunerService; + private StatusBarComponent mStatusBarComponent; + // Flags for disabling the status bar // Two variables becaseu the first one evidently ran out of room for new flags. private int mDisabled1 = 0; @@ -690,6 +692,7 @@ public class StatusBar extends SystemUI implements public StatusBar( Context context, NotificationsController notificationsController, + FragmentService fragmentService, LightBarController lightBarController, AutoHideController autoHideController, StatusBarWindowController statusBarWindowController, @@ -747,7 +750,6 @@ public class StatusBar extends SystemUI implements CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, StatusBarComponent.Factory statusBarComponentFactory, - StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, PluginManager pluginManager, Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, @@ -791,6 +793,7 @@ public class StatusBar extends SystemUI implements ActivityLaunchAnimator activityLaunchAnimator) { super(context); mNotificationsController = notificationsController; + mFragmentService = fragmentService; mLightBarController = lightBarController; mAutoHideController = autoHideController; mStatusBarWindowController = statusBarWindowController; @@ -852,7 +855,6 @@ public class StatusBar extends SystemUI implements mCommandQueue = commandQueue; mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger; mStatusBarComponentFactory = statusBarComponentFactory; - mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory; mPluginManager = pluginManager; mSplitScreenOptional = splitScreenOptional; mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder; @@ -1184,24 +1186,7 @@ public class StatusBar extends SystemUI implements }).getFragmentManager() .beginTransaction() .replace(R.id.status_bar_container, - new CollapsedStatusBarFragment( - mStatusBarFragmentComponentFactory, - mOngoingCallController, - mAnimationScheduler, - mStatusBarLocationPublisher, - mNotificationIconAreaController, - mPanelExpansionStateManager, - mFeatureFlags, - () -> Optional.of(this), - mStatusBarIconController, - mStatusBarHideIconsForBouncerManager, - mKeyguardStateController, - mNetworkController, - mStatusBarStateController, - mCommandQueue, - mCollapsedStatusBarFragmentLogger, - mOperatorNameViewControllerFactory - ), + mStatusBarComponent.createCollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG) .commit(); @@ -1557,32 +1542,34 @@ public class StatusBar extends SystemUI implements } private void inflateStatusBarWindow() { - StatusBarComponent statusBarComponent = mStatusBarComponentFactory.create(); - mNotificationShadeWindowView = statusBarComponent.getNotificationShadeWindowView(); - mNotificationShadeWindowViewController = statusBarComponent + mStatusBarComponent = mStatusBarComponentFactory.create(); + mFragmentService.addFragmentInstantiationProvider(mStatusBarComponent); + + mNotificationShadeWindowView = mStatusBarComponent.getNotificationShadeWindowView(); + mNotificationShadeWindowViewController = mStatusBarComponent .getNotificationShadeWindowViewController(); mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); mNotificationShadeWindowViewController.setupExpandedStatusBar(); - mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController(); - statusBarComponent.getLockIconViewController().init(); - mStackScrollerController = statusBarComponent.getNotificationStackScrollLayoutController(); + mNotificationPanelViewController = mStatusBarComponent.getNotificationPanelViewController(); + mStatusBarComponent.getLockIconViewController().init(); + mStackScrollerController = mStatusBarComponent.getNotificationStackScrollLayoutController(); mStackScroller = mStackScrollerController.getView(); - mNotificationShelfController = statusBarComponent.getNotificationShelfController(); - mAuthRippleController = statusBarComponent.getAuthRippleController(); + mNotificationShelfController = mStatusBarComponent.getNotificationShelfController(); + mAuthRippleController = mStatusBarComponent.getAuthRippleController(); mAuthRippleController.init(); - mHeadsUpManager.addListener(statusBarComponent.getStatusBarHeadsUpChangeListener()); + mHeadsUpManager.addListener(mStatusBarComponent.getStatusBarHeadsUpChangeListener()); - mHeadsUpManager.addListener(statusBarComponent.getStatusBarHeadsUpChangeListener()); + mHeadsUpManager.addListener(mStatusBarComponent.getStatusBarHeadsUpChangeListener()); // Listen for demo mode changes - mDemoModeController.addCallback(statusBarComponent.getStatusBarDemoMode()); + mDemoModeController.addCallback(mStatusBarComponent.getStatusBarDemoMode()); if (mCommandQueueCallbacks != null) { mCommandQueue.removeCallback(mCommandQueueCallbacks); } - mCommandQueueCallbacks = statusBarComponent.getStatusBarCommandQueueCallbacks(); + mCommandQueueCallbacks = mStatusBarComponent.getStatusBarCommandQueueCallbacks(); // Connect in to the status bar manager service mCommandQueue.addCallback(mCommandQueueCallbacks); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java index e06605eac46f..375641fdb69d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java @@ -29,6 +29,7 @@ import com.android.systemui.statusbar.phone.SplitShadeHeaderController; import com.android.systemui.statusbar.phone.StatusBarCommandQueueCallbacks; import com.android.systemui.statusbar.phone.StatusBarDemoMode; import com.android.systemui.statusbar.phone.StatusBarHeadsUpChangeListener; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -38,7 +39,13 @@ import javax.inject.Scope; import dagger.Subcomponent; /** - * Dagger subcomponent tied to the lifecycle of StatusBar views. + * Dagger subcomponent for classes (semi-)related to the status bar. The component is created once + * inside {@link com.android.systemui.statusbar.phone.StatusBar} and never re-created. + * + * TODO(b/197137564): This should likely be re-factored a bit. It includes classes that aren't + * directly related to status bar functionality, like multiple notification classes. And, the fact + * that it has many getter methods indicates that we need to access many of these classes from + * outside the component. Should more items be moved *into* this component to avoid so many getters? */ @Subcomponent(modules = {StatusBarViewModule.class}) @StatusBarComponent.StatusBarScope @@ -121,4 +128,10 @@ public interface StatusBarComponent { */ @StatusBarScope SplitShadeHeaderController getSplitShadeHeaderController(); + + /** + * Creates a new {@link CollapsedStatusBarFragment} each time it's called. See + * {@link StatusBarViewModule#createCollapsedStatusBarFragment}. + */ + CollapsedStatusBarFragment createCollapsedStatusBarFragment(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 27ece84859d8..50e6151bd3a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -39,6 +39,7 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; @@ -100,7 +101,6 @@ import com.android.systemui.statusbar.phone.StatusBarSignalPolicy; import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; -import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -143,6 +143,7 @@ public interface StatusBarPhoneModule { static StatusBar provideStatusBar( Context context, NotificationsController notificationsController, + FragmentService fragmentService, LightBarController lightBarController, AutoHideController autoHideController, StatusBarWindowController statusBarWindowController, @@ -200,7 +201,6 @@ public interface StatusBarPhoneModule { CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, StatusBarComponent.Factory statusBarComponentFactory, - StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, PluginManager pluginManager, Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, @@ -245,6 +245,7 @@ public interface StatusBarPhoneModule { return new StatusBar( context, notificationsController, + fragmentService, lightBarController, autoHideController, statusBarWindowController, @@ -302,7 +303,6 @@ public interface StatusBarPhoneModule { commandQueue, collapsedStatusBarFragmentLogger, statusBarComponentFactory, - statusBarFragmentComponentFactory, pluginManager, splitScreenOptional, lightsOutNotifController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 2765fe37f846..76176df136b5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -17,6 +17,8 @@ package com.android.systemui.statusbar.phone.dagger; import android.annotation.Nullable; +import android.content.ContentResolver; +import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewStub; @@ -24,19 +26,45 @@ import android.view.ViewStub; import com.android.keyguard.LockIconView; import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; +import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.biometrics.AuthRippleView; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; +import com.android.systemui.statusbar.OperatorNameViewController; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; +import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelView; +import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; +import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; +import com.android.systemui.statusbar.phone.StatusBarIconController; +import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.TapAgainView; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; +import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; +import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.tuner.TunerService; + +import java.util.Optional; import javax.inject.Named; +import dagger.Lazy; import dagger.Module; import dagger.Provides; @@ -44,6 +72,8 @@ import dagger.Provides; public abstract class StatusBarViewModule { public static final String SPLIT_SHADE_HEADER = "split_shade_header"; + private static final String SPLIT_SHADE_BATTERY_VIEW = "split_shade_battery_view"; + public static final String SPLIT_SHADE_BATTERY_CONTROLLER = "split_shade_battery_controller"; /** */ @Provides @@ -143,10 +173,34 @@ public abstract class StatusBarViewModule { /** */ @Provides @StatusBarComponent.StatusBarScope + @Named(SPLIT_SHADE_BATTERY_VIEW) static BatteryMeterView getBatteryMeterView(@Named(SPLIT_SHADE_HEADER) View view) { return view.findViewById(R.id.batteryRemainingIcon); } + @Provides + @StatusBarComponent.StatusBarScope + @Named(SPLIT_SHADE_BATTERY_CONTROLLER) + static BatteryMeterViewController getBatteryMeterViewController( + @Named(SPLIT_SHADE_BATTERY_VIEW) BatteryMeterView batteryMeterView, + ConfigurationController configurationController, + TunerService tunerService, + BroadcastDispatcher broadcastDispatcher, + @Main Handler mainHandler, + ContentResolver contentResolver, + BatteryController batteryController + ) { + return new BatteryMeterViewController( + batteryMeterView, + configurationController, + tunerService, + broadcastDispatcher, + mainHandler, + contentResolver, + batteryController); + + } + /** */ @Provides @StatusBarComponent.StatusBarScope @@ -161,4 +215,54 @@ public abstract class StatusBarViewModule { NotificationShadeWindowView notificationShadeWindowView) { return notificationShadeWindowView.findViewById(R.id.notification_container_parent); } + + /** + * Creates a new {@link CollapsedStatusBarFragment}. + * + * **IMPORTANT**: This method intentionally does not have + * {@link StatusBarComponent.StatusBarScope}, which means a new fragment *will* be created each + * time this method is called. This is intentional because we need fragments to re-created in + * certain lifecycle scenarios. + * + * **IMPORTANT**: This method also intentionally does not have a {@link Provides} annotation. If + * you need to get access to a {@link CollapsedStatusBarFragment}, go through + * {@link StatusBarFragmentComponent} instead. + */ + public static CollapsedStatusBarFragment createCollapsedStatusBarFragment( + StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, + OngoingCallController ongoingCallController, + SystemStatusAnimationScheduler animationScheduler, + StatusBarLocationPublisher locationPublisher, + NotificationIconAreaController notificationIconAreaController, + PanelExpansionStateManager panelExpansionStateManager, + FeatureFlags featureFlags, + Lazy<Optional<StatusBar>> statusBarOptionalLazy, + StatusBarIconController statusBarIconController, + StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, + KeyguardStateController keyguardStateController, + NotificationPanelViewController notificationPanelViewController, + NetworkController networkController, + StatusBarStateController statusBarStateController, + CommandQueue commandQueue, + CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, + OperatorNameViewController.Factory operatorNameViewControllerFactory + ) { + return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory, + ongoingCallController, + animationScheduler, + locationPublisher, + notificationIconAreaController, + panelExpansionStateManager, + featureFlags, + statusBarOptionalLazy, + statusBarIconController, + statusBarHideIconsForBouncerManager, + keyguardStateController, + notificationPanelViewController, + networkController, + statusBarStateController, + commandQueue, + collapsedStatusBarFragmentLogger, + operatorNameViewControllerFactory); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 9bcf4a58ce0b..b32acce51e84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -53,6 +53,7 @@ import com.android.systemui.statusbar.connectivity.SignalCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.NotificationIconAreaController; +import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; @@ -94,6 +95,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private PhoneStatusBarView mStatusBar; private final StatusBarStateController mStatusBarStateController; private final KeyguardStateController mKeyguardStateController; + private final NotificationPanelViewController mNotificationPanelViewController; private final NetworkController mNetworkController; private LinearLayout mSystemIconArea; private View mClockView; @@ -147,6 +149,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue StatusBarIconController statusBarIconController, StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, KeyguardStateController keyguardStateController, + NotificationPanelViewController notificationPanelViewController, NetworkController networkController, StatusBarStateController statusBarStateController, CommandQueue commandQueue, @@ -164,6 +167,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mStatusBarIconController = statusBarIconController; mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; mKeyguardStateController = keyguardStateController; + mNotificationPanelViewController = notificationPanelViewController; mNetworkController = networkController; mStatusBarStateController = statusBarStateController; mCommandQueue = commandQueue; @@ -354,8 +358,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue // The shelf will be hidden when dozing with a custom clock, we must show notification // icons in this occasion. if (mStatusBarStateController.isDozing() - && mStatusBarOptionalLazy.get().map( - sb -> sb.getPanelController().hasCustomClock()).orElse(false)) { + && mNotificationPanelViewController.hasCustomClock()) { state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt new file mode 100644 index 000000000000..77c837b803af --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt @@ -0,0 +1,82 @@ +package com.android.systemui.fragments + +import android.app.Fragment +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 +import org.junit.Test + +@SmallTest +class FragmentServiceTest : SysuiTestCase() { + private val fragmentCreator = TestFragmentCreator() + private val fragmentCreatorFactory = FragmentService.FragmentCreator.Factory { fragmentCreator } + + private lateinit var fragmentService: FragmentService + + @Before + fun setUp() { + if (Looper.myLooper() == null) { + Looper.prepare() + } + + fragmentService = FragmentService(fragmentCreatorFactory, 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) + } + + @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() + } + ) + + val map = fragmentService.injectionMap + assertThat(map).hasSize(4) + assertThat(map.keys).contains(TestFragment2::class.java.name) + assertThat(map.keys).contains(TestFragment3::class.java.name) + } + + @Test + fun addFragmentInstantiationProvider_objectFragmentMethodsAlreadyProvided_nothingAdded() { + fragmentService.addFragmentInstantiationProvider( + @Suppress("unused") + object : Any() { + fun createTestFragment() = TestFragmentInCreator() + } + ) + + assertThat(fragmentService.injectionMap).hasSize(2) + } + + class TestFragmentCreator : FragmentService.FragmentCreator { + override fun createQSFragment(): QSFragment = mock() + @Suppress("unused") + fun createTestFragment(): TestFragmentInCreator = TestFragmentInCreator() + } + + class TestFragmentInCreator : Fragment() + class TestFragment2 : Fragment() + class TestFragment3 : Fragment() +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 88d36b0e3d44..d58e13cd8a64 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -86,6 +86,7 @@ import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; @@ -132,7 +133,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; -import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -244,8 +244,6 @@ public class StatusBarTest extends SysuiTestCase { @Mock private CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger; @Mock private StatusBarComponent.Factory mStatusBarComponentFactory; @Mock private StatusBarComponent mStatusBarComponent; - @Mock private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; - @Mock private StatusBarFragmentComponent mStatusBarFragmentComponent; @Mock private PluginManager mPluginManager; @Mock private LegacySplitScreen mLegacySplitScreen; @Mock private LightsOutNotifController mLightsOutNotifController; @@ -350,8 +348,6 @@ public class StatusBarTest extends SysuiTestCase { when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController); when(mStatusBarComponentFactory.create()).thenReturn(mStatusBarComponent); - when(mStatusBarFragmentComponentFactory.create(any())) - .thenReturn(mStatusBarFragmentComponent); when(mStatusBarComponent.getNotificationShadeWindowViewController()).thenReturn( mNotificationShadeWindowViewController); @@ -366,6 +362,7 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar = new StatusBar( mContext, mNotificationsController, + mock(FragmentService.class), mLightBarController, mAutoHideController, mStatusBarWindowController, @@ -422,7 +419,6 @@ public class StatusBarTest extends SysuiTestCase { mCommandQueue, mCollapsedStatusBarFragmentLogger, mStatusBarComponentFactory, - mStatusBarFragmentComponentFactory, mPluginManager, Optional.of(mLegacySplitScreen), mLightsOutNotifController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index ec35edfdfab2..8b5989ff61a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -295,6 +295,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { new StatusBarHideIconsForBouncerManager( mCommandQueue, new FakeExecutor(new FakeSystemClock()), new DumpManager()), mKeyguardStateController, + mock(NotificationPanelViewController.class), mNetworkController, mStatusBarStateController, mCommandQueue, |