[Catalyst] Migrate Airplane Mode preference
NO_IFTTT=Catalyst only
Bug: 375925972
Flag: com.android.settings.flags.catalyst_network_provider_and_internet_screen
Test: Manual testing
atest -c AirplaneModePreferenceTest \
NetworkDashboardFragmentTest
atest -c NetworkDashboardScreenTest
Change-Id: Ie63f2208a64cadf5faaa274fd4e069d839da850e
This commit is contained in:
@@ -16,34 +16,188 @@
|
||||
|
||||
package com.android.settings.network
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Looper
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings
|
||||
import android.telephony.PhoneStateListener
|
||||
import android.telephony.TelephonyManager
|
||||
import android.util.Log
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.AirplaneModeEnabler
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settingslib.RestrictedSwitchPreference
|
||||
import com.android.settingslib.datastore.AbstractKeyedDataObservable
|
||||
import com.android.settingslib.datastore.DataChangeReason
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.SettingsGlobalStore
|
||||
import com.android.settingslib.datastore.SettingsStore
|
||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||
import com.android.settingslib.metadata.PreferenceLifecycleContext
|
||||
import com.android.settingslib.metadata.PreferenceLifecycleProvider
|
||||
import com.android.settingslib.metadata.ReadWritePermit
|
||||
import com.android.settingslib.metadata.SensitivityLevel
|
||||
import com.android.settingslib.metadata.SwitchPreference
|
||||
import com.android.settingslib.preference.SwitchPreferenceBinding
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// LINT.IfChange
|
||||
class AirplaneModePreference :
|
||||
SwitchPreference(KEY, R.string.airplane_mode), PreferenceAvailabilityProvider {
|
||||
open class AirplaneModePreference :
|
||||
SwitchPreference(KEY, R.string.airplane_mode),
|
||||
SwitchPreferenceBinding,
|
||||
PreferenceAvailabilityProvider,
|
||||
PreferenceLifecycleProvider,
|
||||
PreferenceRestrictionMixin {
|
||||
|
||||
override val icon: Int
|
||||
@DrawableRes get() = R.drawable.ic_airplanemode_active
|
||||
|
||||
override fun storage(context: Context) = SettingsGlobalStore.get(context)
|
||||
|
||||
override val sensitivityLevel
|
||||
get() = SensitivityLevel.HIGH_SENSITIVITY
|
||||
|
||||
override fun isAvailable(context: Context) =
|
||||
(context.resources.getBoolean(R.bool.config_show_toggle_airplane) &&
|
||||
!context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
|
||||
|
||||
override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context)
|
||||
|
||||
override val restrictionKeys
|
||||
get() = arrayOf(UserManager.DISALLOW_AIRPLANE_MODE)
|
||||
|
||||
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
|
||||
ReadWritePermit.ALLOW
|
||||
|
||||
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
|
||||
when {
|
||||
isSatelliteOn(context) || isInEcmMode(context) -> ReadWritePermit.DISALLOW
|
||||
else -> ReadWritePermit.ALLOW
|
||||
}
|
||||
|
||||
override val sensitivityLevel
|
||||
get() = SensitivityLevel.HIGH_SENSITIVITY
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
AirplaneModeStorage(context, SettingsGlobalStore.get(context))
|
||||
|
||||
@Suppress("DEPRECATION", "MissingPermission", "UNCHECKED_CAST")
|
||||
private class AirplaneModeStorage(
|
||||
private val context: Context,
|
||||
private val settingsStore: SettingsStore,
|
||||
) : AbstractKeyedDataObservable<String>(), KeyValueStore {
|
||||
private var phoneStateListener: PhoneStateListener? = null
|
||||
|
||||
override fun contains(key: String) =
|
||||
settingsStore.contains(KEY) &&
|
||||
context.getSystemService(TelephonyManager::class.java) != null
|
||||
|
||||
override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) =
|
||||
DEFAULT_VALUE as T
|
||||
|
||||
override fun <T : Any> getValue(key: String, valueType: Class<T>): T =
|
||||
(settingsStore.getBoolean(key) ?: DEFAULT_VALUE) as T
|
||||
|
||||
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
|
||||
if (value is Boolean) {
|
||||
settingsStore.setBoolean(key, value)
|
||||
|
||||
val intent = Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED)
|
||||
intent.putExtra("state", value)
|
||||
context.sendBroadcastAsUser(intent, UserHandle.ALL)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFirstObserverAdded() {
|
||||
context.getSystemService(TelephonyManager::class.java)?.let {
|
||||
phoneStateListener =
|
||||
object : PhoneStateListener(Looper.getMainLooper()) {
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onRadioPowerStateChanged(state: Int) {
|
||||
Log.d(TAG, "onRadioPowerStateChanged(), state=$state")
|
||||
notifyChange(KEY, DataChangeReason.UPDATE)
|
||||
}
|
||||
}
|
||||
it.listen(phoneStateListener, PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLastObserverRemoved() {
|
||||
context
|
||||
.getSystemService(TelephonyManager::class.java)
|
||||
?.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(context: PreferenceLifecycleContext) {
|
||||
context.requirePreference<RestrictedSwitchPreference>(KEY).onPreferenceChangeListener =
|
||||
Preference.OnPreferenceChangeListener { _: Preference, _: Any ->
|
||||
if (isInEcmMode(context)) {
|
||||
showEcmDialog(context)
|
||||
return@OnPreferenceChangeListener false
|
||||
}
|
||||
if (isSatelliteOn(context)) {
|
||||
showSatelliteDialog(context)
|
||||
return@OnPreferenceChangeListener false
|
||||
}
|
||||
return@OnPreferenceChangeListener true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(
|
||||
context: PreferenceLifecycleContext,
|
||||
requestCode: Int,
|
||||
resultCode: Int,
|
||||
data: Intent?,
|
||||
): Boolean {
|
||||
if (requestCode == REQUEST_CODE_EXIT_ECM && resultCode == Activity.RESULT_OK) {
|
||||
storage(context).setValue(KEY, Boolean::class.javaObjectType, true)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isInEcmMode(context: Context) =
|
||||
AirplaneModeEnabler.isInEcmMode(
|
||||
context,
|
||||
context.getSystemService(TelephonyManager::class.java),
|
||||
)
|
||||
|
||||
private fun isSatelliteOn(context: Context): Boolean {
|
||||
try {
|
||||
return SatelliteRepository(context)
|
||||
.requestIsSessionStarted(Executors.newSingleThreadExecutor())
|
||||
.get(2000, TimeUnit.MILLISECONDS)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error to get satellite status : $e")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun showEcmDialog(context: PreferenceLifecycleContext) {
|
||||
val intent =
|
||||
Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null)
|
||||
.setPackage(Utils.PHONE_PACKAGE_NAME)
|
||||
context.startActivityForResult(intent, REQUEST_CODE_EXIT_ECM, null)
|
||||
}
|
||||
|
||||
private fun showSatelliteDialog(context: PreferenceLifecycleContext) {
|
||||
val intent =
|
||||
Intent(context, SatelliteWarningDialogActivity::class.java)
|
||||
.putExtra(
|
||||
SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG,
|
||||
SatelliteWarningDialogActivity.TYPE_IS_AIRPLANE_MODE,
|
||||
)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "AirplaneModePreference"
|
||||
const val KEY = Settings.Global.AIRPLANE_MODE_ON
|
||||
const val DEFAULT_VALUE = false
|
||||
const val REQUEST_CODE_EXIT_ECM = 1
|
||||
|
||||
fun Context.isAirplaneModeOn() = SettingsGlobalStore.get(this).getBoolean(KEY) == true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user