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

Commit e28d775a authored by Zhou Liu's avatar Zhou Liu
Browse files

Add preference data APIs

An API that takes a list of preference keys and return a map of preference key to preference data.

Test: atest PreferenceDataApiTest
Bug: b/405157763
Flag: android.app.supervision.flags.enable_supervision_settings_screen
Change-Id: I9183765fbb8b042630674db09ca795e8fea66050
parent 4bc471f6
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settings.supervision.ipc

import android.os.Bundle

data class PreferenceData(
    val icon: Int? = null,
    val title: CharSequence? = null,
    val summary: CharSequence? = null
) {
    constructor(bundle: Bundle) : this(
        icon = bundle.getInt(ICON, -1).takeIf { it != -1 },
        title = bundle.getCharSequence(TITLE),
        summary = bundle.getCharSequence(SUMMARY)
    )

    fun toBundle(): Bundle {
        return Bundle().apply {
            icon?.let { putInt(ICON, it) }
            title?.let { putCharSequence(TITLE, it) }
            summary?.let { putCharSequence(SUMMARY, it) }
        }
    }

    companion object {
        private const val ICON = "icon"
        private const val TITLE = "title"
        private const val SUMMARY = "summary"
    }
}
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settings.supervision.ipc

import android.os.Bundle
import com.android.settingslib.ipc.ApiDescriptor
import com.android.settingslib.ipc.MessageCodec

/**
 * Message API between UI(Settings App) and data provider(i.e. System Supervision role holder)
 *
 * Request: a list of preference keys to get new preference data of.
 * Response: a map of preference key to preference data.
 *
 * All fields in [PreferenceData] are nullable, null fields will be ignored by UI.
 */
class PreferenceDataApi : ApiDescriptor<PreferenceDataRequest, Map<String, PreferenceData>> {
    override val id: Int
        get() = 1

    override val requestCodec: MessageCodec<PreferenceDataRequest>
        get() =
            object : MessageCodec<PreferenceDataRequest> {
                override fun encode(data: PreferenceDataRequest) =
                    data.toBundle()

                override fun decode(data: Bundle) =
                    PreferenceDataRequest(data)
            }

    override val responseCodec: MessageCodec<Map<String, PreferenceData>>
        get() = object : MessageCodec<Map<String, PreferenceData>> {
            override fun encode(data: Map<String, PreferenceData>) =
                Bundle().apply {
                    for ((key, preferenceData) in data) {
                        putBundle(key, preferenceData.toBundle())
                    }
                }

            override fun decode(data: Bundle): Map<String, PreferenceData> {
                val resultMap = mutableMapOf<String, PreferenceData>()
                for (key in data.keySet()) {
                    data.getBundle(key)?.let {
                        resultMap[key] = PreferenceData(it)
                    }
                }
                return resultMap
            }
        }
}
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settings.supervision.ipc

import android.os.Bundle
import java.util.ArrayList

/**
 * Preference data request.
 *
 * @param keys a list of preference keys to get new preference data of.
 */
data class PreferenceDataRequest(val keys: List<CharSequence>) {
    constructor(bundle: Bundle) : this(keys = bundle.getStringArrayList(KEY) ?: emptyList())

    fun toBundle(): Bundle {
        return Bundle().apply {
            putCharSequenceArrayList(KEY, ArrayList(keys))
        }
    }

    companion object {
        private const val KEY = "key"
    }
}
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settings.supervision.ipc

import org.junit.Assert.assertEquals
import org.junit.Test

class PreferenceDataApiTest {

    private val api = PreferenceDataApi()

    @Test
    fun testRequestCodec() {
        val request = PreferenceDataRequest(listOf("key1", "key2"))
        val encoded = api.requestCodec.encode(request)
        val decoded = api.requestCodec.decode(encoded)
        assertEquals(request, decoded)
    }

    @Test
    fun testResponseCodec() {
        val response = mapOf(
            "key1" to PreferenceData(icon = 1, title = "Title 1", summary = "Summary 1"),
            "key2" to PreferenceData(title = "Title 2"),
            "key3" to PreferenceData(icon = 3, summary = "Summary 3"),
            "key4" to PreferenceData()
        )
        val encoded = api.responseCodec.encode(response)
        val decoded = api.responseCodec.decode(encoded)
        assertEquals(response, decoded)
    }

    @Test
    fun testRequestCodec_emptyList() {
        val request = PreferenceDataRequest(emptyList())
        val encoded = api.requestCodec.encode(request)
        val decoded = api.requestCodec.decode(encoded)
        assertEquals(request, decoded)
    }

    @Test
    fun testResponseCodec_emptyMap() {
        val response = emptyMap<String, PreferenceData>()
        val encoded = api.responseCodec.encode(response)
        val decoded = api.responseCodec.decode(encoded)
        assertEquals(response, decoded)
    }
}