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

Commit 1e5c6d9c authored by Aaron Liu's avatar Aaron Liu
Browse files

[MultiUser] fix async bouncer user

The userswitcher in the bouncer does not update when receiver in the
controller receives the user switcher intent. This change will add a
callback to the aforementioned controller and we can reload the user
switcher upon doing so. With some testing on the device, there does not
seem to be any flickering, but bug is resolved.

Previous CL that was supposed to fix this b/17716871

Bug: 228901381
Test: Manual on device
Change-Id: I7b9fada327db63d744c340f75398c719b20ef392
parent f08f61e9
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -315,6 +315,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
        Log.i(TAG, "Switching mode from " + modeToString(mCurrentMode) + " to "
                + modeToString(mode));
        mCurrentMode = mode;
        mViewMode.onDestroy();

        switch (mode) {
            case MODE_ONE_HANDED:
@@ -710,7 +711,6 @@ public class KeyguardSecurityContainer extends FrameLayout {
     * Enscapsulates the differences between bouncer modes for the container.
     */
    interface ViewMode {

        default void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
                @NonNull KeyguardSecurityViewFlipper viewFlipper,
                @NonNull FalsingManager falsingManager,
@@ -738,6 +738,9 @@ public class KeyguardSecurityContainer extends FrameLayout {
        default int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
            return parentWidthMeasureSpec;
        }

        /** Called when we are setting a new ViewMode */
        default void onDestroy() {};
    }

    /**
@@ -781,6 +784,8 @@ public class KeyguardSecurityContainer extends FrameLayout {
        private UserSwitcherController mUserSwitcherController;
        private KeyguardUserSwitcherPopupMenu mPopup;
        private Resources mResources;
        private UserSwitcherController.UserSwitchCallback mUserSwitchCallback =
                this::setupUserSwitcher;

        @Override
        public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
@@ -805,6 +810,7 @@ public class KeyguardSecurityContainer extends FrameLayout {

            mUserSwitcher = mView.findViewById(R.id.user_switcher_header);
            setupUserSwitcher();
            mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
        }

        @Override
@@ -813,7 +819,11 @@ public class KeyguardSecurityContainer extends FrameLayout {
                mPopup.dismiss();
                mPopup = null;
            }
            setupUserSwitcher();
        }

        @Override
        public void onDestroy() {
            mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback);
        }

        private Drawable findUserIcon(int userId) {
+43 −1
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -161,6 +162,8 @@ public class UserSwitcherController implements Dumpable {
    private View mView;
    private String mCreateSupervisedUserPackage;
    private GlobalSettings mGlobalSettings;
    private List<UserSwitchCallback> mUserSwitchCallbacks =
            Collections.synchronizedList(new ArrayList<>());

    @Inject
    public UserSwitcherController(Context context,
@@ -225,7 +228,8 @@ public class UserSwitcherController implements Dumpable {
        filter.addAction(Intent.ACTION_USER_STOPPED);
        filter.addAction(Intent.ACTION_USER_UNLOCKED);
        mBroadcastDispatcher.registerReceiver(
                mReceiver, filter, null /* handler */, UserHandle.SYSTEM);
                mReceiver, filter, null /* executor */,
                UserHandle.SYSTEM, Context.RECEIVER_EXPORTED, null /* permission */);

        mSimpleUserSwitcher = shouldUseSimpleUserSwitcher();

@@ -652,6 +656,7 @@ public class UserSwitcherController implements Dumpable {
                        i--;
                    }
                }
                notifyUserSwitchCallbacks();
                notifyAdapters();

                // Disconnect from the old secondary user's service
@@ -1053,6 +1058,33 @@ public class UserSwitcherController implements Dumpable {
        mActivityStarter.startActivity(intent, true);
    }

    /**
     *  Add a subscriber to when user switches.
     */
    public void addUserSwitchCallback(UserSwitchCallback callback) {
        mUserSwitchCallbacks.add(callback);
    }

    /**
     *  Remove a subscriber to when user switches.
     */
    public void removeUserSwitchCallback(UserSwitchCallback callback) {
        mUserSwitchCallbacks.remove(callback);
    }

    /**
     *  Notify user switch callbacks that user has switched.
     */
    private void notifyUserSwitchCallbacks() {
        List<UserSwitchCallback> temp;
        synchronized (mUserSwitchCallbacks) {
            temp = new ArrayList<>(mUserSwitchCallbacks);
        }
        for (UserSwitchCallback callback : temp) {
            callback.onUserSwitched();
        }
    }

    public static final class UserRecord {
        public final UserInfo info;
        public final Bitmap picture;
@@ -1233,4 +1265,14 @@ public class UserSwitcherController implements Dumpable {
            }
        }
    }

    /**
     * Callback to for when this controller receives the intent to switch users.
     */
    public interface UserSwitchCallback {
        /**
         * Called when user has switched.
         */
        void onUserSwitched();
    }
}
+21 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.policy

import android.app.IActivityManager
import android.app.admin.DevicePolicyManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
@@ -52,6 +53,10 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.NotificationShadeWindowView
import com.android.systemui.telephony.TelephonyListenerManager
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.time.FakeSystemClock
@@ -63,10 +68,8 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.any
import org.mockito.Mockito.doNothing
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.eq
@@ -529,4 +532,20 @@ class UserSwitcherControllerTest : SysuiTestCase() {
        setupController()
        assertFalse(userSwitcherController.canCreateSupervisedUser())
    }

    @Test
    fun addUserSwitchCallback() {
        val broadcastReceiverCaptor = argumentCaptor<BroadcastReceiver>()
        verify(broadcastDispatcher).registerReceiver(
                capture(broadcastReceiverCaptor),
                any(),
                nullable(), nullable(), anyInt(), nullable())

        val cb = mock(UserSwitcherController.UserSwitchCallback::class.java)
        userSwitcherController.addUserSwitchCallback(cb)

        val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
        broadcastReceiverCaptor.value.onReceive(context, intent)
        verify(cb).onUserSwitched()
    }
}