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

Commit a8b13c95 authored by Darrell Shi's avatar Darrell Shi
Browse files

Introduce communal state proto for backup & restore

- Add a communal_hub_state proto buffer that represents the state of the
  database, used for backup & restore
- Add a utility that takes a snapshot of the database and converts it
  to a state protobuf
- Add a DAO transaction that takes a snapshot of the database and
  returns a state proto
- Make CommunalDatabase a singleton for access outside of the dagger
  dependency graph

Test: atest CommunalBackupUtilsTest
Bug: 309809222
Flag: ACONFIG com.android.systemui.communal_hub TEAMFOOD
Change-Id: Id43281e198f9e56f7bcfb930d47b58ca4571098e
parent 3473ec33
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.communal.data.backup

import android.content.Context
import androidx.annotation.WorkerThread
import com.android.systemui.communal.data.db.CommunalDatabase
import com.android.systemui.communal.nano.CommunalHubState
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking

/** Utilities for communal backup and restore. */
class CommunalBackupUtils(
    private val context: Context,
) {

    /**
     * Retrieves a communal hub state protobuf that represents the current state of the communal
     * database.
     */
    @WorkerThread
    fun getCommunalHubState(): CommunalHubState {
        val database = CommunalDatabase.getInstance(context)
        val widgetsFromDb = runBlocking { database.communalWidgetDao().getWidgets().first() }
        val widgetsState = mutableListOf<CommunalHubState.CommunalWidgetItem>()
        widgetsFromDb.keys.forEach { rankItem ->
            widgetsState.add(
                CommunalHubState.CommunalWidgetItem().apply {
                    rank = rankItem.rank
                    widgetId = widgetsFromDb[rankItem]!!.widgetId
                    componentName = widgetsFromDb[rankItem]?.componentName
                }
            )
        }
        return CommunalHubState().apply { widgets = widgetsState.toTypedArray() }
    }
}
+43 −0
Original line number Diff line number Diff line
@@ -16,10 +16,53 @@

package com.android.systemui.communal.data.db

import android.content.Context
import androidx.annotation.VisibleForTesting
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.android.systemui.res.R

@Database(entities = [CommunalWidgetItem::class, CommunalItemRank::class], version = 1)
abstract class CommunalDatabase : RoomDatabase() {
    abstract fun communalWidgetDao(): CommunalWidgetDao

    companion object {
        private var instance: CommunalDatabase? = null

        /**
         * Gets a singleton instance of the communal database. If this is called for the first time
         * globally, a new instance is created.
         *
         * @param context The context the database is created in. Only effective when a new instance
         *   is created.
         * @param callback An optional callback registered to the database. Only effective when a
         *   new instance is created.
         */
        fun getInstance(
            context: Context,
            callback: Callback? = null,
        ): CommunalDatabase {
            if (instance == null) {
                instance =
                    Room.databaseBuilder(
                            context,
                            CommunalDatabase::class.java,
                            context.resources.getString(R.string.config_communalDatabase)
                        )
                        .also { builder ->
                            builder.fallbackToDestructiveMigration(dropAllTables = false)
                            callback?.let { callback -> builder.addCallback(callback) }
                        }
                        .build()
            }

            return instance!!
        }

        @VisibleForTesting
        fun setInstance(database: CommunalDatabase) {
            instance = database
        }
    }
}
+1 −10
Original line number Diff line number Diff line
@@ -17,10 +17,8 @@
package com.android.systemui.communal.data.db

import android.content.Context
import androidx.room.Room
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.res.R
import dagger.Module
import dagger.Provides

@@ -33,14 +31,7 @@ interface CommunalDatabaseModule {
            @Application context: Context,
            defaultWidgetPopulation: DefaultWidgetPopulation,
        ): CommunalDatabase {
            return Room.databaseBuilder(
                    context,
                    CommunalDatabase::class.java,
                    context.resources.getString(R.string.config_communalDatabase)
                )
                .fallbackToDestructiveMigration()
                .addCallback(defaultWidgetPopulation)
                .build()
            return CommunalDatabase.getInstance(context, defaultWidgetPopulation)
        }

        @SysUISingleton
+10 −1
Original line number Diff line number Diff line
@@ -128,9 +128,18 @@ interface CommunalWidgetDao {

    @Transaction
    fun addWidget(widgetId: Int, provider: ComponentName, priority: Int): Long {
        return insertWidget(
        return addWidget(
            widgetId = widgetId,
            componentName = provider.flattenToString(),
            priority = priority,
        )
    }

    @Transaction
    fun addWidget(widgetId: Int, componentName: String, priority: Int): Long {
        return insertWidget(
            widgetId = widgetId,
            componentName = componentName,
            itemId = insertItemRank(priority),
        )
    }
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

syntax = "proto3";

package com.android.systemui.communal;

option java_multiple_files = true;

// Represents the state of communal hub for backup & restore.
message CommunalHubState {
    // Widgets in the communal hub.
    repeated CommunalWidgetItem widgets = 1;

    // Represents a widget in the communal hub.
    message CommunalWidgetItem {
        // Id of the widget.
        int32 widget_id = 1;

        // Component name of the widget.
        string component_name = 2;

        // Rank or order of the widget in the communal hub.
        int32 rank = 3;
    }
}
Loading