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

Commit 8fd6cb70 authored by Yasin Kilicdere's avatar Yasin Kilicdere Committed by Android (Google) Code Review
Browse files

Merge "Make UserTrackerImpl use UserSwitchObserver instead of broadcast." into tm-qpr-dev

parents 8d30afff 10b33a76
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -62,12 +62,24 @@ interface UserTracker : UserContentResolverProvider, UserContextProvider {
    fun removeCallback(callback: Callback)

    /**
     * Ćallback for notifying of changes.
     * Callback for notifying of changes.
     */
    interface Callback {

        /**
         * Notifies that the current user is being changed.
         * Override this method to run things while the screen is frozen for the user switch.
         * Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
         * screen further. Please be aware that code executed in this callback will lengthen the
         * user switch duration.
         */
        @JvmDefault
        fun onUserChanging(newUser: Int, userContext: Context) {}

        /**
         * Notifies that the current user has changed.
         * Override this method to run things after the screen is unfrozen for the user switch.
         * Please see {@link #onUserChanging} if you need to hide jank.
         */
        @JvmDefault
        fun onUserChanged(newUser: Int, userContext: Context) {}
+48 −16
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.settings

import android.app.IActivityManager
import android.app.UserSwitchObserver
import android.content.BroadcastReceiver
import android.content.ContentResolver
import android.content.Context
@@ -23,6 +25,7 @@ import android.content.Intent
import android.content.IntentFilter
import android.content.pm.UserInfo
import android.os.Handler
import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.util.Log
@@ -34,6 +37,7 @@ import com.android.systemui.util.Assert
import java.io.PrintWriter
import java.lang.IllegalStateException
import java.lang.ref.WeakReference
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@@ -56,6 +60,7 @@ import kotlin.reflect.KProperty
class UserTrackerImpl internal constructor(
    private val context: Context,
    private val userManager: UserManager,
    private val iActivityManager: IActivityManager,
    private val dumpManager: DumpManager,
    private val backgroundHandler: Handler
) : UserTracker, Dumpable, BroadcastReceiver() {
@@ -107,7 +112,6 @@ class UserTrackerImpl internal constructor(
        setUserIdInternal(startingUser)

        val filter = IntentFilter().apply {
            addAction(Intent.ACTION_USER_SWITCHED)
            addAction(Intent.ACTION_USER_INFO_CHANGED)
            // These get called when a managed profile goes in or out of quiet mode.
            addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
@@ -118,14 +122,13 @@ class UserTrackerImpl internal constructor(
        }
        context.registerReceiverForAllUsers(this, filter, null /* permission */, backgroundHandler)

        registerUserSwitchObserver()

        dumpManager.registerDumpable(TAG, this)
    }

    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            Intent.ACTION_USER_SWITCHED -> {
                handleSwitchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL))
            }
            Intent.ACTION_USER_INFO_CHANGED,
            Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
            Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
@@ -157,22 +160,43 @@ class UserTrackerImpl internal constructor(
        return ctx to profiles
    }

    private fun registerUserSwitchObserver() {
        iActivityManager.registerUserSwitchObserver(object : UserSwitchObserver() {
            override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) {
                backgroundHandler.run {
                    handleUserSwitching(newUserId)
                    reply?.sendResult(null)
                }
            }

            override fun onUserSwitchComplete(newUserId: Int) {
                backgroundHandler.run {
                    handleUserSwitchComplete(newUserId)
                }
            }
        }, TAG)
    }

    @WorkerThread
    private fun handleSwitchUser(newUser: Int) {
    private fun handleUserSwitching(newUserId: Int) {
        Assert.isNotMainThread()
        if (newUser == UserHandle.USER_NULL) {
            Log.w(TAG, "handleSwitchUser - Couldn't get new id from intent")
            return
        }
        Log.i(TAG, "Switching to user $newUserId")

        if (newUser == userId) return
        Log.i(TAG, "Switching to user $newUser")
        setUserIdInternal(newUserId)
        notifySubscribers {
            onUserChanging(newUserId, userContext)
        }.await()
    }

        val (ctx, profiles) = setUserIdInternal(newUser)
    @WorkerThread
    private fun handleUserSwitchComplete(newUserId: Int) {
        Assert.isNotMainThread()
        Log.i(TAG, "Switched to user $newUserId")

        setUserIdInternal(newUserId)
        notifySubscribers {
            onUserChanged(newUser, ctx)
            onProfilesChanged(profiles)
            onUserChanged(newUserId, userContext)
            onProfilesChanged(userProfiles)
        }
    }

@@ -201,17 +225,25 @@ class UserTrackerImpl internal constructor(
        }
    }

    private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) {
    private inline fun notifySubscribers(
            crossinline action: UserTracker.Callback.() -> Unit
    ): CountDownLatch {
        val list = synchronized(callbacks) {
            callbacks.toList()
        }
        val latch = CountDownLatch(list.size)

        list.forEach {
            if (it.callback.get() != null) {
                it.executor.execute {
                    it.callback.get()?.action()
                    latch.countDown()
                }
            } else {
                latch.countDown()
            }
        }
        return latch
    }

    override fun dump(pw: PrintWriter, args: Array<out String>) {
+4 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.settings.dagger;

import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Context;
import android.os.Handler;
import android.os.UserManager;
@@ -57,11 +58,13 @@ public abstract class MultiUserUtilsModule {
    static UserTracker provideUserTracker(
            Context context,
            UserManager userManager,
            IActivityManager iActivityManager,
            DumpManager dumpManager,
            @Background Handler handler
    ) {
        int startingUser = ActivityManager.getCurrentUser();
        UserTrackerImpl tracker = new UserTrackerImpl(context, userManager, dumpManager, handler);
        UserTrackerImpl tracker = new UserTrackerImpl(context, userManager, iActivityManager,
                dumpManager, handler);
        tracker.initialize(startingUser);
        return tracker;
    }
+1 −1
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ constructor(

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

+3 −1
Original line number Diff line number Diff line
package com.android.systemui.settings

import android.app.IActivityManager
import android.content.Context
import android.content.Intent
import android.content.pm.UserInfo
@@ -51,6 +52,7 @@ class UserTrackerImplReceiveTest : SysuiTestCase() {

    @Mock private lateinit var context: Context
    @Mock private lateinit var userManager: UserManager
    @Mock private lateinit var iActivityManager: IActivityManager
    @Mock(stubOnly = true) private lateinit var dumpManager: DumpManager
    @Mock(stubOnly = true) private lateinit var handler: Handler

@@ -67,7 +69,7 @@ class UserTrackerImplReceiveTest : SysuiTestCase() {
        `when`(context.user).thenReturn(UserHandle.SYSTEM)
        `when`(context.createContextAsUser(ArgumentMatchers.any(), anyInt())).thenReturn(context)

        tracker = UserTrackerImpl(context, userManager, dumpManager, handler)
        tracker = UserTrackerImpl(context, userManager, iActivityManager, dumpManager, handler)
    }

    @Test
Loading