Merge "Remove user icon avatar from memory when unlocked" into tm-dev am: 5c011d09c9

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17605852

Change-Id: Ie49c53e74036f298a5e949b1fec068c9ee2f7172
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Peter Kalauskas
2022-04-11 17:09:38 +00:00
committed by Automerger Merge Worker
4 changed files with 112 additions and 36 deletions

View File

@@ -176,6 +176,10 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback {
return this; return this;
} }
public boolean isEmpty() {
return getUserIcon() == null && getUserDrawable() == null;
}
public UserIconDrawable setBadge(Drawable badge) { public UserIconDrawable setBadge(Drawable badge) {
mBadge = badge; mBadge = badge;
if (mBadge != null) { if (mBadge != null) {

View File

@@ -137,4 +137,8 @@ public class UserAvatarView extends View {
mDrawable.setIconDrawable(d); mDrawable.setIconDrawable(d);
mDrawable.setBadgeIfManagedUser(getContext(), userId); mDrawable.setBadgeIfManagedUser(getContext(), userId);
} }
public boolean isEmpty() {
return mDrawable.isEmpty();
}
} }

View File

@@ -29,6 +29,7 @@ import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardVisibilityHelper; import com.android.keyguard.KeyguardVisibilityHelper;
@@ -36,7 +37,6 @@ import com.android.keyguard.dagger.KeyguardUserSwitcherScope;
import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.settingslib.drawable.CircleFramedDrawable;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.user.UserSwitchDialogController; import com.android.systemui.qs.user.UserSwitchDialogController;
@@ -68,7 +68,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
private final Context mContext; private final Context mContext;
private Resources mResources; private Resources mResources;
private final UserSwitcherController mUserSwitcherController; private final UserSwitcherController mUserSwitcherController;
private final ScreenLifecycle mScreenLifecycle;
private UserSwitcherController.BaseUserAdapter mAdapter; private UserSwitcherController.BaseUserAdapter mAdapter;
private final KeyguardStateController mKeyguardStateController; private final KeyguardStateController mKeyguardStateController;
private final FalsingManager mFalsingManager; private final FalsingManager mFalsingManager;
@@ -77,8 +76,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper; private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
private final UserSwitchDialogController mUserSwitchDialogController; private final UserSwitchDialogController mUserSwitchDialogController;
private final UiEventLogger mUiEventLogger; private final UiEventLogger mUiEventLogger;
private UserAvatarView mUserAvatarView; @VisibleForTesting
UserAvatarView mUserAvatarView;
UserSwitcherController.UserRecord mCurrentUser; UserSwitcherController.UserRecord mCurrentUser;
private boolean mIsKeyguardShowing;
// State info for the user switch and keyguard // State info for the user switch and keyguard
private int mBarState; private int mBarState;
@@ -87,8 +88,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
new StatusBarStateController.StateListener() { new StatusBarStateController.StateListener() {
@Override @Override
public void onStateChanged(int newState) { public void onStateChanged(int newState) {
if (DEBUG) Log.d(TAG, String.format("onStateChanged: newState=%d", newState));
boolean goingToFullShade = mStatusBarStateController.goingToFullShade(); boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway(); boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
int oldState = mBarState; int oldState = mBarState;
@@ -102,12 +101,34 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
} }
}; };
private ConfigurationController.ConfigurationListener private ConfigurationController.ConfigurationListener mConfigurationListener =
mConfigurationListener = new ConfigurationController.ConfigurationListener() { new ConfigurationController.ConfigurationListener() {
@Override @Override
public void onUiModeChanged() { public void onUiModeChanged() {
updateView(true); // Force update when dark theme toggled. Otherwise, icon will not update
// until it is clicked
if (mIsKeyguardShowing) {
updateView();
}
}
};
private final KeyguardStateController.Callback mKeyguardStateCallback =
new KeyguardStateController.Callback() {
@Override
public void onUnlockedChanged() {
updateKeyguardShowing(false /* forceViewUpdate */);
}
@Override
public void onKeyguardShowingChanged() {
updateKeyguardShowing(false /* forceViewUpdate */);
}
@Override
public void onKeyguardFadingAwayChanged() {
updateKeyguardShowing(false /* forceViewUpdate */);
} }
}; };
@@ -116,7 +137,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
FrameLayout view, FrameLayout view,
Context context, Context context,
@Main Resources resources, @Main Resources resources,
ScreenLifecycle screenLifecycle,
UserSwitcherController userSwitcherController, UserSwitcherController userSwitcherController,
KeyguardStateController keyguardStateController, KeyguardStateController keyguardStateController,
FalsingManager falsingManager, FalsingManager falsingManager,
@@ -130,7 +150,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController"); if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController");
mContext = context; mContext = context;
mResources = resources; mResources = resources;
mScreenLifecycle = screenLifecycle;
mUserSwitcherController = userSwitcherController; mUserSwitcherController = userSwitcherController;
mKeyguardStateController = keyguardStateController; mKeyguardStateController = keyguardStateController;
mFalsingManager = falsingManager; mFalsingManager = falsingManager;
@@ -188,7 +207,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
mDataSetObserver.onChanged(); mDataSetObserver.onChanged();
mStatusBarStateController.addCallback(mStatusBarStateListener); mStatusBarStateController.addCallback(mStatusBarStateListener);
mConfigurationController.addCallback(mConfigurationListener); mConfigurationController.addCallback(mConfigurationListener);
updateView(true /* forceUpdate */); mKeyguardStateController.addCallback(mKeyguardStateCallback);
// Force update when view attached in case configuration changed while the view was detached
updateCurrentUser();
updateKeyguardShowing(true /* forceViewUpdate */);
} }
@Override @Override
@@ -198,15 +220,48 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
mAdapter.unregisterDataSetObserver(mDataSetObserver); mAdapter.unregisterDataSetObserver(mDataSetObserver);
mStatusBarStateController.removeCallback(mStatusBarStateListener); mStatusBarStateController.removeCallback(mStatusBarStateListener);
mConfigurationController.removeCallback(mConfigurationListener); mConfigurationController.removeCallback(mConfigurationListener);
mKeyguardStateController.removeCallback(mKeyguardStateCallback);
} }
public final DataSetObserver mDataSetObserver = new DataSetObserver() { public final DataSetObserver mDataSetObserver = new DataSetObserver() {
@Override @Override
public void onChanged() { public void onChanged() {
updateView(false /* forceUpdate */); boolean userChanged = updateCurrentUser();
if (userChanged || (mIsKeyguardShowing && mUserAvatarView.isEmpty())) {
updateView();
}
} }
}; };
private void clearAvatar() {
if (DEBUG) Log.d(TAG, "clearAvatar");
mUserAvatarView.setAvatar(null);
}
/**
* @param forceViewUpdate whether view should be updated regardless of whether
* keyguard-showing state changed
*/
@VisibleForTesting
void updateKeyguardShowing(boolean forceViewUpdate) {
boolean wasKeyguardShowing = mIsKeyguardShowing;
mIsKeyguardShowing = mKeyguardStateController.isShowing()
|| mKeyguardStateController.isKeyguardGoingAway();
if (wasKeyguardShowing == mIsKeyguardShowing && !forceViewUpdate) {
return;
}
if (DEBUG) {
Log.d(TAG, "updateKeyguardShowing:"
+ " mIsKeyguardShowing=" + mIsKeyguardShowing
+ " forceViewUpdate=" + forceViewUpdate);
}
if (mIsKeyguardShowing) {
updateView();
} else {
clearAvatar();
}
}
/** /**
* @return true if the current user has changed * @return true if the current user has changed
*/ */
@@ -223,31 +278,22 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
return mCurrentUser == null && previousUser != null; return mCurrentUser == null && previousUser != null;
} }
/** private String getContentDescription() {
* @param forceUpdate whether to update view even if current user did not change if (mCurrentUser != null && mCurrentUser.info != null
*/ && !TextUtils.isEmpty(mCurrentUser.info.name)) {
private void updateView(boolean forceUpdate) {
if (!updateCurrentUser() && !forceUpdate) {
return;
}
String contentDescription = null;
if (mCurrentUser != null && mCurrentUser.info != null && !TextUtils.isEmpty(
mCurrentUser.info.name)) {
// If we know the current user's name, have TalkBack to announce "Signed in as [user // If we know the current user's name, have TalkBack to announce "Signed in as [user
// name]" when the icon is selected // name]" when the icon is selected
contentDescription = mContext.getString(R.string.accessibility_quick_settings_user, return mContext.getString(
mCurrentUser.info.name); R.string.accessibility_quick_settings_user, mCurrentUser.info.name);
} else { } else {
// As a fallback, have TalkBack announce "Switch user" // As a fallback, have TalkBack announce "Switch user"
contentDescription = mContext.getString( return mContext.getString(R.string.accessibility_multi_user_switch_switcher);
R.string.accessibility_multi_user_switch_switcher);
}
if (!TextUtils.equals(mUserAvatarView.getContentDescription(), contentDescription)) {
mUserAvatarView.setContentDescription(contentDescription);
} }
}
private void updateView() {
if (DEBUG) Log.d(TAG, "updateView");
mUserAvatarView.setContentDescription(getContentDescription());
int userId = mCurrentUser != null ? mCurrentUser.resolveId() : UserHandle.USER_NULL; int userId = mCurrentUser != null ? mCurrentUser.resolveId() : UserHandle.USER_NULL;
mUserAvatarView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId); mUserAvatarView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId);
} }

