1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.network 18 19 import android.app.Activity 20 import android.app.settings.SettingsEnums.ACTION_AIRPLANE_TOGGLE 21 import android.content.Context 22 import android.content.Intent 23 import android.content.pm.PackageManager 24 import android.os.UserHandle 25 import android.os.UserManager 26 import android.provider.Settings 27 import android.telephony.TelephonyManager 28 import androidx.annotation.DrawableRes 29 import androidx.preference.Preference 30 import com.android.settings.AirplaneModeEnabler 31 import com.android.settings.R 32 import com.android.settings.Utils 33 import com.android.settings.contract.KEY_AIRPLANE_MODE 34 import com.android.settings.metrics.PreferenceActionMetricsProvider 35 import com.android.settings.network.SatelliteRepository.Companion.isSatelliteOn 36 import com.android.settings.restriction.PreferenceRestrictionMixin 37 import com.android.settingslib.RestrictedSwitchPreference 38 import com.android.settingslib.datastore.KeyValueStore 39 import com.android.settingslib.datastore.KeyValueStoreDelegate 40 import com.android.settingslib.datastore.SettingsGlobalStore 41 import com.android.settingslib.metadata.PreferenceAvailabilityProvider 42 import com.android.settingslib.metadata.PreferenceLifecycleContext 43 import com.android.settingslib.metadata.PreferenceLifecycleProvider 44 import com.android.settingslib.metadata.ReadWritePermit 45 import com.android.settingslib.metadata.SensitivityLevel 46 import com.android.settingslib.metadata.SwitchPreference 47 48 // LINT.IfChange 49 class AirplaneModePreference : 50 SwitchPreference(KEY, R.string.airplane_mode), 51 PreferenceActionMetricsProvider, 52 PreferenceAvailabilityProvider, 53 PreferenceLifecycleProvider, 54 PreferenceRestrictionMixin { 55 56 override val icon: Int 57 @DrawableRes get() = R.drawable.ic_airplanemode_active 58 59 override fun tags(context: Context) = arrayOf(KEY_AIRPLANE_MODE) 60 61 override fun isAvailable(context: Context) = 62 (context.resources.getBoolean(R.bool.config_show_toggle_airplane) && 63 !context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) 64 65 override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context) 66 67 override val restrictionKeys 68 get() = arrayOf(UserManager.DISALLOW_AIRPLANE_MODE) 69 70 override fun getReadPermissions(context: Context) = SettingsGlobalStore.getReadPermissions() 71 72 override fun getWritePermissions(context: Context) = SettingsGlobalStore.getWritePermissions() 73 74 override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = 75 ReadWritePermit.ALLOW 76 77 override fun getWritePermit(context: Context, callingPid: Int, callingUid: Int) = 78 when { 79 isSatelliteOn(context) || isInEcmMode(context) -> ReadWritePermit.DISALLOW 80 else -> ReadWritePermit.ALLOW 81 } 82 83 override val sensitivityLevel 84 get() = SensitivityLevel.HIGH_SENSITIVITY 85 86 override val preferenceActionMetrics: Int 87 get() = ACTION_AIRPLANE_TOGGLE 88 89 override fun storage(context: Context): KeyValueStore = AirplaneModeStorage(context) 90 91 @Suppress("UNCHECKED_CAST") 92 private class AirplaneModeStorage( 93 private val context: Context, 94 private val settingsStore: KeyValueStore = SettingsGlobalStore.get(context), 95 ) : KeyValueStoreDelegate { 96 97 override val keyValueStoreDelegate 98 get() = settingsStore 99 100 override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) = 101 DEFAULT_VALUE as T 102 103 override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) { 104 settingsStore.setValue(key, valueType, value) 105 106 val intent = Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED) 107 intent.putExtra("state", getBoolean(KEY)!!) 108 context.sendBroadcastAsUser(intent, UserHandle.ALL) 109 } 110 } 111 112 override fun onCreate(context: PreferenceLifecycleContext) { 113 context.requirePreference<RestrictedSwitchPreference>(KEY).onPreferenceChangeListener = 114 Preference.OnPreferenceChangeListener { _: Preference, _: Any -> 115 if (isInEcmMode(context)) { 116 showEcmDialog(context) 117 return@OnPreferenceChangeListener false 118 } 119 if (isSatelliteOn(context)) { 120 showSatelliteDialog(context) 121 return@OnPreferenceChangeListener false 122 } 123 return@OnPreferenceChangeListener true 124 } 125 } 126 127 override fun onActivityResult( 128 context: PreferenceLifecycleContext, 129 requestCode: Int, 130 resultCode: Int, 131 data: Intent?, 132 ): Boolean { 133 if (requestCode == REQUEST_CODE_EXIT_ECM && resultCode == Activity.RESULT_OK) { 134 context.getKeyValueStore(KEY)?.setBoolean(KEY, true) 135 } 136 return true 137 } 138 139 private fun isInEcmMode(context: Context) = 140 AirplaneModeEnabler.isInEcmMode( 141 context, 142 context.getSystemService(TelephonyManager::class.java), 143 ) 144 145 private fun showEcmDialog(context: PreferenceLifecycleContext) { 146 val intent = 147 Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null) 148 .setPackage(Utils.PHONE_PACKAGE_NAME) 149 context.startActivityForResult(intent, REQUEST_CODE_EXIT_ECM, null) 150 } 151 152 private fun showSatelliteDialog(context: PreferenceLifecycleContext) { 153 val intent = 154 Intent(context, SatelliteWarningDialogActivity::class.java) 155 .putExtra( 156 SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, 157 SatelliteWarningDialogActivity.TYPE_IS_AIRPLANE_MODE, 158 ) 159 context.startActivity(intent) 160 } 161 162 companion object { 163 const val KEY = Settings.Global.AIRPLANE_MODE_ON 164 const val DEFAULT_VALUE = false 165 const val REQUEST_CODE_EXIT_ECM = 1 166 167 fun Context.isAirplaneModeOn() = AirplaneModeStorage(this).getBoolean(KEY) == true 168 } 169 } 170 // LINT.ThenChange(AirplaneModePreferenceController.java) 171