Refactor airplane mode preference controller.

- Convert inheritance from AbstractPreferenceController to
TogglePreferenceController.
- Register AirplaneModePreferenceController in XML.
- Decouple AirplaneModeEnabler with preference, leave the UI be
controled by PreferenceController.
- Add RoboTests test cases for AirplaneModePreferenceController.

Fixes: 67997339
Test: RunSettingsRoboTests
Change-Id: I7398943ed51345e014ee7aa774bfae1ca28632f1
diff --git a/src/com/android/settings/AirplaneModeEnabler.java b/src/com/android/settings/AirplaneModeEnabler.java
index 5f93589..11f1a28 100644
--- a/src/com/android/settings/AirplaneModeEnabler.java
+++ b/src/com/android/settings/AirplaneModeEnabler.java
@@ -24,8 +24,6 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.PhoneStateIntentReceiver;
@@ -33,16 +31,26 @@
 import com.android.settingslib.WirelessUtils;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
-public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListener {
+public class AirplaneModeEnabler {
 
     private static final int EVENT_SERVICE_STATE_CHANGED = 3;
 
     private final Context mContext;
-    private final SwitchPreference mSwitchPref;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
 
     private PhoneStateIntentReceiver mPhoneStateReceiver;
 
+    private OnAirplaneModeChangedListener mOnAirplaneModeChangedListener;
+
+    public interface OnAirplaneModeChangedListener {
+        /**
+         * Called when airplane mode status is changed.
+         *
+         * @param isAirplaneModeOn the airplane mode is on
+         */
+        void onAirplaneModeChanged(boolean isAirplaneModeOn);
+    }
+
     private Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -61,25 +69,19 @@
         }
     };
 
-    public AirplaneModeEnabler(Context context, SwitchPreference airplaneModeSwitchPreference,
-            MetricsFeatureProvider metricsFeatureProvider) {
+    public AirplaneModeEnabler(Context context, MetricsFeatureProvider metricsFeatureProvider,
+            OnAirplaneModeChangedListener listener) {
 
         mContext = context;
-        mSwitchPref = airplaneModeSwitchPreference;
         mMetricsFeatureProvider = metricsFeatureProvider;
-
-        airplaneModeSwitchPreference.setPersistent(false);
+        mOnAirplaneModeChangedListener = listener;
 
         mPhoneStateReceiver = new PhoneStateIntentReceiver(mContext, mHandler);
         mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
     }
 
     public void resume() {
-
-        mSwitchPref.setChecked(WirelessUtils.isAirplaneModeOn(mContext));
-
         mPhoneStateReceiver.registerIntent();
-        mSwitchPref.setOnPreferenceChangeListener(this);
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
                 mAirplaneModeObserver);
@@ -87,7 +89,6 @@
 
     public void pause() {
         mPhoneStateReceiver.unregisterIntent();
-        mSwitchPref.setOnPreferenceChangeListener(null);
         mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver);
     }
 
@@ -95,8 +96,11 @@
         // Change the system setting
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
                 enabling ? 1 : 0);
-        // Update the UI to reflect system setting
-        mSwitchPref.setChecked(enabling);
+
+        // Notify listener the system setting is changed.
+        if (mOnAirplaneModeChangedListener != null) {
+            mOnAirplaneModeChangedListener.onAirplaneModeChanged(enabling);
+        }
 
         // Post the intent
         Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
@@ -113,22 +117,20 @@
      * - mobile does not send failure notification, fail on timeout.
      */
     private void onAirplaneModeChanged() {
-        mSwitchPref.setChecked(WirelessUtils.isAirplaneModeOn(mContext));
+        if (mOnAirplaneModeChangedListener != null) {
+            mOnAirplaneModeChangedListener.onAirplaneModeChanged(isAirplaneModeOn());
+        }
     }
 
-    /**
-     * Called when someone clicks on the checkbox preference.
-     */
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
+    public void setAirplaneMode(boolean isAirplaneModeOn) {
         if (Boolean.parseBoolean(
                 SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
             // In ECM mode, do not update database at this point
         } else {
-            Boolean value = (Boolean) newValue;
-            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_AIRPLANE_TOGGLE, value);
-            setAirplaneModeOn(value);
+            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_AIRPLANE_TOGGLE,
+                    isAirplaneModeOn);
+            setAirplaneModeOn(isAirplaneModeOn);
         }
-        return true;
     }
 
     public void setAirplaneModeInECM(boolean isECMExit, boolean isAirplaneModeOn) {
@@ -141,4 +143,7 @@
         }
     }
 
