diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java index f23118a3fa9..19a22ba990f 100644 --- a/src/com/android/settings/network/TetherPreferenceController.java +++ b/src/com/android/settings/network/TetherPreferenceController.java @@ -19,8 +19,12 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; import android.content.Context; +import android.database.ContentObserver; import android.net.ConnectivityManager; +import android.net.Uri; +import android.os.Handler; import android.os.UserHandle; +import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; @@ -31,6 +35,8 @@ import com.android.settings.core.PreferenceController; import com.android.settings.core.lifecycle.Lifecycle; import com.android.settings.core.lifecycle.LifecycleObserver; import com.android.settings.core.lifecycle.events.OnDestroy; +import com.android.settings.core.lifecycle.events.OnPause; +import com.android.settings.core.lifecycle.events.OnResume; import java.util.concurrent.atomic.AtomicReference; @@ -39,7 +45,7 @@ import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnfo import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction; public class TetherPreferenceController extends PreferenceController - implements LifecycleObserver, OnDestroy { + implements LifecycleObserver, OnResume, OnPause, OnDestroy { private static final String KEY_TETHER_SETTINGS = "tether_settings"; @@ -47,7 +53,6 @@ public class TetherPreferenceController extends PreferenceController private final AtomicReference mBluetoothPan; private final ConnectivityManager mConnectivityManager; private final BluetoothAdapter mBluetoothAdapter; - private final BluetoothProfile.ServiceListener mBtProfileServiceListener = new android.bluetooth.BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { @@ -60,6 +65,7 @@ public class TetherPreferenceController extends PreferenceController } }; + private SettingObserver mAirplaneModeObserver; private Preference mPreference; @VisibleForTesting(otherwise = VisibleForTesting.NONE) @@ -120,6 +126,22 @@ public class TetherPreferenceController extends PreferenceController return KEY_TETHER_SETTINGS; } + @Override + public void onResume() { + if (mAirplaneModeObserver == null) { + mAirplaneModeObserver = new SettingObserver(); + } + mContext.getContentResolver() + .registerContentObserver(mAirplaneModeObserver.uri, false, mAirplaneModeObserver); + } + + @Override + public void onPause() { + if (mAirplaneModeObserver != null) { + mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver); + } + } + @Override public void onDestroy() { final BluetoothProfile profile = mBluetoothPan.getAndSet(null); @@ -128,7 +150,7 @@ public class TetherPreferenceController extends PreferenceController } } - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + @VisibleForTesting void updateSummary() { if (mPreference == null) { // Preference is not ready yet. @@ -183,4 +205,37 @@ public class TetherPreferenceController extends PreferenceController mPreference.setSummary(R.string.tether_settings_summary_hotspot_off_tether_on); } } + + private void updateSummaryToOff() { + if (mPreference == null) { + // Preference is not ready yet. + return; + } + mPreference.setSummary(R.string.switch_off_text); + } + + class SettingObserver extends ContentObserver { + + public final Uri uri; + + public SettingObserver() { + super(new Handler()); + uri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + if (this.uri.equals(uri)) { + boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) != 0; + if (isAirplaneMode) { + // Airplane mode is on. Update summary to say tether is OFF directly. We cannot + // go through updateSummary() because turning off tether takes time, and we + // might still get "ON" status when rerun updateSummary(). So, just say it's off + updateSummaryToOff(); + } + } + } + } } diff --git a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java index 6f751eb87a2..7e92bc5e72c 100644 --- a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java @@ -21,7 +21,9 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; import android.content.Context; +import android.database.ContentObserver; import android.net.ConnectivityManager; +import android.provider.Settings; import android.support.v7.preference.Preference; import com.android.settings.R; @@ -33,6 +35,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; @@ -42,6 +45,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @@ -66,6 +70,7 @@ public class TetherPreferenceControllerTest { ReflectionHelpers.setField(mController, "mContext", mContext); ReflectionHelpers.setField(mController, "mConnectivityManager", mConnectivityManager); ReflectionHelpers.setField(mController, "mBluetoothAdapter", mBluetoothAdapter); + ReflectionHelpers.setField(mController, "mPreference", mPreference); } @Test @@ -82,13 +87,13 @@ public class TetherPreferenceControllerTest { @Test public void updateSummary_noPreference_noInteractionWithConnectivityManager() { + ReflectionHelpers.setField(mController, "mPreference", null); mController.updateSummary(); verifyNoMoreInteractions(mConnectivityManager); } @Test public void updateSummary_wifiTethered_shouldShowHotspotMessage() { - ReflectionHelpers.setField(mController, "mPreference", mPreference); when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"}); when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"123"}); @@ -98,7 +103,6 @@ public class TetherPreferenceControllerTest { @Test public void updateSummary_btThetherOn_shouldShowTetherMessage() { - ReflectionHelpers.setField(mController, "mPreference", mPreference); when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"}); when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"}); @@ -108,7 +112,6 @@ public class TetherPreferenceControllerTest { @Test public void updateSummary_tetherOff_shouldShowTetherOffMessage() { - ReflectionHelpers.setField(mController, "mPreference", mPreference); when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"}); when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"}); @@ -118,7 +121,6 @@ public class TetherPreferenceControllerTest { @Test public void updateSummary_wifiBtTetherOn_shouldShowHotspotAndTetherMessage() { - ReflectionHelpers.setField(mController, "mPreference", mPreference); when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123", "456"}); when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"}); when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"23"}); @@ -127,4 +129,25 @@ public class TetherPreferenceControllerTest { verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_on_tether_on); } + @Test + public void airplaneModeOn_shouldUpdateSummaryToOff() { + ReflectionHelpers.setField(mController, "mContext", RuntimeEnvironment.application); + + Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0); + + mController.onResume(); + + verifyZeroInteractions(mPreference); + + Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 1); + + final ContentObserver observer = ReflectionHelpers.getField(mController, + "mAirplaneModeObserver"); + observer.onChange(true, Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON)); + + verify(mPreference).setSummary(R.string.switch_off_text); + } + }