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

Commit 574d0b6e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[SB Refactor] Ensure the initial value is also logged to the table." into tm-qpr-dev

parents 0b903945 e3926eeb
Loading
Loading
Loading
Loading
+19 −3
Original line number Original line Diff line number Diff line
@@ -30,10 +30,11 @@ import kotlinx.coroutines.flow.Flow
 */
 */
interface Diffable<T> {
interface Diffable<T> {
    /**
    /**
     * Finds the differences between [prevVal] and [this] and logs those diffs to [row].
     * Finds the differences between [prevVal] and this object and logs those diffs to [row].
     *
     *
     * Each implementer should determine which individual fields have changed between [prevVal] and
     * Each implementer should determine which individual fields have changed between [prevVal] and
     * [this], and only log the fields that have actually changed. This helps save buffer space.
     * this object, and only log the fields that have actually changed. This helps save buffer
     * space.
     *
     *
     * For example, if:
     * For example, if:
     * - prevVal = Object(val1=100, val2=200, val3=300)
     * - prevVal = Object(val1=100, val2=200, val3=300)
@@ -42,6 +43,16 @@ interface Diffable<T> {
     * Then only the val3 change should be logged.
     * Then only the val3 change should be logged.
     */
     */
    fun logDiffs(prevVal: T, row: TableRowLogger)
    fun logDiffs(prevVal: T, row: TableRowLogger)

    /**
     * Logs all the relevant fields of this object to [row].
     *
     * As opposed to [logDiffs], this method should log *all* fields.
     *
     * Implementation is optional. This method will only be used with [logDiffsForTable] in order to
     * fully log the initial value of the flow.
     */
    fun logFull(row: TableRowLogger) {}
}
}


/**
/**
@@ -57,7 +68,12 @@ fun <T : Diffable<T>> Flow<T>.logDiffsForTable(
    columnPrefix: String,
    columnPrefix: String,
    initialValue: T,
    initialValue: T,
): Flow<T> {
): Flow<T> {
    return this.pairwiseBy(initialValue) { prevVal, newVal ->
    // Fully log the initial value to the table.
    val getInitialValue = {
        tableLogBuffer.logChange(columnPrefix) { row -> initialValue.logFull(row) }
        initialValue
    }
    return this.pairwiseBy(getInitialValue) { prevVal: T, newVal: T ->
        tableLogBuffer.logDiffs(columnPrefix, prevVal, newVal)
        tableLogBuffer.logDiffs(columnPrefix, prevVal, newVal)
        newVal
        newVal
    }
    }
+14 −0
Original line number Original line Diff line number Diff line
@@ -113,6 +113,20 @@ class TableLogBuffer(
        newVal.logDiffs(prevVal, row)
        newVal.logDiffs(prevVal, row)
    }
    }


    /**
     * Logs change(s) to the buffer using [rowInitializer].
     *
     * @param rowInitializer a function that will be called immediately to store relevant data on
     * the row.
     */
    @Synchronized
    fun logChange(columnPrefix: String, rowInitializer: (TableRowLogger) -> Unit) {
        val row = tempRow
        row.timestamp = systemClock.currentTimeMillis()
        row.columnPrefix = columnPrefix
        rowInitializer(row)
    }

    // 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.)


+13 −16
Original line number Original line Diff line number Diff line
@@ -31,15 +31,19 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
            if (prevVal is Inactive) {
            if (prevVal is Inactive) {
                return
                return
            }
            }
            row.logChange(COL_NETWORK_TYPE, TYPE_INACTIVE)


            if (prevVal is CarrierMerged) {
            if (prevVal is CarrierMerged) {
                // The only difference between CarrierMerged and Inactive is the type
                // The only difference between CarrierMerged and Inactive is the type
                row.logChange(COL_NETWORK_TYPE, TYPE_INACTIVE)
                return
                return
            }
            }


            // When changing from Active to Inactive, we need to log diffs to all the fields.
            // When changing from Active to Inactive, we need to log diffs to all the fields.
            logDiffsFromActiveToNotActive(prevVal as Active, row)
            logFullNonActiveNetwork(TYPE_INACTIVE, row)
        }

        override fun logFull(row: TableRowLogger) {
            logFullNonActiveNetwork(TYPE_INACTIVE, row)
        }
        }
    }
    }


@@ -56,15 +60,15 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
            if (prevVal is CarrierMerged) {
            if (prevVal is CarrierMerged) {
                return
                return
            }
            }
            row.logChange(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED)


            if (prevVal is Inactive) {
            if (prevVal is Inactive) {
                // The only difference between CarrierMerged and Inactive is the type.
                // The only difference between CarrierMerged and Inactive is the type.
                row.logChange(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED)
                return
                return
            }
            }


            // When changing from Active to CarrierMerged, we need to log diffs to all the fields.
            // When changing from Active to CarrierMerged, we need to log diffs to all the fields.
            logDiffsFromActiveToNotActive(prevVal as Active, row)
            logFullNonActiveNetwork(TYPE_CARRIER_MERGED, row)
        }
        }
    }
    }