+    public boolean isAirplaneModeOn() {
+        return WirelessUtils.isAirplaneModeOn(mContext);
+    }
 }
diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java
index 0b77179..b4851e6 100644
--- a/src/com/android/settings/network/AirplaneModePreferenceController.java
+++ b/src/com/android/settings/network/AirplaneModePreferenceController.java
@@ -27,17 +27,17 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.settings.AirplaneModeEnabler;
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.TogglePreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.R;
-import com.android.settingslib.core.AbstractPreferenceController;
 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;
 
-public class AirplaneModePreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
+public class AirplaneModePreferenceController extends TogglePreferenceController
+        implements LifecycleObserver, OnResume, OnPause,
+        AirplaneModeEnabler.OnAirplaneModeChangedListener {
 
     public static final int REQUEST_CODE_EXIT_ECM = 1;
 
@@ -45,18 +45,21 @@
 
     private static final String EXIT_ECM_RESULT = "exit_ecm_result";
 
-    private final Fragment mFragment;
+    private Fragment mFragment;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private AirplaneModeEnabler mAirplaneModeEnabler;
     private SwitchPreference mAirplaneModePreference;
 
 
-    public AirplaneModePreferenceController(Context context, Fragment hostFragment) {
-        super(context);
-        mFragment = hostFragment;
+    public AirplaneModePreferenceController(Context context, String key) {
+        super(context, key);
         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
+    public void setFragment(Fragment hostFragment) {
+        mFragment = hostFragment;
+    }
+
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
         if (KEY_TOGGLE_AIRPLANE.equals(preference.getKey()) && Boolean.parseBoolean(
@@ -75,30 +78,22 @@
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
         if (isAvailable()) {
             mAirplaneModePreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
-            if (mAirplaneModePreference != null) {
-                mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, mAirplaneModePreference,
-                        mMetricsFeatureProvider);
-            }
-        } else {
-            setVisible(screen, getPreferenceKey(), false /* visible */);
+            mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, mMetricsFeatureProvider, this);
         }
     }
 
-    @Override
-    public boolean isAvailable() {
-        return isAvailable(mContext);
-    }
-
     public static boolean isAvailable(Context context) {
         return context.getResources().getBoolean(R.bool.config_show_toggle_airplane)
                 && !context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_TOGGLE_AIRPLANE;
+    @AvailabilityStatus
+    public int getAvailabilityStatus() {
+        return isAvailable(mContext) ? AVAILABLE : DISABLED_UNSUPPORTED;
     }
 
     public void onResume() {
@@ -122,4 +117,23 @@
                     mAirplaneModePreference.isChecked());
         }
     }
+
+    @Override
+    public boolean isChecked() {
+        return mAirplaneModeEnabler.isAirplaneModeOn();
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        if (isChecked() == isChecked) {
+            return false;
+        }
+        mAirplaneModeEnabler.setAirplaneMode(isChecked);
+        return true;
+    }
+
+    @Override
+    public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
+        mAirplaneModePreference.setChecked(isAirplaneModeOn);
+    }
 }
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 955c503..466fa01 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -71,6 +71,8 @@
     public void onAttach(Context context) {
         super.onAttach(context);
         mNetworkResetController = new NetworkResetActionMenuController(context, MENU_NETWORK_RESET);
+
+        use(AirplaneModePreferenceController.class).setFragment(this);
     }
 
     @Override
@@ -94,8 +96,6 @@
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle, MetricsFeatureProvider metricsFeatureProvider, Fragment fragment,
             MobilePlanPreferenceHost mobilePlanHost) {
-        final AirplaneModePreferenceController airplaneModePreferenceController =
-                new AirplaneModePreferenceController(context, fragment);
         final MobilePlanPreferenceController mobilePlanPreferenceController =
                 new MobilePlanPreferenceController(context, mobilePlanHost);
         final WifiMasterSwitchPreferenceController wifiPreferenceController =
@@ -108,7 +108,6 @@
                 new PrivateDnsPreferenceController(context);
 
         if (lifecycle != null) {
-            lifecycle.addObserver(airplaneModePreferenceController);
             lifecycle.addObserver(mobilePlanPreferenceController);
             lifecycle.addObserver(wifiPreferenceController);
             lifecycle.addObserver(mobileNetworkPreferenceController);
@@ -117,7 +116,6 @@
         }
 
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(airplaneModePreferenceController);
         controllers.add(mobileNetworkPreferenceController);
         controllers.add(new TetherPreferenceController(context, lifecycle));
         controllers.add(vpnPreferenceController);