Support GetMetadata for Preference Service
Bug: 379750656 Flag: com.android.settingslib.flags.settings_catalyst Test: unit test Change-Id: Ia9b438360b60ff509a259df0a079ec4d745fb595
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.service
|
||||
|
||||
import android.app.Application
|
||||
import android.os.Binder
|
||||
import android.os.OutcomeReceiver
|
||||
import android.os.Process
|
||||
@@ -26,38 +27,49 @@ import android.service.settings.preferences.MetadataResult
|
||||
import android.service.settings.preferences.SetValueRequest
|
||||
import android.service.settings.preferences.SetValueResult
|
||||
import android.service.settings.preferences.SettingsPreferenceService
|
||||
import com.android.settingslib.graph.GetPreferenceGraphApiHandler
|
||||
import com.android.settingslib.graph.GetPreferenceGraphRequest
|
||||
import com.android.settingslib.graph.PreferenceGetterApiHandler
|
||||
import com.android.settingslib.graph.PreferenceGetterFlags
|
||||
import com.android.settingslib.graph.PreferenceSetterApiHandler
|
||||
import com.android.settingslib.ipc.ApiPermissionChecker
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import java.lang.Exception
|
||||
|
||||
class PreferenceService : SettingsPreferenceService() {
|
||||
|
||||
private val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
|
||||
private val getApiHandler = PreferenceGetterApiHandler(1, ApiPermissionChecker.alwaysAllow())
|
||||
private val setApiHandler = PreferenceSetterApiHandler(2, ApiPermissionChecker.alwaysAllow())
|
||||
private val graphApi = GraphProvider(3)
|
||||
|
||||
override fun onGetAllPreferenceMetadata(
|
||||
request: MetadataRequest,
|
||||
callback: OutcomeReceiver<MetadataResult, Exception>
|
||||
) {
|
||||
// TODO(379750656): Update graph API to be usable outside SettingsLib
|
||||
callback.onError(UnsupportedOperationException("Not yet supported"))
|
||||
scope.launch {
|
||||
val graphProto = graphApi.invoke(application, Process.myUid(), Binder.getCallingUid(),
|
||||
GetPreferenceGraphRequest(
|
||||
includeValue = false,
|
||||
flags = PreferenceGetterFlags.METADATA
|
||||
))
|
||||
val result = transformCatalystGetMetadataResponse(this@PreferenceService, graphProto)
|
||||
callback.onResult(result)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGetPreferenceValue(
|
||||
request: GetValueRequest,
|
||||
callback: OutcomeReceiver<GetValueResult, Exception>
|
||||
) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
scope.launch {
|
||||
val apiRequest = transformFrameworkGetValueRequest(request)
|
||||
val response = getApiHandler.invoke(application, Process.myUid(),
|
||||
Binder.getCallingPid(), apiRequest)
|
||||
Binder.getCallingUid(), apiRequest)
|
||||
val result = transformCatalystGetValueResponse(
|
||||
this@PreferenceService,
|
||||
request,
|
||||
@@ -75,7 +87,7 @@ class PreferenceService : SettingsPreferenceService() {
|
||||
request: SetValueRequest,
|
||||
callback: OutcomeReceiver<SetValueResult, Exception>
|
||||
) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
scope.launch {
|
||||
val apiRequest = transformFrameworkSetValueRequest(request)
|
||||
if (apiRequest == null) {
|
||||
callback.onResult(
|
||||
@@ -83,10 +95,20 @@ class PreferenceService : SettingsPreferenceService() {
|
||||
)
|
||||
} else {
|
||||
val response = setApiHandler.invoke(application, Process.myUid(),
|
||||
Binder.getCallingPid(), apiRequest)
|
||||
Binder.getCallingUid(), apiRequest)
|
||||
|
||||
callback.onResult(transformCatalystSetValueResponse(response))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Basic implementation - we already have permission to access Graph for Metadata via superclass
|
||||
private class GraphProvider(override val id: Int) : GetPreferenceGraphApiHandler(emptySet()) {
|
||||
override fun hasPermission(
|
||||
application: Application,
|
||||
myUid: Int,
|
||||
callingUid: Int,
|
||||
request: GetPreferenceGraphRequest
|
||||
) = true
|
||||
}
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ package com.android.settings.service
|
||||
import android.content.Context
|
||||
import android.service.settings.preferences.GetValueRequest
|
||||
import android.service.settings.preferences.GetValueResult
|
||||
import android.service.settings.preferences.MetadataResult
|
||||
import android.service.settings.preferences.SetValueRequest
|
||||
import android.service.settings.preferences.SetValueResult
|
||||
import android.service.settings.preferences.SettingsPreferenceMetadata
|
||||
@@ -34,9 +35,55 @@ import com.android.settingslib.graph.preferenceValueProto
|
||||
import com.android.settingslib.graph.proto.PreferenceProto
|
||||
import com.android.settingslib.graph.proto.PreferenceValueProto
|
||||
import com.android.settingslib.graph.getText
|
||||
import com.android.settingslib.graph.proto.PreferenceGraphProto
|
||||
import com.android.settingslib.graph.proto.PreferenceOrGroupProto
|
||||
import com.android.settingslib.graph.toIntent
|
||||
import com.android.settingslib.metadata.SensitivityLevel
|
||||
|
||||
/** Transform Catalyst Graph result to Framework GET METADATA result */
|
||||
fun transformCatalystGetMetadataResponse(
|
||||
context: Context,
|
||||
graph: PreferenceGraphProto
|
||||
): MetadataResult {
|
||||
val preferences = mutableSetOf<PreferenceWithScreen>()
|
||||
// recursive function to visit all nodes in preference group
|
||||
fun traverseGroupOrPref(
|
||||
screenKey: String,
|
||||
groupOrPref: PreferenceOrGroupProto,
|
||||
) {
|
||||
when (groupOrPref.kindCase) {
|
||||
PreferenceOrGroupProto.KindCase.PREFERENCE ->
|
||||
preferences.add(
|
||||
PreferenceWithScreen(screenKey, groupOrPref.preference)
|
||||
)
|
||||
PreferenceOrGroupProto.KindCase.GROUP -> {
|
||||
for (child in groupOrPref.group.preferencesList) {
|
||||
traverseGroupOrPref(screenKey, child)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
// traverse all screens and all preferences on screen
|
||||
for ((screenKey, screen) in graph.screensMap) {
|
||||
for (groupOrPref in screen.root.preferencesList) {
|
||||
traverseGroupOrPref(screenKey, groupOrPref)
|
||||
}
|
||||
}
|
||||
|
||||
return if (preferences.isNotEmpty()) {
|
||||
MetadataResult.Builder(MetadataResult.RESULT_OK)
|
||||
.setMetadataList(
|
||||
preferences.map {
|
||||
it.preference.toMetadata(context, it.screenKey)
|
||||
}
|
||||
)
|
||||
.build()
|
||||
} else {
|
||||
MetadataResult.Builder(MetadataResult.RESULT_UNSUPPORTED).build()
|
||||
}
|
||||
}
|
||||
|
||||
/** Translate Framework GET VALUE request to Catalyst GET VALUE request */
|
||||
fun transformFrameworkGetValueRequest(
|
||||
request: GetValueRequest,
|
||||
@@ -133,6 +180,11 @@ fun transformCatalystSetValueResponse(@PreferenceSetterResult response: Int): Se
|
||||
return SetValueResult.Builder(resultCode).build()
|
||||
}
|
||||
|
||||
private data class PreferenceWithScreen(
|
||||
val screenKey: String,
|
||||
val preference: PreferenceProto,
|
||||
)
|
||||
|
||||
private fun PreferenceProto.toMetadata(
|
||||
context: Context,
|
||||
screenKey: String
|
||||
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.service
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled
|
||||
@@ -24,6 +23,7 @@ import android.platform.test.flag.junit.CheckFlagsRule
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider
|
||||
import android.service.settings.preferences.GetValueRequest
|
||||
import android.service.settings.preferences.GetValueResult
|
||||
import android.service.settings.preferences.MetadataResult
|
||||
import android.service.settings.preferences.SetValueRequest
|
||||
import android.service.settings.preferences.SetValueResult
|
||||
import android.service.settings.preferences.SettingsPreferenceMetadata
|
||||
@@ -37,9 +37,15 @@ import com.android.settingslib.graph.PreferenceGetterErrorCode
|
||||
import com.android.settingslib.graph.PreferenceGetterFlags
|
||||
import com.android.settingslib.graph.PreferenceGetterResponse
|
||||
import com.android.settingslib.graph.PreferenceSetterResult
|
||||
import com.android.settingslib.graph.preferenceGroupProto
|
||||
import com.android.settingslib.graph.preferenceOrGroupProto
|
||||
import com.android.settingslib.graph.preferenceProto
|
||||
import com.android.settingslib.graph.preferenceScreenProto
|
||||
import com.android.settingslib.graph.proto.PreferenceGraphProto
|
||||
import com.android.settingslib.graph.proto.PreferenceProto
|
||||
import com.android.settingslib.graph.proto.PreferenceValueProto
|
||||
import com.android.settingslib.graph.proto.TextProto
|
||||
import com.android.settingslib.graph.textProto
|
||||
import com.android.settingslib.graph.toProto
|
||||
import com.android.settingslib.metadata.SensitivityLevel
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
@@ -54,6 +60,73 @@ class PreferenceServiceRequestTransformerTest {
|
||||
@get:Rule
|
||||
val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
|
||||
|
||||
@Test
|
||||
fun transformCatalystGetMetadataResponse_emptyGraph_returnsFrameworkResponseWithError() {
|
||||
val context: Context = ApplicationProvider.getApplicationContext()
|
||||
val graphProto = PreferenceGraphProto.newBuilder().build()
|
||||
val fResult = transformCatalystGetMetadataResponse(context, graphProto)
|
||||
with(fResult) {
|
||||
assertThat(resultCode).isEqualTo(MetadataResult.RESULT_UNSUPPORTED)
|
||||
assertThat(metadataList).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transformCatalystGetMetadataResponse_populatedGraph_returnsFrameworkResponseWithSuccess() {
|
||||
val context: Context = ApplicationProvider.getApplicationContext()
|
||||
val screen = preferenceScreenProto {
|
||||
root = preferenceGroupProto {
|
||||
addAllPreferences(
|
||||
listOf(
|
||||
preferenceOrGroupProto {
|
||||
group = preferenceGroupProto {
|
||||
addPreferences(
|
||||
preferenceOrGroupProto {
|
||||
preference = preferenceProto {
|
||||
key = "key1"
|
||||
title = textProto { string = "title1" }
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
preferenceOrGroupProto {
|
||||
preference = preferenceProto {
|
||||
key = "key2"
|
||||
title = textProto { string = "title2" }
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
val graphProto = PreferenceGraphProto.newBuilder().putScreens("screen", screen).build()
|
||||
|
||||
val fResult = transformCatalystGetMetadataResponse(context, graphProto)
|
||||
with(fResult) {
|
||||
assertThat(resultCode).isEqualTo(MetadataResult.RESULT_OK)
|
||||
assertThat(metadataList.size).isEqualTo(2)
|
||||
}
|
||||
assertThat(
|
||||
fResult.metadataList.any {
|
||||
it.key == "key1" &&
|
||||
it.screenKey == "screen" &&
|
||||
it.title == "title1" &&
|
||||
it.isEnabled == true
|
||||
}
|
||||
).isTrue()
|
||||
assertThat(
|
||||
fResult.metadataList.any {
|
||||
it.key == "key2" &&
|
||||
it.screenKey == "screen" &&
|
||||
it.title == "title2" &&
|
||||
it.isEnabled == false
|
||||
}
|
||||
).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transformFrameworkGetValueRequest_returnsValidCatalystRequest() {
|
||||
val fRequest = GetValueRequest.Builder("screen", "pref").build()
|
||||
|
Reference in New Issue
Block a user