Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74ddf829 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Android (Google) Code Review
Browse files

Merge "[CS] 1/N: Have LockscreenWallpaper listen for user changes directly." into udc-qpr-dev

parents 54906d06 d2609d03
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import com.android.systemui.settings.dagger.MultiUserUtilsModule
import com.android.systemui.shortcut.ShortcutKeyDispatcher
import com.android.systemui.statusbar.notification.InstantAppNotifier
import com.android.systemui.statusbar.phone.KeyguardLiftController
import com.android.systemui.statusbar.phone.LockscreenWallpaper
import com.android.systemui.stylus.StylusUsiPowerStartable
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import com.android.systemui.theme.ThemeOverlayController
@@ -301,4 +302,9 @@ abstract class SystemUICoreStartableModule {
    @IntoMap
    @ClassKey(KeyguardViewConfigurator::class)
    abstract fun bindKeyguardViewConfigurator(impl: KeyguardViewConfigurator): CoreStartable

    @Binds
    @IntoMap
    @ClassKey(LockscreenWallpaper::class)
    abstract fun bindLockscreenWallpaper(impl: LockscreenWallpaper): CoreStartable
}
+0 −3
Original line number Diff line number Diff line
@@ -2177,9 +2177,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
     */
    @Override
    public void setLockscreenUser(int newUserId) {
        if (mLockscreenWallpaper != null && !mWallpaperManager.isLockscreenLiveWallpaperEnabled()) {
            mLockscreenWallpaper.setCurrentUser(newUserId);
        }
        if (mWallpaperSupported) {
            mWallpaperChangedReceiver.onReceive(mContext, null);
        }
+27 −2
Original line number Diff line number Diff line
@@ -40,12 +40,17 @@ import androidx.annotation.NonNull;

import com.android.internal.util.IndentingPrintWriter;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.CoreStartable;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.user.data.model.SelectedUserModel;
import com.android.systemui.user.data.model.SelectionStatus;
import com.android.systemui.user.data.repository.UserRepository;
import com.android.systemui.util.kotlin.JavaAdapter;

import libcore.io.IoUtils;

@@ -59,7 +64,7 @@ import javax.inject.Inject;
 */
@SysUISingleton
public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable,
        Dumpable {
        Dumpable, CoreStartable {

    private static final String TAG = "LockscreenWallpaper";

@@ -72,6 +77,8 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
    private final WallpaperManager mWallpaperManager;
    private final KeyguardUpdateMonitor mUpdateMonitor;
    private final Handler mH;
    private final JavaAdapter mJavaAdapter;
    private final UserRepository mUserRepository;

    private boolean mCached;
    private Bitmap mCache;
@@ -88,6 +95,8 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
            DumpManager dumpManager,
            NotificationMediaManager mediaManager,
            @Main Handler mainHandler,
            JavaAdapter javaAdapter,
            UserRepository userRepository,
            UserTracker userTracker) {
        dumpManager.registerDumpable(getClass().getSimpleName(), this);
        mWallpaperManager = wallpaperManager;
@@ -95,6 +104,8 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
        mUpdateMonitor = keyguardUpdateMonitor;
        mMediaManager = mediaManager;
        mH = mainHandler;
        mJavaAdapter = javaAdapter;
        mUserRepository = userRepository;

        if (iWallpaperManager != null && !mWallpaperManager.isLockscreenLiveWallpaperEnabled()) {
            // Service is disabled on some devices like Automotive
@@ -106,6 +117,14 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
        }
    }

    @Override
    public void start() {
        if (!isLockscreenLiveWallpaperEnabled()) {
            mJavaAdapter.alwaysCollectFlow(
                    mUserRepository.getSelectedUser(), this::setSelectedUser);
        }
    }

    public Bitmap getBitmap() {
        assertLockscreenLiveWallpaperNotEnabled();

@@ -169,9 +188,15 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
        }
    }

    public void setCurrentUser(int user) {
    private void setSelectedUser(SelectedUserModel selectedUserModel) {
        assertLockscreenLiveWallpaperNotEnabled();

        if (selectedUserModel.getSelectionStatus().equals(SelectionStatus.SELECTION_IN_PROGRESS)) {
            // Wait until the selection has finished before updating.
            return;
        }

        int user = selectedUserModel.getUserInfo().id;
        if (user != mCurrentUserId) {
            if (mSelectedUser == null || user != mSelectedUser.getIdentifier()) {
                mCached = false;
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.user.data.model

import android.content.pm.UserInfo

/** A model for the currently selected user. */
data class SelectedUserModel(
    /** Information about the user. */
    val userInfo: UserInfo,
    /** The current status of the selection. */
    val selectionStatus: SelectionStatus,
)

/** The current status of the selection. */
enum class SelectionStatus {
    /** This user has started being selected but the selection hasn't completed. */
    SELECTION_IN_PROGRESS,
    /** The selection of this user has completed. */
    SELECTION_COMPLETE,
}
+52 −37
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
import com.android.systemui.settings.UserTracker
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
@@ -69,6 +71,9 @@ interface UserRepository {
    /** List of all users on the device. */
    val userInfos: Flow<List<UserInfo>>

    /** Information about the currently-selected user, including [UserInfo] and other details. */
    val selectedUser: StateFlow<SelectedUserModel>

    /** [UserInfo] of the currently-selected user. */
    val selectedUserInfo: Flow<UserInfo>

@@ -146,9 +151,6 @@ constructor(
    private val _userInfos = MutableStateFlow<List<UserInfo>?>(null)
    override val userInfos: Flow<List<UserInfo>> = _userInfos.filterNotNull()

    private val _selectedUserInfo = MutableStateFlow<UserInfo?>(null)
    override val selectedUserInfo: Flow<UserInfo> = _selectedUserInfo.filterNotNull()

    override var mainUserId: Int = UserHandle.USER_NULL
        private set
    override var lastSelectedNonGuestUserId: Int = UserHandle.USER_NULL
@@ -174,12 +176,57 @@ constructor(
    override var isRefreshUsersPaused: Boolean = false

    init {
        observeSelectedUser()
        if (featureFlags.isEnabled(FACE_AUTH_REFACTOR)) {
            observeUserSwitching()
        }
    }

    override val selectedUser: StateFlow<SelectedUserModel> = run {
        // Some callbacks don't modify the selection status, so maintain the current value.
        var currentSelectionStatus = SelectionStatus.SELECTION_COMPLETE
        conflatedCallbackFlow {
                fun send(selectionStatus: SelectionStatus) {
                    currentSelectionStatus = selectionStatus
                    trySendWithFailureLogging(
                        SelectedUserModel(tracker.userInfo, selectionStatus),
                        TAG,
                    )
                }

                val callback =
                    object : UserTracker.Callback {
                        override fun onUserChanging(newUser: Int, userContext: Context) {
                            send(SelectionStatus.SELECTION_IN_PROGRESS)
                        }

                        override fun onUserChanged(newUser: Int, userContext: Context) {
                            send(SelectionStatus.SELECTION_COMPLETE)
                        }

                        override fun onProfilesChanged(profiles: List<UserInfo>) {
                            send(currentSelectionStatus)
                        }
                    }

                tracker.addCallback(callback, mainDispatcher.asExecutor())
                send(currentSelectionStatus)

                awaitClose { tracker.removeCallback(callback) }
            }
            .onEach {
                if (!it.userInfo.isGuest) {
                    lastSelectedNonGuestUserId = it.userInfo.id
                }
            }
            .stateIn(
                applicationScope,
                SharingStarted.Eagerly,
                initialValue = SelectedUserModel(tracker.userInfo, currentSelectionStatus)
            )
    }

    override val selectedUserInfo: Flow<UserInfo> = selectedUser.map { it.userInfo }

    override fun refreshUsers() {
        applicationScope.launch {
            val result = withContext(backgroundDispatcher) { manager.aliveUsers }
@@ -201,7 +248,7 @@ constructor(
    }

    override fun getSelectedUserInfo(): UserInfo {
        return checkNotNull(_selectedUserInfo.value)
        return selectedUser.value.userInfo
    }

    override fun isSimpleUserSwitcher(): Boolean {
@@ -234,38 +281,6 @@ constructor(
            .launchIn(applicationScope)
    }

    private fun observeSelectedUser() {
        conflatedCallbackFlow {
                fun send() {
                    trySendWithFailureLogging(tracker.userInfo, TAG)
                }

                val callback =
                    object : UserTracker.Callback {
                        override fun onUserChanging(newUser: Int, userContext: Context) {
                            send()
                        }

                        override fun onProfilesChanged(profiles: List<UserInfo>) {
                            send()
                        }
                    }

                tracker.addCallback(callback, mainDispatcher.asExecutor())
                send()

                awaitClose { tracker.removeCallback(callback) }
            }
            .onEach {
                if (!it.isGuest) {
                    lastSelectedNonGuestUserId = it.id
                }

                _selectedUserInfo.value = it
            }
            .launchIn(applicationScope)
    }

    private suspend fun getSettings(): UserSwitcherSettingsModel {
        return withContext(backgroundDispatcher) {
            val isSimpleUserSwitcher =
Loading