summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt80
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/KeyguardStatusBarInteractor.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ui/binder/KeyguardStatusBarViewBinder.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModel.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/repository/UserSwitcherRepository.kt (renamed from packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/UserSwitcherRepository.kt)10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt130
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt59
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/data/repository/FakeUserSwitcherRepository.kt26
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt4
17 files changed, 454 insertions, 20 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt
index 38fe34eb8f9f..42d3f81ceed6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt
@@ -18,8 +18,6 @@ package com.android.systemui.qs.footer.dagger
import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepositoryImpl
-import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
-import com.android.systemui.qs.footer.data.repository.UserSwitcherRepositoryImpl
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
import dagger.Binds
@@ -28,7 +26,6 @@ import dagger.Module
/** Dagger module to provide/bind footer actions singletons. */
@Module
interface FooterActionsModule {
- @Binds fun userSwitcherRepository(impl: UserSwitcherRepositoryImpl): UserSwitcherRepository
@Binds
fun foregroundServicesRepository(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
index 8b2c3de18469..c91ed133a11e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
@@ -38,10 +38,10 @@ import com.android.systemui.qs.FgsManagerController
import com.android.systemui.qs.QSSecurityFooterUtils
import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
-import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.security.data.repository.SecurityRepository
import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.user.data.repository.UserSwitcherRepository
import com.android.systemui.user.domain.interactor.UserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
index 249c83166c51..e2de37fcbcbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.dagger
import com.android.systemui.CoreStartable
import com.android.systemui.statusbar.core.StatusBarInitializer
+import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepository
+import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepositoryImpl
import com.android.systemui.statusbar.data.repository.StatusBarModeRepository
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryImpl
import com.android.systemui.statusbar.phone.LightBarController
@@ -49,6 +51,11 @@ abstract class StatusBarModule {
abstract fun bindStatusBarModeRepositoryStart(impl: StatusBarModeRepositoryImpl): CoreStartable
@Binds
+ abstract fun bindKeyguardStatusBarRepository(
+ impl: KeyguardStatusBarRepositoryImpl
+ ): KeyguardStatusBarRepository
+
+ @Binds
@IntoMap
@ClassKey(OngoingCallController::class)
abstract fun bindOngoingCallController(impl: OngoingCallController): CoreStartable
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
new file mode 100644
index 000000000000..8136de9b7ac4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.statusbar.data.repository
+
+import android.content.Context
+import com.android.internal.R
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.user.data.repository.UserSwitcherRepository
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+
+/**
+ * Repository for data that's specific to the status bar **on keyguard**. For data that applies to
+ * all status bars, use [StatusBarModeRepository].
+ */
+interface KeyguardStatusBarRepository {
+ /** True if we can show the user switcher on keyguard and false otherwise. */
+ val isKeyguardUserSwitcherEnabled: Flow<Boolean>
+}
+
+@SysUISingleton
+class KeyguardStatusBarRepositoryImpl
+@Inject
+constructor(
+ context: Context,
+ configurationController: ConfigurationController,
+ userSwitcherRepository: UserSwitcherRepository,
+) : KeyguardStatusBarRepository {
+ private val relevantConfigChanges: Flow<Unit> =
+ ConflatedCallbackFlow.conflatedCallbackFlow {
+ val callback =
+ object : ConfigurationController.ConfigurationListener {
+ override fun onSmallestScreenWidthChanged() {
+ trySend(Unit)
+ }
+
+ override fun onDensityOrFontScaleChanged() {
+ trySend(Unit)
+ }
+ }
+ configurationController.addCallback(callback)
+ awaitClose { configurationController.removeCallback(callback) }
+ }
+
+ private val isKeyguardUserSwitcherConfigEnabled: Flow<Boolean> =
+ // The config depends on screen size and user enabled settings, so re-fetch whenever any of
+ // those change.
+ merge(userSwitcherRepository.isEnabled.map {}, relevantConfigChanges).map {
+ context.resources.getBoolean(R.bool.config_keyguardUserSwitcher)
+ }
+
+ /** True if we can show the user switcher on keyguard and false otherwise. */
+ override val isKeyguardUserSwitcherEnabled: Flow<Boolean> =
+ combine(
+ userSwitcherRepository.isEnabled,
+ isKeyguardUserSwitcherConfigEnabled,
+ ) { isEnabled, isKeyguardEnabled ->
+ isEnabled && isKeyguardEnabled
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/KeyguardStatusBarInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/KeyguardStatusBarInteractor.kt
new file mode 100644
index 000000000000..e0c30e5ec5c4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/KeyguardStatusBarInteractor.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.statusbar.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepository
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+@SysUISingleton
+class KeyguardStatusBarInteractor
+@Inject
+constructor(
+ keyguardStatusBarRepository: KeyguardStatusBarRepository,
+) {
+ /** True if we can show the user switcher on keyguard and false otherwise. */
+ val isKeyguardUserSwitcherEnabled: Flow<Boolean> =
+ keyguardStatusBarRepository.isKeyguardUserSwitcherEnabled
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 7efa705b7929..58126ae41a1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -43,9 +43,9 @@ import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import com.android.settingslib.Utils;
-import com.android.systemui.res.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
@@ -367,15 +367,22 @@ public class KeyguardStatusBarView extends RelativeLayout {
mMultiUserAvatar.setImageDrawable(picture);
}
- /** Should only be called from {@link KeyguardStatusBarViewController}. */
- void onBatteryLevelChanged(boolean charging) {
+ /**
+ * Should only be called from {@link KeyguardStatusBarViewController} or
+ * {@link com.android.systemui.statusbar.ui.binder.KeyguardStatusBarViewBinder}.
+ */
+ public void onBatteryChargingChanged(boolean charging) {
if (mBatteryCharging != charging) {
mBatteryCharging = charging;
updateVisibilities();
}
}
- void setKeyguardUserSwitcherEnabled(boolean enabled) {
+ /**
+ * Should only be called from {@link KeyguardStatusBarViewController} or
+ * {@link com.android.systemui.statusbar.ui.binder.KeyguardStatusBarViewBinder}.
+ */
+ public void setKeyguardUserSwitcherEnabled(boolean enabled) {
mKeyguardUserSwitcherEnabled = enabled;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index 9cf9714c274c..2960520f00b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -172,7 +172,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
new BatteryController.BatteryStateChangeCallback() {
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- mView.onBatteryLevelChanged(charging);
+ mView.onBatteryChargingChanged(charging);
}
};
@@ -430,11 +430,18 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
/** Sets whether user switcher is enabled. */
public void setKeyguardUserSwitcherEnabled(boolean enabled) {
+ if (isMigrationEnabled()) {
+ return;
+ }
mView.setKeyguardUserSwitcherEnabled(enabled);
}
/** Sets whether this controller should listen to battery updates. */
public void setBatteryListening(boolean listening) {
+ if (isMigrationEnabled()) {
+ return;
+ }
+
if (listening == mBatteryListening) {
return;
}
@@ -472,6 +479,10 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
/** Animate the keyguard status bar in. */
public void animateKeyguardStatusBarIn() {
+ if (isMigrationEnabled()) {
+ return;
+ }
+
mLogger.log(TAG, LogLevel.DEBUG, "animating status bar in");
if (mDisableStateTracker.isDisabled()) {
// If our view is disabled, don't allow us to animate in.
@@ -488,6 +499,10 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
/** Animate the keyguard status bar out. */
public void animateKeyguardStatusBarOut(long startDelay, long duration) {
+ if (isMigrationEnabled()) {
+ return;
+ }
+
mLogger.log(TAG, LogLevel.DEBUG, "animating status bar out");
ValueAnimator anim = ValueAnimator.ofFloat(mView.getAlpha(), 0f);
anim.addUpdateListener(mAnimatorUpdateListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ui/binder/KeyguardStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ui/binder/KeyguardStatusBarViewBinder.kt
index c63ef9e5e012..6988e211855b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ui/binder/KeyguardStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ui/binder/KeyguardStatusBarViewBinder.kt
@@ -22,6 +22,8 @@ import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.phone.KeyguardStatusBarView
import com.android.systemui.statusbar.ui.viewmodel.KeyguardStatusBarViewModel
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.launch
/** Binds [KeyguardStatusBarViewModel] to [KeyguardStatusBarView]. */
object KeyguardStatusBarViewBinder {
@@ -32,8 +34,18 @@ object KeyguardStatusBarViewBinder {
) {
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
- viewModel.isVisible.collect { isVisible ->
- view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
+ launch {
+ viewModel.isVisible.collect { isVisible ->
+ view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
+ }
+ }
+
+ launch { viewModel.isBatteryCharging.collect { view.onBatteryChargingChanged(it) } }
+
+ launch {
+ viewModel.isKeyguardUserSwitcherEnabled.distinctUntilChanged().collect {
+ view.setKeyguardUserSwitcherEnabled(it)
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModel.kt
index ddfed8795fcf..5da01e23e268 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModel.kt
@@ -16,12 +16,18 @@
package com.android.systemui.statusbar.ui.viewmodel
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.statusbar.domain.interactor.KeyguardStatusBarInteractor
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
@@ -41,6 +47,8 @@ class KeyguardStatusBarViewModel
constructor(
@Application scope: CoroutineScope,
keyguardInteractor: KeyguardInteractor,
+ keyguardStatusBarInteractor: KeyguardStatusBarInteractor,
+ batteryController: BatteryController,
) {
/** True if this view should be visible and false otherwise. */
val isVisible: StateFlow<Boolean> =
@@ -51,4 +59,26 @@ constructor(
!isDozing && statusBarState == StatusBarState.KEYGUARD
}
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+ /** True if the device's battery is currently charging and false otherwise. */
+ // Note: Never make this an eagerly-started state flow so that the callback is removed when the
+ // keyguard status bar view isn't attached.
+ val isBatteryCharging: Flow<Boolean> = conflatedCallbackFlow {
+ val callback =
+ object : BatteryStateChangeCallback {
+ override fun onBatteryLevelChanged(
+ level: Int,
+ pluggedIn: Boolean,
+ charging: Boolean,
+ ) {
+ trySend(charging)
+ }
+ }
+ batteryController.addCallback(callback)
+ awaitClose { batteryController.removeCallback(callback) }
+ }
+
+ /** True if we can show the user switcher on keyguard and false otherwise. */
+ val isKeyguardUserSwitcherEnabled: Flow<Boolean> =
+ keyguardStatusBarInteractor.isKeyguardUserSwitcherEnabled
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt
index 18ae1070e1bb..71352eff026c 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt
@@ -23,4 +23,6 @@ import dagger.Module
@Module
interface UserRepositoryModule {
@Binds fun bindRepository(impl: UserRepositoryImpl): UserRepository
+
+ @Binds fun userSwitcherRepository(impl: UserSwitcherRepositoryImpl): UserSwitcherRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/UserSwitcherRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserSwitcherRepository.kt
index 5fa75ad68165..dc7fadd5eb14 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/UserSwitcherRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserSwitcherRepository.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.qs.footer.data.repository
+package com.android.systemui.user.data.repository
import android.content.Context
import android.graphics.drawable.Drawable
@@ -22,7 +22,6 @@ import android.os.Handler
import android.os.UserManager
import android.provider.Settings.Global.USER_SWITCHER_ENABLED
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.res.R
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
@@ -30,6 +29,7 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.qs.SettingObserver
import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
+import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.UserInfoController
import com.android.systemui.statusbar.policy.UserSwitcherController
@@ -48,6 +48,9 @@ import kotlinx.coroutines.withContext
interface UserSwitcherRepository {
/** The current [UserSwitcherStatusModel]. */
val userSwitcherStatus: Flow<UserSwitcherStatusModel>
+
+ /** Whether the user switcher is currently enabled. */
+ val isEnabled: Flow<Boolean>
}
@SysUISingleton
@@ -66,8 +69,7 @@ constructor(
private val showUserSwitcherForSingleUser =
context.resources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)
- /** Whether the user switcher is currently enabled. */
- private val isEnabled: Flow<Boolean> = conflatedCallbackFlow {
+ override val isEnabled: Flow<Boolean> = conflatedCallbackFlow {
suspend fun updateState() {
trySendWithFailureLogging(isUserSwitcherEnabled(), TAG)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt
new file mode 100644
index 000000000000..f1e6a053643f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.statusbar.data.repository
+
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeKeyguardStatusBarRepository : KeyguardStatusBarRepository {
+ override val isKeyguardUserSwitcherEnabled = MutableStateFlow(false)
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt
new file mode 100644
index 000000000000..b1c994c2374e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt
@@ -0,0 +1,130 @@
+/*
+ * 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.statusbar.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.internal.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.user.data.repository.FakeUserSwitcherRepository
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.mockito.Mockito.verify
+
+@SmallTest
+class KeyguardStatusBarRepositoryImplTest : SysuiTestCase() {
+ private val testScope = TestScope()
+ private val configurationController = mock<ConfigurationController>()
+ private val userSwitcherRepository = FakeUserSwitcherRepository()
+
+ val underTest =
+ KeyguardStatusBarRepositoryImpl(
+ context,
+ configurationController,
+ userSwitcherRepository,
+ )
+
+ private val configurationListener: ConfigurationController.ConfigurationListener
+ get() {
+ val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
+ verify(configurationController).addCallback(capture(captor))
+ return captor.value
+ }
+
+ @Test
+ fun isKeyguardUserSwitcherEnabled_switcherNotEnabled_false() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isKeyguardUserSwitcherEnabled)
+
+ userSwitcherRepository.isEnabled.value = false
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ fun isKeyguardUserSwitcherEnabled_keyguardConfigNotEnabled_false() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isKeyguardUserSwitcherEnabled)
+ userSwitcherRepository.isEnabled.value = true
+
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, false)
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ fun isKeyguardUserSwitcherEnabled_switchEnabledAndKeyguardConfigEnabled_true() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isKeyguardUserSwitcherEnabled)
+
+ userSwitcherRepository.isEnabled.value = true
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, true)
+
+ assertThat(latest).isTrue()
+ }
+
+ @Test
+ fun isKeyguardUserSwitcherEnabled_refetchedOnSmallestWidthChanged() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isKeyguardUserSwitcherEnabled)
+ userSwitcherRepository.isEnabled.value = true
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, true)
+ assertThat(latest).isTrue()
+
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, false)
+ configurationListener.onSmallestScreenWidthChanged()
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ fun isKeyguardUserSwitcherEnabled_refetchedOnDensityChanged() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isKeyguardUserSwitcherEnabled)
+ userSwitcherRepository.isEnabled.value = true
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, true)
+ assertThat(latest).isTrue()
+
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, false)
+ configurationListener.onDensityOrFontScaleChanged()
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ fun isKeyguardUserSwitcherEnabled_refetchedOnEnabledChanged() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isKeyguardUserSwitcherEnabled)
+
+ userSwitcherRepository.isEnabled.value = false
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, true)
+ assertThat(latest).isFalse()
+
+ // WHEN the switcher becomes enabled but the keyguard switcher becomes disabled
+ context.orCreateTestableResources.addOverride(R.bool.config_keyguardUserSwitcher, false)
+ userSwitcherRepository.isEnabled.value = true
+
+ // THEN the value is still false because the keyguard config is refetched
+ assertThat(latest).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index c0d248ea15e7..648438997166 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -64,12 +64,13 @@ import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.power.domain.interactor.PowerInteractorFactory;
import com.android.systemui.res.R;
import com.android.systemui.scene.SceneTestUtils;
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
import com.android.systemui.shade.ShadeViewStateProvider;
import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.data.repository.FakeKeyguardStatusBarRepository;
+import com.android.systemui.statusbar.domain.interactor.KeyguardStatusBarInteractor;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -156,7 +157,6 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
public void setup() throws Exception {
mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, false);
mShadeViewStateProvider = new TestShadeViewStateProvider();
- mShadeViewStateProvider = new TestShadeViewStateProvider();
MockitoAnnotations.initMocks(this);
@@ -176,7 +176,9 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
mViewModel =
new KeyguardStatusBarViewModel(
mTestScope.getBackgroundScope(),
- mKeyguardInteractor);
+ mKeyguardInteractor,
+ new KeyguardStatusBarInteractor(new FakeKeyguardStatusBarRepository()),
+ mBatteryController);
allowTestableLooperAsMainThread();
TestableLooper.get(this).runWithLooper(() -> {
@@ -320,6 +322,15 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
}
@Test
+ public void setBatteryListening_true_flagOn_callbackNotAdded() {
+ mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, true);
+
+ mController.setBatteryListening(true);
+
+ verify(mBatteryController, never()).addCallback(any());
+ }
+
+ @Test
public void updateTopClipping_viewClippingUpdated() {
int viewTop = 20;
mKeyguardStatusBarView.setTop(viewTop);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
index f4078d59bbdb..1bc346de1568 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
@@ -29,13 +29,23 @@ import com.android.systemui.power.domain.interactor.PowerInteractorFactory
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.data.repository.FakeKeyguardStatusBarRepository
+import com.android.systemui.statusbar.domain.interactor.KeyguardStatusBarInteractor
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
+import org.mockito.Mockito.verify
@SmallTest
+@OptIn(ExperimentalCoroutinesApi::class)
class KeyguardStatusBarViewModelTest : SysuiTestCase() {
private val testScope = TestScope()
private val sceneTestUtils = SceneTestUtils(this)
@@ -54,11 +64,18 @@ class KeyguardStatusBarViewModelTest : SysuiTestCase() {
) {
sceneTestUtils.sceneInteractor()
}
+ private val keyguardStatusBarInteractor =
+ KeyguardStatusBarInteractor(
+ FakeKeyguardStatusBarRepository(),
+ )
+ private val batteryController = mock<BatteryController>()
private val underTest =
KeyguardStatusBarViewModel(
testScope.backgroundScope,
keyguardInteractor,
+ keyguardStatusBarInteractor,
+ batteryController,
)
@Test
@@ -102,4 +119,46 @@ class KeyguardStatusBarViewModelTest : SysuiTestCase() {
assertThat(latest).isTrue()
}
+
+ @Test
+ fun isBatteryCharging_matchesCallback() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isBatteryCharging)
+ runCurrent()
+
+ val captor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(captor))
+ val callback = captor.value
+
+ callback.onBatteryLevelChanged(
+ /* level= */ 2,
+ /* pluggedIn= */ false,
+ /* charging= */ true,
+ )
+
+ assertThat(latest).isTrue()
+
+ callback.onBatteryLevelChanged(
+ /* level= */ 2,
+ /* pluggedIn= */ true,
+ /* charging= */ false,
+ )
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ fun isBatteryCharging_unregistersWhenNotListening() =
+ testScope.runTest {
+ val job = underTest.isBatteryCharging.launchIn(this)
+ runCurrent()
+
+ val captor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(captor))
+
+ job.cancel()
+ runCurrent()
+
+ verify(batteryController).removeCallback(captor.value)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/FakeUserSwitcherRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/FakeUserSwitcherRepository.kt
new file mode 100644
index 000000000000..758fe93a658c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/FakeUserSwitcherRepository.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.repository
+
+import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeUserSwitcherRepository : UserSwitcherRepository {
+ override val isEnabled = MutableStateFlow(false)
+ override val userSwitcherStatus =
+ MutableStateFlow<UserSwitcherStatusModel>(UserSwitcherStatusModel.Disabled)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
index 1a893f8c523c..bf77b1a050cd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
@@ -36,8 +36,6 @@ import com.android.systemui.qs.FgsManagerController
import com.android.systemui.qs.QSSecurityFooterUtils
import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepositoryImpl
-import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
-import com.android.systemui.qs.footer.data.repository.UserSwitcherRepositoryImpl
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
@@ -51,6 +49,8 @@ import com.android.systemui.statusbar.policy.FakeUserInfoController
import com.android.systemui.statusbar.policy.SecurityController
import com.android.systemui.statusbar.policy.UserInfoController
import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.user.data.repository.UserSwitcherRepository
+import com.android.systemui.user.data.repository.UserSwitcherRepositoryImpl
import com.android.systemui.user.domain.interactor.UserInteractor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.settings.FakeSettings