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

Commit b1708588 authored by Faye Yan's avatar Faye Yan Committed by Android (Google) Code Review
Browse files

Merge "Revert "Add the second toggle for the egress data permission on voice activation"" into main

parents 245cb5f6 97e198b0
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -9623,10 +9623,6 @@
    <string name="permit_voice_activation_apps">Allow voice activation</string>
    <!-- Description for a setting which controls whether an app can be voice activated [CHAR LIMIT=NONE] -->
    <string name ="allow_voice_activation_apps_description">Voice activation turns-on approved apps, hands-free, using voice command. Built-in adaptive sensing ensures data stays private only to you.\n\n<a href="">More about protected adaptive sensing</a></string>
    <!-- Label for a setting which controls whether an app can receive sandboxed detection training data [CHAR LIMIT=NONE] -->
    <string name = "permit_receive_sandboxed_detection_training_data">Improve voice activation</string>
    <!-- Description for a setting which controls whether an app can receive sandboxed detection training data [CHAR LIMIT=NONE] -->
    <string name= "receive_sandboxed_detection_training_data_description">This device uses private intelligence to improve the voice activation model. Apps can receive summarized updates that are aggregated across many users to maintain privacy while improving the model for everyone.\n\n<a href="">More about private intelligence</a></string>
    <!-- Manage full screen intent permission title [CHAR LIMIT=40] -->
    <string name="full_screen_intent_title">Full screen notifications</string>
+0 −90
Original line number Diff line number Diff line
@@ -20,24 +20,12 @@ import android.Manifest
import android.app.AppOpsManager
import android.app.settings.SettingsEnums
import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import com.android.settings.R
import com.android.settings.overlay.FeatureFactory
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spaprivileged.model.app.AppOpsController
import com.android.settingslib.spaprivileged.model.app.PackageManagers.hasGrantPermission
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
import kotlinx.coroutines.Dispatchers

/**
 * This class builds an App List under voice activation apps and the individual page which
@@ -65,84 +53,6 @@ class VoiceActivationAppsListModel(context: Context) : AppOpPermissionListModel(
    override fun isChangeable(record: AppOpPermissionRecord): Boolean =
        super.isChangeable(record) && record.app.hasGrantPermission(permission)

    @Composable
    override fun InfoPageAdditionalContent(
        record: AppOpPermissionRecord,
        isAllowed: () -> Boolean?,
    ) {
        SwitchPreference(createReceiveDetectionTrainingDataOpSwitchModel(record, isAllowed))
    }

    @Composable
    private fun createReceiveDetectionTrainingDataOpSwitchModel(
        record: AppOpPermissionRecord,
        isReceiveSandBoxTriggerAudioOpAllowed: () -> Boolean?
    ): ReceiveDetectionTrainingDataOpSwitchModel {
        val context = LocalContext.current
        val ReceiveDetectionTrainingDataOpController = remember {
            AppOpsController(
                context = context,
                app = record.app,
                op = AppOpsManager.OP_RECEIVE_SANDBOXED_DETECTION_TRAINING_DATA,
            )
        }
        val isReceiveDetectionTrainingDataOpAllowed = isReceiveDetectionTrainingDataOpAllowed(record, ReceiveDetectionTrainingDataOpController)
        return remember(record) {
            ReceiveDetectionTrainingDataOpSwitchModel(
                context,
                record,
                isReceiveSandBoxTriggerAudioOpAllowed,
                ReceiveDetectionTrainingDataOpController,
                isReceiveDetectionTrainingDataOpAllowed,
            )
        }.also { model -> LaunchedEffect(model, Dispatchers.Default) { model.initState() } }
    }

    private inner class ReceiveDetectionTrainingDataOpSwitchModel(
        context: Context,
        private val record: AppOpPermissionRecord,
        isReceiveSandBoxTriggerAudioOpAllowed: () -> Boolean?,
        receiveDetectionTrainingDataOpController: AppOpsController,
        isReceiveDetectionTrainingDataOpAllowed: () -> Boolean?,
    ) : SwitchPreferenceModel {
        private var appChangeable by mutableStateOf(true)

        override val title: String = context.getString(R.string.permit_receive_sandboxed_detection_training_data)
        override val summary: () -> String = { context.getString(R.string.receive_sandboxed_detection_training_data_description) }
        override val checked = { isReceiveDetectionTrainingDataOpAllowed() == true && isReceiveSandBoxTriggerAudioOpAllowed() == true }
        override val changeable = { appChangeable && isReceiveSandBoxTriggerAudioOpAllowed() == true }

        fun initState() {
            appChangeable = isChangeable(record)
        }

        override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
            receiveDetectionTrainingDataOpController.setAllowed(newChecked)
        }
    }

    @Composable
    private fun isReceiveDetectionTrainingDataOpAllowed(
        record: AppOpPermissionRecord,
        controller: AppOpsController
    ): () -> Boolean? {
        if (record.hasRequestBroaderPermission) {
            // Broader permission trumps the specific permission.
            return { true }
        }

        val mode = controller.mode.observeAsState()
        return {
            when (mode.value) {
                null -> null
                AppOpsManager.MODE_ALLOWED -> true
                AppOpsManager.MODE_DEFAULT -> record.app.hasGrantPermission(
                    Manifest.permission.RECEIVE_SANDBOXED_DETECTION_TRAINING_DATA)
                else -> false
            }
        }
    }

    private fun logPermissionChange(newAllowed: Boolean) {
        val category = when {
            newAllowed -> SettingsEnums.APP_SPECIAL_PERMISSION_RECEIVE_SANDBOX_TRIGGER_AUDIO_ALLOW