Merge changes from topic "new-keyguard-user-switcher" into sc-dev
* changes: New keyguard user switcher Remove MultiUserSwitch from KeyguardStatusBarView
This commit is contained in:
committed by
Android (Google) Code Review
commit
3dba81dfea
@@ -14,14 +14,10 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License
|
||||
-->
|
||||
<com.android.keyguard.AlphaOptimizedLinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/keyguard_user_switcher_inner"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
|
||||
android:layout_gravity="end"
|
||||
android:gravity="end"
|
||||
android:paddingTop="4dp">
|
||||
</com.android.keyguard.AlphaOptimizedLinearLayout>
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:state_activated="true"
|
||||
android:color="@color/kg_user_switcher_avatar_background" />
|
||||
<item android:color="@color/kg_user_switcher_avatar_background" />
|
||||
</selector>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?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
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="@dimen/end_guest_button_border_size"
|
||||
android:color="?android:attr/colorControlHighlight" />
|
||||
<corners android:radius="@dimen/end_guest_button_corner_radius" />
|
||||
</shape>
|
||||
28
packages/SystemUI/res/drawable/kg_bg_avatar.xml
Normal file
28
packages/SystemUI/res/drawable/kg_bg_avatar.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="100"
|
||||
android:viewportHeight="100">
|
||||
|
||||
<path
|
||||
android:fillColor="@color/kg_user_switcher_avatar_background"
|
||||
android:pathData="M50,50m-50,0a50,50 0,1 1,100 0a50,50 0,1 1,-100 0"/>
|
||||
|
||||
</vector>
|
||||
@@ -43,17 +43,12 @@
|
||||
<include layout="@layout/system_icons" />
|
||||
</FrameLayout>
|
||||
|
||||
<com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
|
||||
android:layout_width="@dimen/multi_user_switch_width_keyguard"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/ripple_drawable"
|
||||
android:layout_marginEnd="@dimen/multi_user_switch_keyguard_margin">
|
||||
<ImageView android:id="@+id/multi_user_avatar"
|
||||
android:layout_width="@dimen/multi_user_avatar_keyguard_size"
|
||||
android:layout_height="@dimen/multi_user_avatar_keyguard_size"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerInside"/>
|
||||
</com.android.systemui.statusbar.phone.MultiUserSwitch>
|
||||
|
||||
<ImageView android:id="@+id/multi_user_avatar"
|
||||
android:layout_width="@dimen/multi_user_avatar_keyguard_size"
|
||||
android:layout_height="@dimen/multi_user_avatar_keyguard_size"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerInside"/>
|
||||
</LinearLayout>
|
||||
|
||||
<Space
|
||||
|
||||
@@ -14,10 +14,50 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License
|
||||
-->
|
||||
<view xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
class="com.android.systemui.statusbar.policy.KeyguardUserSwitcher$Container"
|
||||
android:visibility="gone"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
<!-- KeyguardUserSwitcher loads keyguard_user_switcher_inner.xml here -->
|
||||
</view>
|
||||
<!-- This is a view that shows a user switcher in Keyguard. -->
|
||||
<com.android.systemui.statusbar.policy.KeyguardUserSwitcherView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/keyguard_user_switcher_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end">
|
||||
|
||||
<com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView
|
||||
android:id="@+id/keyguard_user_switcher_list"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="top|end"
|
||||
android:gravity="end" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/end_guest_button"
|
||||
android:layout_height="@dimen/end_guest_button_layout_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="@dimen/end_guest_button_margin_bottom"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="@dimen/end_guest_button_padding_horizontal"
|
||||
android:paddingRight="@dimen/end_guest_button_padding_horizontal"
|
||||
android:background="@drawable/end_guest_button_background"
|
||||
android:visibility="gone">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_exit_to_app"
|
||||
android:background="@android:color/transparent"
|
||||
android:color="?attr/wallpaperTextColor" />
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:gravity="center"
|
||||
android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
|
||||
android:textColor="?attr/wallpaperTextColor"
|
||||
android:textSize="13sp"
|
||||
android:text="@string/guest_exit_button" />
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.systemui.statusbar.policy.KeyguardUserSwitcherView>
|
||||
|
||||
@@ -19,29 +19,30 @@
|
||||
<!-- LinearLayout -->
|
||||
<com.android.systemui.statusbar.policy.KeyguardUserDetailItemView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:sysui="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:systemui="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:gravity="end|center_vertical"
|
||||
android:clickable="true"
|
||||
android:background="@drawable/ripple_drawable"
|
||||
sysui:regularTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
|
||||
sysui:activatedTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.Activated">
|
||||
<TextView android:id="@+id/user_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="13dp"
|
||||
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
|
||||
/>
|
||||
<com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
|
||||
android:layout_width="@dimen/kg_framed_avatar_size"
|
||||
android:layout_height="@dimen/kg_framed_avatar_size"
|
||||
android:contentDescription="@null"
|
||||
sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness"
|
||||
sysui:framePadding="2.5dp"
|
||||
sysui:badgeDiameter="18dp"
|
||||
sysui:badgeMargin="1dp"
|
||||
sysui:frameColor="@color/kg_user_switcher_rounded_background_color" />
|
||||
android:background="@drawable/kg_user_switcher_rounded_bg"
|
||||
systemui:activatedTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
|
||||
systemui:regularTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher">
|
||||
<TextView
|
||||
android:id="@+id/user_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="16dp" />
|
||||
<com.android.systemui.statusbar.phone.UserAvatarView
|
||||
android:id="@+id/user_picture"
|
||||
android:layout_width="@dimen/kg_framed_avatar_size"
|
||||
android:layout_height="@dimen/kg_framed_avatar_size"
|
||||
systemui:avatarPadding="0dp"
|
||||
systemui:badgeDiameter="18dp"
|
||||
systemui:badgeMargin="1dp"
|
||||
systemui:frameWidth="0dp"
|
||||
systemui:framePadding="0dp"
|
||||
systemui:frameColor="@color/kg_user_avatar_frame" />
|
||||
</com.android.systemui.statusbar.policy.KeyguardUserDetailItemView>
|
||||
|
||||
@@ -31,6 +31,12 @@
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/keyguard_user_switcher_stub"
|
||||
android:layout="@layout/keyguard_user_switcher"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<include
|
||||
layout="@layout/keyguard_status_view"
|
||||
android:visibility="gone" />
|
||||
@@ -72,12 +78,6 @@
|
||||
|
||||
<include layout="@layout/photo_preview_overlay" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/keyguard_user_switcher"
|
||||
android:layout="@layout/keyguard_user_switcher"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<include
|
||||
layout="@layout/keyguard_status_bar"
|
||||
android:visibility="invisible" />
|
||||
|
||||
@@ -89,6 +89,8 @@
|
||||
<color name="kg_user_switcher_avatar_icon_color">@android:color/background_light</color>
|
||||
<!-- Icon color for selected user avatars in keyguard user switcher -->
|
||||
<color name="kg_user_switcher_selected_avatar_icon_color">#202124</color>
|
||||
<!-- Color of background circle of user avatars in keyguard user switcher -->
|
||||
<color name="kg_user_switcher_avatar_background">#3C4043</color>
|
||||
<!-- Icon color for user avatars in quick settings user switcher -->
|
||||
<color name="qs_user_switcher_avatar_icon_color">@android:color/background_light</color>
|
||||
<!-- Icon color for selected user avatars in quick settings user switcher -->
|
||||
|
||||
@@ -23,13 +23,6 @@
|
||||
<item name="numColumns">4</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.StatusBar.Expanded.UserSwitcher">
|
||||
<item name="android:textSize">@dimen/kg_user_switcher_text_size</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
|
||||
<item name="android:textColor">?attr/wallpaperTextColor</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.QS.UserSwitcher">
|
||||
<item name="android:textSize">@dimen/kg_user_switcher_text_size</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
|
||||
@@ -66,9 +66,13 @@
|
||||
<!-- Color for rounded background for activated user in keyguard user switcher -->
|
||||
<color name="kg_user_switcher_activated_background_color">#26000000</color>
|
||||
<!-- Icon color for user avatars in keyguard user switcher -->
|
||||
<color name="kg_user_switcher_avatar_icon_color">@android:color/background_light</color>
|
||||
<!-- Icon color for selected user avatars in keyguard user switcher -->
|
||||
<color name="kg_user_switcher_selected_avatar_icon_color">@android:color/background_light</color>
|
||||
<color name="kg_user_switcher_avatar_icon_color">@color/GM2_grey_800</color>
|
||||
<!-- Icon color for user avatars in keyguard user switcher that restricted
|
||||
(e.g. cannot be switched to) -->
|
||||
<color name="kg_user_switcher_restricted_avatar_icon_color">@color/GM2_grey_600</color>
|
||||
<!-- Color of background circle of user avatars in keyguard user switcher -->
|
||||
<color name="kg_user_switcher_avatar_background">@color/GM2_grey_300</color>
|
||||
|
||||
<!-- Icon color for user avatars in user switcher quick settings -->
|
||||
<color name="qs_user_switcher_avatar_icon_color">#3C4043</color>
|
||||
<!-- Icon color for selected user avatars in user switcher quick settings -->
|
||||
|
||||
@@ -743,9 +743,6 @@
|
||||
<!-- end margin for system icons if multi user switch is hidden -->
|
||||
<dimen name="system_icons_switcher_hidden_expanded_margin">16dp</dimen>
|
||||
|
||||
<!-- The thickness of the colored border around the current user. -->
|
||||
<dimen name="keyguard_user_switcher_border_thickness">2dp</dimen>
|
||||
|
||||
<dimen name="data_usage_graph_marker_width">4dp</dimen>
|
||||
|
||||
<!-- The padding bottom of the clock group when QS is expanded. -->
|
||||
@@ -805,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">54dp</dimen>
|
||||
<dimen name="kg_framed_avatar_size">32dp</dimen>
|
||||
|
||||
<!-- Margin on the left side of the carrier text on Keyguard -->
|
||||
<dimen name="keyguard_carrier_text_margin">16dp</dimen>
|
||||
@@ -1324,8 +1321,16 @@
|
||||
<dimen name="screenrecord_status_icon_height">17.5dp</dimen>
|
||||
<dimen name="screenrecord_status_icon_bg_radius">8dp</dimen>
|
||||
|
||||
<!-- Keyguard user switcher -->
|
||||
<dimen name="kg_user_switcher_text_size">16sp</dimen>
|
||||
|
||||
<!-- End guest session button -->
|
||||
<dimen name="end_guest_button_layout_height">32dp</dimen>
|
||||
<dimen name="end_guest_button_padding_horizontal">16dp</dimen>
|
||||
<dimen name="end_guest_button_margin_bottom">96dp</dimen>
|
||||
<dimen name="end_guest_button_border_size">1dp</dimen>
|
||||
<dimen name="end_guest_button_corner_radius">16dp</dimen>
|
||||
|
||||
<!-- Opacity at which the background for the shutdown UI will be drawn. -->
|
||||
<item name="shutdown_scrim_behind_alpha" format="float" type="dimen">0.95</item>
|
||||
|
||||
|
||||
@@ -1112,6 +1112,9 @@
|
||||
<!-- Name for a freshly added user [CHAR LIMIT=30] -->
|
||||
<string name="user_new_user_name">New user</string>
|
||||
|
||||
<!-- Label for button that exits guest session and clears the guest user data [CHAR LIMIT=50]-->
|
||||
<string name="guest_exit_button">End guest session</string>
|
||||
|
||||
<!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
|
||||
<string name="guest_exit_guest_dialog_title">End guest session?</string>
|
||||
|
||||
|
||||
@@ -114,12 +114,12 @@
|
||||
<style name="TextAppearance.StatusBar.Expanded.UserSwitcher">
|
||||
<item name="android:textSize">@dimen/kg_user_switcher_text_size</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
|
||||
<item name="android:textColor">?attr/wallpaperTextColor</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.StatusBar.Expanded.UserSwitcher.Activated">
|
||||
<item name="android:fontWeight">700</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance" />
|
||||
|
||||
@@ -16,13 +16,9 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
|
||||
|
||||
import android.util.Slog;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.notification.AnimatableProperty;
|
||||
import com.android.systemui.statusbar.notification.PropertyAnimator;
|
||||
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
||||
@@ -50,13 +46,12 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
|
||||
private final KeyguardSliceViewController mKeyguardSliceViewController;
|
||||
private final KeyguardClockSwitchController mKeyguardClockSwitchController;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final ConfigurationController mConfigurationController;
|
||||
private final NotificationIconAreaController mNotificationIconAreaController;
|
||||
private final DozeParameters mDozeParameters;
|
||||
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
|
||||
|
||||
private boolean mKeyguardStatusViewVisibilityAnimating;
|
||||
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
|
||||
|
||||
@Inject
|
||||
@@ -72,11 +67,12 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
super(keyguardStatusView);
|
||||
mKeyguardSliceViewController = keyguardSliceViewController;
|
||||
mKeyguardClockSwitchController = keyguardClockSwitchController;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mConfigurationController = configurationController;
|
||||
mNotificationIconAreaController = notificationIconAreaController;
|
||||
mDozeParameters = dozeParameters;
|
||||
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
|
||||
dozeParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,7 +140,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
* Set keyguard status view alpha.
|
||||
*/
|
||||
public void setAlpha(float alpha) {
|
||||
if (!mKeyguardStatusViewVisibilityAnimating) {
|
||||
if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
|
||||
mView.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
@@ -200,7 +196,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
public void updatePosition(int x, int y, float scale, boolean animate) {
|
||||
// We animate the status view visible/invisible using Y translation, so don't change it
|
||||
// while the animation is running.
|
||||
if (!mKeyguardStatusViewVisibilityAnimating) {
|
||||
if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
|
||||
PropertyAnimator.setProperty(mView, AnimatableProperty.Y, y, CLOCK_ANIMATION_PROPERTIES,
|
||||
animate);
|
||||
}
|
||||
@@ -230,69 +226,8 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
boolean keyguardFadingAway,
|
||||
boolean goingToFullShade,
|
||||
int oldStatusBarState) {
|
||||
mView.animate().cancel();
|
||||
mKeyguardStatusViewVisibilityAnimating = false;
|
||||
if ((!keyguardFadingAway && oldStatusBarState == KEYGUARD
|
||||
&& statusBarState != KEYGUARD) || goingToFullShade) {
|
||||
mKeyguardStatusViewVisibilityAnimating = true;
|
||||
mView.animate()
|
||||
.alpha(0f)
|
||||
.setStartDelay(0)
|
||||
.setDuration(160)
|
||||
.setInterpolator(Interpolators.ALPHA_OUT)
|
||||
.withEndAction(
|
||||
mAnimateKeyguardStatusViewGoneEndRunnable);
|
||||
if (keyguardFadingAway) {
|
||||
mView.animate()
|
||||
.setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
|
||||
.setDuration(mKeyguardStateController.getShortenedFadingAwayDuration())
|
||||
.start();
|
||||
}
|
||||
} else if (oldStatusBarState == StatusBarState.SHADE_LOCKED && statusBarState == KEYGUARD) {
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mKeyguardStatusViewVisibilityAnimating = true;
|
||||
mView.setAlpha(0f);
|
||||
mView.animate()
|
||||
.alpha(1f)
|
||||
.setStartDelay(0)
|
||||
.setDuration(320)
|
||||
.setInterpolator(Interpolators.ALPHA_IN)
|
||||
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable);
|
||||
} else if (statusBarState == KEYGUARD) {
|
||||
if (keyguardFadingAway) {
|
||||
mKeyguardStatusViewVisibilityAnimating = true;
|
||||
mView.animate()
|
||||
.alpha(0)
|
||||
.translationYBy(-getHeight() * 0.05f)
|
||||
.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
|
||||
.setDuration(125)
|
||||
.setStartDelay(0)
|
||||
.withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
|
||||
.start();
|
||||
} else if (mDozeParameters.shouldControlUnlockedScreenOff()) {
|
||||
mKeyguardStatusViewVisibilityAnimating = true;
|
||||
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mView.setAlpha(0f);
|
||||
|
||||
float curTranslationY = mView.getTranslationY();
|
||||
mView.setTranslationY(curTranslationY - getHeight() * 0.1f);
|
||||
mView.animate()
|
||||
.setStartDelay((int) (StackStateAnimator.ANIMATION_DURATION_WAKEUP * .6f))
|
||||
.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
|
||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
||||
.alpha(1f)
|
||||
.translationY(curTranslationY)
|
||||
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
|
||||
.start();
|
||||
} else {
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mView.setAlpha(1f);
|
||||
}
|
||||
} else {
|
||||
mView.setVisibility(View.GONE);
|
||||
mView.setAlpha(1f);
|
||||
}
|
||||
mKeyguardVisibilityHelper.setViewVisibility(
|
||||
statusBarState, keyguardFadingAway, goingToFullShade, oldStatusBarState);
|
||||
}
|
||||
|
||||
private void refreshTime() {
|
||||
@@ -393,19 +328,4 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
mView.updateLogoutView();
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = () -> {
|
||||
mKeyguardStatusViewVisibilityAnimating = false;
|
||||
mView.setVisibility(View.INVISIBLE);
|
||||
};
|
||||
|
||||
|
||||
private final Runnable mAnimateKeyguardStatusViewGoneEndRunnable = () -> {
|
||||
mKeyguardStatusViewVisibilityAnimating = false;
|
||||
mView.setVisibility(View.GONE);
|
||||
};
|
||||
|
||||
private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
|
||||
mKeyguardStatusViewVisibilityAnimating = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
|
||||
/**
|
||||
* Helper class for updating visibility of keyguard views based on keyguard and status bar state.
|
||||
* This logic is shared by both the keyguard status view and the keyguard user switcher.
|
||||
*/
|
||||
public class KeyguardVisibilityHelper {
|
||||
|
||||
private View mView;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final DozeParameters mDozeParameters;
|
||||
private boolean mKeyguardViewVisibilityAnimating;
|
||||
|
||||
public KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController,
|
||||
DozeParameters dozeParameters) {
|
||||
mView = view;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mDozeParameters = dozeParameters;
|
||||
}
|
||||
|
||||
public boolean isVisibilityAnimating() {
|
||||
return mKeyguardViewVisibilityAnimating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the visibility of a keyguard view based on some new state.
|
||||
*/
|
||||
public void setViewVisibility(
|
||||
int statusBarState,
|
||||
boolean keyguardFadingAway,
|
||||
boolean goingToFullShade,
|
||||
int oldStatusBarState) {
|
||||
mView.animate().cancel();
|
||||
mKeyguardViewVisibilityAnimating = false;
|
||||
if ((!keyguardFadingAway && oldStatusBarState == KEYGUARD
|
||||
&& statusBarState != KEYGUARD) || goingToFullShade) {
|
||||
mKeyguardViewVisibilityAnimating = true;
|
||||
mView.animate()
|
||||
.alpha(0f)
|
||||
.setStartDelay(0)
|
||||
.setDuration(160)
|
||||
.setInterpolator(Interpolators.ALPHA_OUT)
|
||||
.withEndAction(
|
||||
mAnimateKeyguardStatusViewGoneEndRunnable);
|
||||
if (keyguardFadingAway) {
|
||||
mView.animate()
|
||||
.setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
|
||||
.setDuration(mKeyguardStateController.getShortenedFadingAwayDuration())
|
||||
.start();
|
||||
}
|
||||
} else if (oldStatusBarState == StatusBarState.SHADE_LOCKED && statusBarState == KEYGUARD) {
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mKeyguardViewVisibilityAnimating = true;
|
||||
mView.setAlpha(0f);
|
||||
mView.animate()
|
||||
.alpha(1f)
|
||||
.setStartDelay(0)
|
||||
.setDuration(320)
|
||||
.setInterpolator(Interpolators.ALPHA_IN)
|
||||
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable);
|
||||
} else if (statusBarState == KEYGUARD) {
|
||||
if (keyguardFadingAway) {
|
||||
mKeyguardViewVisibilityAnimating = true;
|
||||
mView.animate()
|
||||
.alpha(0)
|
||||
.translationYBy(-mView.getHeight() * 0.05f)
|
||||
.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
|
||||
.setDuration(125)
|
||||
.setStartDelay(0)
|
||||
.withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
|
||||
.start();
|
||||
} else if (mDozeParameters.shouldControlUnlockedScreenOff()) {
|
||||
mKeyguardViewVisibilityAnimating = true;
|
||||
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mView.setAlpha(0f);
|
||||
|
||||
float curTranslationY = mView.getTranslationY();
|
||||
mView.setTranslationY(curTranslationY - mView.getHeight() * 0.1f);
|
||||
mView.animate()
|
||||
.setStartDelay((int) (StackStateAnimator.ANIMATION_DURATION_WAKEUP * .6f))
|
||||
.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
|
||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
||||
.alpha(1f)
|
||||
.translationY(curTranslationY)
|
||||
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
|
||||
.start();
|
||||
} else {
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mView.setAlpha(1f);
|
||||
}
|
||||
} else {
|
||||
mView.setVisibility(View.GONE);
|
||||
mView.setAlpha(1f);
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = () -> {
|
||||
mKeyguardViewVisibilityAnimating = false;
|
||||
mView.setVisibility(View.INVISIBLE);
|
||||
};
|
||||
|
||||
private final Runnable mAnimateKeyguardStatusViewGoneEndRunnable = () -> {
|
||||
mKeyguardViewVisibilityAnimating = false;
|
||||
mView.setVisibility(View.GONE);
|
||||
};
|
||||
|
||||
private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
|
||||
mKeyguardViewVisibilityAnimating = false;
|
||||
};
|
||||
}
|
||||
@@ -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.policy.KeyguardUserSwitcherController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Subcomponent;
|
||||
|
||||
/**
|
||||
* Subcomponent for helping work with KeyguardUserSwitcher and its children.
|
||||
*/
|
||||
@Subcomponent(modules = {KeyguardUserSwitcherModule.class})
|
||||
@KeyguardUserSwitcherScope
|
||||
public interface KeyguardUserSwitcherComponent {
|
||||
/** Simple factory for {@link KeyguardUserSwitcherComponent}. */
|
||||
@Subcomponent.Factory
|
||||
interface Factory {
|
||||
KeyguardUserSwitcherComponent build(
|
||||
@BindsInstance KeyguardUserSwitcherView keyguardUserSwitcherView);
|
||||
}
|
||||
|
||||
/** Builds a {@link com.android.systemui.statusbar.policy.KeyguardUserSwitcherController}. */
|
||||
KeyguardUserSwitcherController getKeyguardUserSwitcherController();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 dagger.Module;
|
||||
|
||||
/** Dagger module for {@link KeyguardUserSwitcherComponent}. */
|
||||
@Module
|
||||
public abstract class KeyguardUserSwitcherModule {
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import javax.inject.Scope;
|
||||
|
||||
/**
|
||||
* Scope annotation for singleton items within the KeyguardUserSwitcherComponent.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Scope
|
||||
public @interface KeyguardUserSwitcherScope {}
|
||||
@@ -415,6 +415,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
|
||||
|
||||
@Override
|
||||
public void onUserSwitching(int userId) {
|
||||
if (DEBUG) Log.d(TAG, String.format("onUserSwitching %d", userId));
|
||||
// Note that the mLockPatternUtils user has already been updated from setCurrentUser.
|
||||
// We need to force a reset of the views, since lockNow (called by
|
||||
// ActivityManagerService) will not reconstruct the keyguard if it is already showing.
|
||||
@@ -432,6 +433,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
|
||||
|
||||
@Override
|
||||
public void onUserSwitchComplete(int userId) {
|
||||
if (DEBUG) Log.d(TAG, String.format("onUserSwitchComplete %d", userId));
|
||||
if (userId != UserHandle.USER_SYSTEM) {
|
||||
UserInfo info = UserManager.get(mContext).getUserInfo(userId);
|
||||
// Don't try to dismiss if the user has Pin/Patter/Password set
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.android.keyguard.KeyguardDisplayManager;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardViewController;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.classifier.FalsingModule;
|
||||
@@ -61,7 +62,7 @@ import dagger.Provides;
|
||||
/**
|
||||
* Dagger Module providing {@link StatusBar}.
|
||||
*/
|
||||
@Module(subcomponents = {KeyguardStatusViewComponent.class},
|
||||
@Module(subcomponents = {KeyguardStatusViewComponent.class, KeyguardUserSwitcherComponent.class},
|
||||
includes = {FalsingModule.class})
|
||||
public class KeyguardModule {
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,7 @@ public class UserDetailItemView extends LinearLayout {
|
||||
protected static int layoutResId = R.layout.qs_user_detail_item;
|
||||
|
||||
private UserAvatarView mAvatar;
|
||||
private TextView mName;
|
||||
protected TextView mName;
|
||||
private int mActivatedStyle;
|
||||
private int mRegularStyle;
|
||||
private View mRestrictedPadlock;
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.keyguard.KeyguardStatusView;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView;
|
||||
|
||||
/**
|
||||
* Utility class to calculate the clock position and top padding of notifications on Keyguard.
|
||||
@@ -54,6 +55,12 @@ public class KeyguardClockPositionAlgorithm {
|
||||
*/
|
||||
private int mKeyguardStatusHeight;
|
||||
|
||||
/**
|
||||
* Height of {@link KeyguardUserSwitcherListView} when it
|
||||
* is closed and only the current user's icon is visible.
|
||||
*/
|
||||
private int mKeyguardUserSwitcherHeight;
|
||||
|
||||
/**
|
||||
* Preferred Y position of clock.
|
||||
*/
|
||||
@@ -173,17 +180,20 @@ public class KeyguardClockPositionAlgorithm {
|
||||
* Sets up algorithm values.
|
||||
*/
|
||||
public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
|
||||
float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
|
||||
boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
|
||||
boolean bypassEnabled, int unlockedStackScrollerPadding, boolean showLockIcon,
|
||||
float qsExpansion, int cutoutTopInset) {
|
||||
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) {
|
||||
mMinTopMargin = statusBarMinHeight + (showLockIcon
|
||||
? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon);
|
||||
? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon)
|
||||
+ keyguardUserSwitcherHeight;
|
||||
mMaxShadeBottom = maxShadeBottom;
|
||||
mNotificationStackHeight = notificationStackHeight;
|
||||
mPanelExpansion = panelExpansion;
|
||||
mHeight = parentHeight;
|
||||
mKeyguardStatusHeight = keyguardStatusHeight;
|
||||
mKeyguardUserSwitcherHeight = keyguardUserSwitcherHeight;
|
||||
mClockPreferredY = clockPreferredY;
|
||||
mHasCustomClock = hasCustomClock;
|
||||
mHasVisibleNotifs = hasVisibleNotifs;
|
||||
@@ -246,7 +256,8 @@ public class KeyguardClockPositionAlgorithm {
|
||||
final int availableHeight = mMaxShadeBottom - mMinTopMargin;
|
||||
final int containerCenter = mMinTopMargin + availableHeight / 2;
|
||||
|
||||
float y = containerCenter - mKeyguardStatusHeight * CLOCK_HEIGHT_WEIGHT
|
||||
float y = containerCenter
|
||||
- (mKeyguardStatusHeight + mKeyguardUserSwitcherHeight) * CLOCK_HEIGHT_WEIGHT
|
||||
- mClockNotificationsMargin - mNotificationStackHeight / 2;
|
||||
if (y < mMinTopMargin) {
|
||||
y = mMinTopMargin;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import static com.android.systemui.DejankUtils.whitelistIpcs;
|
||||
import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
|
||||
|
||||
import android.annotation.ColorInt;
|
||||
@@ -25,6 +26,7 @@ import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.UserManager;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
@@ -45,18 +47,15 @@ import com.android.systemui.Dependency;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||
import com.android.systemui.qs.QSDetailDisplayer;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
|
||||
import com.android.systemui.statusbar.policy.UserInfoController;
|
||||
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
|
||||
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
|
||||
import com.android.systemui.statusbar.policy.UserSwitcherController;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -75,18 +74,16 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
|
||||
private boolean mShowPercentAvailable;
|
||||
private boolean mBatteryCharging;
|
||||
private boolean mKeyguardUserSwitcherShowing;
|
||||
private boolean mBatteryListening;
|
||||
|
||||
private TextView mCarrierLabel;
|
||||
private MultiUserSwitch mMultiUserSwitch;
|
||||
private ImageView mMultiUserAvatar;
|
||||
private BatteryMeterView mBatteryView;
|
||||
private StatusIconContainer mStatusIconContainer;
|
||||
|
||||
private BatteryController mBatteryController;
|
||||
private KeyguardUserSwitcher mKeyguardUserSwitcher;
|
||||
private UserSwitcherController mUserSwitcherController;
|
||||
private boolean mKeyguardUserSwitcherEnabled;
|
||||
private final UserManager mUserManager;
|
||||
|
||||
private int mSystemIconsSwitcherHiddenExpandedMargin;
|
||||
private int mSystemIconsBaseMargin;
|
||||
@@ -109,13 +106,13 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
|
||||
public KeyguardStatusBarView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mUserManager = UserManager.get(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mSystemIconsContainer = findViewById(R.id.system_icons_container);
|
||||
mMultiUserSwitch = findViewById(R.id.multi_user_switch);
|
||||
mMultiUserAvatar = findViewById(R.id.multi_user_avatar);
|
||||
mCarrierLabel = findViewById(R.id.keyguard_carrier_text);
|
||||
mBatteryView = mSystemIconsContainer.findViewById(R.id.battery);
|
||||
@@ -124,7 +121,6 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
mStatusIconContainer = findViewById(R.id.statusIcons);
|
||||
|
||||
loadDimens();
|
||||
updateUserSwitcher();
|
||||
mBatteryController = Dependency.get(BatteryController.class);
|
||||
}
|
||||
|
||||
@@ -137,14 +133,6 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
R.dimen.multi_user_avatar_keyguard_size);
|
||||
mMultiUserAvatar.setLayoutParams(lp);
|
||||
|
||||
// Multi-user switch
|
||||
lp = (MarginLayoutParams) mMultiUserSwitch.getLayoutParams();
|
||||
lp.width = getResources().getDimensionPixelSize(
|
||||
R.dimen.multi_user_switch_width_keyguard);
|
||||
lp.setMarginEnd(getResources().getDimensionPixelSize(
|
||||
R.dimen.multi_user_switch_keyguard_margin));
|
||||
mMultiUserSwitch.setLayoutParams(lp);
|
||||
|
||||
// System icons
|
||||
lp = (MarginLayoutParams) mSystemIconsContainer.getLayoutParams();
|
||||
lp.setMarginStart(getResources().getDimensionPixelSize(
|
||||
@@ -194,22 +182,28 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
}
|
||||
|
||||
private void updateVisibilities() {
|
||||
if (mMultiUserSwitch.getParent() != mStatusIconArea && !mKeyguardUserSwitcherShowing) {
|
||||
if (mMultiUserSwitch.getParent() != null) {
|
||||
getOverlay().remove(mMultiUserSwitch);
|
||||
if (mMultiUserAvatar.getParent() != mStatusIconArea
|
||||
&& !mKeyguardUserSwitcherEnabled) {
|
||||
if (mMultiUserAvatar.getParent() != null) {
|
||||
getOverlay().remove(mMultiUserAvatar);
|
||||
}
|
||||
mStatusIconArea.addView(mMultiUserSwitch, 0);
|
||||
} else if (mMultiUserSwitch.getParent() == mStatusIconArea && mKeyguardUserSwitcherShowing) {
|
||||
mStatusIconArea.removeView(mMultiUserSwitch);
|
||||
mStatusIconArea.addView(mMultiUserAvatar, 0);
|
||||
} else if (mMultiUserAvatar.getParent() == mStatusIconArea
|
||||
&& mKeyguardUserSwitcherEnabled) {
|
||||
mStatusIconArea.removeView(mMultiUserAvatar);
|
||||
}
|
||||
if (mKeyguardUserSwitcher == null) {
|
||||
if (!mKeyguardUserSwitcherEnabled) {
|
||||
// If we have no keyguard switcher, the screen width is under 600dp. In this case,
|
||||
// we only show the multi-user switch if it's enabled through UserManager as well as
|
||||
// by the user.
|
||||
if (mMultiUserSwitch.isMultiUserEnabled()) {
|
||||
mMultiUserSwitch.setVisibility(View.VISIBLE);
|
||||
// TODO(b/138661450) Move IPC calls to background
|
||||
boolean isMultiUserEnabled = whitelistIpcs(() -> mUserManager.isUserSwitcherEnabled(
|
||||
mContext.getResources().getBoolean(
|
||||
R.bool.qs_show_user_switcher_for_single_user)));
|
||||
if (isMultiUserEnabled) {
|
||||
mMultiUserAvatar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mMultiUserSwitch.setVisibility(View.GONE);
|
||||
mMultiUserAvatar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable);
|
||||
@@ -220,11 +214,12 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
|
||||
// If the avatar icon is gone, we need to have some end margin to display the system icons
|
||||
// correctly.
|
||||
int baseMarginEnd = mMultiUserSwitch.getVisibility() == View.GONE
|
||||
int baseMarginEnd = mMultiUserAvatar.getVisibility() == View.GONE
|
||||
? mSystemIconsBaseMargin
|
||||
: 0;
|
||||
int marginEnd = mKeyguardUserSwitcherShowing ? mSystemIconsSwitcherHiddenExpandedMargin :
|
||||
baseMarginEnd;
|
||||
int marginEnd =
|
||||
mKeyguardUserSwitcherEnabled ? mSystemIconsSwitcherHiddenExpandedMargin
|
||||
: baseMarginEnd;
|
||||
marginEnd = calculateMargin(marginEnd, mPadding.second);
|
||||
if (marginEnd != lp.getMarginEnd()) {
|
||||
lp.setMarginEnd(marginEnd);
|
||||
@@ -334,20 +329,11 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUserSwitcher() {
|
||||
boolean keyguardSwitcherAvailable = mKeyguardUserSwitcher != null;
|
||||
mMultiUserSwitch.setClickable(keyguardSwitcherAvailable);
|
||||
mMultiUserSwitch.setFocusable(keyguardSwitcherAvailable);
|
||||
mMultiUserSwitch.setKeyguardMode(keyguardSwitcherAvailable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
UserInfoController userInfoController = Dependency.get(UserInfoController.class);
|
||||
userInfoController.addCallback(this);
|
||||
mUserSwitcherController = Dependency.get(UserSwitcherController.class);
|
||||
mMultiUserSwitch.setUserSwitcherController(mUserSwitcherController);
|
||||
userInfoController.reloadUserInfo();
|
||||
Dependency.get(ConfigurationController.class).addCallback(this);
|
||||
mIconManager = new TintedIconManager(findViewById(R.id.statusIcons),
|
||||
@@ -369,11 +355,6 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
mMultiUserAvatar.setImageDrawable(picture);
|
||||
}
|
||||
|
||||
/** */
|
||||
public void setQSDetailDisplayer(QSDetailDisplayer detailDisplayer) {
|
||||
mMultiUserSwitch.setQSDetailDisplayer(detailDisplayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
|
||||
if (mBatteryCharging != charging) {
|
||||
@@ -387,54 +368,42 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
// could not care less
|
||||
}
|
||||
|
||||
public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
|
||||
mKeyguardUserSwitcher = keyguardUserSwitcher;
|
||||
mMultiUserSwitch.setKeyguardUserSwitcher(keyguardUserSwitcher);
|
||||
updateUserSwitcher();
|
||||
}
|
||||
|
||||
public void setKeyguardUserSwitcherShowing(boolean showing, boolean animate) {
|
||||
mKeyguardUserSwitcherShowing = showing;
|
||||
if (animate) {
|
||||
animateNextLayoutChange();
|
||||
}
|
||||
updateVisibilities();
|
||||
updateLayoutConsideringCutout();
|
||||
updateSystemIconsLayoutParams();
|
||||
public void setKeyguardUserSwitcherEnabled(boolean enabled) {
|
||||
mKeyguardUserSwitcherEnabled = enabled;
|
||||
}
|
||||
|
||||
private void animateNextLayoutChange() {
|
||||
final int systemIconsCurrentX = mSystemIconsContainer.getLeft();
|
||||
final boolean userSwitcherVisible = mMultiUserSwitch.getParent() == mStatusIconArea;
|
||||
final boolean userAvatarVisible = mMultiUserAvatar.getParent() == mStatusIconArea;
|
||||
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
boolean userSwitcherHiding = userSwitcherVisible
|
||||
&& mMultiUserSwitch.getParent() != mStatusIconArea;
|
||||
boolean userAvatarHiding = userAvatarVisible
|
||||
&& mMultiUserAvatar.getParent() != mStatusIconArea;
|
||||
mSystemIconsContainer.setX(systemIconsCurrentX);
|
||||
mSystemIconsContainer.animate()
|
||||
.translationX(0)
|
||||
.setDuration(400)
|
||||
.setStartDelay(userSwitcherHiding ? 300 : 0)
|
||||
.setStartDelay(userAvatarHiding ? 300 : 0)
|
||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
||||
.start();
|
||||
if (userSwitcherHiding) {
|
||||
getOverlay().add(mMultiUserSwitch);
|
||||
mMultiUserSwitch.animate()
|
||||
if (userAvatarHiding) {
|
||||
getOverlay().add(mMultiUserAvatar);
|
||||
mMultiUserAvatar.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(300)
|
||||
.setStartDelay(0)
|
||||
.setInterpolator(Interpolators.ALPHA_OUT)
|
||||
.withEndAction(() -> {
|
||||
mMultiUserSwitch.setAlpha(1f);
|
||||
getOverlay().remove(mMultiUserSwitch);
|
||||
mMultiUserAvatar.setAlpha(1f);
|
||||
getOverlay().remove(mMultiUserAvatar);
|
||||
})
|
||||
.start();
|
||||
|
||||
} else {
|
||||
mMultiUserSwitch.setAlpha(0f);
|
||||
mMultiUserSwitch.animate()
|
||||
mMultiUserAvatar.setAlpha(0f);
|
||||
mMultiUserAvatar.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(300)
|
||||
.setStartDelay(200)
|
||||
@@ -452,8 +421,8 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
if (visibility != View.VISIBLE) {
|
||||
mSystemIconsContainer.animate().cancel();
|
||||
mSystemIconsContainer.setTranslationX(0);
|
||||
mMultiUserSwitch.animate().cancel();
|
||||
mMultiUserSwitch.setAlpha(1f);
|
||||
mMultiUserAvatar.animate().cancel();
|
||||
mMultiUserAvatar.setAlpha(1f);
|
||||
} else {
|
||||
updateVisibilities();
|
||||
updateSystemIconsLayoutParams();
|
||||
@@ -523,9 +492,9 @@ public class KeyguardStatusBarView extends RelativeLayout
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("KeyguardStatusBarView:");
|
||||
pw.println(" mBatteryCharging: " + mBatteryCharging);
|
||||
pw.println(" mKeyguardUserSwitcherShowing: " + mKeyguardUserSwitcherShowing);
|
||||
pw.println(" mBatteryListening: " + mBatteryListening);
|
||||
pw.println(" mLayoutState: " + mLayoutState);
|
||||
pw.println(" mKeyguardUserSwitcherEnabled: " + mKeyguardUserSwitcherEnabled);
|
||||
if (mBatteryView != null) {
|
||||
mBatteryView.dump(fd, pw, args);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.android.systemui.Prefs.Key;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.qs.DetailAdapter;
|
||||
import com.android.systemui.qs.QSDetailDisplayer;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
|
||||
import com.android.systemui.statusbar.policy.UserSwitcherController;
|
||||
|
||||
/**
|
||||
@@ -44,8 +43,6 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
|
||||
public class MultiUserSwitch extends FrameLayout implements View.OnClickListener {
|
||||
|
||||
protected QSDetailDisplayer mQSDetailDisplayer;
|
||||
private KeyguardUserSwitcher mKeyguardUserSwitcher;
|
||||
private boolean mKeyguardMode;
|
||||
private UserSwitcherController.BaseUserAdapter mUserListener;
|
||||
|
||||
final UserManager mUserManager;
|
||||
@@ -85,15 +82,6 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
|
||||
refreshContentDescription();
|
||||
}
|
||||
|
||||
public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
|
||||
mKeyguardUserSwitcher = keyguardUserSwitcher;
|
||||
}
|
||||
|
||||
public void setKeyguardMode(boolean keyguardShowing) {
|
||||
mKeyguardMode = keyguardShowing;
|
||||
registerListener();
|
||||
}
|
||||
|
||||
public boolean isMultiUserEnabled() {
|
||||
// TODO(b/138661450) Move IPC calls to background
|
||||
return whitelistIpcs(() -> mUserManager.isUserSwitcherEnabled(
|
||||
@@ -123,11 +111,7 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mKeyguardMode) {
|
||||
if (mKeyguardUserSwitcher != null) {
|
||||
mKeyguardUserSwitcher.show(true /* animate */);
|
||||
}
|
||||
} else if (mQSDetailDisplayer != null && mUserSwitcherController != null) {
|
||||
if (mQSDetailDisplayer != null && mUserSwitcherController != null) {
|
||||
View center = getChildCount() > 0 ? getChildAt(0) : this;
|
||||
|
||||
int[] tmpInt = new int[2];
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.hardware.biometrics.BiometricSourceType;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.view.DisplayCutout;
|
||||
@@ -57,6 +58,7 @@ import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
import android.view.ViewStub;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
@@ -76,6 +78,7 @@ import com.android.keyguard.KeyguardStatusViewController;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
|
||||
import com.android.systemui.DejankUtils;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
@@ -95,7 +98,6 @@ import com.android.systemui.plugins.FalsingManager;
|
||||
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;
|
||||
@@ -132,7 +134,8 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUi
|
||||
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
|
||||
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
|
||||
import com.android.systemui.util.Utils;
|
||||
import com.android.wm.shell.animation.FlingAnimationUtils;
|
||||
@@ -284,6 +287,22 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
};
|
||||
|
||||
final KeyguardUserSwitcherController.KeyguardUserSwitcherListener
|
||||
mKeyguardUserSwitcherListener =
|
||||
new KeyguardUserSwitcherController.KeyguardUserSwitcherListener() {
|
||||
@Override
|
||||
public void onKeyguardUserSwitcherChanged(boolean open) {
|
||||
if (mKeyguardUserSwitcherController != null
|
||||
&& mKeyguardUserSwitcherController.isSimpleUserSwitcher()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateUserSwitcherVisibility(open
|
||||
&& mKeyguardStateController.isShowing()
|
||||
&& !mKeyguardStateController.isKeyguardFadingAway());
|
||||
}
|
||||
};
|
||||
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final PowerManager mPowerManager;
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
@@ -296,7 +315,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private final MediaHierarchyManager mMediaHierarchyManager;
|
||||
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
|
||||
private final QSDetailDisplayer mQSDetailDisplayer;
|
||||
private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final ScrimController mScrimController;
|
||||
private final ControlsComponent mControlsComponent;
|
||||
@@ -308,7 +327,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private int mMaxAllowedKeyguardNotifications;
|
||||
|
||||
private KeyguardAffordanceHelper mAffordanceHelper;
|
||||
private KeyguardUserSwitcher mKeyguardUserSwitcher;
|
||||
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
|
||||
private KeyguardStatusBarView mKeyguardStatusBar;
|
||||
private ViewGroup mBigClockContainer;
|
||||
private QS mQs;
|
||||
@@ -333,6 +352,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private boolean mQsExpandedWhenExpandingStarted;
|
||||
private boolean mQsFullyExpanded;
|
||||
private boolean mKeyguardShowing;
|
||||
private boolean mKeyguardUserSwitcherEnabled;
|
||||
private boolean mDozing;
|
||||
private boolean mDozingOnDown;
|
||||
private int mBarState;
|
||||
@@ -465,6 +485,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final NotificationLockscreenUserManager mLockscreenUserManager;
|
||||
private final UserManager mUserManager;
|
||||
private final ShadeController mShadeController;
|
||||
private final MediaDataManager mMediaDataManager;
|
||||
private int mDisplayId;
|
||||
@@ -557,11 +578,12 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
||||
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
|
||||
KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
|
||||
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
NotificationIconAreaController notificationIconAreaController,
|
||||
AuthController authController,
|
||||
QSDetailDisplayer qsDetailDisplayer,
|
||||
ScrimController scrimController,
|
||||
UserManager userManager,
|
||||
MediaDataManager mediaDataManager,
|
||||
AmbientState ambientState,
|
||||
FeatureFlags featureFlags,
|
||||
@@ -582,8 +604,10 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mGroupManager = groupManager;
|
||||
mNotificationIconAreaController = notificationIconAreaController;
|
||||
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
|
||||
mQSDetailDisplayer = qsDetailDisplayer;
|
||||
mFeatureFlags = featureFlags;
|
||||
mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory;
|
||||
mKeyguardUserSwitcherEnabled = mResources.getBoolean(
|
||||
com.android.internal.R.bool.config_keyguardUserSwitcher);
|
||||
mView.setWillNotDraw(!DEBUG);
|
||||
mLayoutInflater = layoutInflater;
|
||||
mFalsingManager = falsingManager;
|
||||
@@ -599,6 +623,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mDozeParameters = dozeParameters;
|
||||
mBiometricUnlockController = biometricUnlockController;
|
||||
mScrimController = scrimController;
|
||||
mUserManager = userManager;
|
||||
mMediaDataManager = mediaDataManager;
|
||||
mControlsComponent = controlsComponent;
|
||||
pulseExpansionHandler.setPulseExpandAbortListener(() -> {
|
||||
@@ -661,9 +686,17 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private void onFinishInflate() {
|
||||
loadDimens();
|
||||
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
|
||||
mKeyguardStatusBar.setQSDetailDisplayer(mQSDetailDisplayer);
|
||||
mBigClockContainer = mView.findViewById(R.id.big_clock_container);
|
||||
updateViewControllers(mView.findViewById(R.id.keyguard_status_view));
|
||||
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView = null;
|
||||
|
||||
if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled()) {
|
||||
ViewStub userSwitcherStub = mView.findViewById(R.id.keyguard_user_switcher_stub);
|
||||
keyguardUserSwitcherView = (KeyguardUserSwitcherView) userSwitcherStub.inflate();
|
||||
}
|
||||
|
||||
updateViewControllers(mView.findViewById(R.id.keyguard_status_view),
|
||||
keyguardUserSwitcherView);
|
||||
mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
|
||||
NotificationStackScrollLayout stackScrollLayout = mView.findViewById(
|
||||
R.id.notification_stack_scroller);
|
||||
@@ -736,7 +769,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
R.dimen.heads_up_status_bar_padding);
|
||||
}
|
||||
|
||||
private void updateViewControllers(KeyguardStatusView keyguardStatusView) {
|
||||
private void updateViewControllers(KeyguardStatusView keyguardStatusView,
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView) {
|
||||
// Re-associate the KeyguardStatusViewController
|
||||
KeyguardStatusViewComponent statusViewComponent =
|
||||
mKeyguardStatusViewComponentFactory.build(keyguardStatusView);
|
||||
@@ -747,6 +781,28 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
KeyguardClockSwitchController keyguardClockSwitchController =
|
||||
statusViewComponent.getKeyguardClockSwitchController();
|
||||
keyguardClockSwitchController.setBigClockContainer(mBigClockContainer);
|
||||
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
// Try to close the switcher so that callbacks are triggered if necessary.
|
||||
// Otherwise, NPV can get into a state where some of the views are still hidden
|
||||
mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(false);
|
||||
mKeyguardUserSwitcherController.removeCallback();
|
||||
}
|
||||
|
||||
// Re-associate the KeyguardUserSwitcherController
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -801,6 +857,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
|
||||
private void reInflateViews() {
|
||||
if (DEBUG) Log.d(TAG, "reInflateViews");
|
||||
// Re-inflate the status view group.
|
||||
KeyguardStatusView keyguardStatusView = mView.findViewById(R.id.keyguard_status_view);
|
||||
int index = mView.indexOfChild(keyguardStatusView);
|
||||
@@ -809,8 +866,27 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
R.layout.keyguard_status_view, mView, false);
|
||||
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();
|
||||
}
|
||||
|
||||
mBigClockContainer.removeAllViews();
|
||||
updateViewControllers(keyguardStatusView);
|
||||
updateViewControllers(keyguardStatusView, keyguardUserSwitcherView);
|
||||
|
||||
// Update keyguard bottom area
|
||||
index = mView.indexOfChild(mKeyguardBottomArea);
|
||||
@@ -834,6 +910,13 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
false,
|
||||
false,
|
||||
mBarState);
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.setKeyguardUserSwitcherVisibility(
|
||||
mBarState,
|
||||
false,
|
||||
false,
|
||||
mBarState);
|
||||
}
|
||||
setKeyguardBottomAreaVisibility(mBarState, false);
|
||||
}
|
||||
|
||||
@@ -938,6 +1021,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
? mKeyguardStatusViewController.getHeight()
|
||||
: (int) (mKeyguardStatusViewController.getHeight()
|
||||
- mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
|
||||
mKeyguardUserSwitcherController == null
|
||||
? 0 : mKeyguardUserSwitcherController.getUserIconHeight(),
|
||||
clockPreferredY, hasCustomClock(),
|
||||
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
|
||||
bypassEnabled, getUnlockedStackScrollerPadding(),
|
||||
@@ -948,6 +1033,13 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mKeyguardStatusViewController.updatePosition(
|
||||
mClockPositionResult.clockX, mClockPositionResult.clockY,
|
||||
mClockPositionResult.clockScale, animateClock);
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.updatePosition(
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.clockY
|
||||
- mKeyguardUserSwitcherController.getUserIconHeight(),
|
||||
animateClock);
|
||||
}
|
||||
updateNotificationTranslucency();
|
||||
updateClock();
|
||||
stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
|
||||
@@ -1088,6 +1180,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
|
||||
private void updateClock() {
|
||||
mKeyguardStatusViewController.setAlpha(mClockPositionResult.clockAlpha);
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.setAlpha(mClockPositionResult.clockAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
public void animateToFullShade(long delay) {
|
||||
@@ -1769,8 +1864,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mBarState != KEYGUARD && (!mQsExpanded
|
||||
|| mQsExpansionFromOverscroll));
|
||||
|
||||
if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
|
||||
mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
|
||||
if (mKeyguardUserSwitcherController != null && mQsExpanded
|
||||
&& !mStackScrollerOverscrolling) {
|
||||
mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(true);
|
||||
}
|
||||
if (mQs == null) return;
|
||||
mQs.setExpanded(mQsExpanded);
|
||||
@@ -2604,10 +2700,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
|
||||
mKeyguardUserSwitcher = keyguardUserSwitcher;
|
||||
}
|
||||
|
||||
public void onScreenTurningOn() {
|
||||
mKeyguardStatusViewController.dozeTimeTick();
|
||||
}
|
||||
@@ -3074,6 +3166,13 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
true /* keyguardFadingAway */,
|
||||
false /* goingToFullShade */,
|
||||
mBarState);
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.setKeyguardUserSwitcherVisibility(
|
||||
mBarState,
|
||||
true /* keyguardFadingAway */,
|
||||
false /* goingToFullShade */,
|
||||
mBarState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3316,6 +3415,44 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
return mNotificationStackScrollLayoutController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the keyguard user switcher if it is open and capable of closing.
|
||||
*
|
||||
* Has no effect if user switcher isn't supported, if the user switcher is already closed, or
|
||||
* if the user switcher uses "simple" mode. The simple user switcher cannot be closed.
|
||||
*
|
||||
* @return true if the keyguard user switcher was open, and is now closed
|
||||
*/
|
||||
public boolean closeUserSwitcherIfOpen() {
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
return mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(
|
||||
true /* animate */);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateUserSwitcherVisibility(boolean open) {
|
||||
if (open) {
|
||||
animateKeyguardStatusBarOut();
|
||||
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
|
||||
mBarState,
|
||||
true /* keyguardFadingAway */,
|
||||
true /* goingToFullShade */,
|
||||
mBarState);
|
||||
setKeyguardBottomAreaVisibility(mBarState, true);
|
||||
mNotificationContainerParent.setVisibility(View.GONE);
|
||||
} else {
|
||||
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
|
||||
StatusBarState.KEYGUARD,
|
||||
false,
|
||||
false,
|
||||
StatusBarState.SHADE_LOCKED);
|
||||
setKeyguardBottomAreaVisibility(mBarState, false);
|
||||
mNotificationContainerParent.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private class OnHeightChangedListener implements ExpandableView.OnHeightChangedListener {
|
||||
@Override
|
||||
public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
|
||||
@@ -3616,6 +3753,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private class ConfigurationListener implements ConfigurationController.ConfigurationListener {
|
||||
@Override
|
||||
public void onThemeChanged() {
|
||||
if (DEBUG) Log.d(TAG, "onThemeChanged");
|
||||
final int themeResId = mView.getContext().getThemeResId();
|
||||
if (mThemeResId == themeResId) {
|
||||
return;
|
||||
@@ -3627,11 +3765,15 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
|
||||
@Override
|
||||
public void onOverlayChanged() {
|
||||
if (DEBUG) Log.d(TAG, "onOverlayChanged");
|
||||
reInflateViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUiModeChanged() {}
|
||||
public void onDensityOrFontScaleChanged() {
|
||||
if (DEBUG) Log.d(TAG, "onDensityOrFontScaleChanged");
|
||||
reInflateViews();
|
||||
}
|
||||
}
|
||||
|
||||
private class StatusBarStateListener implements StateListener {
|
||||
|
||||
@@ -22,8 +22,6 @@ import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewStub;
|
||||
import android.view.ViewStub.OnInflateListener;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
@@ -44,14 +42,11 @@ import java.util.Comparator;
|
||||
* The container with notification stack scroller and quick settings inside.
|
||||
*/
|
||||
public class NotificationsQuickSettingsContainer extends ConstraintLayout
|
||||
implements OnInflateListener, FragmentListener,
|
||||
AboveShelfObserver.HasViewAboveShelfChangedListener {
|
||||
implements FragmentListener, AboveShelfObserver.HasViewAboveShelfChangedListener {
|
||||
|
||||
private FrameLayout mQsFrame;
|
||||
private View mUserSwitcher;
|
||||
private NotificationStackScrollLayout mStackScroller;
|
||||
private View mKeyguardStatusBar;
|
||||
private boolean mInflated;
|
||||
private boolean mQsExpanded;
|
||||
private boolean mCustomizerAnimating;
|
||||
|
||||
@@ -73,9 +68,6 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
|
||||
mStackScroller = findViewById(R.id.notification_stack_scroller);
|
||||
mStackScrollerMargin = ((LayoutParams) mStackScroller.getLayoutParams()).bottomMargin;
|
||||
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
|
||||
ViewStub userSwitcher = findViewById(R.id.keyguard_user_switcher);
|
||||
userSwitcher.setOnInflateListener(this);
|
||||
mUserSwitcher = userSwitcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,10 +111,6 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
|
||||
// touches first but the panel gets drawn above.
|
||||
mDrawingOrderedChildren.clear();
|
||||
mLayoutDrawingOrder.clear();
|
||||
if (mInflated && mUserSwitcher.getVisibility() == View.VISIBLE) {
|
||||
mDrawingOrderedChildren.add(mUserSwitcher);
|
||||
mLayoutDrawingOrder.add(mUserSwitcher);
|
||||
}
|
||||
if (mKeyguardStatusBar.getVisibility() == View.VISIBLE) {
|
||||
mDrawingOrderedChildren.add(mKeyguardStatusBar);
|
||||
mLayoutDrawingOrder.add(mKeyguardStatusBar);
|
||||
@@ -157,14 +145,6 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInflate(ViewStub stub, View inflated) {
|
||||
if (stub == mUserSwitcher) {
|
||||
mUserSwitcher = inflated;
|
||||
mInflated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentViewCreated(String tag, Fragment fragment) {
|
||||
QS container = (QS) fragment;
|
||||
|
||||
@@ -89,7 +89,6 @@ import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
@@ -226,7 +225,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
|
||||
import com.android.systemui.statusbar.policy.ExtensionController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
|
||||
import com.android.systemui.statusbar.policy.NetworkController;
|
||||
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
|
||||
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
|
||||
@@ -623,7 +621,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
}
|
||||
};
|
||||
|
||||
private KeyguardUserSwitcher mKeyguardUserSwitcher;
|
||||
private final UserSwitcherController mUserSwitcherController;
|
||||
private final NetworkController mNetworkController;
|
||||
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
|
||||
@@ -1212,9 +1209,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
});
|
||||
|
||||
mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
|
||||
if (UserManager.get(mContext).isUserSwitcherEnabled()) {
|
||||
createUserSwitcher();
|
||||
}
|
||||
|
||||
// Set up the quick settings tile panel
|
||||
final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
|
||||
@@ -1441,9 +1435,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
// TODO: Bring these out of StatusBar.
|
||||
mUserInfoControllerImpl.onDensityOrFontScaleChanged();
|
||||
mUserSwitcherController.onDensityOrFontScaleChanged();
|
||||
if (mKeyguardUserSwitcher != null) {
|
||||
mKeyguardUserSwitcher.onDensityOrFontScaleChanged();
|
||||
}
|
||||
mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
|
||||
mHeadsUpManager.onDensityOrFontScaleChanged();
|
||||
}
|
||||
@@ -1477,13 +1468,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
}
|
||||
}
|
||||
|
||||
protected void createUserSwitcher() {
|
||||
mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
|
||||
mNotificationShadeWindowView.findViewById(R.id.keyguard_user_switcher),
|
||||
mNotificationShadeWindowView.findViewById(R.id.keyguard_header),
|
||||
mNotificationPanelViewController);
|
||||
}
|
||||
|
||||
private void inflateStatusBarWindow() {
|
||||
mNotificationShadeWindowView = mSuperStatusBarViewFactory.getNotificationShadeWindowView();
|
||||
StatusBarComponent statusBarComponent = mStatusBarComponentBuilder.get()
|
||||
@@ -3266,7 +3250,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
|
||||
if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) {
|
||||
mStatusBarStateController.setState(StatusBarState.FULLSCREEN_USER_SWITCHER);
|
||||
} else if (!mPulseExpansionHandler.isWakingToShadeLocked()){
|
||||
} else if (!mPulseExpansionHandler.isWakingToShadeLocked()) {
|
||||
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
|
||||
}
|
||||
updatePanelExpansionForKeyguard();
|
||||
@@ -3565,15 +3549,15 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
|
||||
return true;
|
||||
}
|
||||
if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) {
|
||||
if (mNotificationPanelViewController.canPanelBeCollapsed()) {
|
||||
mShadeController.animateCollapsePanels();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3622,20 +3606,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
updateTheme();
|
||||
mNavigationBarController.touchAutoDim(mDisplayId);
|
||||
Trace.beginSection("StatusBar#updateKeyguardState");
|
||||
if (mState == StatusBarState.KEYGUARD) {
|
||||
if (mKeyguardUserSwitcher != null) {
|
||||
mKeyguardUserSwitcher.setKeyguard(true,
|
||||
mStatusBarStateController.fromShadeLocked());
|
||||
}
|
||||
if (mStatusBarView != null) mStatusBarView.removePendingHideExpandedRunnables();
|
||||
} else {
|
||||
if (mKeyguardUserSwitcher != null) {
|
||||
mKeyguardUserSwitcher.setKeyguard(false,
|
||||
mStatusBarStateController.goingToFullShade() ||
|
||||
mState == StatusBarState.SHADE_LOCKED ||
|
||||
mStatusBarStateController.fromShadeLocked());
|
||||
}
|
||||
|
||||
if (mState == StatusBarState.KEYGUARD && mStatusBarView != null) {
|
||||
mStatusBarView.removePendingHideExpandedRunnables();
|
||||
}
|
||||
updateDozingState();
|
||||
checkBarModes();
|
||||
|
||||
@@ -17,8 +17,15 @@
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.keyguard.KeyguardConstants;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.qs.tiles.UserDetailItemView;
|
||||
|
||||
@@ -27,6 +34,14 @@ import com.android.systemui.qs.tiles.UserDetailItemView;
|
||||
*/
|
||||
public class KeyguardUserDetailItemView extends UserDetailItemView {
|
||||
|
||||
private static final String TAG = "KeyguardUserDetailItemView";
|
||||
private static final boolean DEBUG = KeyguardConstants.DEBUG;
|
||||
|
||||
private static final int ANIMATION_DURATION_FADE_NAME = 240;
|
||||
|
||||
private float mDarkAmount;
|
||||
private int mTextColor;
|
||||
|
||||
public KeyguardUserDetailItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -48,4 +63,89 @@ public class KeyguardUserDetailItemView extends UserDetailItemView {
|
||||
protected int getFontSizeDimen() {
|
||||
return R.dimen.kg_user_switcher_text_size;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mTextColor = mName.getCurrentTextColor();
|
||||
updateDark();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update visibility of this view.
|
||||
*
|
||||
* @param showItem If true, this item is visible on the screen to the user. Generally this
|
||||
* means that the item would be clickable. If false, item visibility will be
|
||||
* set to GONE and hidden entirely.
|
||||
* @param showTextName Whether or not the name should be shown next to the icon. If false,
|
||||
* only the icon is shown.
|
||||
* @param animate Whether the transition should be animated. Note, this only applies to
|
||||
* animating the text name. The item itself will not animate (i.e. fade in/out).
|
||||
* Instead, we delegate that to the parent view.
|
||||
*/
|
||||
void updateVisibilities(boolean showItem, boolean showTextName, boolean animate) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("updateVisibilities itemIsShown=%b nameIsShown=%b animate=%b",
|
||||
showItem, showTextName, animate));
|
||||
}
|
||||
|
||||
getBackground().setAlpha((showItem && showTextName) ? 255 : 0);
|
||||
|
||||
if (showItem) {
|
||||
if (showTextName) {
|
||||
mName.setVisibility(View.VISIBLE);
|
||||
if (animate) {
|
||||
mName.setAlpha(0f);
|
||||
mName.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(ANIMATION_DURATION_FADE_NAME)
|
||||
.setInterpolator(Interpolators.ALPHA_IN);
|
||||
} else {
|
||||
mName.setAlpha(1f);
|
||||
}
|
||||
} else {
|
||||
if (animate) {
|
||||
mName.setVisibility(View.VISIBLE);
|
||||
mName.setAlpha(1f);
|
||||
mName.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(ANIMATION_DURATION_FADE_NAME)
|
||||
.setInterpolator(Interpolators.ALPHA_OUT)
|
||||
.withEndAction(() -> {
|
||||
mName.setVisibility(View.GONE);
|
||||
mName.setAlpha(1f);
|
||||
});
|
||||
} else {
|
||||
mName.setVisibility(View.GONE);
|
||||
mName.setAlpha(1f);
|
||||
}
|
||||
}
|
||||
setVisibility(View.VISIBLE);
|
||||
setAlpha(1f);
|
||||
} else {
|
||||
// If item isn't shown, don't animate. The parent class will animate the view instead
|
||||
setVisibility(View.GONE);
|
||||
setAlpha(1f);
|
||||
mName.setVisibility(showTextName ? View.VISIBLE : View.GONE);
|
||||
mName.setAlpha(1f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void setDarkAmount(float darkAmount) {
|
||||
if (mDarkAmount == darkAmount) {
|
||||
return;
|
||||
}
|
||||
mDarkAmount = darkAmount;
|
||||
updateDark();
|
||||
}
|
||||
|
||||
private void updateDark() {
|
||||
final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
|
||||
mName.setTextColor(blendedTextColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,414 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
|
||||
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.database.DataSetObserver;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewStub;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.qs.tiles.UserDetailItemView;
|
||||
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Manages the user switcher on the Keyguard.
|
||||
*/
|
||||
public class KeyguardUserSwitcher {
|
||||
|
||||
private static final String TAG = "KeyguardUserSwitcher";
|
||||
private static final boolean ALWAYS_ON = false;
|
||||
|
||||
private final Container mUserSwitcherContainer;
|
||||
private final KeyguardStatusBarView mStatusBarView;
|
||||
private final KeyguardUserAdapter mAdapter;
|
||||
private final AppearAnimationUtils mAppearAnimationUtils;
|
||||
private final KeyguardUserSwitcherScrim mBackground;
|
||||
|
||||
private ViewGroup mUserSwitcher;
|
||||
private ObjectAnimator mBgAnimator;
|
||||
private UserSwitcherController mUserSwitcherController;
|
||||
private boolean mAnimating;
|
||||
|
||||
public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
|
||||
KeyguardStatusBarView statusBarView,
|
||||
NotificationPanelViewController panelViewController) {
|
||||
boolean keyguardUserSwitcherEnabled =
|
||||
context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_keyguardUserSwitcher) || ALWAYS_ON;
|
||||
UserSwitcherController userSwitcherController = Dependency.get(UserSwitcherController.class);
|
||||
if (userSwitcherController != null && keyguardUserSwitcherEnabled) {
|
||||
mUserSwitcherContainer = (Container) userSwitcher.inflate();
|
||||
mBackground = new KeyguardUserSwitcherScrim(context);
|
||||
reinflateViews();
|
||||
mStatusBarView = statusBarView;
|
||||
mStatusBarView.setKeyguardUserSwitcher(this);
|
||||
panelViewController.setKeyguardUserSwitcher(this);
|
||||
mAdapter = new KeyguardUserAdapter(context, userSwitcherController, this);
|
||||
mAdapter.registerDataSetObserver(mDataSetObserver);
|
||||
mUserSwitcherController = userSwitcherController;
|
||||
mAppearAnimationUtils = new AppearAnimationUtils(context, 400, -0.5f, 0.5f,
|
||||
Interpolators.FAST_OUT_SLOW_IN);
|
||||
mUserSwitcherContainer.setKeyguardUserSwitcher(this);
|
||||
} else {
|
||||
mUserSwitcherContainer = null;
|
||||
mStatusBarView = null;
|
||||
mAdapter = null;
|
||||
mAppearAnimationUtils = null;
|
||||
mBackground = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void reinflateViews() {
|
||||
if (mUserSwitcher != null) {
|
||||
mUserSwitcher.setBackground(null);
|
||||
mUserSwitcher.removeOnLayoutChangeListener(mBackground);
|
||||
}
|
||||
mUserSwitcherContainer.removeAllViews();
|
||||
|
||||
LayoutInflater.from(mUserSwitcherContainer.getContext())
|
||||
.inflate(R.layout.keyguard_user_switcher_inner, mUserSwitcherContainer);
|
||||
|
||||
mUserSwitcher = (ViewGroup) mUserSwitcherContainer.findViewById(
|
||||
R.id.keyguard_user_switcher_inner);
|
||||
mUserSwitcher.addOnLayoutChangeListener(mBackground);
|
||||
mUserSwitcher.setBackground(mBackground);
|
||||
}
|
||||
|
||||
public void setKeyguard(boolean keyguard, boolean animate) {
|
||||
if (mUserSwitcher != null) {
|
||||
if (keyguard && shouldExpandByDefault()) {
|
||||
show(animate);
|
||||
} else {
|
||||
hide(animate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the user switcher should be expanded by default on the lock screen.
|
||||
* @see android.os.UserManager#isUserSwitcherEnabled()
|
||||
*/
|
||||
private boolean shouldExpandByDefault() {
|
||||
return (mUserSwitcherController != null) && mUserSwitcherController.isSimpleUserSwitcher();
|
||||
}
|
||||
|
||||
public void show(boolean animate) {
|
||||
if (mUserSwitcher != null && mUserSwitcherContainer.getVisibility() != View.VISIBLE) {
|
||||
cancelAnimations();
|
||||
mAdapter.refresh();
|
||||
mUserSwitcherContainer.setVisibility(View.VISIBLE);
|
||||
mStatusBarView.setKeyguardUserSwitcherShowing(true, animate);
|
||||
if (animate) {
|
||||
startAppearAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hide(boolean animate) {
|
||||
if (mUserSwitcher != null && mUserSwitcherContainer.getVisibility() == View.VISIBLE) {
|
||||
cancelAnimations();
|
||||
if (animate) {
|
||||
startDisappearAnimation();
|
||||
} else {
|
||||
mUserSwitcherContainer.setVisibility(View.GONE);
|
||||
}
|
||||
mStatusBarView.setKeyguardUserSwitcherShowing(false, animate);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void cancelAnimations() {
|
||||
int count = mUserSwitcher.getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mUserSwitcher.getChildAt(i).animate().cancel();
|
||||
}
|
||||
if (mBgAnimator != null) {
|
||||
mBgAnimator.cancel();
|
||||
}
|
||||
mUserSwitcher.animate().cancel();
|
||||
mAnimating = false;
|
||||
}
|
||||
|
||||
private void startAppearAnimation() {
|
||||
int count = mUserSwitcher.getChildCount();
|
||||
View[] objects = new View[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
objects[i] = mUserSwitcher.getChildAt(i);
|
||||
}
|
||||
mUserSwitcher.setClipChildren(false);
|
||||
mUserSwitcher.setClipToPadding(false);
|
||||
mAppearAnimationUtils.startAnimation(objects, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mUserSwitcher.setClipChildren(true);
|
||||
mUserSwitcher.setClipToPadding(true);
|
||||
}
|
||||
});
|
||||
mAnimating = true;
|
||||
mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
|
||||
mBgAnimator.setDuration(400);
|
||||
mBgAnimator.setInterpolator(Interpolators.ALPHA_IN);
|
||||
mBgAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mBgAnimator = null;
|
||||
mAnimating = false;
|
||||
}
|
||||
});
|
||||
mBgAnimator.start();
|
||||
}
|
||||
|
||||
private void startDisappearAnimation() {
|
||||
mAnimating = true;
|
||||
mUserSwitcher.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(300)
|
||||
.setInterpolator(Interpolators.ALPHA_OUT)
|
||||
.withEndAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mUserSwitcherContainer.setVisibility(View.GONE);
|
||||
mUserSwitcher.setAlpha(1f);
|
||||
mAnimating = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
final int childCount = mUserSwitcher.getChildCount();
|
||||
final int adapterCount = mAdapter.getCount();
|
||||
final int N = Math.max(childCount, adapterCount);
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (i < adapterCount) {
|
||||
View oldView = null;
|
||||
if (i < childCount) {
|
||||
oldView = mUserSwitcher.getChildAt(i);
|
||||
}
|
||||
View newView = mAdapter.getView(i, oldView, mUserSwitcher);
|
||||
if (oldView == null) {
|
||||
// We ran out of existing views. Add it at the end.
|
||||
mUserSwitcher.addView(newView);
|
||||
} else if (oldView != newView) {
|
||||
// We couldn't rebind the view. Replace it.
|
||||
mUserSwitcher.removeViewAt(i);
|
||||
mUserSwitcher.addView(newView, i);
|
||||
}
|
||||
} else {
|
||||
int lastIndex = mUserSwitcher.getChildCount() - 1;
|
||||
mUserSwitcher.removeViewAt(lastIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hideIfNotSimple(boolean animate) {
|
||||
if (mUserSwitcherContainer != null && !mUserSwitcherController.isSimpleUserSwitcher()) {
|
||||
return hide(animate);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isAnimating() {
|
||||
return mAnimating;
|
||||
}
|
||||
|
||||
public final DataSetObserver mDataSetObserver = new DataSetObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
refresh();
|
||||
}
|
||||
};
|
||||
|
||||
public void onDensityOrFontScaleChanged() {
|
||||
if (mUserSwitcherContainer != null) {
|
||||
reinflateViews();
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
static class KeyguardUserAdapter extends
|
||||
UserSwitcherController.BaseUserAdapter implements View.OnClickListener {
|
||||
|
||||
private Context mContext;
|
||||
private KeyguardUserSwitcher mKeyguardUserSwitcher;
|
||||
private View mCurrentUserView;
|
||||
// List of users where the first entry is always the current user
|
||||
private ArrayList<UserSwitcherController.UserRecord> mUsersOrdered = new ArrayList<>();
|
||||
|
||||
KeyguardUserAdapter(Context context, UserSwitcherController controller,
|
||||
KeyguardUserSwitcher kgu) {
|
||||
super(controller);
|
||||
mContext = context;
|
||||
mKeyguardUserSwitcher = kgu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
refreshUserOrder();
|
||||
super.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
void refreshUserOrder() {
|
||||
ArrayList<UserSwitcherController.UserRecord> users = super.getUsers();
|
||||
mUsersOrdered = new ArrayList<>(users.size());
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
UserSwitcherController.UserRecord record = users.get(i);
|
||||
if (record.isCurrent) {
|
||||
mUsersOrdered.add(0, record);
|
||||
} else {
|
||||
mUsersOrdered.add(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrayList<UserSwitcherController.UserRecord> getUsers() {
|
||||
return mUsersOrdered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
UserSwitcherController.UserRecord item = getItem(position);
|
||||
return createUserDetailItemView(convertView, parent, item);
|
||||
}
|
||||
|
||||
KeyguardUserDetailItemView convertOrInflate(View convertView, ViewGroup parent) {
|
||||
if (!(convertView instanceof KeyguardUserDetailItemView)
|
||||
|| !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) {
|
||||
convertView = LayoutInflater.from(mContext).inflate(
|
||||
R.layout.keyguard_user_switcher_item, parent, false);
|
||||
}
|
||||
return (KeyguardUserDetailItemView) convertView;
|
||||
}
|
||||
|
||||
UserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
|
||||
UserSwitcherController.UserRecord item) {
|
||||
KeyguardUserDetailItemView v = convertOrInflate(convertView, parent);
|
||||
if (!item.isCurrent || item.isGuest) {
|
||||
v.setOnClickListener(this);
|
||||
} else {
|
||||
v.setOnClickListener(null);
|
||||
v.setClickable(false);
|
||||
}
|
||||
|
||||
String name = getName(mContext, item);
|
||||
if (item.picture == null) {
|
||||
v.bind(name, getDrawable(mContext, item).mutate(), item.resolveId());
|
||||
} else {
|
||||
int avatarSize =
|
||||
(int) mContext.getResources().getDimension(R.dimen.kg_framed_avatar_size);
|
||||
Drawable drawable = new CircleFramedDrawable(item.picture, avatarSize);
|
||||
drawable.setColorFilter(
|
||||
item.isSwitchToEnabled ? null : getDisabledUserAvatarColorFilter());
|
||||
v.bind(name, drawable, item.info.id);
|
||||
}
|
||||
v.setActivated(item.isCurrent);
|
||||
v.setDisabledByAdmin(item.isDisabledByAdmin);
|
||||
v.setEnabled(item.isSwitchToEnabled);
|
||||
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
|
||||
|
||||
if (item.isCurrent) {
|
||||
mCurrentUserView = v;
|
||||
}
|
||||
v.setTag(item);
|
||||
return v;
|
||||
}
|
||||
|
||||
private static Drawable getDrawable(Context context,
|
||||
UserSwitcherController.UserRecord item) {
|
||||
Drawable drawable = getIconDrawable(context, item);
|
||||
int iconColorRes;
|
||||
if (item.isCurrent) {
|
||||
iconColorRes = R.color.kg_user_switcher_selected_avatar_icon_color;
|
||||
} else if (!item.isSwitchToEnabled) {
|
||||
iconColorRes = R.color.GM2_grey_600;
|
||||
} else {
|
||||
iconColorRes = R.color.kg_user_switcher_avatar_icon_color;
|
||||
}
|
||||
drawable.setTint(context.getResources().getColor(iconColorRes, context.getTheme()));
|
||||
|
||||
if (item.isCurrent) {
|
||||
Drawable bg = context.getDrawable(R.drawable.bg_avatar_selected);
|
||||
drawable = new LayerDrawable(new Drawable[]{bg, drawable});
|
||||
}
|
||||
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
UserSwitcherController.UserRecord user = (UserSwitcherController.UserRecord) v.getTag();
|
||||
if (user.isCurrent && !user.isGuest) {
|
||||
// Close the switcher if tapping the current user. Guest is excluded because
|
||||
// tapping the guest user while it's current clears the session.
|
||||
mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
|
||||
} else if (user.isSwitchToEnabled) {
|
||||
if (!user.isAddUser && !user.isRestricted && !user.isDisabledByAdmin) {
|
||||
if (mCurrentUserView != null) {
|
||||
mCurrentUserView.setActivated(false);
|
||||
}
|
||||
v.setActivated(true);
|
||||
}
|
||||
onUserListItemClicked(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Container extends FrameLayout {
|
||||
|
||||
private KeyguardUserSwitcher mKeyguardUserSwitcher;
|
||||
|
||||
public Container(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setClipChildren(false);
|
||||
}
|
||||
|
||||
public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
|
||||
mKeyguardUserSwitcher = keyguardUserSwitcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
// Hide switcher if it didn't handle the touch event (and let the event go through).
|
||||
if (mKeyguardUserSwitcher != null && !mKeyguardUserSwitcher.isAnimating()) {
|
||||
mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
* 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 static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
|
||||
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
|
||||
|
||||
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.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.keyguard.KeyguardConstants;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||
import com.android.keyguard.KeyguardVisibilityHelper;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherScope;
|
||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||
import com.android.systemui.Interpolators;
|
||||
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.util.ViewController;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Manages the user switcher on the Keyguard.
|
||||
*/
|
||||
@KeyguardUserSwitcherScope
|
||||
public class KeyguardUserSwitcherController extends ViewController<KeyguardUserSwitcherView> {
|
||||
|
||||
private static final String TAG = "KeyguardUserSwitcherController";
|
||||
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 final UserSwitcherController mUserSwitcherController;
|
||||
private final ScreenLifecycle mScreenLifecycle;
|
||||
private final KeyguardUserAdapter mAdapter;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private WeakReference<KeyguardUserSwitcherListener> mKeyguardUserSwitcherCallback;
|
||||
protected final SysuiStatusBarStateController mStatusBarStateController;
|
||||
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
|
||||
|
||||
// Child views of KeyguardUserSwitcherView
|
||||
private KeyguardUserSwitcherListView mListView;
|
||||
private LinearLayout mEndGuestButton;
|
||||
|
||||
// State info for the user switcher
|
||||
private boolean mUserSwitcherOpen;
|
||||
private int mCurrentUserId = UserHandle.USER_NULL;
|
||||
private boolean mCurrentUserIsGuest;
|
||||
private int mBarState;
|
||||
private float mDarkAmount;
|
||||
|
||||
private final KeyguardUpdateMonitorCallback mInfoCallback =
|
||||
new KeyguardUpdateMonitorCallback() {
|
||||
@Override
|
||||
public void onKeyguardVisibilityChanged(boolean showing) {
|
||||
if (DEBUG) Log.d(TAG, String.format("onKeyguardVisibilityChanged %b", showing));
|
||||
// Any time the keyguard is hidden, try to close the user switcher menu to
|
||||
// restore keyguard to the default state
|
||||
if (!showing) {
|
||||
closeSwitcherIfOpenAndNotSimple(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserSwitching(int userId) {
|
||||
closeSwitcherIfOpenAndNotSimple(false);
|
||||
}
|
||||
};
|
||||
|
||||
private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
|
||||
@Override
|
||||
public void onScreenTurnedOff() {
|
||||
if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
|
||||
closeSwitcherIfOpenAndNotSimple(false);
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
if (mStatusBarStateController.goingToFullShade()
|
||||
|| mKeyguardStateController.isKeyguardFadingAway()) {
|
||||
closeSwitcherIfOpenAndNotSimple(true);
|
||||
}
|
||||
|
||||
setKeyguardUserSwitcherVisibility(
|
||||
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 KeyguardUserSwitcherController(
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView,
|
||||
Context context,
|
||||
@Main Resources resources,
|
||||
LayoutInflater layoutInflater,
|
||||
ScreenLifecycle screenLifecycle,
|
||||
UserSwitcherController userSwitcherController,
|
||||
KeyguardStateController keyguardStateController,
|
||||
SysuiStatusBarStateController statusBarStateController,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
DozeParameters dozeParameters) {
|
||||
super(keyguardUserSwitcherView);
|
||||
if (DEBUG) Log.d(TAG, "New KeyguardUserSwitcherController");
|
||||
mContext = context;
|
||||
mScreenLifecycle = screenLifecycle;
|
||||
mUserSwitcherController = userSwitcherController;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mAdapter = new KeyguardUserAdapter(mContext, resources, layoutInflater,
|
||||
mUserSwitcherController, this);
|
||||
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
|
||||
keyguardStateController, dozeParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
|
||||
if (DEBUG) Log.d(TAG, "onInit");
|
||||
|
||||
mListView = mView.findViewById(R.id.keyguard_user_switcher_list);
|
||||
mEndGuestButton = mView.findViewById(R.id.end_guest_button);
|
||||
|
||||
mEndGuestButton.setOnClickListener(v -> {
|
||||
mUserSwitcherController.showExitGuestDialog(mCurrentUserId);
|
||||
});
|
||||
|
||||
mView.setOnTouchListener((v, event) -> {
|
||||
if (!isListAnimating()) {
|
||||
// Hide switcher if it didn't handle the touch event (and block the event from
|
||||
// going through).
|
||||
return closeSwitcherIfOpenAndNotSimple(true);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
if (DEBUG) Log.d(TAG, "onViewAttached");
|
||||
mAdapter.registerDataSetObserver(mDataSetObserver);
|
||||
mDataSetObserver.onChanged();
|
||||
mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
|
||||
mStatusBarStateController.addCallback(mStatusBarStateListener);
|
||||
mScreenLifecycle.addObserver(mScreenObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
if (DEBUG) Log.d(TAG, "onViewDetached");
|
||||
|
||||
// Detaching the view will always close the switcher
|
||||
closeSwitcherIfOpenAndNotSimple(false);
|
||||
|
||||
mAdapter.unregisterDataSetObserver(mDataSetObserver);
|
||||
mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
|
||||
mStatusBarStateController.removeCallback(mStatusBarStateListener);
|
||||
mScreenLifecycle.removeObserver(mScreenObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* See:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link com.android.internal.R.bool.config_expandLockScreenUserSwitcher}</li>
|
||||
* <li>{@link UserSwitcherController.SIMPLE_USER_SWITCHER_GLOBAL_SETTING}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return true if the user switcher should be open by default on the lock screen.
|
||||
* @see android.os.UserManager#isUserSwitcherEnabled()
|
||||
*/
|
||||
public boolean isSimpleUserSwitcher() {
|
||||
return mUserSwitcherController.isSimpleUserSwitcher();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param animate if the transition should be animated
|
||||
* @return true if the switcher state changed
|
||||
*/
|
||||
public boolean closeSwitcherIfOpenAndNotSimple(boolean animate) {
|
||||
if (isUserSwitcherOpen() && !isSimpleUserSwitcher()) {
|
||||
setUserSwitcherOpened(false /* open */, animate);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final DataSetObserver mDataSetObserver = new DataSetObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
refreshUserList();
|
||||
}
|
||||
};
|
||||
|
||||
void refreshUserList() {
|
||||
final int childCount = mListView.getChildCount();
|
||||
final int adapterCount = mAdapter.getCount();
|
||||
final int count = Math.max(childCount, adapterCount);
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("refreshUserList childCount=%d adapterCount=%d", childCount,
|
||||
adapterCount));
|
||||
}
|
||||
|
||||
boolean foundCurrentUser = false;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i < adapterCount) {
|
||||
View oldView = null;
|
||||
if (i < childCount) {
|
||||
oldView = mListView.getChildAt(i);
|
||||
}
|
||||
KeyguardUserDetailItemView newView = (KeyguardUserDetailItemView)
|
||||
mAdapter.getView(i, oldView, mListView);
|
||||
UserSwitcherController.UserRecord userTag =
|
||||
(UserSwitcherController.UserRecord) newView.getTag();
|
||||
if (userTag.isCurrent) {
|
||||
if (i != 0) {
|
||||
Log.w(TAG, "Current user is not the first view in the list");
|
||||
}
|
||||
foundCurrentUser = true;
|
||||
mCurrentUserId = userTag.info.id;
|
||||
mCurrentUserIsGuest = userTag.isGuest;
|
||||
// Current user is always visible
|
||||
newView.updateVisibilities(true /* showItem */,
|
||||
mUserSwitcherOpen /* showTextName */, false /* animate */);
|
||||
} else {
|
||||
// Views for non-current users are always expanded (e.g. they should the name
|
||||
// next to the user icon). However, they could be hidden entirely if the list
|
||||
// is closed.
|
||||
newView.updateVisibilities(mUserSwitcherOpen /* showItem */,
|
||||
true /* showTextName */, false /* animate */);
|
||||
}
|
||||
newView.setDarkAmount(mDarkAmount);
|
||||
if (oldView == null) {
|
||||
// We ran out of existing views. Add it at the end.
|
||||
mListView.addView(newView);
|
||||
} else if (oldView != newView) {
|
||||
// We couldn't rebind the view. Replace it.
|
||||
mListView.replaceView(newView, i);
|
||||
}
|
||||
} else {
|
||||
mListView.removeLastView();
|
||||
}
|
||||
}
|
||||
if (!foundCurrentUser) {
|
||||
Log.w(TAG, "Current user is not listed");
|
||||
mCurrentUserId = UserHandle.USER_NULL;
|
||||
mCurrentUserIsGuest = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the keyguard user switcher view when closed.
|
||||
*/
|
||||
public int getUserIconHeight() {
|
||||
View firstChild = mListView.getChildAt(0);
|
||||
return firstChild == null ? 0 : firstChild.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the visibility of the keyguard user switcher view based on some new state.
|
||||
*/
|
||||
public void setKeyguardUserSwitcherVisibility(
|
||||
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(mListView, AnimatableProperty.Y, y, ANIMATION_PROPERTIES,
|
||||
animate);
|
||||
PropertyAnimator.setProperty(mListView, AnimatableProperty.TRANSLATION_X, -Math.abs(x),
|
||||
ANIMATION_PROPERTIES, animate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set keyguard user switcher 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;
|
||||
mListView.setDarkAmount(darkAmount);
|
||||
mView.setVisibility(isAwake ? View.VISIBLE : View.GONE);
|
||||
if (!isAwake) {
|
||||
closeSwitcherIfOpenAndNotSimple(false);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isListAnimating() {
|
||||
return mKeyguardVisibilityHelper.isVisibilityAnimating() || mListView.isAnimating();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the callback if it exists.
|
||||
*/
|
||||
public void removeCallback() {
|
||||
if (DEBUG) Log.d(TAG, "removeCallback");
|
||||
mKeyguardUserSwitcherCallback = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to receive notifications about keyguard user switcher state
|
||||
* (see {@link KeyguardUserSwitcherListener}.
|
||||
*
|
||||
* Only one callback can be used at a time.
|
||||
*
|
||||
* @param callback The callback to register
|
||||
*/
|
||||
public void setCallback(KeyguardUserSwitcherListener callback) {
|
||||
if (DEBUG) Log.d(TAG, "setCallback");
|
||||
mKeyguardUserSwitcherCallback = new WeakReference<>(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* If user switcher state changes, notifies all {@link KeyguardUserSwitcherListener}.
|
||||
* Switcher state is updatd before animations finish.
|
||||
*
|
||||
* @param animate true to animate transition. The user switcher state (i.e.
|
||||
* {@link #isUserSwitcherOpen()}) is updated before animation is finished.
|
||||
*/
|
||||
private void setUserSwitcherOpened(boolean open, boolean animate) {
|
||||
boolean wasOpen = mUserSwitcherOpen;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("setUserSwitcherOpened: %b -> %b (animate=%b)", wasOpen,
|
||||
open, animate));
|
||||
}
|
||||
mUserSwitcherOpen = open;
|
||||
if (mUserSwitcherOpen != wasOpen) {
|
||||
notifyUserSwitcherStateChanged();
|
||||
}
|
||||
updateVisibilities(animate);
|
||||
}
|
||||
|
||||
private void updateVisibilities(boolean animate) {
|
||||
if (DEBUG) Log.d(TAG, String.format("updateVisibilities: animate=%b", animate));
|
||||
mEndGuestButton.animate().cancel();
|
||||
if (mUserSwitcherOpen && mCurrentUserIsGuest) {
|
||||
// Show the "End guest session" button
|
||||
mEndGuestButton.setVisibility(View.VISIBLE);
|
||||
if (animate) {
|
||||
mEndGuestButton.setAlpha(0f);
|
||||
mEndGuestButton.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(360)
|
||||
.setInterpolator(Interpolators.ALPHA_IN)
|
||||
.withEndAction(() -> {
|
||||
mEndGuestButton.setClickable(true);
|
||||
});
|
||||
} else {
|
||||
mEndGuestButton.setClickable(true);
|
||||
mEndGuestButton.setAlpha(1f);
|
||||
}
|
||||
} else {
|
||||
// Hide the "End guest session" button. If it's already GONE, don't try to
|
||||
// animate it or it will appear again for an instant.
|
||||
mEndGuestButton.setClickable(false);
|
||||
if (animate && mEndGuestButton.getVisibility() != View.GONE) {
|
||||
mEndGuestButton.setVisibility(View.VISIBLE);
|
||||
mEndGuestButton.setAlpha(1f);
|
||||
mEndGuestButton.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(360)
|
||||
.setInterpolator(Interpolators.ALPHA_OUT)
|
||||
.withEndAction(() -> {
|
||||
mEndGuestButton.setVisibility(View.GONE);
|
||||
mEndGuestButton.setAlpha(1f);
|
||||
});
|
||||
} else {
|
||||
mEndGuestButton.setVisibility(View.GONE);
|
||||
mEndGuestButton.setAlpha(1f);
|
||||
}
|
||||
}
|
||||
|
||||
mListView.updateVisibilities(mUserSwitcherOpen, animate);
|
||||
}
|
||||
|
||||
private boolean isUserSwitcherOpen() {
|
||||
return mUserSwitcherOpen;
|
||||
}
|
||||
|
||||
private void notifyUserSwitcherStateChanged() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("notifyUserSwitcherStateChanged: mUserSwitcherOpen=%b",
|
||||
mUserSwitcherOpen));
|
||||
}
|
||||
if (mKeyguardUserSwitcherCallback != null) {
|
||||
KeyguardUserSwitcherListener cb = mKeyguardUserSwitcherCallback.get();
|
||||
if (cb != null) {
|
||||
cb.onKeyguardUserSwitcherChanged(mUserSwitcherOpen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for keyguard user switcher state information
|
||||
*/
|
||||
public interface KeyguardUserSwitcherListener {
|
||||
|
||||
/**
|
||||
* Called when the keyguard enters or leaves user switcher mode. This will be called
|
||||
* before the animations are finished.
|
||||
*
|
||||
* @param open if true, keyguard is showing the user switcher or transitioning from/to user
|
||||
* switcher mode.
|
||||
*/
|
||||
void onKeyguardUserSwitcherChanged(boolean open);
|
||||
}
|
||||
|
||||
static class KeyguardUserAdapter extends
|
||||
UserSwitcherController.BaseUserAdapter implements View.OnClickListener {
|
||||
|
||||
private final Context mContext;
|
||||
private final Resources mResources;
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
|
||||
private View mCurrentUserView;
|
||||
// List of users where the first entry is always the current user
|
||||
private ArrayList<UserSwitcherController.UserRecord> mUsersOrdered = new ArrayList<>();
|
||||
|
||||
KeyguardUserAdapter(Context context, Resources resources, LayoutInflater layoutInflater,
|
||||
UserSwitcherController controller,
|
||||
KeyguardUserSwitcherController keyguardUserSwitcherController) {
|
||||
super(controller);
|
||||
mContext = context;
|
||||
mResources = resources;
|
||||
mLayoutInflater = layoutInflater;
|
||||
mKeyguardUserSwitcherController = keyguardUserSwitcherController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
// At this point, value of isSimpleUserSwitcher() may have changed in addition to the
|
||||
// data set
|
||||
refreshUserOrder();
|
||||
super.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
void refreshUserOrder() {
|
||||
ArrayList<UserSwitcherController.UserRecord> users = super.getUsers();
|
||||
mUsersOrdered = new ArrayList<>(users.size());
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
UserSwitcherController.UserRecord record = users.get(i);
|
||||
if (record.isCurrent) {
|
||||
mUsersOrdered.add(0, record);
|
||||
} else {
|
||||
mUsersOrdered.add(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrayList<UserSwitcherController.UserRecord> getUsers() {
|
||||
return mUsersOrdered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
UserSwitcherController.UserRecord item = getItem(position);
|
||||
return createUserDetailItemView(convertView, parent, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Context context, UserSwitcherController.UserRecord item) {
|
||||
if (item.isGuest) {
|
||||
return context.getString(com.android.settingslib.R.string.guest_nickname);
|
||||
} else {
|
||||
return super.getName(context, item);
|
||||
}
|
||||
}
|
||||
|
||||
KeyguardUserDetailItemView convertOrInflate(View convertView, ViewGroup parent) {
|
||||
if (!(convertView instanceof KeyguardUserDetailItemView)
|
||||
|| !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) {
|
||||
convertView = mLayoutInflater.inflate(
|
||||
R.layout.keyguard_user_switcher_item, parent, false);
|
||||
}
|
||||
return (KeyguardUserDetailItemView) convertView;
|
||||
}
|
||||
|
||||
KeyguardUserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
|
||||
UserSwitcherController.UserRecord item) {
|
||||
KeyguardUserDetailItemView v = convertOrInflate(convertView, parent);
|
||||
v.setOnClickListener(this);
|
||||
|
||||
String name = getName(mContext, item);
|
||||
if (item.picture == null) {
|
||||
v.bind(name, getDrawable(item).mutate(), item.resolveId());
|
||||
} else {
|
||||
int avatarSize =
|
||||
(int) mResources.getDimension(R.dimen.kg_framed_avatar_size);
|
||||
Drawable drawable = new CircleFramedDrawable(item.picture, avatarSize);
|
||||
drawable.setColorFilter(
|
||||
item.isSwitchToEnabled ? null : getDisabledUserAvatarColorFilter());
|
||||
v.bind(name, drawable, item.info.id);
|
||||
}
|
||||
v.setActivated(item.isCurrent);
|
||||
v.setDisabledByAdmin(item.isDisabledByAdmin);
|
||||
v.setEnabled(item.isSwitchToEnabled);
|
||||
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
|
||||
|
||||
if (item.isCurrent) {
|
||||
mCurrentUserView = v;
|
||||
}
|
||||
v.setTag(item);
|
||||
return v;
|
||||
}
|
||||
|
||||
private Drawable getDrawable(UserSwitcherController.UserRecord item) {
|
||||
Drawable drawable;
|
||||
if (item.isCurrent && item.isGuest) {
|
||||
drawable = mContext.getDrawable(R.drawable.ic_avatar_guest_user);
|
||||
} else {
|
||||
drawable = 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
UserSwitcherController.UserRecord user = (UserSwitcherController.UserRecord) v.getTag();
|
||||
|
||||
if (mKeyguardUserSwitcherController.isListAnimating()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mKeyguardUserSwitcherController.isUserSwitcherOpen()) {
|
||||
if (user.isCurrent) {
|
||||
// Close the switcher if tapping the current user
|
||||
mKeyguardUserSwitcherController.setUserSwitcherOpened(
|
||||
false /* open */, true /* animate */);
|
||||
} else if (user.isSwitchToEnabled) {
|
||||
if (!user.isAddUser && !user.isRestricted && !user.isDisabledByAdmin) {
|
||||
if (mCurrentUserView != null) {
|
||||
mCurrentUserView.setActivated(false);
|
||||
}
|
||||
v.setActivated(true);
|
||||
}
|
||||
onUserListItemClicked(user);
|
||||
}
|
||||
} else {
|
||||
// If switcher is closed, tapping anywhere in the view will open it
|
||||
mKeyguardUserSwitcherController.setUserSwitcherOpened(
|
||||
true /* open */, true /* animate */);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.keyguard.AlphaOptimizedLinearLayout;
|
||||
import com.android.keyguard.KeyguardConstants;
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
import com.android.settingslib.animation.DisappearAnimationUtils;
|
||||
import com.android.systemui.Interpolators;
|
||||
|
||||
/**
|
||||
* The container for the user switcher on Keyguard.
|
||||
*/
|
||||
public class KeyguardUserSwitcherListView extends AlphaOptimizedLinearLayout {
|
||||
|
||||
private static final String TAG = "KeyguardUserSwitcherListView";
|
||||
private static final boolean DEBUG = KeyguardConstants.DEBUG;
|
||||
|
||||
private static final int ANIMATION_DURATION_OPENING = 360;
|
||||
private static final int ANIMATION_DURATION_CLOSING = 240;
|
||||
|
||||
private boolean mAnimating;
|
||||
private final AppearAnimationUtils mAppearAnimationUtils;
|
||||
private final DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
|
||||
public KeyguardUserSwitcherListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setClipChildren(false);
|
||||
mAppearAnimationUtils = new AppearAnimationUtils(context, ANIMATION_DURATION_OPENING,
|
||||
-0.5f, 0.5f, Interpolators.FAST_OUT_SLOW_IN);
|
||||
mDisappearAnimationUtils = new DisappearAnimationUtils(context, ANIMATION_DURATION_CLOSING,
|
||||
0.5f, 0.5f, Interpolators.FAST_OUT_LINEAR_IN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void setDarkAmount(float darkAmount) {
|
||||
int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View v = getChildAt(i);
|
||||
if (v instanceof KeyguardUserDetailItemView) {
|
||||
((KeyguardUserDetailItemView) v).setDarkAmount(darkAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAnimating() {
|
||||
return mAnimating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update visibilities of this view and child views for when the user list is open or closed.
|
||||
* If closed, this hides everything but the first item (which is always the current user).
|
||||
*/
|
||||
void updateVisibilities(boolean open, boolean animate) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("updateVisibilities: open=%b animate=%b childCount=%d",
|
||||
open, animate, getChildCount()));
|
||||
}
|
||||
|
||||
mAnimating = false;
|
||||
|
||||
int userListCount = getChildCount();
|
||||
if (userListCount > 0) {
|
||||
// The first child is always the current user.
|
||||
KeyguardUserDetailItemView currentUserView = ((KeyguardUserDetailItemView) getChildAt(
|
||||
0));
|
||||
currentUserView.updateVisibilities(true /* showItem */, open /* showTextName */,
|
||||
animate);
|
||||
currentUserView.setClickable(true);
|
||||
currentUserView.clearAnimation();
|
||||
}
|
||||
|
||||
if (userListCount <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (animate) {
|
||||
// Create an array of all the remaining users (that aren't the current user).
|
||||
KeyguardUserDetailItemView[] otherUserViews =
|
||||
new KeyguardUserDetailItemView[userListCount - 1];
|
||||
for (int i = 1, n = 0; i < userListCount; i++, n++) {
|
||||
otherUserViews[n] = (KeyguardUserDetailItemView) getChildAt(i);
|
||||
|
||||
// Update clickable state immediately so that the menu feels more responsive
|
||||
otherUserViews[n].setClickable(open);
|
||||
|
||||
// Before running the animation, ensure visibility is set correctly
|
||||
otherUserViews[n].updateVisibilities(
|
||||
true /* showItem */, true /* showTextName */, false /* animate */);
|
||||
otherUserViews[n].clearAnimation();
|
||||
}
|
||||
|
||||
setClipChildren(false);
|
||||
setClipToPadding(false);
|
||||
|
||||
mAnimating = true;
|
||||
|
||||
final int nonCurrentUserCount = otherUserViews.length;
|
||||
if (open) {
|
||||
mAppearAnimationUtils.startAnimation(otherUserViews, () -> {
|
||||
setClipChildren(true);
|
||||
setClipToPadding(true);
|
||||
mAnimating = false;
|
||||
});
|
||||
} else {
|
||||
mDisappearAnimationUtils.startAnimation(otherUserViews, () -> {
|
||||
setClipChildren(true);
|
||||
setClipToPadding(true);
|
||||
for (int i = 0; i < nonCurrentUserCount; i++) {
|
||||
otherUserViews[i].updateVisibilities(
|
||||
false /* showItem */, true /* showTextName */, false /* animate */);
|
||||
}
|
||||
mAnimating = false;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (int i = 1; i < userListCount; i++) {
|
||||
KeyguardUserDetailItemView nonCurrentUserView =
|
||||
((KeyguardUserDetailItemView) getChildAt(i));
|
||||
nonCurrentUserView.clearAnimation();
|
||||
nonCurrentUserView.updateVisibilities(
|
||||
open /* showItem */, true /* showTextName */, false /* animate */);
|
||||
nonCurrentUserView.setClickable(open);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the view at the specified position in the group.
|
||||
*
|
||||
* @param index the position in the group of the view to remove
|
||||
*/
|
||||
void replaceView(KeyguardUserDetailItemView newView, int index) {
|
||||
removeViewAt(index);
|
||||
addView(newView, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last view in the group.
|
||||
*/
|
||||
void removeLastView() {
|
||||
int lastIndex = getChildCount() - 1;
|
||||
removeViewAt(lastIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* The container for the user switcher on Keyguard.
|
||||
*/
|
||||
public class KeyguardUserSwitcherView extends FrameLayout {
|
||||
|
||||
public KeyguardUserSwitcherView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
}
|
||||
@@ -423,7 +423,7 @@ public class UserSwitcherController implements Dumpable {
|
||||
}
|
||||
}
|
||||
|
||||
private void showExitGuestDialog(int id) {
|
||||
protected void showExitGuestDialog(int id) {
|
||||
int newId = UserHandle.USER_SYSTEM;
|
||||
if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) {
|
||||
UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
|
||||
|
||||
@@ -393,10 +393,11 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
|
||||
|
||||
private void positionClock() {
|
||||
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
|
||||
mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY,
|
||||
mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
|
||||
0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */,
|
||||
mQsExpansion, mCutoutTopInset);
|
||||
mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight,
|
||||
0 /* keyguardUserSwitcherHeight */, mPreferredClockY, mHasCustomClock,
|
||||
mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
|
||||
0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */, mQsExpansion,
|
||||
mCutoutTopInset);
|
||||
mClockPositionAlgorithm.run(mClockPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.biometrics.BiometricSourceType;
|
||||
import android.os.PowerManager;
|
||||
import android.os.UserManager;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.util.DisplayMetrics;
|
||||
@@ -58,6 +59,7 @@ import com.android.keyguard.KeyguardStatusView;
|
||||
import com.android.keyguard.KeyguardStatusViewController;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
|
||||
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.biometrics.AuthController;
|
||||
@@ -68,7 +70,6 @@ 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;
|
||||
@@ -193,6 +194,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
|
||||
@Mock
|
||||
private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponent;
|
||||
@Mock
|
||||
private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
|
||||
@Mock
|
||||
private KeyguardClockSwitchController mKeyguardClockSwitchController;
|
||||
@@ -216,6 +219,9 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
private NotificationsQuickSettingsContainer mNotificationContainerParent;
|
||||
@Mock
|
||||
private AmbientState mAmbientState;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
private NotificationPanelViewController mNotificationPanelViewController;
|
||||
private View.AccessibilityDelegate mAccessibiltyDelegate;
|
||||
|
||||
@@ -299,11 +305,12 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
mBiometricUnlockController, mStatusBarKeyguardViewManager,
|
||||
mNotificationStackScrollLayoutController,
|
||||
mKeyguardStatusViewComponentFactory,
|
||||
mKeyguardUserSwitcherComponent,
|
||||
mGroupManager,
|
||||
mNotificationAreaController,
|
||||
mAuthController,
|
||||
new QSDetailDisplayer(),
|
||||
mScrimController,
|
||||
mUserManager,
|
||||
mMediaDataManager,
|
||||
mAmbientState,
|
||||
mFeatureFlags,
|
||||
|
||||
@@ -60,9 +60,9 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var layoutInflater: LayoutInflater
|
||||
@Mock
|
||||
private lateinit var keyguardUserSwitcher: KeyguardUserSwitcher
|
||||
private lateinit var keyguardUserSwitcherController: KeyguardUserSwitcherController
|
||||
|
||||
private lateinit var adapter: KeyguardUserSwitcher.KeyguardUserAdapter
|
||||
private lateinit var adapter: KeyguardUserSwitcherController.KeyguardUserAdapter
|
||||
private lateinit var picture: Bitmap
|
||||
|
||||
@Before
|
||||
@@ -72,8 +72,11 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
|
||||
mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, layoutInflater)
|
||||
`when`(layoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
|
||||
.thenReturn(inflatedUserDetailItemView)
|
||||
adapter = KeyguardUserSwitcher.KeyguardUserAdapter(mContext, userSwitcherController,
|
||||
keyguardUserSwitcher)
|
||||
adapter = KeyguardUserSwitcherController.KeyguardUserAdapter(
|
||||
mContext,
|
||||
mContext.resources,
|
||||
LayoutInflater.from(mContext),
|
||||
userSwitcherController, keyguardUserSwitcherController)
|
||||
picture = UserIcons.convertToBitmap(mContext.getDrawable(R.drawable.ic_avatar_user))
|
||||
}
|
||||
|
||||
@@ -118,11 +121,11 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldRemoveOnClickListener_currentUser_notGuestUser_oldViewIsSameType() {
|
||||
fun shouldSetOnOnClickListener_currentUser_notGuestUser_oldViewIsSameType() {
|
||||
val v: UserDetailItemView? = createViewFromSameType(
|
||||
isCurrentUser = true, isGuestUser = false)
|
||||
assertNotNull(v)
|
||||
verify(v)!!.setOnClickListener(null)
|
||||
verify(v)!!.setOnClickListener(adapter)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,11 +153,11 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldRemoveOnClickListener_currentUser_notGuestUser_oldViewIsDifferentType() {
|
||||
fun shouldSetOnOnClickListener_currentUser_notGuestUser_oldViewIsDifferentType() {
|
||||
val v: UserDetailItemView? = createViewFromDifferentType(
|
||||
isCurrentUser = true, isGuestUser = false)
|
||||
assertNotNull(v)
|
||||
verify(v)!!.setOnClickListener(null)
|
||||
verify(v)!!.setOnClickListener(adapter)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user