Merge "Update lock screen user switcher on settings update and re-create view stub after disabling multi-user" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-06-23 18:43:10 +00:00
committed by Android (Google) Code Review
4 changed files with 159 additions and 7 deletions

View File

@@ -27,6 +27,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
private val listeners: MutableList<ConfigurationController.ConfigurationListener> = ArrayList()
private val lastConfig = Configuration()
private var density: Int = 0
private var smallestScreenWidth: Int = 0
private var fontScale: Float = 0.toFloat()
private val inCarMode: Boolean
private var uiMode: Int = 0
@@ -38,6 +39,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
this.context = context
fontScale = currentConfig.fontScale
density = currentConfig.densityDpi
smallestScreenWidth = currentConfig.smallestScreenWidthDp
inCarMode = currentConfig.uiMode and Configuration.UI_MODE_TYPE_MASK ==
Configuration.UI_MODE_TYPE_CAR
uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
@@ -72,6 +74,14 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
this.fontScale = fontScale
}
val smallestScreenWidth = newConfig.smallestScreenWidthDp
if (smallestScreenWidth != this.smallestScreenWidth) {
this.smallestScreenWidth = smallestScreenWidth
listeners.filterForEach({ this.listeners.contains(it) }) {
it.onSmallestScreenWidthChanged()
}
}
val localeList = newConfig.locales
if (localeList != this.localeList) {
this.localeList = localeList

View File

@@ -36,9 +36,11 @@ import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.Fragment;
import android.app.StatusBarManager;
import android.content.ContentResolver;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
@@ -50,10 +52,12 @@ import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserManager;
import android.os.VibrationEffect;
import android.provider.Settings;
import android.util.Log;
import android.util.MathUtils;
import android.view.LayoutInflater;
@@ -210,6 +214,8 @@ public class NotificationPanelViewController extends PanelViewController {
new MyOnHeadsUpChangedListener();
private final HeightListener mHeightListener = new HeightListener();
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
private final SettingsChangeObserver mSettingsChangeObserver;
@VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
new StatusBarStateListener();
private final BiometricUnlockController mBiometricUnlockController;
@@ -594,6 +600,8 @@ public class NotificationPanelViewController extends PanelViewController {
private int mScreenCornerRadius;
private boolean mQSAnimatingHiddenFromCollapsed;
private final ContentResolver mContentResolver;
private final Executor mUiExecutor;
private final SecureSettings mSecureSettings;
@@ -635,6 +643,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Inject
public NotificationPanelViewController(NotificationPanelView view,
@Main Resources resources,
@Main Handler handler,
LayoutInflater layoutInflater,
NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
DynamicPrivacyController dynamicPrivacyController,
@@ -678,6 +687,7 @@ public class NotificationPanelViewController extends PanelViewController {
TapAgainViewController tapAgainViewController,
NavigationModeController navigationModeController,
FragmentService fragmentService,
ContentResolver contentResolver,
QuickAccessWalletController quickAccessWalletController,
@Main Executor uiExecutor,
SecureSettings secureSettings,
@@ -704,15 +714,12 @@ public class NotificationPanelViewController extends PanelViewController {
mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory;
mDepthController = notificationShadeDepthController;
mFeatureFlags = featureFlags;
mContentResolver = contentResolver;
mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory;
mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory;
mQSDetailDisplayer = qsDetailDisplayer;
mFragmentService = fragmentService;
mKeyguardUserSwitcherEnabled = mResources.getBoolean(
com.android.internal.R.bool.config_keyguardUserSwitcher);
mKeyguardQsUserSwitchEnabled =
mKeyguardUserSwitcherEnabled && mResources.getBoolean(
R.bool.config_keyguard_user_switch_opens_qs_details);
mSettingsChangeObserver = new SettingsChangeObserver(handler);
mShouldUseSplitNotificationShade =
Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources);
mView.setWillNotDraw(!DEBUG);
@@ -795,6 +802,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count);
updateUserSwitcherFlags();
onFinishInflate();
}
@@ -1034,6 +1042,10 @@ public class NotificationPanelViewController extends PanelViewController {
view = mLayoutInflater.inflate(layoutId, mView, false);
mView.addView(view, index);
} else {
// Add the stub back so we can re-inflate it again if necessary
ViewStub stub = new ViewStub(mView.getContext(), layoutId);
stub.setId(stubId);
mView.addView(stub, index);
view = null;
}
} else if (enabled) {
@@ -1061,6 +1073,7 @@ public class NotificationPanelViewController extends PanelViewController {
updateResources();
// Re-inflate the keyguard user switcher group.
updateUserSwitcherFlags();
boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled();
boolean showQsUserSwitch = mKeyguardQsUserSwitchEnabled && isUserSwitcherEnabled;
boolean showKeyguardUserSwitcher =
@@ -3873,6 +3886,26 @@ public class NotificationPanelViewController extends PanelViewController {
return false;
}
private void updateUserSwitcherFlags() {
mKeyguardUserSwitcherEnabled = mResources.getBoolean(
com.android.internal.R.bool.config_keyguardUserSwitcher);
mKeyguardQsUserSwitchEnabled =
mKeyguardUserSwitcherEnabled && mResources.getBoolean(
R.bool.config_keyguard_user_switch_opens_qs_details);
}
private void registerSettingsChangeListener() {
mContentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.USER_SWITCHER_ENABLED),
/* notifyForDescendants */ false,
mSettingsChangeObserver
);
}
private void unregisterSettingsChangeListener() {
mContentResolver.unregisterContentObserver(mSettingsChangeObserver);
}
private class OnHeightChangedListener implements ExpandableView.OnHeightChangedListener {
@Override
public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
@@ -4193,6 +4226,15 @@ public class NotificationPanelViewController extends PanelViewController {
reInflateViews();
}
@Override
public void onSmallestScreenWidthChanged() {
if (DEBUG) Log.d(TAG, "onSmallestScreenWidthChanged");
// Can affect multi-user switcher visibility as it depends on screen size by default:
// it is enabled only for devices with large screens (see config_keyguardUserSwitcher)
reInflateViews();
}
@Override
public void onOverlayChanged() {
if (DEBUG) Log.d(TAG, "onOverlayChanged");
@@ -4206,6 +4248,21 @@ public class NotificationPanelViewController extends PanelViewController {
}
}
private class SettingsChangeObserver extends ContentObserver {
SettingsChangeObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
if (DEBUG) Log.d(TAG, "onSettingsChanged");
// Can affect multi-user switcher visibility
reInflateViews();
}
}
private class StatusBarStateListener implements StateListener {
@Override
public void onStateChanged(int statusBarState) {
@@ -4321,10 +4378,12 @@ public class NotificationPanelViewController extends PanelViewController {
mConfigurationListener.onThemeChanged();
mFalsingManager.addTapListener(mFalsingTapListener);
mKeyguardIndicationController.init();
registerSettingsChangeListener();
}
@Override
public void onViewDetachedFromWindow(View v) {
unregisterSettingsChangeListener();
mFragmentService.getFragmentHostManager(mView)
.removeTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.removeCallback(mStatusBarStateListener);

View File

@@ -33,6 +33,7 @@ public interface ConfigurationController extends CallbackController<Configuratio
interface ConfigurationListener {
default void onConfigChanged(Configuration newConfig) {}
default void onDensityOrFontScaleChanged() {}
default void onSmallestScreenWidthChanged() {}
default void onOverlayChanged() {}
default void onUiModeChanged() {}
default void onThemeChanged() {}

View File

@@ -26,9 +26,12 @@ import static com.android.systemui.statusbar.notification.ViewGroupFadeHelper.re
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -37,9 +40,13 @@ import static org.mockito.Mockito.when;
import android.annotation.IdRes;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.UserManager;
import android.testing.AndroidTestingRunner;
@@ -50,6 +57,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.ViewStub;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -60,6 +68,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardClockSwitchController;
@@ -140,6 +149,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private KeyguardBottomAreaView mKeyguardBottomArea;
@Mock
private KeyguardBottomAreaView mQsFrame;
private KeyguardStatusView mKeyguardStatusView;
@Mock
private ViewGroup mBigClockContainer;
@Mock
@@ -153,6 +163,10 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private KeyguardStatusBarView mKeyguardStatusBar;
@Mock
private View mUserSwitcherView;
@Mock
private ViewStub mUserSwitcherStubView;
@Mock
private HeadsUpTouchHelper.Callback mHeadsUpCallback;
@Mock
private PanelBar mPanelBar;
@@ -204,7 +218,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private KeyguardClockSwitch mKeyguardClockSwitch;
private PanelViewController.TouchHandler mTouchHandler;
@Mock
private ConfigurationController mConfigurationController;
@Mock
private MediaHierarchyManager mMediaHiearchyManager;
@@ -265,6 +278,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private SecureSettings mSecureSettings;
@Mock
private ContentResolver mContentResolver;
@Mock
private TapAgainViewController mTapAgainViewController;
@Mock
private KeyguardIndicationController mKeyguardIndicationController;
@@ -287,6 +302,9 @@ public class NotificationPanelViewTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger);
mKeyguardStatusView = new KeyguardStatusView(mContext);
mKeyguardStatusView.setId(R.id.keyguard_status_view);
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
when(mHeadsUpCallback.getContext()).thenReturn(mContext);
when(mView.getResources()).thenReturn(mResources);
@@ -301,6 +319,9 @@ public class NotificationPanelViewTest extends SysuiTestCase {
when(mResources.getDimensionPixelSize(R.dimen.notification_panel_width)).thenReturn(400);
when(mView.getContext()).thenReturn(getContext());
when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
mUserSwitcherStubView);
when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
when(mView.findViewById(R.id.notification_stack_scroller))
.thenReturn(mNotificationStackScrollLayout);
@@ -320,7 +341,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
mNotificationContainerParent.addView(newViewWithId(R.id.keyguard_status_view));
mNotificationContainerParent.addView(mKeyguardStatusView);
when(mView.findViewById(R.id.notification_container_parent))
.thenReturn(mNotificationContainerParent);
when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
@@ -348,6 +369,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mFalsingManager,
mLockscreenShadeTransitionController,
new FalsingCollectorFake());
mConfigurationController = new ConfigurationControllerImpl(mContext);
when(mKeyguardStatusViewComponentFactory.build(any()))
.thenReturn(mKeyguardStatusViewComponent);
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
@@ -358,10 +380,16 @@ public class NotificationPanelViewTest extends SysuiTestCase {
.thenReturn(mKeyguardStatusBarViewComponent);
when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
.thenReturn(mKeyguardStatusBarViewController);
when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
.thenReturn(mKeyguardStatusView);
when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
.thenReturn(mKeyguardBottomArea);
reset(mView);
mNotificationPanelViewController = new NotificationPanelViewController(mView,
mResources,
new Handler(Looper.getMainLooper()),
mLayoutInflater,
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
mFalsingManager, new FalsingCollectorFake(),
@@ -395,6 +423,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mTapAgainViewController,
mNavigationModeController,
mFragmentService,
mContentResolver,
mQuickAccessWalletController,
new FakeExecutor(new FakeSystemClock()),
mSecureSettings,
@@ -548,6 +577,38 @@ public class NotificationPanelViewTest extends SysuiTestCase {
.isEqualTo(R.id.qs_edge_guideline);
}
@Test
public void testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() {
givenViewAttached();
when(mResources.getBoolean(
com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
updateMultiUserSetting(true);
clearInvocations(mView);
updateMultiUserSetting(false);
ArgumentCaptor<View> captor = ArgumentCaptor.forClass(View.class);
verify(mView, atLeastOnce()).addView(captor.capture(), anyInt());
final View userSwitcherStub = CollectionUtils.find(captor.getAllValues(),
view -> view.getId() == R.id.keyguard_user_switcher_stub);
assertThat(userSwitcherStub).isNotNull();
assertThat(userSwitcherStub).isInstanceOf(ViewStub.class);
}
@Test
public void testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() {
givenViewAttached();
when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(null);
updateSmallestScreenWidth(300);
when(mResources.getBoolean(
com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
when(mUserManager.isUserSwitcherEnabled()).thenReturn(true);
updateSmallestScreenWidth(800);
verify(mUserSwitcherStubView).inflate();
}
@Test
public void testSplitShadeLayout_isAlignedToGuideline() {
enableSplitShade();
@@ -682,6 +743,12 @@ public class NotificationPanelViewTest extends SysuiTestCase {
return mFalsingManager.getTapListeners().get(0);
}
private void givenViewAttached() {
for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
listener.onViewAttachedToWindow(mView);
}
}
private View newViewWithId(int id) {
View view = new View(mContext);
view.setId(id);
@@ -704,6 +771,21 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationPanelViewController.updateResources();
}
private void updateMultiUserSetting(boolean enabled) {
when(mUserManager.isUserSwitcherEnabled()).thenReturn(enabled);
final ArgumentCaptor<ContentObserver> observerCaptor =
ArgumentCaptor.forClass(ContentObserver.class);
verify(mContentResolver)
.registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
observerCaptor.getValue().onChange(/* selfChange */ false);
}
private void updateSmallestScreenWidth(int smallestScreenWidthDp) {
Configuration configuration = new Configuration();
configuration.smallestScreenWidthDp = smallestScreenWidthDp;
mConfigurationController.onConfigurationChanged(configuration);
}
private void onTouchEvent(MotionEvent ev) {
mTouchHandler.onTouch(mView, ev);
}