@@ -147,7 +151,6 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
            }
            }
        }
        }



        override fun toString(): String {
        override fun toString(): String {
            // Only include the passpoint-related values in the string if we have them. (Most
            // Only include the passpoint-related values in the string if we have them. (Most
            // networks won't have them so they'll be mostly clutter.)
            // networks won't have them so they'll be mostly clutter.)
@@ -174,23 +177,17 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
        }
        }
    }
    }


    internal fun logDiffsFromActiveToNotActive(prevActive: Active, row: TableRowLogger) {
    internal fun logFullNonActiveNetwork(type: String, row: TableRowLogger) {
        row.logChange(COL_NETWORK_TYPE, type)
        row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
        row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
        row.logChange(COL_VALIDATED, false)
        row.logChange(COL_VALIDATED, false)
        row.logChange(COL_LEVEL, LEVEL_DEFAULT)
        row.logChange(COL_LEVEL, LEVEL_DEFAULT)
        row.logChange(COL_SSID, null)
        row.logChange(COL_SSID, null)

        if (prevActive.isPasspointAccessPoint) {
        row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
        row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
        }
        if (prevActive.isOnlineSignUpForPasspointAccessPoint) {
        row.logChange(COL_ONLINE_SIGN_UP, false)
        row.logChange(COL_ONLINE_SIGN_UP, false)
        }
        if (prevActive.passpointProviderFriendlyName != null) {
        row.logChange(COL_PASSPOINT_NAME, null)
        row.logChange(COL_PASSPOINT_NAME, null)
    }
    }
}
}
}


const val TYPE_CARRIER_MERGED = "CarrierMerged"
const val TYPE_CARRIER_MERGED = "CarrierMerged"
const val TYPE_INACTIVE = "Inactive"
const val TYPE_INACTIVE = "Inactive"
+16 −1
Original line number Original line Diff line number Diff line
@@ -20,7 +20,6 @@ import java.util.concurrent.atomic.AtomicReference
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.onStart
@@ -57,6 +56,22 @@ fun <T, R> Flow<T>.pairwiseBy(
): Flow<R> =
): Flow<R> =
    onStart { emit(initialValue) }.pairwiseBy(transform)
    onStart { emit(initialValue) }.pairwiseBy(transform)


/**
 * Returns a new [Flow] that combines the two most recent emissions from [this] using [transform].
 *
 *
 * The output of [getInitialValue] will be used as the "old" value for the first emission. As
 * opposed to the initial value in the above [pairwiseBy], [getInitialValue] can do some work before
 * returning the initial value.
 *
 * Useful for code that needs to compare the current value to the previous value.
 */
fun <T, R> Flow<T>.pairwiseBy(
    getInitialValue: suspend () -> T,
    transform: suspend (previousValue: T, newValue: T) -> R,
): Flow<R> =
    onStart { emit(getInitialValue()) }.pairwiseBy(transform)

/**
/**
 * Returns a new [Flow] that produces the two most recent emissions from [this]. Note that the new
 * Returns a new [Flow] that produces the two most recent emissions from [this]. Note that the new
 * Flow will not start emitting until it has received two emissions from the upstream Flow.
 * Flow will not start emitting until it has received two emissions from the upstream Flow.
+62 −0
Original line number Original line Diff line number Diff line
@@ -336,6 +336,68 @@ class TableLogBufferTest : SysuiTestCase() {
        assertThat(dumpedString).contains(expected2)
        assertThat(dumpedString).contains(expected2)
    }
    }


    @Test
    fun logChange_rowInitializer_dumpsCorrectly() {
        systemClock.setCurrentTimeMillis(100L)

        underTest.logChange("") { row ->
            row.logChange("column1", "val1")
            row.logChange("column2", 2)
            row.logChange("column3", true)
        }

        val dumpedString = dumpChanges()

        val timestamp = TABLE_LOG_DATE_FORMAT.format(100L)
        val expected1 = timestamp + SEPARATOR + "column1" + SEPARATOR + "val1"
        val expected2 = timestamp + SEPARATOR + "column2" + SEPARATOR + "2"
        val expected3 = timestamp + SEPARATOR + "column3" + SEPARATOR + "true"
        assertThat(dumpedString).contains(expected1)
        assertThat(dumpedString).contains(expected2)
        assertThat(dumpedString).contains(expected3)
    }

    @Test
    fun logChangeAndLogDiffs_bothLogged() {
        systemClock.setCurrentTimeMillis(100L)

        underTest.logChange("") { row ->
            row.logChange("column1", "val1")
            row.logChange("column2", 2)
            row.logChange("column3", true)
        }

        systemClock.setCurrentTimeMillis(200L)
        val prevDiffable = object : TestDiffable() {}
        val nextDiffable =
            object : TestDiffable() {
                override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) {
                    row.logChange("column1", "newVal1")
                    row.logChange("column2", 222)
                    row.logChange("column3", false)
                }
            }

        underTest.logDiffs(columnPrefix = "", prevDiffable, nextDiffable)

        val dumpedString = dumpChanges()

        val timestamp1 = TABLE_LOG_DATE_FORMAT.format(100L)
        val expected1 = timestamp1 + SEPARATOR + "column1" + SEPARATOR + "val1"
        val expected2 = timestamp1 + SEPARATOR + "column2" + SEPARATOR + "2"
        val expected3 = timestamp1 + SEPARATOR + "column3" + SEPARATOR + "true"
        val timestamp2 = TABLE_LOG_DATE_FORMAT.format(200L)
        val expected4 = timestamp2 + SEPARATOR + "column1" + SEPARATOR + "newVal1"
        val expected5 = timestamp2 + SEPARATOR + "column2" + SEPARATOR + "222"
        val expected6 = timestamp2 + SEPARATOR + "column3" + SEPARATOR + "false"
        assertThat(dumpedString).contains(expected1)
        assertThat(dumpedString).contains(expected2)
        assertThat(dumpedString).contains(expected3)
        assertThat(dumpedString).contains(expected4)
        assertThat(dumpedString).contains(expected5)
        assertThat(dumpedString).contains(expected6)
    }

    @Test
    @Test
    fun dumpChanges_rotatesIfBufferIsFull() {
    fun dumpChanges_rotatesIfBufferIsFull() {
        lateinit var valToDump: String
        lateinit var valToDump: String
Loading