diff --git a/src/com/android/settings/AirplaneModeEnabler.java b/src/com/android/settings/AirplaneModeEnabler.java index cdb9793ff54..c6ab58e1039 100644 --- a/src/com/android/settings/AirplaneModeEnabler.java +++ b/src/com/android/settings/AirplaneModeEnabler.java @@ -19,27 +19,35 @@ package com.android.settings; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; -import android.database.ContentObserver; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; import android.os.UserHandle; import android.provider.Settings; -import android.sysprop.TelephonyProperties; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.Log; -import com.android.internal.telephony.PhoneStateIntentReceiver; +import com.android.settings.network.GlobalSettingsChangeListener; +import com.android.settings.network.ProxySubscriptionManager; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.WirelessUtils; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -public class AirplaneModeEnabler { +import java.util.ArrayList; +import java.util.List; - private static final int EVENT_SERVICE_STATE_CHANGED = 3; +/** + * Monitor and update configuration of airplane mode settings + */ +public class AirplaneModeEnabler extends GlobalSettingsChangeListener { + + private static final String LOG_TAG = "AirplaneModeEnabler"; + private static final boolean DEBUG = false; private final Context mContext; private final MetricsFeatureProvider mMetricsFeatureProvider; - private PhoneStateIntentReceiver mPhoneStateReceiver; - private OnAirplaneModeChangedListener mOnAirplaneModeChangedListener; public interface OnAirplaneModeChangedListener { @@ -51,46 +59,64 @@ public class AirplaneModeEnabler { void onAirplaneModeChanged(boolean isAirplaneModeOn); } - private Handler mHandler = new Handler(Looper.getMainLooper()) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case EVENT_SERVICE_STATE_CHANGED: - onAirplaneModeChanged(); - break; - } - } - }; + private TelephonyManager mTelephonyManager; + private ProxySubscriptionManager mProxySubscriptionMgr; + private List mServiceStateListeners; - private ContentObserver mAirplaneModeObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange) { - onAirplaneModeChanged(); - } - }; + private GlobalSettingsChangeListener mAirplaneModeObserver; - public AirplaneModeEnabler(Context context, MetricsFeatureProvider metricsFeatureProvider, + public AirplaneModeEnabler(Context context, OnAirplaneModeChangedListener listener) { + super(context, Settings.Global.AIRPLANE_MODE_ON); mContext = context; - mMetricsFeatureProvider = metricsFeatureProvider; + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mOnAirplaneModeChangedListener = listener; - mPhoneStateReceiver = new PhoneStateIntentReceiver(mContext, mHandler); - mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED); + mTelephonyManager = context.getSystemService(TelephonyManager.class); + mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(context); + } + + /** + * Implementation of GlobalSettingsChangeListener.onChanged + */ + public void onChanged(String field) { + if (DEBUG) { + Log.d(LOG_TAG, "Airplane mode configuration update"); + } + onAirplaneModeChanged(); } public void resume() { - mPhoneStateReceiver.registerIntent(); - mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true, - mAirplaneModeObserver); + final List subInfoList = + mProxySubscriptionMgr.getActiveSubscriptionsInfo(); + + mServiceStateListeners = new ArrayList(); + + // add default listener + mServiceStateListeners.add(new ServiceStateListener(mTelephonyManager, + SubscriptionManager.INVALID_SUBSCRIPTION_ID, this)); + + if (subInfoList == null) { + for (SubscriptionInfo subInfo : subInfoList) { + mServiceStateListeners.add(new ServiceStateListener(mTelephonyManager, + subInfo.getSubscriptionId(), this)); + } + } + + for (ServiceStateListener ssListener : mServiceStateListeners) { + ssListener.start(); + } } public void pause() { - mPhoneStateReceiver.unregisterIntent(); - mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver); + if (mServiceStateListeners == null) { + return; + } + for (ServiceStateListener ssListener : mServiceStateListeners) { + ssListener.stop(); + } + mServiceStateListeners = null; } private void setAirplaneModeOn(boolean enabling) { @@ -104,7 +130,7 @@ public class AirplaneModeEnabler { } // Post the intent - Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", enabling); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } @@ -123,9 +149,36 @@ public class AirplaneModeEnabler { } } + /** + * Check the status of ECM mode + * + * @return any subscription within device is under ECM mode + */ + public boolean isInEcmMode() { + if (mTelephonyManager.getEmergencyCallbackMode()) { + return true; + } + final List subInfoList = + mProxySubscriptionMgr.getActiveSubscriptionsInfo(); + if (subInfoList == null) { + return false; + } + for (SubscriptionInfo subInfo : subInfoList) { + final TelephonyManager telephonyManager = + mTelephonyManager.createForSubscriptionId(subInfo.getSubscriptionId()); + if (telephonyManager != null) { + if (telephonyManager.getEmergencyCallbackMode()) { + return true; + } + } + } + return false; + } + public void setAirplaneMode(boolean isAirplaneModeOn) { - if (TelephonyProperties.in_ecm_mode().orElse(false)) { + if (isInEcmMode()) { // In ECM mode, do not update database at this point + Log.d(LOG_TAG, "ECM airplane mode=" + isAirplaneModeOn); } else { mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AIRPLANE_TOGGLE, isAirplaneModeOn); @@ -134,6 +187,7 @@ public class AirplaneModeEnabler { } public void setAirplaneModeInECM(boolean isECMExit, boolean isAirplaneModeOn) { + Log.d(LOG_TAG, "Exist ECM=" + isECMExit + ", with airplane mode=" + isAirplaneModeOn); if (isECMExit) { // update database based on the current checkbox state setAirplaneModeOn(isAirplaneModeOn); @@ -146,4 +200,51 @@ public class AirplaneModeEnabler { public boolean isAirplaneModeOn() { return WirelessUtils.isAirplaneModeOn(mContext); } + + private static class ServiceStateListener extends PhoneStateListener { + private ServiceStateListener(TelephonyManager telephonyManager, int subscriptionId, + AirplaneModeEnabler enabler) { + super(); + mSubId = subscriptionId; + mTelephonyManager = getSubIdSpecificTelephonyManager(telephonyManager); + mEnabler = enabler; + } + + private int mSubId; + private TelephonyManager mTelephonyManager; + private AirplaneModeEnabler mEnabler; + + int getSubscriptionId() { + return mSubId; + } + + void start() { + if (mTelephonyManager != null) { + mTelephonyManager.listen(this, PhoneStateListener.LISTEN_SERVICE_STATE); + } + } + + void stop() { + if (mTelephonyManager != null) { + mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); + } + } + + @Override + public void onServiceStateChanged(ServiceState serviceState) { + if (DEBUG) { + Log.d(LOG_TAG, "ServiceState in sub" + mSubId + ": " + serviceState); + } + mEnabler.onAirplaneModeChanged(); + } + + private TelephonyManager getSubIdSpecificTelephonyManager( + TelephonyManager telephonyManager) { + if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + return telephonyManager; + } + return telephonyManager.createForSubscriptionId(mSubId); + } + } + } diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java index 5313d3b8f53..1dc95884c3b 100644 --- a/src/com/android/settings/network/AirplaneModePreferenceController.java +++ b/src/com/android/settings/network/AirplaneModePreferenceController.java @@ -23,7 +23,6 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.provider.SettingsSlicesContract; -import android.sysprop.TelephonyProperties; import androidx.fragment.app.Fragment; import androidx.preference.Preference; @@ -34,8 +33,6 @@ import com.android.internal.telephony.TelephonyIntents; import com.android.settings.AirplaneModeEnabler; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; -import com.android.settings.overlay.FeatureFactory; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; @@ -58,14 +55,15 @@ public class AirplaneModePreferenceController extends TogglePreferenceController private static final String EXIT_ECM_RESULT = "exit_ecm_result"; private Fragment mFragment; - private final MetricsFeatureProvider mMetricsFeatureProvider; private AirplaneModeEnabler mAirplaneModeEnabler; private SwitchPreference mAirplaneModePreference; public AirplaneModePreferenceController(Context context, String key) { super(context, key); - mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); - mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, mMetricsFeatureProvider, this); + + if (isAvailable(mContext)) { + mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, this); + } } public void setFragment(Fragment hostFragment) { @@ -75,7 +73,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController @Override public boolean handlePreferenceTreeClick(Preference preference) { if (KEY_AIRPLANE_MODE.equals(preference.getKey()) - && TelephonyProperties.in_ecm_mode().orElse(false)) { + && mAirplaneModeEnabler.isInEcmMode()) { // In ECM mode launch ECM app dialog if (mFragment != null) { mFragment.startActivityForResult( @@ -96,9 +94,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - if (isAvailable()) { - mAirplaneModePreference = screen.findPreference(getPreferenceKey()); - } + mAirplaneModePreference = screen.findPreference(getPreferenceKey()); } public static boolean isAvailable(Context context) { @@ -133,7 +129,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_EXIT_ECM) { - Boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false); + final boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false); // Set Airplane mode based on the return value and checkbox state mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes, mAirplaneModePreference.isChecked());