Merge "[Bouncer] Add bouncer log buffer." into tm-qpr-dev am: 1cd9826aa0
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20667290 Change-Id: I675db79439d5a673f9fe83309642fd7fd2f89f11 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -16,23 +16,36 @@
|
|||||||
|
|
||||||
package com.android.systemui.keyguard.data.repository
|
package com.android.systemui.keyguard.data.repository
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor
|
import android.os.Build
|
||||||
import com.android.keyguard.ViewMediatorCallback
|
import com.android.keyguard.ViewMediatorCallback
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
|
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
|
||||||
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
|
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
|
||||||
|
import com.android.systemui.log.dagger.BouncerLog
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
|
import com.android.systemui.log.table.logDiffsForTable
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBouncer
|
import com.android.systemui.statusbar.phone.KeyguardBouncer
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
/** Encapsulates app state for the lock screen primary and alternate bouncer. */
|
/**
|
||||||
|
* Encapsulates app state for the lock screen primary and alternate bouncer.
|
||||||
|
*
|
||||||
|
* Make sure to add newly added flows to the logger.
|
||||||
|
*/
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
class KeyguardBouncerRepository
|
class KeyguardBouncerRepository
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
private val viewMediatorCallback: ViewMediatorCallback,
|
private val viewMediatorCallback: ViewMediatorCallback,
|
||||||
keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
@Application private val applicationScope: CoroutineScope,
|
||||||
|
@BouncerLog private val buffer: TableLogBuffer,
|
||||||
) {
|
) {
|
||||||
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
|
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
|
||||||
private val _primaryBouncerVisible = MutableStateFlow(false)
|
private val _primaryBouncerVisible = MutableStateFlow(false)
|
||||||
@@ -77,6 +90,10 @@ constructor(
|
|||||||
val bouncerErrorMessage: CharSequence?
|
val bouncerErrorMessage: CharSequence?
|
||||||
get() = viewMediatorCallback.consumeCustomMessage()
|
get() = viewMediatorCallback.consumeCustomMessage()
|
||||||
|
|
||||||
|
init {
|
||||||
|
setUpLogging()
|
||||||
|
}
|
||||||
|
|
||||||
fun setPrimaryScrimmed(isScrimmed: Boolean) {
|
fun setPrimaryScrimmed(isScrimmed: Boolean) {
|
||||||
_primaryBouncerScrimmed.value = isScrimmed
|
_primaryBouncerScrimmed.value = isScrimmed
|
||||||
}
|
}
|
||||||
@@ -132,4 +149,57 @@ constructor(
|
|||||||
fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
|
fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
|
||||||
_onScreenTurnedOff.value = onScreenTurnedOff
|
_onScreenTurnedOff.value = onScreenTurnedOff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets up logs for state flows. */
|
||||||
|
private fun setUpLogging() {
|
||||||
|
if (!Build.IS_DEBUGGABLE) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
primaryBouncerVisible
|
||||||
|
.logDiffsForTable(buffer, "", "PrimaryBouncerVisible", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
primaryBouncerShow
|
||||||
|
.map { it != null }
|
||||||
|
.logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
primaryBouncerShowingSoon
|
||||||
|
.logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
primaryBouncerHide
|
||||||
|
.logDiffsForTable(buffer, "", "PrimaryBouncerHide", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
primaryBouncerStartingToHide
|
||||||
|
.logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
primaryBouncerStartingDisappearAnimation
|
||||||
|
.map { it != null }
|
||||||
|
.logDiffsForTable(buffer, "", "PrimaryBouncerStartingDisappearAnimation", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
primaryBouncerScrimmed
|
||||||
|
.logDiffsForTable(buffer, "", "PrimaryBouncerScrimmed", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
panelExpansionAmount
|
||||||
|
.map { (it * 1000).toInt() }
|
||||||
|
.logDiffsForTable(buffer, "", "PanelExpansionAmountMillis", -1)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
keyguardPosition
|
||||||
|
.map { it.toInt() }
|
||||||
|
.logDiffsForTable(buffer, "", "KeyguardPosition", -1)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
onScreenTurnedOff
|
||||||
|
.logDiffsForTable(buffer, "", "OnScreenTurnedOff", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
isBackButtonEnabled
|
||||||
|
.filterNotNull()
|
||||||
|
.logDiffsForTable(buffer, "", "IsBackButtonEnabled", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
showMessage
|
||||||
|
.map { it?.message }
|
||||||
|
.logDiffsForTable(buffer, "", "ShowMessage", null)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
resourceUpdateRequests
|
||||||
|
.logDiffsForTable(buffer, "", "ResourceUpdateRequests", false)
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.log.dagger
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented
|
||||||
|
import java.lang.annotation.Retention
|
||||||
|
import java.lang.annotation.RetentionPolicy
|
||||||
|
import javax.inject.Qualifier
|
||||||
|
|
||||||
|
/** Logger for the primary and alternative bouncers. */
|
||||||
|
@Qualifier @Documented @Retention(RetentionPolicy.RUNTIME) annotation class BouncerLog
|
||||||
@@ -23,6 +23,8 @@ import android.os.Looper;
|
|||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.log.LogBufferFactory;
|
import com.android.systemui.log.LogBufferFactory;
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer;
|
||||||
|
import com.android.systemui.log.table.TableLogBufferFactory;
|
||||||
import com.android.systemui.plugins.log.LogBuffer;
|
import com.android.systemui.plugins.log.LogBuffer;
|
||||||
import com.android.systemui.plugins.log.LogcatEchoTracker;
|
import com.android.systemui.plugins.log.LogcatEchoTracker;
|
||||||
import com.android.systemui.plugins.log.LogcatEchoTrackerDebug;
|
import com.android.systemui.plugins.log.LogcatEchoTrackerDebug;
|
||||||
@@ -345,6 +347,14 @@ public class LogModule {
|
|||||||
return factory.create("BluetoothLog", 50);
|
return factory.create("BluetoothLog", 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Provides a logging buffer for the primary bouncer. */
|
||||||
|
@Provides
|
||||||
|
@SysUISingleton
|
||||||
|
@BouncerLog
|
||||||
|
public static TableLogBuffer provideBouncerLogBuffer(TableLogBufferFactory factory) {
|
||||||
|
return factory.create("BouncerLog", 250);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a {@link LogBuffer} for general keyguard-related logs.
|
* Provides a {@link LogBuffer} for general keyguard-related logs.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -100,3 +100,46 @@ fun Flow<Boolean>.logDiffsForTable(
|
|||||||
newVal
|
newVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Each time the Int flow is updated with a new value that's different from the previous value, logs
|
||||||
|
* the new value to the given [tableLogBuffer].
|
||||||
|
*/
|
||||||
|
fun Flow<Int>.logDiffsForTable(
|
||||||
|
tableLogBuffer: TableLogBuffer,
|
||||||
|
columnPrefix: String,
|
||||||
|
columnName: String,
|
||||||
|
initialValue: Int,
|
||||||
|
): Flow<Int> {
|
||||||
|
val initialValueFun = {
|
||||||
|
tableLogBuffer.logChange(columnPrefix, columnName, initialValue)
|
||||||
|
initialValue
|
||||||
|
}
|
||||||
|
return this.pairwiseBy(initialValueFun) { prevVal, newVal: Int ->
|
||||||
|
if (prevVal != newVal) {
|
||||||
|
tableLogBuffer.logChange(columnPrefix, columnName, newVal)
|
||||||
|
}
|
||||||
|
newVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each time the String? flow is updated with a new value that's different from the previous value,
|
||||||
|
* logs the new value to the given [tableLogBuffer].
|
||||||
|
*/
|
||||||
|
fun Flow<String?>.logDiffsForTable(
|
||||||
|
tableLogBuffer: TableLogBuffer,
|
||||||
|
columnPrefix: String,
|
||||||
|
columnName: String,
|
||||||
|
initialValue: String?,
|
||||||
|
): Flow<String?> {
|
||||||
|
val initialValueFun = {
|
||||||
|
tableLogBuffer.logChange(columnPrefix, columnName, initialValue)
|
||||||
|
initialValue
|
||||||
|
}
|
||||||
|
return this.pairwiseBy(initialValueFun) { prevVal, newVal: String? ->
|
||||||
|
if (prevVal != newVal) {
|
||||||
|
tableLogBuffer.logChange(columnPrefix, columnName, newVal)
|
||||||
|
}
|
||||||
|
newVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -127,11 +127,21 @@ class TableLogBuffer(
|
|||||||
rowInitializer(row)
|
rowInitializer(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Logs a String? change. */
|
||||||
|
fun logChange(prefix: String, columnName: String, value: String?) {
|
||||||
|
logChange(systemClock.currentTimeMillis(), prefix, columnName, value)
|
||||||
|
}
|
||||||
|
|
||||||
/** Logs a boolean change. */
|
/** Logs a boolean change. */
|
||||||
fun logChange(prefix: String, columnName: String, value: Boolean) {
|
fun logChange(prefix: String, columnName: String, value: Boolean) {
|
||||||
logChange(systemClock.currentTimeMillis(), prefix, columnName, value)
|
logChange(systemClock.currentTimeMillis(), prefix, columnName, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Logs a Int change. */
|
||||||
|
fun logChange(prefix: String, columnName: String, value: Int) {
|
||||||
|
logChange(systemClock.currentTimeMillis(), prefix, columnName, value)
|
||||||
|
}
|
||||||
|
|
||||||
// Keep these individual [logChange] methods private (don't let clients give us their own
|
// Keep these individual [logChange] methods private (don't let clients give us their own
|
||||||
// timestamps.)
|
// timestamps.)
|
||||||
|
|
||||||
|
|||||||
@@ -27,16 +27,19 @@ import com.android.systemui.keyguard.data.BouncerView
|
|||||||
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
|
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
|
||||||
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
|
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
|
||||||
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
|
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.StatusBarState
|
import com.android.systemui.statusbar.StatusBarState
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBouncer
|
import com.android.systemui.statusbar.phone.KeyguardBouncer
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.test.TestCoroutineScope
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
@@ -45,6 +48,7 @@ import org.mockito.MockitoAnnotations
|
|||||||
@TestableLooper.RunWithLooper
|
@TestableLooper.RunWithLooper
|
||||||
class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControllerBaseTest() {
|
class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControllerBaseTest() {
|
||||||
lateinit var keyguardBouncerRepository: KeyguardBouncerRepository
|
lateinit var keyguardBouncerRepository: KeyguardBouncerRepository
|
||||||
|
@Mock private lateinit var bouncerLogger: TableLogBuffer
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
@@ -53,7 +57,8 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
|
|||||||
keyguardBouncerRepository =
|
keyguardBouncerRepository =
|
||||||
KeyguardBouncerRepository(
|
KeyguardBouncerRepository(
|
||||||
mock(com.android.keyguard.ViewMediatorCallback::class.java),
|
mock(com.android.keyguard.ViewMediatorCallback::class.java),
|
||||||
mKeyguardUpdateMonitor
|
TestCoroutineScope(),
|
||||||
|
bouncerLogger,
|
||||||
)
|
)
|
||||||
super.setUp()
|
super.setUp()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.keyguard.data.repository
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.keyguard.ViewMediatorCallback
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.test.TestCoroutineScope
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.JUnit4
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
class KeyguardBouncerRepositoryTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
@Mock private lateinit var viewMediatorCallback: ViewMediatorCallback
|
||||||
|
@Mock private lateinit var bouncerLogger: TableLogBuffer
|
||||||
|
lateinit var underTest: KeyguardBouncerRepository
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
val testCoroutineScope = TestCoroutineScope()
|
||||||
|
underTest =
|
||||||
|
KeyguardBouncerRepository(viewMediatorCallback, testCoroutineScope, bouncerLogger)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun changingFlowValueTriggersLogging() = runBlocking {
|
||||||
|
underTest.setPrimaryHide(true)
|
||||||
|
verify(bouncerLogger).logChange("", "PrimaryBouncerHide", false)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user