Merge "Add keyguard shortcut for opening QS user panel" into sc-dev am: 7e24b8beff
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13567820 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Id4d58e04c3ddbb89501bcfc8d66e418c257adcfb
This commit is contained in:
@@ -46,6 +46,21 @@ public interface DetailAdapter {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if detail panel should animate when shown or closed
|
||||
*/
|
||||
default boolean shouldAnimate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the callback handled the event and wants to keep the detail panel open, false
|
||||
* otherwise. Returning false will close the panel.
|
||||
*/
|
||||
default boolean onDoneButtonClicked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default UiEventLogger.UiEventEnum openDetailEvent() {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
32
packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
Normal file
32
packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2021 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
|
||||
-->
|
||||
<!-- This is a view that shows a user switcher in Keyguard. -->
|
||||
<com.android.systemui.statusbar.phone.UserAvatarView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:systemui="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/keyguard_qs_user_switch_view"
|
||||
android:layout_width="@dimen/kg_framed_avatar_size"
|
||||
android:layout_height="@dimen/kg_framed_avatar_size"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
systemui:avatarPadding="0dp"
|
||||
systemui:badgeDiameter="18dp"
|
||||
systemui:badgeMargin="1dp"
|
||||
systemui:frameColor="@color/kg_user_avatar_frame"
|
||||
systemui:framePadding="0dp"
|
||||
systemui:frameWidth="0dp">
|
||||
</com.android.systemui.statusbar.phone.UserAvatarView>
|
||||
@@ -31,6 +31,12 @@
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/keyguard_qs_user_switch_stub"
|
||||
android:layout="@layout/keyguard_qs_user_switch"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/keyguard_user_switcher_stub"
|
||||
android:layout="@layout/keyguard_user_switcher"
|
||||
|
||||
@@ -279,6 +279,11 @@
|
||||
<!-- Whether to show the full screen user switcher. -->
|
||||
<bool name="config_enableFullscreenUserSwitcher">false</bool>
|
||||
|
||||
<!-- Whether the multi-user switch on the keyguard opens QS user panel. If false, clicking the
|
||||
user switch on the keyguard will replace the notifications and status area with the user
|
||||
switcher. The multi-user switch is only shown if config_keyguardUserSwitcher=false. -->
|
||||
<bool name="config_keyguard_user_switch_opens_qs_details">false</bool>
|
||||
|
||||
<!-- SystemUIFactory component -->
|
||||
<string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>
|
||||
|
||||
|
||||
@@ -802,7 +802,7 @@
|
||||
<!-- Size of user icon + frame in the qs user picker (incl. frame) -->
|
||||
<dimen name="qs_framed_avatar_size">54dp</dimen>
|
||||
<!-- Size of user icon + frame in the keyguard user picker (incl. frame) -->
|
||||
<dimen name="kg_framed_avatar_size">32dp</dimen>
|
||||
<dimen name="kg_framed_avatar_size">48dp</dimen>
|
||||
|
||||
<!-- Margin on the left side of the carrier text on Keyguard -->
|
||||
<dimen name="keyguard_carrier_text_margin">16dp</dimen>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.keyguard.dagger;
|
||||
|
||||
import com.android.systemui.statusbar.phone.UserAvatarView;
|
||||
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Subcomponent;
|
||||
|
||||
/**
|
||||
* Subcomponent for helping work with KeyguardQsUserSwitch and its children.
|
||||
*/
|
||||
@Subcomponent(modules = {KeyguardUserSwitcherModule.class})
|
||||
@KeyguardUserSwitcherScope
|
||||
public interface KeyguardQsUserSwitchComponent {
|
||||
/** Simple factory for {@link KeyguardUserSwitcherComponent}. */
|
||||
@Subcomponent.Factory
|
||||
interface Factory {
|
||||
KeyguardQsUserSwitchComponent build(
|
||||
@BindsInstance UserAvatarView userAvatarView);
|
||||
}
|
||||
|
||||
/** Builds a {@link KeyguardQsUserSwitchController}. */
|
||||
KeyguardQsUserSwitchController getKeyguardQsUserSwitchController();
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardDisplayManager;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardViewController;
|
||||
import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
@@ -62,7 +63,8 @@ import dagger.Provides;
|
||||
/**
|
||||
* Dagger Module providing {@link StatusBar}.
|
||||
*/
|
||||
@Module(subcomponents = {KeyguardStatusViewComponent.class, KeyguardUserSwitcherComponent.class},
|
||||
@Module(subcomponents = {KeyguardStatusViewComponent.class,
|
||||
KeyguardQsUserSwitchComponent.class, KeyguardUserSwitcherComponent.class},
|
||||
includes = {FalsingModule.class})
|
||||
public class KeyguardModule {
|
||||
/**
|
||||
|
||||
@@ -72,6 +72,7 @@ public class QSDetail extends LinearLayout {
|
||||
private boolean mFullyExpanded;
|
||||
private QuickStatusBarHeader mHeader;
|
||||
private boolean mTriggeredExpand;
|
||||
private boolean mShouldAnimate;
|
||||
private int mOpenX;
|
||||
private int mOpenY;
|
||||
private boolean mAnimatingOpen;
|
||||
@@ -108,16 +109,6 @@ public class QSDetail extends LinearLayout {
|
||||
updateDetailText();
|
||||
|
||||
mClipper = new QSDetailClipper(this);
|
||||
|
||||
final OnClickListener doneListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
announceForAccessibility(
|
||||
mContext.getString(R.string.accessibility_desc_quick_settings));
|
||||
mQsPanelController.closeDetail();
|
||||
}
|
||||
};
|
||||
mDetailDoneButton.setOnClickListener(doneListener);
|
||||
}
|
||||
|
||||
/** */
|
||||
@@ -169,6 +160,7 @@ public class QSDetail extends LinearLayout {
|
||||
public void handleShowingDetail(final DetailAdapter adapter, int x, int y,
|
||||
boolean toggleQs) {
|
||||
final boolean showingDetail = adapter != null;
|
||||
final boolean wasShowingDetail = mDetailAdapter != null;
|
||||
setClickable(showingDetail);
|
||||
if (showingDetail) {
|
||||
setupDetailHeader(adapter);
|
||||
@@ -178,6 +170,7 @@ public class QSDetail extends LinearLayout {
|
||||
} else {
|
||||
mTriggeredExpand = false;
|
||||
}
|
||||
mShouldAnimate = adapter.shouldAnimate();
|
||||
mOpenX = x;
|
||||
mOpenY = y;
|
||||
} else {
|
||||
@@ -190,10 +183,10 @@ public class QSDetail extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
boolean visibleDiff = (mDetailAdapter != null) != (adapter != null);
|
||||
if (!visibleDiff && mDetailAdapter == adapter) return; // already in right state
|
||||
AnimatorListener listener = null;
|
||||
if (adapter != null) {
|
||||
boolean visibleDiff = wasShowingDetail != showingDetail;
|
||||
if (!visibleDiff && !wasShowingDetail) return; // already in right state
|
||||
AnimatorListener listener;
|
||||
if (showingDetail) {
|
||||
int viewCacheIndex = adapter.getMetricsCategory();
|
||||
View detailView = adapter.createDetailView(mContext, mDetailViews.get(viewCacheIndex),
|
||||
mDetailContent);
|
||||
@@ -213,7 +206,7 @@ public class QSDetail extends LinearLayout {
|
||||
listener = mHideGridContentWhenDone;
|
||||
setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (mDetailAdapter != null) {
|
||||
if (wasShowingDetail) {
|
||||
Dependency.get(MetricsLogger.class).hidden(mDetailAdapter.getMetricsCategory());
|
||||
mUiEventLogger.log(mDetailAdapter.closeDetailEvent());
|
||||
}
|
||||
@@ -227,7 +220,15 @@ public class QSDetail extends LinearLayout {
|
||||
}
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
|
||||
animateDetailVisibleDiff(x, y, visibleDiff, listener);
|
||||
if (mShouldAnimate) {
|
||||
animateDetailVisibleDiff(x, y, visibleDiff, listener);
|
||||
} else {
|
||||
if (showingDetail) {
|
||||
showImmediately();
|
||||
} else {
|
||||
hideImmediately();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void animateDetailVisibleDiff(int x, int y, boolean visibleDiff, AnimatorListener listener) {
|
||||
@@ -245,6 +246,17 @@ public class QSDetail extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
void showImmediately() {
|
||||
setVisibility(VISIBLE);
|
||||
mClipper.cancelAnimator();
|
||||
mClipper.showBackground();
|
||||
}
|
||||
|
||||
public void hideImmediately() {
|
||||
mClipper.cancelAnimator();
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
protected void setupDetailFooter(DetailAdapter adapter) {
|
||||
final Intent settingsIntent = adapter.getSettingsIntent();
|
||||
mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
|
||||
@@ -255,6 +267,13 @@ public class QSDetail extends LinearLayout {
|
||||
Dependency.get(ActivityStarter.class)
|
||||
.postStartActivityDismissingKeyguard(settingsIntent, 0);
|
||||
});
|
||||
mDetailDoneButton.setOnClickListener(v -> {
|
||||
announceForAccessibility(
|
||||
mContext.getString(R.string.accessibility_desc_quick_settings));
|
||||
if (!adapter.onDoneButtonClicked()) {
|
||||
mQsPanelController.closeDetail();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void setupDetailHeader(final DetailAdapter adapter) {
|
||||
|
||||
@@ -39,7 +39,7 @@ public class QSDetailDisplayer {
|
||||
/** Show the supplied DetailAdapter in the Quick Settings. */
|
||||
public void showDetailAdapter(DetailAdapter detailAdapter, int x, int y) {
|
||||
if (mQsPanelController != null) {
|
||||
mQsPanelController.showDetailDapater(detailAdapter, x, y);
|
||||
mQsPanelController.showDetailAdapter(detailAdapter, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
|
||||
}
|
||||
|
||||
/** */
|
||||
public void showDetailDapater(DetailAdapter detailAdapter, int x, int y) {
|
||||
public void showDetailAdapter(DetailAdapter detailAdapter, int x, int y) {
|
||||
mView.showDetailAdapter(true, detailAdapter, new int[]{x, y});
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public class UserTile extends QSTileImpl<State> implements UserInfoController.On
|
||||
|
||||
@Override
|
||||
public DetailAdapter getDetailAdapter() {
|
||||
return mUserSwitcherController.userDetailAdapter;
|
||||
return mUserSwitcherController.mUserDetailAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -56,16 +56,23 @@ public class KeyguardClockPositionAlgorithm {
|
||||
private int mKeyguardStatusHeight;
|
||||
|
||||
/**
|
||||
* Height of {@link KeyguardUserSwitcherListView} when it
|
||||
* is closed and only the current user's icon is visible.
|
||||
* Height of user avatar used by the multi-user switcher. This could either be the
|
||||
* {@link KeyguardUserSwitcherListView} when it is closed and only the current user's icon is
|
||||
* visible, or it could be height of the avatar used by the
|
||||
* {@link com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController}.
|
||||
*/
|
||||
private int mKeyguardUserSwitcherHeight;
|
||||
private int mUserSwitchHeight;
|
||||
|
||||
/**
|
||||
* Preferred Y position of clock.
|
||||
*/
|
||||
private int mClockPreferredY;
|
||||
|
||||
/**
|
||||
* Preferred Y position of user avatar used by the multi-user switcher.
|
||||
*/
|
||||
private int mUserSwitchPreferredY;
|
||||
|
||||
/**
|
||||
* Whether or not there is a custom clock face on keyguard.
|
||||
*/
|
||||
@@ -181,20 +188,21 @@ public class KeyguardClockPositionAlgorithm {
|
||||
*/
|
||||
public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
|
||||
float panelExpansion, int parentHeight, int keyguardStatusHeight,
|
||||
int keyguardUserSwitcherHeight, int clockPreferredY, boolean hasCustomClock,
|
||||
boolean hasVisibleNotifs, float dark, float emptyDragAmount, boolean bypassEnabled,
|
||||
int unlockedStackScrollerPadding, boolean showLockIcon, float qsExpansion,
|
||||
int cutoutTopInset) {
|
||||
int userSwitchHeight, int clockPreferredY, int userSwitchPreferredY,
|
||||
boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
|
||||
boolean bypassEnabled, int unlockedStackScrollerPadding, boolean showLockIcon,
|
||||
float qsExpansion, int cutoutTopInset) {
|
||||
mMinTopMargin = statusBarMinHeight + (showLockIcon
|
||||
? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon)
|
||||
+ keyguardUserSwitcherHeight;
|
||||
+ userSwitchHeight;
|
||||
mMaxShadeBottom = maxShadeBottom;
|
||||
mNotificationStackHeight = notificationStackHeight;
|
||||
mPanelExpansion = panelExpansion;
|
||||
mHeight = parentHeight;
|
||||
mKeyguardStatusHeight = keyguardStatusHeight;
|
||||
mKeyguardUserSwitcherHeight = keyguardUserSwitcherHeight;
|
||||
mUserSwitchHeight = userSwitchHeight;
|
||||
mClockPreferredY = clockPreferredY;
|
||||
mUserSwitchPreferredY = userSwitchPreferredY;
|
||||
mHasCustomClock = hasCustomClock;
|
||||
mHasVisibleNotifs = hasVisibleNotifs;
|
||||
mDarkAmount = dark;
|
||||
@@ -208,6 +216,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
public void run(Result result) {
|
||||
final int y = getClockY(mPanelExpansion, mDarkAmount);
|
||||
result.clockY = y;
|
||||
result.userSwitchY = getUserSwitcherY(mPanelExpansion);
|
||||
result.clockYFullyDozing = getClockY(
|
||||
1.0f /* panelExpansion */, 1.0f /* darkAmount */);
|
||||
result.clockAlpha = getClockAlpha(y);
|
||||
@@ -241,7 +250,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
|
||||
private int getExpandedPreferredClockY() {
|
||||
if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
|
||||
return mMinTopMargin;
|
||||
return mMinTopMargin + mUserSwitchHeight;
|
||||
}
|
||||
return (mHasCustomClock && (!mHasVisibleNotifs || mBypassEnabled)) ? getPreferredClockY()
|
||||
: getExpandedClockPosition();
|
||||
@@ -257,7 +266,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
final int containerCenter = mMinTopMargin + availableHeight / 2;
|
||||
|
||||
float y = containerCenter
|
||||
- (mKeyguardStatusHeight + mKeyguardUserSwitcherHeight) * CLOCK_HEIGHT_WEIGHT
|
||||
- (mKeyguardStatusHeight + mUserSwitchHeight) * CLOCK_HEIGHT_WEIGHT
|
||||
- mClockNotificationsMargin - mNotificationStackHeight / 2;
|
||||
if (y < mMinTopMargin) {
|
||||
y = mMinTopMargin;
|
||||
@@ -299,6 +308,17 @@ public class KeyguardClockPositionAlgorithm {
|
||||
return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mEmptyDragAmount);
|
||||
}
|
||||
|
||||
private int getUserSwitcherY(float panelExpansion) {
|
||||
float userSwitchYRegular = mUserSwitchPreferredY;
|
||||
float userSwitchYBouncer = -mKeyguardStatusHeight - mUserSwitchHeight;
|
||||
|
||||
// Move user-switch up while collapsing the shade
|
||||
float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
|
||||
float userSwitchY = MathUtils.lerp(userSwitchYBouncer, userSwitchYRegular, shadeExpansion);
|
||||
|
||||
return (int) (userSwitchY + mEmptyDragAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* We might want to fade out the clock when the user is swiping up.
|
||||
* One exception is when the bouncer will become visible, in this cause the clock
|
||||
@@ -340,6 +360,11 @@ public class KeyguardClockPositionAlgorithm {
|
||||
*/
|
||||
public int clockY;
|
||||
|
||||
/**
|
||||
* The y translation of the multi-user switch.
|
||||
*/
|
||||
public int userSwitchY;
|
||||
|
||||
/**
|
||||
* The y translation of the clock when we're fully dozing.
|
||||
*/
|
||||
|
||||
@@ -168,6 +168,6 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
|
||||
}
|
||||
|
||||
protected DetailAdapter getUserDetailAdapter() {
|
||||
return mUserSwitcherController.userDetailAdapter;
|
||||
return mUserSwitcherController.mUserDetailAdapter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ import com.android.keyguard.KeyguardStatusView;
|
||||
import com.android.keyguard.KeyguardStatusViewController;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||
import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
|
||||
import com.android.systemui.DejankUtils;
|
||||
@@ -95,9 +96,11 @@ import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
|
||||
import com.android.systemui.media.MediaDataManager;
|
||||
import com.android.systemui.media.MediaHierarchyManager;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.plugins.qs.DetailAdapter;
|
||||
import com.android.systemui.plugins.qs.QS;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
|
||||
import com.android.systemui.qs.QSDetailDisplayer;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.GestureRecorder;
|
||||
@@ -133,6 +136,7 @@ import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
|
||||
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
|
||||
@@ -292,14 +296,13 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
new KeyguardUserSwitcherController.KeyguardUserSwitcherListener() {
|
||||
@Override
|
||||
public void onKeyguardUserSwitcherChanged(boolean open) {
|
||||
if (mKeyguardUserSwitcherController != null
|
||||
&& mKeyguardUserSwitcherController.isSimpleUserSwitcher()) {
|
||||
return;
|
||||
if (mKeyguardUserSwitcherController == null) {
|
||||
updateUserSwitcherVisibility(false);
|
||||
} else if (!mKeyguardUserSwitcherController.isSimpleUserSwitcher()) {
|
||||
updateUserSwitcherVisibility(open
|
||||
&& mKeyguardStateController.isShowing()
|
||||
&& !mKeyguardStateController.isKeyguardFadingAway());
|
||||
}
|
||||
|
||||
updateUserSwitcherVisibility(open
|
||||
&& mKeyguardStateController.isShowing()
|
||||
&& !mKeyguardStateController.isKeyguardFadingAway());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -315,7 +318,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private final MediaHierarchyManager mMediaHierarchyManager;
|
||||
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
|
||||
private final KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
|
||||
private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
|
||||
private final QSDetailDisplayer mQSDetailDisplayer;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final ScrimController mScrimController;
|
||||
private final ControlsComponent mControlsComponent;
|
||||
@@ -327,6 +332,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private int mMaxAllowedKeyguardNotifications;
|
||||
|
||||
private KeyguardAffordanceHelper mAffordanceHelper;
|
||||
private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
|
||||
private boolean mKeyguardUserSwitcherIsShowing;
|
||||
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
|
||||
private KeyguardStatusBarView mKeyguardStatusBar;
|
||||
private ViewGroup mBigClockContainer;
|
||||
@@ -352,6 +359,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private boolean mQsExpandedWhenExpandingStarted;
|
||||
private boolean mQsFullyExpanded;
|
||||
private boolean mKeyguardShowing;
|
||||
private boolean mKeyguardQsUserSwitchEnabled;
|
||||
private boolean mKeyguardUserSwitcherEnabled;
|
||||
private boolean mDozing;
|
||||
private boolean mDozingOnDown;
|
||||
@@ -578,7 +586,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
||||
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
|
||||
KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
|
||||
KeyguardQsUserSwitchComponent.Factory keyguardQsUserSwitchComponentFactory,
|
||||
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
||||
QSDetailDisplayer qsDetailDisplayer,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
NotificationIconAreaController notificationIconAreaController,
|
||||
AuthController authController,
|
||||
@@ -605,9 +615,14 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mNotificationIconAreaController = notificationIconAreaController;
|
||||
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
|
||||
mFeatureFlags = featureFlags;
|
||||
mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory;
|
||||
mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory;
|
||||
mQSDetailDisplayer = qsDetailDisplayer;
|
||||
mKeyguardUserSwitcherEnabled = mResources.getBoolean(
|
||||
com.android.internal.R.bool.config_keyguardUserSwitcher);
|
||||
mKeyguardQsUserSwitchEnabled =
|
||||
mKeyguardUserSwitcherEnabled && mResources.getBoolean(
|
||||
R.bool.config_keyguard_user_switch_opens_qs_details);
|
||||
mView.setWillNotDraw(!DEBUG);
|
||||
mLayoutInflater = layoutInflater;
|
||||
mFalsingManager = falsingManager;
|
||||
@@ -688,15 +703,21 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
|
||||
mBigClockContainer = mView.findViewById(R.id.big_clock_container);
|
||||
|
||||
UserAvatarView userAvatarView = null;
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView = null;
|
||||
|
||||
if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled()) {
|
||||
ViewStub userSwitcherStub = mView.findViewById(R.id.keyguard_user_switcher_stub);
|
||||
keyguardUserSwitcherView = (KeyguardUserSwitcherView) userSwitcherStub.inflate();
|
||||
if (mKeyguardQsUserSwitchEnabled) {
|
||||
ViewStub stub = mView.findViewById(R.id.keyguard_qs_user_switch_stub);
|
||||
userAvatarView = (UserAvatarView) stub.inflate();
|
||||
} else {
|
||||
ViewStub stub = mView.findViewById(R.id.keyguard_user_switcher_stub);
|
||||
keyguardUserSwitcherView = (KeyguardUserSwitcherView) stub.inflate();
|
||||
}
|
||||
}
|
||||
|
||||
updateViewControllers(mView.findViewById(R.id.keyguard_status_view),
|
||||
keyguardUserSwitcherView);
|
||||
userAvatarView, keyguardUserSwitcherView);
|
||||
mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
|
||||
NotificationStackScrollLayout stackScrollLayout = mView.findViewById(
|
||||
R.id.notification_stack_scroller);
|
||||
@@ -770,7 +791,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
|
||||
private void updateViewControllers(KeyguardStatusView keyguardStatusView,
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView) {
|
||||
UserAvatarView userAvatarView, KeyguardUserSwitcherView keyguardUserSwitcherView) {
|
||||
// Re-associate the KeyguardStatusViewController
|
||||
KeyguardStatusViewComponent statusViewComponent =
|
||||
mKeyguardStatusViewComponentFactory.build(keyguardStatusView);
|
||||
@@ -789,18 +810,27 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mKeyguardUserSwitcherController.removeCallback();
|
||||
}
|
||||
|
||||
mKeyguardQsUserSwitchController = null;
|
||||
mKeyguardUserSwitcherController = null;
|
||||
|
||||
// Re-associate the KeyguardUserSwitcherController
|
||||
if (keyguardUserSwitcherView != null) {
|
||||
if (userAvatarView != null) {
|
||||
KeyguardQsUserSwitchComponent userSwitcherComponent =
|
||||
mKeyguardQsUserSwitchComponentFactory.build(userAvatarView);
|
||||
mKeyguardQsUserSwitchController =
|
||||
userSwitcherComponent.getKeyguardQsUserSwitchController();
|
||||
mKeyguardQsUserSwitchController.setNotificationPanelViewController(this);
|
||||
mKeyguardQsUserSwitchController.init();
|
||||
mKeyguardStatusBar.setKeyguardUserSwitcherEnabled(true);
|
||||
} else if (keyguardUserSwitcherView != null) {
|
||||
KeyguardUserSwitcherComponent userSwitcherComponent =
|
||||
mKeyguardUserSwitcherComponentFactory.build(keyguardUserSwitcherView);
|
||||
|
||||
mKeyguardUserSwitcherController =
|
||||
userSwitcherComponent.getKeyguardUserSwitcherController();
|
||||
mKeyguardUserSwitcherController.setCallback(mKeyguardUserSwitcherListener);
|
||||
mKeyguardUserSwitcherController.init();
|
||||
mKeyguardStatusBar.setKeyguardUserSwitcherEnabled(true);
|
||||
} else {
|
||||
mKeyguardUserSwitcherController = null;
|
||||
mKeyguardStatusBar.setKeyguardUserSwitcherEnabled(false);
|
||||
}
|
||||
}
|
||||
@@ -856,6 +886,25 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private View reInflateStub(int viewId, int stubId, int layoutId, boolean enabled) {
|
||||
View view = mView.findViewById(viewId);
|
||||
if (view != null) {
|
||||
int index = mView.indexOfChild(view);
|
||||
mView.removeView(view);
|
||||
if (enabled) {
|
||||
view = mLayoutInflater.inflate(layoutId, mView, false);
|
||||
mView.addView(view, index);
|
||||
} else {
|
||||
view = null;
|
||||
}
|
||||
} else if (enabled) {
|
||||
// It's possible the stub was never inflated if the configuration changed
|
||||
ViewStub stub = mView.findViewById(stubId);
|
||||
view = stub.inflate();
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private void reInflateViews() {
|
||||
if (DEBUG) Log.d(TAG, "reInflateViews");
|
||||
// Re-inflate the status view group.
|
||||
@@ -867,26 +916,26 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mView.addView(keyguardStatusView, index);
|
||||
|
||||
// Re-inflate the keyguard user switcher group.
|
||||
boolean showUserSwitcher =
|
||||
mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled();
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView = mView.findViewById(
|
||||
R.id.keyguard_user_switcher_view);
|
||||
if (keyguardUserSwitcherView != null) {
|
||||
index = mView.indexOfChild(keyguardUserSwitcherView);
|
||||
mView.removeView(keyguardUserSwitcherView);
|
||||
if (showUserSwitcher) {
|
||||
keyguardUserSwitcherView = (KeyguardUserSwitcherView) mLayoutInflater.inflate(
|
||||
R.layout.keyguard_user_switcher, mView, false);
|
||||
mView.addView(keyguardUserSwitcherView, index);
|
||||
}
|
||||
} else if (showUserSwitcher) {
|
||||
// It's possible the user switcher was never inflated if the configuration changed
|
||||
ViewStub userSwitcherStub = mView.findViewById(R.id.keyguard_user_switcher_stub);
|
||||
keyguardUserSwitcherView = (KeyguardUserSwitcherView) userSwitcherStub.inflate();
|
||||
}
|
||||
boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled();
|
||||
boolean showQsUserSwitch = mKeyguardQsUserSwitchEnabled && isUserSwitcherEnabled;
|
||||
boolean showKeyguardUserSwitcher =
|
||||
!mKeyguardQsUserSwitchEnabled
|
||||
&& mKeyguardUserSwitcherEnabled
|
||||
&& isUserSwitcherEnabled;
|
||||
UserAvatarView userAvatarView = (UserAvatarView) reInflateStub(
|
||||
R.id.keyguard_qs_user_switch_view /* viewId */,
|
||||
R.id.keyguard_qs_user_switch_stub /* stubId */,
|
||||
R.layout.keyguard_qs_user_switch /* layoutId */,
|
||||
showQsUserSwitch /* enabled */);
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView =
|
||||
(KeyguardUserSwitcherView) reInflateStub(
|
||||
R.id.keyguard_user_switcher_view /* viewId */,
|
||||
R.id.keyguard_user_switcher_stub /* stubId */,
|
||||
R.layout.keyguard_user_switcher /* layoutId */,
|
||||
showKeyguardUserSwitcher /* enabled */);
|
||||
|
||||
mBigClockContainer.removeAllViews();
|
||||
updateViewControllers(keyguardStatusView, keyguardUserSwitcherView);
|
||||
updateViewControllers(keyguardStatusView, userAvatarView, keyguardUserSwitcherView);
|
||||
|
||||
// Update keyguard bottom area
|
||||
index = mView.indexOfChild(mKeyguardBottomArea);
|
||||
@@ -910,6 +959,13 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
false,
|
||||
false,
|
||||
mBarState);
|
||||
if (mKeyguardQsUserSwitchController != null) {
|
||||
mKeyguardQsUserSwitchController.setKeyguardQsUserSwitchVisibility(
|
||||
mBarState,
|
||||
false,
|
||||
false,
|
||||
mBarState);
|
||||
}
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.setKeyguardUserSwitcherVisibility(
|
||||
mBarState,
|
||||
@@ -1009,10 +1065,15 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
int totalHeight = mView.getHeight();
|
||||
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
|
||||
int clockPreferredY = mKeyguardStatusViewController.getClockPreferredY(totalHeight);
|
||||
int userSwitcherPreferredY = mStatusBarMinHeight;
|
||||
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
|
||||
final boolean hasVisibleNotifications = mNotificationStackScrollLayoutController
|
||||
.getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia();
|
||||
mKeyguardStatusViewController.setHasVisibleNotifications(hasVisibleNotifications);
|
||||
int userIconHeight = mKeyguardQsUserSwitchController != null
|
||||
? mKeyguardQsUserSwitchController.getUserIconHeight()
|
||||
: (mKeyguardUserSwitcherController != null
|
||||
? mKeyguardUserSwitcherController.getUserIconHeight() : 0);
|
||||
mClockPositionAlgorithm.setup(mStatusBarMinHeight, totalHeight - bottomPadding,
|
||||
mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
|
||||
getExpandedFraction(),
|
||||
@@ -1021,9 +1082,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
? mKeyguardStatusViewController.getHeight()
|
||||
: (int) (mKeyguardStatusViewController.getHeight()
|
||||
- mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
|
||||
mKeyguardUserSwitcherController == null
|
||||
? 0 : mKeyguardUserSwitcherController.getUserIconHeight(),
|
||||
clockPreferredY, hasCustomClock(),
|
||||
userIconHeight,
|
||||
clockPreferredY, userSwitcherPreferredY, hasCustomClock(),
|
||||
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
|
||||
bypassEnabled, getUnlockedStackScrollerPadding(),
|
||||
mUpdateMonitor.canShowLockIcon(),
|
||||
@@ -1033,11 +1093,16 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mKeyguardStatusViewController.updatePosition(
|
||||
mClockPositionResult.clockX, mClockPositionResult.clockY,
|
||||
mClockPositionResult.clockScale, animateClock);
|
||||
if (mKeyguardQsUserSwitchController != null) {
|
||||
mKeyguardQsUserSwitchController.updatePosition(
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.userSwitchY,
|
||||
animateClock);
|
||||
}
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.updatePosition(
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.clockY
|
||||
- mKeyguardUserSwitcherController.getUserIconHeight(),
|
||||
mClockPositionResult.userSwitchY,
|
||||
animateClock);
|
||||
}
|
||||
updateNotificationTranslucency();
|
||||
@@ -1180,6 +1245,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
|
||||
private void updateClock() {
|
||||
mKeyguardStatusViewController.setAlpha(mClockPositionResult.clockAlpha);
|
||||
if (mKeyguardQsUserSwitchController != null) {
|
||||
mKeyguardQsUserSwitchController.setAlpha(mClockPositionResult.clockAlpha);
|
||||
}
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.setAlpha(mClockPositionResult.clockAlpha);
|
||||
}
|
||||
@@ -1271,6 +1339,12 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public void expandWithQsDetail(DetailAdapter qsDetailAdapter) {
|
||||
traceQsJank(true /* startTracing */, false /* wasCancelled */);
|
||||
flingSettings(0 /* velocity */, FLING_EXPAND);
|
||||
mQSDetailDisplayer.showDetailAdapter(qsDetailAdapter, 0, 0);
|
||||
}
|
||||
|
||||
public void expandWithoutQs() {
|
||||
if (isQsExpanded()) {
|
||||
flingSettings(0 /* velocity */, FLING_COLLAPSE);
|
||||
@@ -3166,6 +3240,13 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
true /* keyguardFadingAway */,
|
||||
false /* goingToFullShade */,
|
||||
mBarState);
|
||||
if (mKeyguardQsUserSwitchController != null) {
|
||||
mKeyguardQsUserSwitchController.setKeyguardQsUserSwitchVisibility(
|
||||
mBarState,
|
||||
true /* keyguardFadingAway */,
|
||||
false /* goingToFullShade */,
|
||||
mBarState);
|
||||
}
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.setKeyguardUserSwitcherVisibility(
|
||||
mBarState,
|
||||
@@ -3432,6 +3513,12 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
|
||||
private void updateUserSwitcherVisibility(boolean open) {
|
||||
// Do not update if previously called with the same state.
|
||||
if (mKeyguardUserSwitcherIsShowing == open) {
|
||||
return;
|
||||
}
|
||||
mKeyguardUserSwitcherIsShowing = open;
|
||||
|
||||
if (open) {
|
||||
animateKeyguardStatusBarOut();
|
||||
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.statusbar.policy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.DataSetObserver;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.keyguard.KeyguardConstants;
|
||||
import com.android.keyguard.KeyguardVisibilityHelper;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherScope;
|
||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.keyguard.ScreenLifecycle;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.AnimatableProperty;
|
||||
import com.android.systemui.statusbar.notification.PropertyAnimator;
|
||||
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
|
||||
import com.android.systemui.statusbar.phone.UserAvatarView;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Manages the user switch on the Keyguard that is used for opening the QS user panel.
|
||||
*/
|
||||
@KeyguardUserSwitcherScope
|
||||
public class KeyguardQsUserSwitchController extends ViewController<UserAvatarView> {
|
||||
|
||||
private static final String TAG = "KeyguardQsUserSwitchController";
|
||||
private static final boolean DEBUG = KeyguardConstants.DEBUG;
|
||||
|
||||
private static final AnimationProperties ANIMATION_PROPERTIES =
|
||||
new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||
|
||||
private final Context mContext;
|
||||
private Resources mResources;
|
||||
private final UserSwitcherController mUserSwitcherController;
|
||||
private final ScreenLifecycle mScreenLifecycle;
|
||||
private UserSwitcherController.BaseUserAdapter mAdapter;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
protected final SysuiStatusBarStateController mStatusBarStateController;
|
||||
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
|
||||
private final KeyguardUserDetailAdapter mUserDetailAdapter;
|
||||
private NotificationPanelViewController mNotificationPanelViewController;
|
||||
private UserManager mUserManager;
|
||||
UserSwitcherController.UserRecord mCurrentUser;
|
||||
|
||||
// State info for the user switch and keyguard
|
||||
private int mBarState;
|
||||
private float mDarkAmount;
|
||||
|
||||
private final StatusBarStateController.StateListener mStatusBarStateListener =
|
||||
new StatusBarStateController.StateListener() {
|
||||
@Override
|
||||
public void onStateChanged(int newState) {
|
||||
if (DEBUG) Log.d(TAG, String.format("onStateChanged: newState=%d", newState));
|
||||
|
||||
boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
|
||||
boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
|
||||
int oldState = mBarState;
|
||||
mBarState = newState;
|
||||
|
||||
setKeyguardQsUserSwitchVisibility(
|
||||
newState,
|
||||
keyguardFadingAway,
|
||||
goingToFullShade,
|
||||
oldState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDozeAmountChanged(float linearAmount, float amount) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("onDozeAmountChanged: linearAmount=%f amount=%f",
|
||||
linearAmount, amount));
|
||||
}
|
||||
setDarkAmount(amount);
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public KeyguardQsUserSwitchController(
|
||||
UserAvatarView view,
|
||||
Context context,
|
||||
@Main Resources resources,
|
||||
UserManager userManager,
|
||||
ScreenLifecycle screenLifecycle,
|
||||
UserSwitcherController userSwitcherController,
|
||||
KeyguardStateController keyguardStateController,
|
||||
SysuiStatusBarStateController statusBarStateController,
|
||||
DozeParameters dozeParameters,
|
||||
UiEventLogger uiEventLogger) {
|
||||
super(view);
|
||||
if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController");
|
||||
mContext = context;
|
||||
mResources = resources;
|
||||
mUserManager = userManager;
|
||||
mScreenLifecycle = screenLifecycle;
|
||||
mUserSwitcherController = userSwitcherController;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
|
||||
keyguardStateController, dozeParameters);
|
||||
mUserDetailAdapter = new KeyguardUserDetailAdapter(mUserSwitcherController, mContext,
|
||||
uiEventLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
if (DEBUG) Log.d(TAG, "onInit");
|
||||
mAdapter = new UserSwitcherController.BaseUserAdapter(mUserSwitcherController) {
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
mView.setOnClickListener(v -> {
|
||||
if (isListAnimating()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tapping anywhere in the view will open QS user panel
|
||||
openQsUserPanel();
|
||||
});
|
||||
|
||||
updateView(true /* forceUpdate */);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
if (DEBUG) Log.d(TAG, "onViewAttached");
|
||||
mAdapter.registerDataSetObserver(mDataSetObserver);
|
||||
mDataSetObserver.onChanged();
|
||||
mStatusBarStateController.addCallback(mStatusBarStateListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
if (DEBUG) Log.d(TAG, "onViewDetached");
|
||||
|
||||
mAdapter.unregisterDataSetObserver(mDataSetObserver);
|
||||
mStatusBarStateController.removeCallback(mStatusBarStateListener);
|
||||
}
|
||||
|
||||
public final DataSetObserver mDataSetObserver = new DataSetObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
updateView(false /* forceUpdate */);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return true if the current user has changed
|
||||
*/
|
||||
private boolean updateCurrentUser() {
|
||||
UserSwitcherController.UserRecord previousUser = mCurrentUser;
|
||||
mCurrentUser = null;
|
||||
for (int i = 0; i < mAdapter.getCount(); i++) {
|
||||
UserSwitcherController.UserRecord r = mAdapter.getItem(i);
|
||||
if (r.isCurrent) {
|
||||
mCurrentUser = r;
|
||||
return !mCurrentUser.equals(previousUser);
|
||||
}
|
||||
}
|
||||
return mCurrentUser == null && previousUser != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forceUpdate whether to update view even if current user did not change
|
||||
*/
|
||||
private void updateView(boolean forceUpdate) {
|
||||
if (!updateCurrentUser() && !forceUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCurrentUser == null) {
|
||||
mView.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
|
||||
String currentUserName = mCurrentUser.info.name;
|
||||
String contentDescription = null;
|
||||
|
||||
if (!TextUtils.isEmpty(currentUserName)) {
|
||||
contentDescription = mContext.getString(
|
||||
R.string.accessibility_quick_settings_user,
|
||||
currentUserName);
|
||||
}
|
||||
|
||||
if (!TextUtils.equals(mView.getContentDescription(), contentDescription)) {
|
||||
mView.setContentDescription(contentDescription);
|
||||
}
|
||||
|
||||
if (mCurrentUser.picture == null) {
|
||||
mView.setDrawableWithBadge(getDrawable(mCurrentUser).mutate(),
|
||||
mCurrentUser.resolveId());
|
||||
} else {
|
||||
int avatarSize =
|
||||
(int) mResources.getDimension(R.dimen.kg_framed_avatar_size);
|
||||
Drawable drawable = new CircleFramedDrawable(mCurrentUser.picture, avatarSize);
|
||||
drawable.setColorFilter(
|
||||
mCurrentUser.isSwitchToEnabled ? null
|
||||
: mAdapter.getDisabledUserAvatarColorFilter());
|
||||
mView.setDrawableWithBadge(drawable, mCurrentUser.info.id);
|
||||
}
|
||||
}
|
||||
|
||||
Drawable getDrawable(UserSwitcherController.UserRecord item) {
|
||||
Drawable drawable;
|
||||
if (item.isCurrent && item.isGuest) {
|
||||
drawable = mContext.getDrawable(R.drawable.ic_avatar_guest_user);
|
||||
} else {
|
||||
drawable = mAdapter.getIconDrawable(mContext, item);
|
||||
}
|
||||
|
||||
int iconColorRes;
|
||||
if (item.isSwitchToEnabled) {
|
||||
iconColorRes = R.color.kg_user_switcher_avatar_icon_color;
|
||||
} else {
|
||||
iconColorRes = R.color.kg_user_switcher_restricted_avatar_icon_color;
|
||||
}
|
||||
drawable.setTint(mResources.getColor(iconColorRes, mContext.getTheme()));
|
||||
|
||||
Drawable bg = mContext.getDrawable(R.drawable.kg_bg_avatar);
|
||||
drawable = new LayerDrawable(new Drawable[]{bg, drawable});
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the keyguard user switcher view when closed.
|
||||
*/
|
||||
public int getUserIconHeight() {
|
||||
return mView.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the visibility of the user avatar view based on some new state.
|
||||
*/
|
||||
public void setKeyguardQsUserSwitchVisibility(
|
||||
int statusBarState,
|
||||
boolean keyguardFadingAway,
|
||||
boolean goingToFullShade,
|
||||
int oldStatusBarState) {
|
||||
mKeyguardVisibilityHelper.setViewVisibility(
|
||||
statusBarState, keyguardFadingAway, goingToFullShade, oldStatusBarState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update position of the view with an optional animation
|
||||
*/
|
||||
public void updatePosition(int x, int y, boolean animate) {
|
||||
PropertyAnimator.setProperty(mView, AnimatableProperty.Y, y, ANIMATION_PROPERTIES, animate);
|
||||
PropertyAnimator.setProperty(mView, AnimatableProperty.TRANSLATION_X, -Math.abs(x),
|
||||
ANIMATION_PROPERTIES, animate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set keyguard user avatar view alpha.
|
||||
*/
|
||||
public void setAlpha(float alpha) {
|
||||
if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
|
||||
mView.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount (ratio) that the device has transitioned to doze.
|
||||
*
|
||||
* @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
|
||||
*/
|
||||
private void setDarkAmount(float darkAmount) {
|
||||
boolean isAwake = darkAmount != 0;
|
||||
if (darkAmount == mDarkAmount) {
|
||||
return;
|
||||
}
|
||||
mDarkAmount = darkAmount;
|
||||
mView.setVisibility(isAwake ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private boolean isListAnimating() {
|
||||
return mKeyguardVisibilityHelper.isVisibilityAnimating();
|
||||
}
|
||||
|
||||
private void openQsUserPanel() {
|
||||
mNotificationPanelViewController.expandWithQsDetail(mUserDetailAdapter);
|
||||
}
|
||||
|
||||
public void setNotificationPanelViewController(
|
||||
NotificationPanelViewController notificationPanelViewController) {
|
||||
mNotificationPanelViewController = notificationPanelViewController;
|
||||
}
|
||||
|
||||
class KeyguardUserDetailAdapter extends UserSwitcherController.UserDetailAdapter {
|
||||
KeyguardUserDetailAdapter(UserSwitcherController userSwitcherController, Context context,
|
||||
UiEventLogger uiEventLogger) {
|
||||
super(userSwitcherController, context, uiEventLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAnimate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoneButtonClicked() {
|
||||
if (mNotificationPanelViewController != null) {
|
||||
mNotificationPanelViewController.animateCloseQs(true /* animateAway */);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,7 @@ public class UserSwitcherController implements Dumpable {
|
||||
private Intent mSecondaryUserServiceIntent;
|
||||
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
public final DetailAdapter mUserDetailAdapter;
|
||||
|
||||
@Inject
|
||||
public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
|
||||
@@ -131,6 +132,7 @@ public class UserSwitcherController implements Dumpable {
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mActivityTaskManager = activityTaskManager;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mUserDetailAdapter = new UserDetailAdapter(this, mContext, mUiEventLogger);
|
||||
if (!UserManager.isGuestUserEphemeral()) {
|
||||
mGuestResumeSessionReceiver.register(mBroadcastDispatcher);
|
||||
}
|
||||
@@ -781,9 +783,20 @@ public class UserSwitcherController implements Dumpable {
|
||||
}
|
||||
}
|
||||
|
||||
public final DetailAdapter userDetailAdapter = new DetailAdapter() {
|
||||
public static class UserDetailAdapter implements DetailAdapter {
|
||||
private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
|
||||
|
||||
private final UserSwitcherController mUserSwitcherController;
|
||||
private final Context mContext;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
UserDetailAdapter(UserSwitcherController userSwitcherController, Context context,
|
||||
UiEventLogger uiEventLogger) {
|
||||
mUserSwitcherController = userSwitcherController;
|
||||
mContext = context;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getTitle() {
|
||||
return mContext.getString(R.string.quick_settings_user_title);
|
||||
@@ -794,7 +807,7 @@ public class UserSwitcherController implements Dumpable {
|
||||
UserDetailView v;
|
||||
if (!(convertView instanceof UserDetailView)) {
|
||||
v = UserDetailView.inflate(context, parent, false);
|
||||
v.createAndSetAdapter(UserSwitcherController.this, mUiEventLogger);
|
||||
v.createAndSetAdapter(mUserSwitcherController, mUiEventLogger);
|
||||
} else {
|
||||
v = (UserDetailView) convertView;
|
||||
}
|
||||
|
||||
@@ -394,8 +394,8 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
|
||||
private void positionClock() {
|
||||
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
|
||||
mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight,
|
||||
0 /* keyguardUserSwitcherHeight */, mPreferredClockY, mHasCustomClock,
|
||||
mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
|
||||
0 /* userSwitchHeight */, mPreferredClockY, 0 /* userSwitchPreferredY */,
|
||||
mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
|
||||
0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */, mQsExpansion,
|
||||
mCutoutTopInset);
|
||||
mClockPositionAlgorithm.run(mClockPosition);
|
||||
|
||||
@@ -58,6 +58,7 @@ import com.android.keyguard.KeyguardClockSwitchController;
|
||||
import com.android.keyguard.KeyguardStatusView;
|
||||
import com.android.keyguard.KeyguardStatusViewController;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
|
||||
import com.android.systemui.R;
|
||||
@@ -70,6 +71,7 @@ import com.android.systemui.controls.dagger.ControlsComponent;
|
||||
import com.android.systemui.doze.DozeLog;
|
||||
import com.android.systemui.media.MediaDataManager;
|
||||
import com.android.systemui.media.MediaHierarchyManager;
|
||||
import com.android.systemui.qs.QSDetailDisplayer;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||
@@ -194,7 +196,11 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
|
||||
@Mock
|
||||
private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponent;
|
||||
private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
|
||||
@Mock
|
||||
private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
|
||||
@Mock
|
||||
private QSDetailDisplayer mQSDetailDisplayer;
|
||||
@Mock
|
||||
private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
|
||||
@Mock
|
||||
@@ -305,7 +311,9 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
mBiometricUnlockController, mStatusBarKeyguardViewManager,
|
||||
mNotificationStackScrollLayoutController,
|
||||
mKeyguardStatusViewComponentFactory,
|
||||
mKeyguardUserSwitcherComponent,
|
||||
mKeyguardQsUserSwitchComponentFactory,
|
||||
mKeyguardUserSwitcherComponentFactory,
|
||||
mQSDetailDisplayer,
|
||||
mGroupManager,
|
||||
mNotificationAreaController,
|
||||
mAuthController,
|
||||
|
||||
Reference in New Issue
Block a user