Loading packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt +14 −2 Original line number Diff line number Diff line Loading @@ -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) {} Loading packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt +48 −16 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -33,6 +36,7 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.util.Assert import java.io.PrintWriter import java.lang.ref.WeakReference import java.util.concurrent.CountDownLatch import java.util.concurrent.Executor import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty Loading @@ -55,6 +59,7 @@ import kotlin.reflect.KProperty open 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() { Loading Loading @@ -106,7 +111,6 @@ open 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) Loading @@ -117,14 +121,13 @@ open 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, Loading Loading @@ -156,22 +159,43 @@ open 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 protected open fun handleSwitchUser(newUser: Int) { protected open 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 protected open 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) } } Loading Loading @@ -200,17 +224,25 @@ open 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>) { Loading packages/SystemUI/src/com/android/systemui/settings/dagger/MultiUserUtilsModule.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt +1 −1 Original line number Diff line number Diff line Loading @@ -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() } Loading packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt +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 Loading Loading @@ -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 Loading @@ -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 Loading
packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt +14 −2 Original line number Diff line number Diff line Loading @@ -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) {} Loading
packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt +48 −16 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -33,6 +36,7 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.util.Assert import java.io.PrintWriter import java.lang.ref.WeakReference import java.util.concurrent.CountDownLatch import java.util.concurrent.Executor import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty Loading @@ -55,6 +59,7 @@ import kotlin.reflect.KProperty open 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() { Loading Loading @@ -106,7 +111,6 @@ open 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) Loading @@ -117,14 +121,13 @@ open 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, Loading Loading @@ -156,22 +159,43 @@ open 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 protected open fun handleSwitchUser(newUser: Int) { protected open 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 protected open 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) } } Loading Loading @@ -200,17 +224,25 @@ open 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>) { Loading
packages/SystemUI/src/com/android/systemui/settings/dagger/MultiUserUtilsModule.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading
packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt +1 −1 Original line number Diff line number Diff line Loading @@ -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() } Loading
packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt +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 Loading Loading @@ -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 Loading @@ -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