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

Commit 44ed47e2 authored by helencheuk's avatar helencheuk Committed by Android Build Coastguard Worker
Browse files

[Contextual Edu] Add corruptionHandler to handle file corruption

When the proto file is corrupted, it should replace it with a new healthy file instead of throwing fatal exception in systemui.

Bug: 386211247
Test: manually use below command to create a corrupted file and replace the existing one.
It creates a corrupted file by only getting the first 10 bytes of the existing file
 "head -c 10 USER10_ContextualEducation.preferences_pb > USER10_ContextualEducation.preferences_pb_corrupted"
run "adb shell stop && adb shell start". With this change, a new empty proto file replaces the corrupted one.
Flag: com.android.systemui.keyboard_touchpad_contextual_education
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:725577915491aa80c30512f87381df3b34d54e27)
Merged-In: I9a5a75420a76ff0aefab2e2f9b14770fd7b2ad7a
Change-Id: I9a5a75420a76ff0aefab2e2f9b14770fd7b2ad7a
parent 2c22b745
Loading
Loading
Loading
Loading
+14 −10
Original line number Original line Diff line number Diff line
@@ -20,10 +20,12 @@ import android.content.Context
import android.hardware.input.InputManager
import android.hardware.input.InputManager
import android.hardware.input.KeyGestureEvent
import android.hardware.input.KeyGestureEvent
import androidx.datastore.core.DataStore
import androidx.datastore.core.DataStore
import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.preferences.core.MutablePreferences
import androidx.datastore.preferences.core.MutablePreferences
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.preferencesDataStoreFile
import androidx.datastore.preferences.preferencesDataStoreFile
@@ -68,7 +70,7 @@ interface ContextualEducationRepository {


    suspend fun updateGestureEduModel(
    suspend fun updateGestureEduModel(
        gestureType: GestureType,
        gestureType: GestureType,
        transform: (GestureEduModel) -> GestureEduModel
        transform: (GestureEduModel) -> GestureEduModel,
    )
    )


    suspend fun updateEduDeviceConnectionTime(
    suspend fun updateEduDeviceConnectionTime(
@@ -149,6 +151,8 @@ constructor(
                        String.format(DATASTORE_DIR, userId)
                        String.format(DATASTORE_DIR, userId)
                    )
                    )
                },
                },
                corruptionHandler =
                    ReplaceFileCorruptionHandler(produceNewData = { emptyPreferences() }),
                scope = newDsScope,
                scope = newDsScope,
            )
            )
        dataStoreScope = newDsScope
        dataStoreScope = newDsScope
@@ -159,7 +163,7 @@ constructor(


    private fun getGestureEduModel(
    private fun getGestureEduModel(
        gestureType: GestureType,
        gestureType: GestureType,
        preferences: Preferences
        preferences: Preferences,
    ): GestureEduModel {
    ): GestureEduModel {
        return GestureEduModel(
        return GestureEduModel(
            signalCount = preferences[getSignalCountKey(gestureType)] ?: 0,
            signalCount = preferences[getSignalCountKey(gestureType)] ?: 0,
@@ -183,7 +187,7 @@ constructor(


    override suspend fun updateGestureEduModel(
    override suspend fun updateGestureEduModel(
        gestureType: GestureType,
        gestureType: GestureType,
        transform: (GestureEduModel) -> GestureEduModel
        transform: (GestureEduModel) -> GestureEduModel,
    ) {
    ) {
        datastore.filterNotNull().first().edit { preferences ->
        datastore.filterNotNull().first().edit { preferences ->
            val currentModel = getGestureEduModel(gestureType, preferences)
            val currentModel = getGestureEduModel(gestureType, preferences)
@@ -193,17 +197,17 @@ constructor(
            setInstant(
            setInstant(
                preferences,
                preferences,
                updatedModel.lastShortcutTriggeredTime,
                updatedModel.lastShortcutTriggeredTime,
                getLastShortcutTriggeredTimeKey(gestureType)
                getLastShortcutTriggeredTimeKey(gestureType),
            )
            )
            setInstant(
            setInstant(
                preferences,
                preferences,
                updatedModel.usageSessionStartTime,
                updatedModel.usageSessionStartTime,
                getUsageSessionStartTimeKey(gestureType)
                getUsageSessionStartTimeKey(gestureType),
            )
            )
            setInstant(
            setInstant(
                preferences,
                preferences,
                updatedModel.lastEducationTime,
                updatedModel.lastEducationTime,
                getLastEducationTimeKey(gestureType)
                getLastEducationTimeKey(gestureType),
            )
            )
        }
        }
    }
    }
@@ -220,12 +224,12 @@ constructor(
            setInstant(
            setInstant(
                preferences,
                preferences,
                updatedModel.keyboardFirstConnectionTime,
                updatedModel.keyboardFirstConnectionTime,
                getKeyboardFirstConnectionTimeKey()
                getKeyboardFirstConnectionTimeKey(),
            )
            )
            setInstant(
            setInstant(
                preferences,
                preferences,
                updatedModel.touchpadFirstConnectionTime,
                updatedModel.touchpadFirstConnectionTime,
                getTouchpadFirstConnectionTimeKey()
                getTouchpadFirstConnectionTimeKey(),
            )
            )
        }
        }
    }
    }
@@ -235,7 +239,7 @@ constructor(
            keyboardFirstConnectionTime =
            keyboardFirstConnectionTime =
                preferences[getKeyboardFirstConnectionTimeKey()]?.let { Instant.ofEpochSecond(it) },
                preferences[getKeyboardFirstConnectionTimeKey()]?.let { Instant.ofEpochSecond(it) },
            touchpadFirstConnectionTime =
            touchpadFirstConnectionTime =
                preferences[getTouchpadFirstConnectionTimeKey()]?.let { Instant.ofEpochSecond(it) }
                preferences[getTouchpadFirstConnectionTimeKey()]?.let { Instant.ofEpochSecond(it) },
        )
        )
    }
    }


@@ -263,7 +267,7 @@ constructor(
    private fun setInstant(
    private fun setInstant(
        preferences: MutablePreferences,
        preferences: MutablePreferences,
        instant: Instant?,
        instant: Instant?,
        key: Preferences.Key<Long>
        key: Preferences.Key<Long>,
    ) {
    ) {
        if (instant != null) {
        if (instant != null) {
            // Use epochSecond because an instant is defined as a signed long (64bit number) of
            // Use epochSecond because an instant is defined as a signed long (64bit number) of