[Status Bar Refactor] Inject NotificationPanelViewController into

CollapsedStatusBarFragment.

Because NotificationPanelViewController is not @Singleton but
@StatusBarScope, we need to update the fragment creation classes to
know how to get references to @StatusBarScope classes and that's the
bulk of this CL.

Bug: 205609837
Bug: 204792508
Test: atest FragmentServiceTest
Test: atest SystemUITests
Test: manual
Change-Id: I84ef8c7621944d6924775c1fe54178af296a3485
This commit is contained in:
Caitlin Cassidy
2021-11-08 22:02:00 +00:00
parent d71cc85846
commit 3652989a71
11 changed files with 278 additions and 73 deletions

View File

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

View File

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

View File

@@ -26,6 +26,7 @@ import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
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
@@ -36,7 +37,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 {

View File

@@ -151,6 +151,7 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
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;
@@ -491,7 +492,6 @@ public class StatusBar extends CoreStartable 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
@@ -539,7 +539,7 @@ public class StatusBar extends CoreStartable 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;
@@ -547,6 +547,8 @@ public class StatusBar extends CoreStartable 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;
@@ -692,6 +694,7 @@ public class StatusBar extends CoreStartable implements
public StatusBar(
Context context,
NotificationsController notificationsController,
FragmentService fragmentService,
LightBarController lightBarController,
AutoHideController autoHideController,
StatusBarWindowController statusBarWindowController,
@@ -748,7 +751,6 @@ public class StatusBar extends CoreStartable implements
CommandQueue commandQueue,
CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
StatusBarComponent.Factory statusBarComponentFactory,
StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
PluginManager pluginManager,
Optional<LegacySplitScreen> splitScreenOptional,
LightsOutNotifController lightsOutNotifController,
@@ -793,6 +795,7 @@ public class StatusBar extends CoreStartable implements
NotifPipelineFlags notifPipelineFlags) {
super(context);
mNotificationsController = notificationsController;
mFragmentService = fragmentService;
mLightBarController = lightBarController;
mAutoHideController = autoHideController;
mStatusBarWindowController = statusBarWindowController;
@@ -854,7 +857,6 @@ public class StatusBar extends CoreStartable implements
mCommandQueue = commandQueue;
mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger;
mStatusBarComponentFactory = statusBarComponentFactory;
mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
mPluginManager = pluginManager;
mSplitScreenOptional = splitScreenOptional;
mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder;
@@ -1185,24 +1187,7 @@ public class StatusBar extends CoreStartable implements
}).getFragmentManager()
.beginTransaction()
.replace(R.id.status_bar_container,
new CollapsedStatusBarFragment(
mStatusBarFragmentComponentFactory,
mOngoingCallController,
mAnimationScheduler,
mStatusBarLocationPublisher,
mNotificationIconAreaController,
mPanelExpansionStateManager,
mFeatureFlags,
mStatusBarIconController,
mStatusBarHideIconsForBouncerManager,
mKeyguardStateController,
mNetworkController,
mStatusBarStateController,
() -> Optional.of(this),
mCommandQueue,
mCollapsedStatusBarFragmentLogger,
mOperatorNameViewControllerFactory
),
mStatusBarComponent.createCollapsedStatusBarFragment(),
CollapsedStatusBarFragment.TAG)
.commit();
@@ -1558,32 +1543,34 @@ public class StatusBar extends CoreStartable 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);
}

View File

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

View File

@@ -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.StatusBarNotificationActivityStarter
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,
@@ -199,7 +200,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,
@@ -301,7 +302,6 @@ public interface StatusBarPhoneModule {
commandQueue,
collapsedStatusBarFragmentLogger,
statusBarComponentFactory,
statusBarFragmentComponentFactory,
pluginManager,
splitScreenOptional,
lightsOutNotifController,

View File

@@ -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,20 +26,46 @@ 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.flags.Flags;
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;
@@ -45,6 +73,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
@@ -144,10 +174,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
@@ -162,4 +216,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,
StatusBarIconController statusBarIconController,
StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
KeyguardStateController keyguardStateController,
NotificationPanelViewController notificationPanelViewController,
NetworkController networkController,
StatusBarStateController statusBarStateController,
Lazy<Optional<StatusBar>> statusBarOptionalLazy,
CommandQueue commandQueue,
CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
OperatorNameViewController.Factory operatorNameViewControllerFactory
) {
return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory,
ongoingCallController,
animationScheduler,
locationPublisher,
notificationIconAreaController,
panelExpansionStateManager,
featureFlags,
statusBarIconController,
statusBarHideIconsForBouncerManager,
keyguardStateController,
notificationPanelViewController,
networkController,
statusBarStateController,
statusBarOptionalLazy,
commandQueue,
collapsedStatusBarFragmentLogger,
operatorNameViewControllerFactory);
}
}

View File

@@ -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;
@@ -146,6 +148,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
StatusBarIconController statusBarIconController,
StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
KeyguardStateController keyguardStateController,
NotificationPanelViewController notificationPanelViewController,
NetworkController networkController,
StatusBarStateController statusBarStateController,
Lazy<Optional<StatusBar>> statusBarOptionalLazy,
@@ -163,6 +166,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
mStatusBarIconController = statusBarIconController;
mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
mKeyguardStateController = keyguardStateController;
mNotificationPanelViewController = notificationPanelViewController;
mNetworkController = networkController;
mStatusBarStateController = statusBarStateController;
mStatusBarOptionalLazy = statusBarOptionalLazy;
@@ -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;
}

View File

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

View File

@@ -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;
@@ -135,7 +136,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;
@@ -246,8 +246,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;
@@ -362,8 +360,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);
@@ -378,6 +374,7 @@ public class StatusBarTest extends SysuiTestCase {
mStatusBar = new StatusBar(
mContext,
mNotificationsController,
mock(FragmentService.class),
mLightBarController,
mAutoHideController,
mStatusBarWindowController,
@@ -433,7 +430,6 @@ public class StatusBarTest extends SysuiTestCase {
mCommandQueue,
mCollapsedStatusBarFragmentLogger,
mStatusBarComponentFactory,
mStatusBarFragmentComponentFactory,
mPluginManager,
Optional.of(mLegacySplitScreen),
mLightsOutNotifController,

View File

@@ -294,6 +294,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
new StatusBarHideIconsForBouncerManager(
mCommandQueue, new FakeExecutor(new FakeSystemClock()), new DumpManager()),
mKeyguardStateController,
mock(NotificationPanelViewController.class),
mNetworkController,
mStatusBarStateController,
() -> Optional.of(mStatusBar),