Loading src/com/android/settings/Metrics.kt +1 −1 Original line number Diff line number Diff line Loading @@ -19,9 +19,9 @@ package com.android.settings import android.content.Context import com.android.settings.overlay.FeatureFactory import com.android.settingslib.core.instrumentation.MetricsFeatureProvider import com.android.settingslib.metadata.PreferenceUiActionMetricsLogger import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceScreenMetadata import com.android.settingslib.metadata.PreferenceUiActionMetricsLogger /** Provides metrics for preference action. */ interface PreferenceActionMetricsProvider { Loading src/com/android/settings/SettingsService.kt +4 −27 Original line number Diff line number Diff line Loading @@ -16,11 +16,9 @@ package com.android.settings import android.app.Application import android.content.Intent import com.android.settings.flags.Flags import com.android.settingslib.graph.PreferenceGetterRequest import com.android.settingslib.graph.PreferenceSetterRequest import com.android.settings.metrics.SettingsRemoteOpMetricsLogger import com.android.settingslib.ipc.ApiPermissionChecker import com.android.settingslib.service.PreferenceService Loading @@ -28,32 +26,11 @@ import com.android.settingslib.service.PreferenceService class SettingsService : PreferenceService( graphPermissionChecker = ApiPermissionChecker.alwaysAllow(), setterPermissionChecker = SetterPermissionChecker(), getterPermissionChecker = GetterPermissionChecker(), setterPermissionChecker = ApiPermissionChecker.alwaysAllow(), getterPermissionChecker = ApiPermissionChecker.alwaysAllow(), metricsLogger = SettingsRemoteOpMetricsLogger(), ) { override fun onBind(intent: Intent) = if (Flags.catalystService()) super.onBind(intent) else null } /** Permission checker for external setter API. */ private class SetterPermissionChecker : ApiPermissionChecker<PreferenceSetterRequest> { override fun hasPermission( application: Application, callingPid: Int, callingUid: Int, request: PreferenceSetterRequest, ) = true } /** Permission checker for external getter API. */ private class GetterPermissionChecker : ApiPermissionChecker<PreferenceGetterRequest> { override fun hasPermission( application: Application, callingPid: Int, callingUid: Int, request: PreferenceGetterRequest, ) = true } src/com/android/settings/metrics/SettingsRemoteOpMetricsLogger.kt 0 → 100644 +159 −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.metrics import android.app.settings.SettingsEnums import android.content.Context import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.core.instrumentation.SettingsStatsLog import com.android.settingslib.graph.PreferenceGetterErrorCode import com.android.settingslib.graph.PreferenceSetterResult import com.android.settingslib.metadata.PreferenceCoordinate import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceRemoteOpMetricsLogger import com.android.settingslib.metadata.PreferenceScreenMetadata /** Metrics logger for settings remote operations. */ class SettingsRemoteOpMetricsLogger : PreferenceRemoteOpMetricsLogger { override fun logGetterApi( context: Context, callingUid: Int, preferenceCoordinate: PreferenceCoordinate, screen: PreferenceScreenMetadata?, preference: PreferenceMetadata?, errorCode: Int, latencyMs: Long, ) = SettingsStatsLog.SETTINGS_EXT_API_REPORTED__TYPE__ACTION_READ.log( context, callingUid, preferenceCoordinate, preference, errorCode, latencyMs, Int::convertGetterErrorCode, ) override fun logSetterApi( context: Context, callingUid: Int, preferenceCoordinate: PreferenceCoordinate, screen: PreferenceScreenMetadata?, preference: PreferenceMetadata?, errorCode: Int, latencyMs: Long, ) = SettingsStatsLog.SETTINGS_EXT_API_REPORTED__TYPE__ACTION_WRITE.log( context, callingUid, preferenceCoordinate, preference, errorCode, latencyMs, Int::convertSetterErrorCode, ) private fun Int.log( context: Context, callingUid: Int, preferenceCoordinate: PreferenceCoordinate, preference: PreferenceMetadata?, errorCode: Int, latencyMs: Long, errorCodeToMetricsResult: (Int) -> Int, ) { if (preference is PreferenceActionMetricsProvider) { SettingsStatsLog.write( SettingsStatsLog.SETTINGS_EXTAPI_REPORTED, context.packageNameOfUid(callingUid), "", this, errorCodeToMetricsResult(errorCode), latencyMs, preference.preferenceActionMetrics, ) } else { SettingsStatsLog.write( SettingsStatsLog.SETTINGS_EXTAPI_REPORTED, context.packageNameOfUid(callingUid), preferenceCoordinate.settingsId, this, errorCodeToMetricsResult(errorCode), latencyMs, SettingsEnums.ACTION_UNKNOWN, ) } } override fun logGraphApi(context: Context, callingUid: Int, success: Boolean, latencyMs: Long) { val result = if (success) { SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_OK } else { SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INTERNAL_ERROR } SettingsStatsLog.write( SettingsStatsLog.SETTINGS_EXTAPI_REPORTED, context.packageNameOfUid(callingUid), "", SettingsStatsLog.SETTINGS_EXT_API_REPORTED__TYPE__ACTION_GET_METADATA, result, latencyMs, SettingsEnums.ACTION_UNKNOWN, ) } } private fun Context.packageNameOfUid(uid: Int) = packageManager.getNameForUid(uid) ?: "" private val PreferenceCoordinate.settingsId: String get() = "$screenKey/$key" private fun Int.convertGetterErrorCode() = when (this) { PreferenceGetterErrorCode.OK -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_OK PreferenceGetterErrorCode.NOT_FOUND -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_UNSUPPORTED PreferenceGetterErrorCode.DISALLOW -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_DISALLOW else -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INTERNAL_ERROR } private fun Int.convertSetterErrorCode() = when (this) { PreferenceSetterResult.OK -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_OK PreferenceSetterResult.UNSUPPORTED -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_UNSUPPORTED PreferenceSetterResult.DISABLED -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_DISABLED PreferenceSetterResult.RESTRICTED -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_RESTRICTED PreferenceSetterResult.UNAVAILABLE -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_UNAVAILABLE PreferenceSetterResult.REQUIRE_APP_PERMISSION -> SettingsStatsLog .SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_REQUIRE_APP_PERMISSION PreferenceSetterResult.REQUIRE_USER_AGREEMENT -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_REQUIRE_USER_CONSENT PreferenceSetterResult.DISALLOW -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_DISALLOW PreferenceSetterResult.INVALID_REQUEST -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INVALID_REQUEST else -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INTERNAL_ERROR } src/com/android/settings/service/PreferenceService.kt +15 −17 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.settings.service import android.app.Application import android.os.Binder import android.os.OutcomeReceiver import android.service.settings.preferences.GetValueRequest Loading @@ -26,6 +25,7 @@ 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.settings.metrics.SettingsRemoteOpMetricsLogger import com.android.settingslib.graph.GetPreferenceGraphApiHandler import com.android.settingslib.graph.GetPreferenceGraphRequest import com.android.settingslib.graph.PreferenceGetterApiHandler Loading @@ -41,9 +41,19 @@ class PreferenceService : SettingsPreferenceService() { 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) private val getApiHandler: PreferenceGetterApiHandler private val setApiHandler: PreferenceSetterApiHandler private val graphApi: GetPreferenceGraphApiHandler init { val metricsLogger = SettingsRemoteOpMetricsLogger() getApiHandler = PreferenceGetterApiHandler(1, ApiPermissionChecker.alwaysAllow(), metricsLogger) setApiHandler = PreferenceSetterApiHandler(2, ApiPermissionChecker.alwaysAllow(), metricsLogger) graphApi = GetPreferenceGraphApiHandler(3, ApiPermissionChecker.alwaysAllow(), metricsLogger) } override fun onGetAllPreferenceMetadata( request: MetadataRequest, Loading @@ -58,9 +68,7 @@ class PreferenceService : SettingsPreferenceService() { application, callingPid, callingUid, GetPreferenceGraphRequest( flags = PreferenceGetterFlags.METADATA, ), GetPreferenceGraphRequest(flags = PreferenceGetterFlags.METADATA), ) val result = transformCatalystGetMetadataResponse(this@PreferenceService, graphProto) callback.onResult(result) Loading Loading @@ -107,14 +115,4 @@ class PreferenceService : SettingsPreferenceService() { } } } // 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, callingPid: Int, callingUid: Int, request: GetPreferenceGraphRequest, ) = true } } Loading
src/com/android/settings/Metrics.kt +1 −1 Original line number Diff line number Diff line Loading @@ -19,9 +19,9 @@ package com.android.settings import android.content.Context import com.android.settings.overlay.FeatureFactory import com.android.settingslib.core.instrumentation.MetricsFeatureProvider import com.android.settingslib.metadata.PreferenceUiActionMetricsLogger import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceScreenMetadata import com.android.settingslib.metadata.PreferenceUiActionMetricsLogger /** Provides metrics for preference action. */ interface PreferenceActionMetricsProvider { Loading
src/com/android/settings/SettingsService.kt +4 −27 Original line number Diff line number Diff line Loading @@ -16,11 +16,9 @@ package com.android.settings import android.app.Application import android.content.Intent import com.android.settings.flags.Flags import com.android.settingslib.graph.PreferenceGetterRequest import com.android.settingslib.graph.PreferenceSetterRequest import com.android.settings.metrics.SettingsRemoteOpMetricsLogger import com.android.settingslib.ipc.ApiPermissionChecker import com.android.settingslib.service.PreferenceService Loading @@ -28,32 +26,11 @@ import com.android.settingslib.service.PreferenceService class SettingsService : PreferenceService( graphPermissionChecker = ApiPermissionChecker.alwaysAllow(), setterPermissionChecker = SetterPermissionChecker(), getterPermissionChecker = GetterPermissionChecker(), setterPermissionChecker = ApiPermissionChecker.alwaysAllow(), getterPermissionChecker = ApiPermissionChecker.alwaysAllow(), metricsLogger = SettingsRemoteOpMetricsLogger(), ) { override fun onBind(intent: Intent) = if (Flags.catalystService()) super.onBind(intent) else null } /** Permission checker for external setter API. */ private class SetterPermissionChecker : ApiPermissionChecker<PreferenceSetterRequest> { override fun hasPermission( application: Application, callingPid: Int, callingUid: Int, request: PreferenceSetterRequest, ) = true } /** Permission checker for external getter API. */ private class GetterPermissionChecker : ApiPermissionChecker<PreferenceGetterRequest> { override fun hasPermission( application: Application, callingPid: Int, callingUid: Int, request: PreferenceGetterRequest, ) = true }
src/com/android/settings/metrics/SettingsRemoteOpMetricsLogger.kt 0 → 100644 +159 −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.metrics import android.app.settings.SettingsEnums import android.content.Context import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.core.instrumentation.SettingsStatsLog import com.android.settingslib.graph.PreferenceGetterErrorCode import com.android.settingslib.graph.PreferenceSetterResult import com.android.settingslib.metadata.PreferenceCoordinate import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceRemoteOpMetricsLogger import com.android.settingslib.metadata.PreferenceScreenMetadata /** Metrics logger for settings remote operations. */ class SettingsRemoteOpMetricsLogger : PreferenceRemoteOpMetricsLogger { override fun logGetterApi( context: Context, callingUid: Int, preferenceCoordinate: PreferenceCoordinate, screen: PreferenceScreenMetadata?, preference: PreferenceMetadata?, errorCode: Int, latencyMs: Long, ) = SettingsStatsLog.SETTINGS_EXT_API_REPORTED__TYPE__ACTION_READ.log( context, callingUid, preferenceCoordinate, preference, errorCode, latencyMs, Int::convertGetterErrorCode, ) override fun logSetterApi( context: Context, callingUid: Int, preferenceCoordinate: PreferenceCoordinate, screen: PreferenceScreenMetadata?, preference: PreferenceMetadata?, errorCode: Int, latencyMs: Long, ) = SettingsStatsLog.SETTINGS_EXT_API_REPORTED__TYPE__ACTION_WRITE.log( context, callingUid, preferenceCoordinate, preference, errorCode, latencyMs, Int::convertSetterErrorCode, ) private fun Int.log( context: Context, callingUid: Int, preferenceCoordinate: PreferenceCoordinate, preference: PreferenceMetadata?, errorCode: Int, latencyMs: Long, errorCodeToMetricsResult: (Int) -> Int, ) { if (preference is PreferenceActionMetricsProvider) { SettingsStatsLog.write( SettingsStatsLog.SETTINGS_EXTAPI_REPORTED, context.packageNameOfUid(callingUid), "", this, errorCodeToMetricsResult(errorCode), latencyMs, preference.preferenceActionMetrics, ) } else { SettingsStatsLog.write( SettingsStatsLog.SETTINGS_EXTAPI_REPORTED, context.packageNameOfUid(callingUid), preferenceCoordinate.settingsId, this, errorCodeToMetricsResult(errorCode), latencyMs, SettingsEnums.ACTION_UNKNOWN, ) } } override fun logGraphApi(context: Context, callingUid: Int, success: Boolean, latencyMs: Long) { val result = if (success) { SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_OK } else { SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INTERNAL_ERROR } SettingsStatsLog.write( SettingsStatsLog.SETTINGS_EXTAPI_REPORTED, context.packageNameOfUid(callingUid), "", SettingsStatsLog.SETTINGS_EXT_API_REPORTED__TYPE__ACTION_GET_METADATA, result, latencyMs, SettingsEnums.ACTION_UNKNOWN, ) } } private fun Context.packageNameOfUid(uid: Int) = packageManager.getNameForUid(uid) ?: "" private val PreferenceCoordinate.settingsId: String get() = "$screenKey/$key" private fun Int.convertGetterErrorCode() = when (this) { PreferenceGetterErrorCode.OK -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_OK PreferenceGetterErrorCode.NOT_FOUND -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_UNSUPPORTED PreferenceGetterErrorCode.DISALLOW -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_DISALLOW else -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INTERNAL_ERROR } private fun Int.convertSetterErrorCode() = when (this) { PreferenceSetterResult.OK -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_OK PreferenceSetterResult.UNSUPPORTED -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_UNSUPPORTED PreferenceSetterResult.DISABLED -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_DISABLED PreferenceSetterResult.RESTRICTED -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_RESTRICTED PreferenceSetterResult.UNAVAILABLE -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_UNAVAILABLE PreferenceSetterResult.REQUIRE_APP_PERMISSION -> SettingsStatsLog .SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_REQUIRE_APP_PERMISSION PreferenceSetterResult.REQUIRE_USER_AGREEMENT -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_REQUIRE_USER_CONSENT PreferenceSetterResult.DISALLOW -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_DISALLOW PreferenceSetterResult.INVALID_REQUEST -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INVALID_REQUEST else -> SettingsStatsLog.SETTINGS_EXT_API_REPORTED__RESULT__RESULT_FAILURE_INTERNAL_ERROR }
src/com/android/settings/service/PreferenceService.kt +15 −17 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.settings.service import android.app.Application import android.os.Binder import android.os.OutcomeReceiver import android.service.settings.preferences.GetValueRequest Loading @@ -26,6 +25,7 @@ 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.settings.metrics.SettingsRemoteOpMetricsLogger import com.android.settingslib.graph.GetPreferenceGraphApiHandler import com.android.settingslib.graph.GetPreferenceGraphRequest import com.android.settingslib.graph.PreferenceGetterApiHandler Loading @@ -41,9 +41,19 @@ class PreferenceService : SettingsPreferenceService() { 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) private val getApiHandler: PreferenceGetterApiHandler private val setApiHandler: PreferenceSetterApiHandler private val graphApi: GetPreferenceGraphApiHandler init { val metricsLogger = SettingsRemoteOpMetricsLogger() getApiHandler = PreferenceGetterApiHandler(1, ApiPermissionChecker.alwaysAllow(), metricsLogger) setApiHandler = PreferenceSetterApiHandler(2, ApiPermissionChecker.alwaysAllow(), metricsLogger) graphApi = GetPreferenceGraphApiHandler(3, ApiPermissionChecker.alwaysAllow(), metricsLogger) } override fun onGetAllPreferenceMetadata( request: MetadataRequest, Loading @@ -58,9 +68,7 @@ class PreferenceService : SettingsPreferenceService() { application, callingPid, callingUid, GetPreferenceGraphRequest( flags = PreferenceGetterFlags.METADATA, ), GetPreferenceGraphRequest(flags = PreferenceGetterFlags.METADATA), ) val result = transformCatalystGetMetadataResponse(this@PreferenceService, graphProto) callback.onResult(result) Loading Loading @@ -107,14 +115,4 @@ class PreferenceService : SettingsPreferenceService() { } } } // 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, callingPid: Int, callingUid: Int, request: GetPreferenceGraphRequest, ) = true } }