View File

@@ -26,13 +26,13 @@ import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger import com.android.internal.logging.UiEventLogger
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.ScreenLifecycle
import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.user.UserSwitchDialogController import com.android.systemui.qs.user.UserSwitchDialogController
import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.LockscreenGestureLogger import com.android.systemui.statusbar.phone.LockscreenGestureLogger
import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.statusbar.phone.ScreenOffAnimationController
import com.google.common.truth.Truth.assertThat
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@@ -47,9 +47,6 @@ import org.mockito.MockitoAnnotations
@TestableLooper.RunWithLooper @TestableLooper.RunWithLooper
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
@Mock
private lateinit var screenLifecycle: ScreenLifecycle
@Mock @Mock
private lateinit var userSwitcherController: UserSwitcherController private lateinit var userSwitcherController: UserSwitcherController
@@ -93,7 +90,6 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
view, view,
context, context,
context.resources, context.resources,
screenLifecycle,
userSwitcherController, userSwitcherController,
keyguardStateController, keyguardStateController,
falsingManager, falsingManager,
@@ -108,6 +104,8 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
testableLooper.processAllMessages() testableLooper.processAllMessages()
`when`(userSwitcherController.keyguardStateController).thenReturn(keyguardStateController) `when`(userSwitcherController.keyguardStateController).thenReturn(keyguardStateController)
`when`(userSwitcherController.keyguardStateController.isShowing).thenReturn(true) `when`(userSwitcherController.keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
keyguardQsUserSwitchController.init() keyguardQsUserSwitchController.init()
} }
@@ -122,4 +120,28 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
verify(uiEventLogger, times(1)) verify(uiEventLogger, times(1))
.log(LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP) .log(LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP)
} }
@Test
fun testAvatarExistsWhenKeyguardGoingAway() {
`when`(keyguardStateController.isShowing).thenReturn(false)
`when`(keyguardStateController.isKeyguardGoingAway).thenReturn(true)
keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */)
assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse()
}
@Test
fun testAvatarExistsWhenKeyguardShown() {
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */)
assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse()
}
@Test
fun testAvatarGoneWhenKeyguardGone() {
`when`(keyguardStateController.isShowing).thenReturn(false)
`when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */)
assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isTrue()
}
} }