Loading packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,16 @@ flag { bug: "302578396" } flag { name: "multiuser_wifi_picker_tracker_support" namespace: "systemui" description: "Adds WifiPickerTracker support for multiple users to support when HSUM is enabled." bug: "371586248" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "udfps_view_performance" namespace: "systemui" Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt +50 −35 Original line number Diff line number Diff line Loading @@ -16,18 +16,22 @@ package com.android.systemui.statusbar.connectivity import android.content.Context import android.os.UserHandle import android.os.UserManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import android.platform.test.annotations.EnableFlags import android.testing.TestableLooper.RunWithLooper import androidx.lifecycle.Lifecycle import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_MULTIUSER_WIFI_PICKER_TRACKER_SUPPORT import com.android.systemui.SysuiTestCase import com.android.systemui.settings.UserTracker import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.wifitrackerlib.WifiEntry import com.android.wifitrackerlib.WifiPickerTracker import com.google.common.truth.Truth.assertThat import java.util.concurrent.Executor import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -35,36 +39,28 @@ import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyList import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations import java.util.concurrent.Executor import org.mockito.kotlin.any import org.mockito.kotlin.mock @SmallTest @RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) class AccessPointControllerImplTest : SysuiTestCase() { @Mock private lateinit var userManager: UserManager @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var wifiPickerTrackerFactory: WifiPickerTrackerFactory @Mock private lateinit var wifiPickerTracker: WifiPickerTracker @Mock private lateinit var callback: AccessPointController.AccessPointCallback @Mock private lateinit var otherCallback: AccessPointController.AccessPointCallback @Mock private lateinit var wifiEntryConnected: WifiEntry @Mock private lateinit var wifiEntryOther: WifiEntry @Captor private lateinit var wifiEntryListCaptor: ArgumentCaptor<List<WifiEntry>> @Mock private lateinit var userManager: UserManager @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var wifiPickerTrackerFactory: WifiPickerTrackerFactory @Mock private lateinit var wifiPickerTracker: WifiPickerTracker @Mock private lateinit var callback: AccessPointController.AccessPointCallback @Mock private lateinit var otherCallback: AccessPointController.AccessPointCallback @Mock private lateinit var wifiEntryConnected: WifiEntry @Mock private lateinit var wifiEntryOther: WifiEntry @Captor private lateinit var wifiEntryListCaptor: ArgumentCaptor<List<WifiEntry>> private val instantExecutor = Executor { it.run() } private lateinit var controller: AccessPointControllerImpl Loading @@ -72,18 +68,20 @@ class AccessPointControllerImplTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) `when`(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(wifiPickerTracker) `when`(wifiPickerTrackerFactory.create(any(), any(), any(), any())) .thenReturn(wifiPickerTracker) `when`(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntryConnected) `when`(wifiPickerTracker.wifiEntries).thenReturn(ArrayList<WifiEntry>().apply { add(wifiEntryOther) }) `when`(wifiPickerTracker.wifiEntries) .thenReturn(ArrayList<WifiEntry>().apply { add(wifiEntryOther) }) controller = AccessPointControllerImpl( controller = AccessPointControllerImpl( mContext, userManager, userTracker, instantExecutor, wifiPickerTrackerFactory wifiPickerTrackerFactory, ) controller.init() Loading Loading @@ -183,12 +181,14 @@ class AccessPointControllerImplTest : SysuiTestCase() { @Test fun testReturnEmptyListWhenNoWifiPickerTracker() { `when`(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(null) val otherController = AccessPointControllerImpl( `when`(wifiPickerTrackerFactory.create(any(), any(), any(), any())).thenReturn(null) val otherController = AccessPointControllerImpl( mContext, userManager, userTracker, instantExecutor, wifiPickerTrackerFactory wifiPickerTrackerFactory, ) otherController.init() Loading Loading @@ -244,4 +244,19 @@ class AccessPointControllerImplTest : SysuiTestCase() { verify(wifiEntryOther).connect(any()) verify(callback, never()).onSettingsActivityTriggered(any()) } @Test @EnableFlags(FLAG_MULTIUSER_WIFI_PICKER_TRACKER_SUPPORT) fun switchUsers() { val primaryUserMockContext = mock<Context>() mContext.prepareCreateContextAsUser(UserHandle.of(PRIMARY_USER_ID), primaryUserMockContext) controller.onUserSwitched(PRIMARY_USER_ID) // Create is expected to be called once when the test starts and a second time when the user // is switched. verify(wifiPickerTrackerFactory, times(2)).create(any(), any(), any(), any()) } private companion object { private const val PRIMARY_USER_ID = 1 } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt +7 −6 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoMod import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.kotlinArgumentCaptor Loading Loading @@ -71,6 +72,7 @@ class WifiRepositorySwitcherTest : SysuiTestCase() { private val demoModelFlow = MutableStateFlow<FakeWifiEventModel?>(null) private val mainExecutor = FakeExecutor(FakeSystemClock()) private val userRepository = FakeUserRepository() private val testDispatcher = UnconfinedTestDispatcher() private val testScope = TestScope(testDispatcher) Loading @@ -82,10 +84,13 @@ class WifiRepositorySwitcherTest : SysuiTestCase() { // Never start in demo mode whenever(demoModeController.isInDemoMode).thenReturn(false) whenever(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(wifiPickerTracker) whenever(wifiPickerTrackerFactory.create(any(), any(), any(), any())) .thenReturn(wifiPickerTracker) realImpl = WifiRepositoryImpl( mContext, userRepository, testScope.backgroundScope, mainExecutor, testDispatcher, Loading @@ -97,11 +102,7 @@ class WifiRepositorySwitcherTest : SysuiTestCase() { whenever(demoModeWifiDataSource.wifiEvents).thenReturn(demoModelFlow) demoImpl = DemoWifiRepository( demoModeWifiDataSource, testScope.backgroundScope, ) demoImpl = DemoWifiRepository(demoModeWifiDataSource, testScope.backgroundScope) underTest = WifiRepositorySwitcher( Loading packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java +24 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.systemui.statusbar.connectivity; import static com.android.systemui.Flags.multiuserWifiPickerTrackerSupport; import android.content.Context; import android.content.Intent; import android.os.UserHandle; import android.os.UserManager; Loading Loading @@ -65,13 +68,16 @@ public class AccessPointControllerImpl implements AccessPointController, private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this); private int mCurrentUser; private Context mContext; public AccessPointControllerImpl( Context context, UserManager userManager, UserTracker userTracker, Executor mainExecutor, WifiPickerTrackerFactory wifiPickerTrackerFactory ) { mContext = context; mUserManager = userManager; mUserTracker = userTracker; mCurrentUser = userTracker.getUserId(); Loading @@ -87,7 +93,11 @@ public class AccessPointControllerImpl implements AccessPointController, */ public void init() { if (mWifiPickerTracker == null) { mWifiPickerTracker = mWifiPickerTrackerFactory.create(this.getLifecycle(), this, TAG); // We are creating the WifiPickerTracker during init to make sure we have one // available at all times however we expect this to be recreated very quickly // with a user-specific context in onUserSwitched. mWifiPickerTracker = mWifiPickerTrackerFactory.create(mContext, this.getLifecycle(), this, TAG); } } Loading Loading @@ -116,6 +126,19 @@ public class AccessPointControllerImpl implements AccessPointController, void onUserSwitched(int newUserId) { mCurrentUser = newUserId; // Return early if multiuser support is not enabled. if (!multiuserWifiPickerTrackerSupport()) { return; } if (mWifiPickerTracker != null) { mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.CREATED)); } Context context = mContext.createContextAsUser(UserHandle.of(newUserId), /* flags= */ 0); mWifiPickerTracker = mWifiPickerTrackerFactory.create(context, mLifecycle, this, TAG); if (!mCallbacks.isEmpty()) { mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.STARTED)); } } @Override Loading packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiPickerTrackerFactory.kt +12 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.net.wifi.WifiManager import android.os.Handler import android.os.SimpleClock import androidx.lifecycle.Lifecycle import com.android.systemui.Flags.multiuserWifiPickerTrackerSupport import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.util.concurrency.ThreadFactory Loading @@ -41,7 +42,7 @@ import javax.inject.Inject class WifiPickerTrackerFactory @Inject constructor( private val context: Context, private val applicationContext: Context, private val wifiManager: WifiManager?, private val connectivityManager: ConnectivityManager, private val systemClock: SystemClock, Loading @@ -64,16 +65,23 @@ constructor( * @return a new [WifiPickerTracker] or null if [WifiManager] is null. */ fun create( userContext: Context, lifecycle: Lifecycle, listener: WifiPickerTrackerCallback, name: String, ): WifiPickerTracker? { return if (wifiManager == null) { null } else } else { val contextToUse = if (multiuserWifiPickerTrackerSupport()) { userContext } else { applicationContext } WifiPickerTracker( lifecycle, context, contextToUse, wifiManager, connectivityManager, mainHandler, Loading @@ -87,6 +95,7 @@ constructor( listener, ) } } companion object { /** Max age of tracked WifiEntries. */ Loading Loading
packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,16 @@ flag { bug: "302578396" } flag { name: "multiuser_wifi_picker_tracker_support" namespace: "systemui" description: "Adds WifiPickerTracker support for multiple users to support when HSUM is enabled." bug: "371586248" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "udfps_view_performance" namespace: "systemui" Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt +50 −35 Original line number Diff line number Diff line Loading @@ -16,18 +16,22 @@ package com.android.systemui.statusbar.connectivity import android.content.Context import android.os.UserHandle import android.os.UserManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import android.platform.test.annotations.EnableFlags import android.testing.TestableLooper.RunWithLooper import androidx.lifecycle.Lifecycle import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_MULTIUSER_WIFI_PICKER_TRACKER_SUPPORT import com.android.systemui.SysuiTestCase import com.android.systemui.settings.UserTracker import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.wifitrackerlib.WifiEntry import com.android.wifitrackerlib.WifiPickerTracker import com.google.common.truth.Truth.assertThat import java.util.concurrent.Executor import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -35,36 +39,28 @@ import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyList import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations import java.util.concurrent.Executor import org.mockito.kotlin.any import org.mockito.kotlin.mock @SmallTest @RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) class AccessPointControllerImplTest : SysuiTestCase() { @Mock private lateinit var userManager: UserManager @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var wifiPickerTrackerFactory: WifiPickerTrackerFactory @Mock private lateinit var wifiPickerTracker: WifiPickerTracker @Mock private lateinit var callback: AccessPointController.AccessPointCallback @Mock private lateinit var otherCallback: AccessPointController.AccessPointCallback @Mock private lateinit var wifiEntryConnected: WifiEntry @Mock private lateinit var wifiEntryOther: WifiEntry @Captor private lateinit var wifiEntryListCaptor: ArgumentCaptor<List<WifiEntry>> @Mock private lateinit var userManager: UserManager @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var wifiPickerTrackerFactory: WifiPickerTrackerFactory @Mock private lateinit var wifiPickerTracker: WifiPickerTracker @Mock private lateinit var callback: AccessPointController.AccessPointCallback @Mock private lateinit var otherCallback: AccessPointController.AccessPointCallback @Mock private lateinit var wifiEntryConnected: WifiEntry @Mock private lateinit var wifiEntryOther: WifiEntry @Captor private lateinit var wifiEntryListCaptor: ArgumentCaptor<List<WifiEntry>> private val instantExecutor = Executor { it.run() } private lateinit var controller: AccessPointControllerImpl Loading @@ -72,18 +68,20 @@ class AccessPointControllerImplTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) `when`(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(wifiPickerTracker) `when`(wifiPickerTrackerFactory.create(any(), any(), any(), any())) .thenReturn(wifiPickerTracker) `when`(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntryConnected) `when`(wifiPickerTracker.wifiEntries).thenReturn(ArrayList<WifiEntry>().apply { add(wifiEntryOther) }) `when`(wifiPickerTracker.wifiEntries) .thenReturn(ArrayList<WifiEntry>().apply { add(wifiEntryOther) }) controller = AccessPointControllerImpl( controller = AccessPointControllerImpl( mContext, userManager, userTracker, instantExecutor, wifiPickerTrackerFactory wifiPickerTrackerFactory, ) controller.init() Loading Loading @@ -183,12 +181,14 @@ class AccessPointControllerImplTest : SysuiTestCase() { @Test fun testReturnEmptyListWhenNoWifiPickerTracker() { `when`(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(null) val otherController = AccessPointControllerImpl( `when`(wifiPickerTrackerFactory.create(any(), any(), any(), any())).thenReturn(null) val otherController = AccessPointControllerImpl( mContext, userManager, userTracker, instantExecutor, wifiPickerTrackerFactory wifiPickerTrackerFactory, ) otherController.init() Loading Loading @@ -244,4 +244,19 @@ class AccessPointControllerImplTest : SysuiTestCase() { verify(wifiEntryOther).connect(any()) verify(callback, never()).onSettingsActivityTriggered(any()) } @Test @EnableFlags(FLAG_MULTIUSER_WIFI_PICKER_TRACKER_SUPPORT) fun switchUsers() { val primaryUserMockContext = mock<Context>() mContext.prepareCreateContextAsUser(UserHandle.of(PRIMARY_USER_ID), primaryUserMockContext) controller.onUserSwitched(PRIMARY_USER_ID) // Create is expected to be called once when the test starts and a second time when the user // is switched. verify(wifiPickerTrackerFactory, times(2)).create(any(), any(), any(), any()) } private companion object { private const val PRIMARY_USER_ID = 1 } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt +7 −6 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoMod import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.kotlinArgumentCaptor Loading Loading @@ -71,6 +72,7 @@ class WifiRepositorySwitcherTest : SysuiTestCase() { private val demoModelFlow = MutableStateFlow<FakeWifiEventModel?>(null) private val mainExecutor = FakeExecutor(FakeSystemClock()) private val userRepository = FakeUserRepository() private val testDispatcher = UnconfinedTestDispatcher() private val testScope = TestScope(testDispatcher) Loading @@ -82,10 +84,13 @@ class WifiRepositorySwitcherTest : SysuiTestCase() { // Never start in demo mode whenever(demoModeController.isInDemoMode).thenReturn(false) whenever(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(wifiPickerTracker) whenever(wifiPickerTrackerFactory.create(any(), any(), any(), any())) .thenReturn(wifiPickerTracker) realImpl = WifiRepositoryImpl( mContext, userRepository, testScope.backgroundScope, mainExecutor, testDispatcher, Loading @@ -97,11 +102,7 @@ class WifiRepositorySwitcherTest : SysuiTestCase() { whenever(demoModeWifiDataSource.wifiEvents).thenReturn(demoModelFlow) demoImpl = DemoWifiRepository( demoModeWifiDataSource, testScope.backgroundScope, ) demoImpl = DemoWifiRepository(demoModeWifiDataSource, testScope.backgroundScope) underTest = WifiRepositorySwitcher( Loading
packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java +24 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.systemui.statusbar.connectivity; import static com.android.systemui.Flags.multiuserWifiPickerTrackerSupport; import android.content.Context; import android.content.Intent; import android.os.UserHandle; import android.os.UserManager; Loading Loading @@ -65,13 +68,16 @@ public class AccessPointControllerImpl implements AccessPointController, private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this); private int mCurrentUser; private Context mContext; public AccessPointControllerImpl( Context context, UserManager userManager, UserTracker userTracker, Executor mainExecutor, WifiPickerTrackerFactory wifiPickerTrackerFactory ) { mContext = context; mUserManager = userManager; mUserTracker = userTracker; mCurrentUser = userTracker.getUserId(); Loading @@ -87,7 +93,11 @@ public class AccessPointControllerImpl implements AccessPointController, */ public void init() { if (mWifiPickerTracker == null) { mWifiPickerTracker = mWifiPickerTrackerFactory.create(this.getLifecycle(), this, TAG); // We are creating the WifiPickerTracker during init to make sure we have one // available at all times however we expect this to be recreated very quickly // with a user-specific context in onUserSwitched. mWifiPickerTracker = mWifiPickerTrackerFactory.create(mContext, this.getLifecycle(), this, TAG); } } Loading Loading @@ -116,6 +126,19 @@ public class AccessPointControllerImpl implements AccessPointController, void onUserSwitched(int newUserId) { mCurrentUser = newUserId; // Return early if multiuser support is not enabled. if (!multiuserWifiPickerTrackerSupport()) { return; } if (mWifiPickerTracker != null) { mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.CREATED)); } Context context = mContext.createContextAsUser(UserHandle.of(newUserId), /* flags= */ 0); mWifiPickerTracker = mWifiPickerTrackerFactory.create(context, mLifecycle, this, TAG); if (!mCallbacks.isEmpty()) { mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.STARTED)); } } @Override Loading
packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiPickerTrackerFactory.kt +12 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.net.wifi.WifiManager import android.os.Handler import android.os.SimpleClock import androidx.lifecycle.Lifecycle import com.android.systemui.Flags.multiuserWifiPickerTrackerSupport import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.util.concurrency.ThreadFactory Loading @@ -41,7 +42,7 @@ import javax.inject.Inject class WifiPickerTrackerFactory @Inject constructor( private val context: Context, private val applicationContext: Context, private val wifiManager: WifiManager?, private val connectivityManager: ConnectivityManager, private val systemClock: SystemClock, Loading @@ -64,16 +65,23 @@ constructor( * @return a new [WifiPickerTracker] or null if [WifiManager] is null. */ fun create( userContext: Context, lifecycle: Lifecycle, listener: WifiPickerTrackerCallback, name: String, ): WifiPickerTracker? { return if (wifiManager == null) { null } else } else { val contextToUse = if (multiuserWifiPickerTrackerSupport()) { userContext } else { applicationContext } WifiPickerTracker( lifecycle, context, contextToUse, wifiManager, connectivityManager, mainHandler, Loading @@ -87,6 +95,7 @@ constructor( listener, ) } } companion object { /** Max age of tracked WifiEntries. */ Loading