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:
Peter Kalauskas
2021-02-11 16:32:54 +00:00
committed by Android (Google) Code Review
36 changed files with 1597 additions and 756 deletions

View File

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

View File

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

View 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>

View File

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

View File

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

View File

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

View File

@@ -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" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 {
/**

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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,

View File

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