/* * 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.settings.network import android.Manifest import android.app.settings.SettingsEnums.ACTION_MOBILE_DATA import android.content.Context import android.telephony.SubscriptionManager import com.android.settings.R import com.android.settings.contract.KEY_MOBILE_DATA import com.android.settings.metrics.PreferenceActionMetricsProvider import com.android.settings.network.telephony.MobileDataRepository import com.android.settings.network.telephony.SubscriptionRepository import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.metadata.SwitchPreference import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking class MobileDataPreference : SwitchPreference( KEY, R.string.mobile_data_settings_title, R.string.mobile_data_settings_summary, ), PreferenceActionMetricsProvider, PreferenceAvailabilityProvider { override val preferenceActionMetrics: Int get() = ACTION_MOBILE_DATA override fun tags(context: Context) = arrayOf(KEY_MOBILE_DATA) override fun isAvailable(context: Context) = SubscriptionRepository(context).getSelectableSubscriptionInfoList().any { it.simSlotIndex > -1 } override fun storage(context: Context): KeyValueStore = MobileDataStorage(context) override fun getReadPermissions(context: Context) = Permissions.anyOf( // TelephonyManager.isDataEnabledForReason Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.READ_PHONE_STATE, Manifest.permission.MODIFY_PHONE_STATE, Manifest.permission.READ_BASIC_PHONE_STATE, ) override fun getWritePermissions(context: Context) = Permissions.allOf( // TelephonyManager.setDataEnabledForReason Manifest.permission.MODIFY_PHONE_STATE ) override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = ReadWritePermit.ALLOW override fun getWritePermit( context: Context, value: Boolean?, callingPid: Int, callingUid: Int, ) = ReadWritePermit.ALLOW override val sensitivityLevel get() = SensitivityLevel.LOW_SENSITIVITY @Suppress("UNCHECKED_CAST") private class MobileDataStorage(private val context: Context) : NoOpKeyedObservable(), KeyValueStore { override fun contains(key: String) = key == KEY override fun getValue(key: String, valueType: Class): T { val subId = SubscriptionManager.getDefaultDataSubscriptionId() val flow = MobileDataRepository(context).isMobileDataEnabledFlow(subId) return runBlocking { flow.first() } as T } override fun setValue(key: String, valueType: Class, value: T?) { val subId = SubscriptionManager.getDefaultDataSubscriptionId() MobileDataRepository(context).setMobileDataEnabled(subId, value as Boolean) } } companion object { const val KEY = "mobile_data" } }