Merge "Do not turn on NFC automatically when airplane mode is off."
diff --git a/src/com/android/settings/nfc/AndroidBeamPreferenceController.java b/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
index 12ab1b7..f99c47c 100644
--- a/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
+++ b/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
@@ -17,7 +17,6 @@
import android.content.Context;
import android.nfc.NfcAdapter;
-import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
@@ -26,15 +25,12 @@
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
-import java.util.List;
-
public class AndroidBeamPreferenceController extends BasePreferenceController
implements LifecycleObserver, OnResume, OnPause {
public static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
private final NfcAdapter mNfcAdapter;
private AndroidBeamEnabler mAndroidBeamEnabler;
- private NfcAirplaneModeObserver mAirplaneModeObserver;
public AndroidBeamPreferenceController(Context context, String key) {
super(context, key);
@@ -52,12 +48,6 @@
final RestrictedPreference restrictedPreference =
(RestrictedPreference) screen.findPreference(getPreferenceKey());
mAndroidBeamEnabler = new AndroidBeamEnabler(mContext, restrictedPreference);
-
- // Manually set dependencies for NFC when not toggleable.
- if (!NfcPreferenceController.isToggleableInAirplaneMode(mContext)) {
- mAirplaneModeObserver = new NfcAirplaneModeObserver(mContext, mNfcAdapter,
- (Preference) restrictedPreference);
- }
}
@Override
@@ -70,9 +60,6 @@
@Override
public void onResume() {
- if (mAirplaneModeObserver != null) {
- mAirplaneModeObserver.register();
- }
if (mAndroidBeamEnabler != null) {
mAndroidBeamEnabler.resume();
}
@@ -80,9 +67,6 @@
@Override
public void onPause() {
- if (mAirplaneModeObserver != null) {
- mAirplaneModeObserver.unregister();
- }
if (mAndroidBeamEnabler != null) {
mAndroidBeamEnabler.pause();
}
diff --git a/src/com/android/settings/nfc/BaseNfcEnabler.java b/src/com/android/settings/nfc/BaseNfcEnabler.java
index 88bafb9..64c6d15 100644
--- a/src/com/android/settings/nfc/BaseNfcEnabler.java
+++ b/src/com/android/settings/nfc/BaseNfcEnabler.java
@@ -28,7 +28,7 @@
* preference. It will receive intent and update state to ensure preference show correct state.
*/
public abstract class BaseNfcEnabler {
- private final Context mContext;
+ protected final Context mContext;
protected final NfcAdapter mNfcAdapter;
private final IntentFilter mIntentFilter;
diff --git a/src/com/android/settings/nfc/NfcAirplaneModeObserver.java b/src/com/android/settings/nfc/NfcAirplaneModeObserver.java
index d0ce045..65ac655 100644
--- a/src/com/android/settings/nfc/NfcAirplaneModeObserver.java
+++ b/src/com/android/settings/nfc/NfcAirplaneModeObserver.java
@@ -70,12 +70,13 @@
}
mAirplaneMode = airplaneMode;
- boolean toggleable = mAirplaneMode != 1;
- if (toggleable) {
- mNfcAdapter.enable();
- } else {
+ if (mAirplaneMode == 1) {
+ // airplane mode is on, need to turn off NFC, and check if user can toggle it
mNfcAdapter.disable();
+ mPreference.setEnabled(NfcPreferenceController.isToggleableInAirplaneMode(mContext));
+ } else {
+ // airplane mode is off, no restriction
+ mPreference.setEnabled(true);
}
- mPreference.setEnabled(toggleable);
}
}
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 507a053..777e7d1 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -18,8 +18,10 @@
import android.content.Context;
import android.nfc.NfcAdapter;
-import androidx.preference.SwitchPreference;
+import android.provider.Settings;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.SwitchPreference;
/**
* NfcEnabler is a helper to manage the Nfc on/off checkbox preference. It turns on/off Nfc
@@ -38,7 +40,7 @@
switch (newState) {
case NfcAdapter.STATE_OFF:
mPreference.setChecked(false);
- mPreference.setEnabled(true);
+ mPreference.setEnabled(isToggleable());
break;
case NfcAdapter.STATE_ON:
mPreference.setChecked(true);
@@ -54,4 +56,15 @@
break;
}
}
+
+ @VisibleForTesting
+ boolean isToggleable() {
+ if (NfcPreferenceController.isToggleableInAirplaneMode(mContext)
+ || !NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)) {
+ return true;
+ }
+ final int airplaneMode = Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
+ return airplaneMode != 1;
+ }
}
diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java
index e1fa1b3..0f68a9c 100644
--- a/src/com/android/settings/nfc/NfcPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPreferenceController.java
@@ -20,7 +20,7 @@
import android.nfc.NfcAdapter;
import android.provider.Settings;
-import androidx.preference.Preference;
+import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
@@ -37,7 +37,8 @@
public static final String KEY_TOGGLE_NFC = "toggle_nfc";
private final NfcAdapter mNfcAdapter;
private NfcEnabler mNfcEnabler;
- private NfcAirplaneModeObserver mAirplaneModeObserver;
+ @VisibleForTesting
+ NfcAirplaneModeObserver mAirplaneModeObserver;
public NfcPreferenceController(Context context, String key) {
super(context, key);
@@ -57,10 +58,10 @@
mNfcEnabler = new NfcEnabler(mContext, switchPreference);
- // Manually set dependencies for NFC when not toggleable.
- if (!isToggleableInAirplaneMode(mContext)) {
- mAirplaneModeObserver = new NfcAirplaneModeObserver(mContext,
- mNfcAdapter, (Preference) switchPreference);
+ // Listen to airplane mode updates if NFC should be turned off when airplane mode is on
+ if (shouldTurnOffNFCInAirplaneMode(mContext) || isToggleableInAirplaneMode(mContext)) {
+ mAirplaneModeObserver =
+ new NfcAirplaneModeObserver(mContext, mNfcAdapter, switchPreference);
}
}
@@ -125,6 +126,12 @@
}
}
+ public static boolean shouldTurnOffNFCInAirplaneMode(Context context) {
+ final String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_RADIOS);
+ return airplaneModeRadios != null && airplaneModeRadios.contains(Settings.Global.RADIO_NFC);
+ }
+
public static boolean isToggleableInAirplaneMode(Context context) {
final String toggleable = Settings.Global.getString(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcAirplaneModeObserverTest.java b/tests/robotests/src/com/android/settings/nfc/NfcAirplaneModeObserverTest.java
index 5efa94a..c5e38a6 100644
--- a/tests/robotests/src/com/android/settings/nfc/NfcAirplaneModeObserverTest.java
+++ b/tests/robotests/src/com/android/settings/nfc/NfcAirplaneModeObserverTest.java
@@ -18,11 +18,12 @@
import static com.google.common.truth.Truth.assertThat;
+import android.content.ContentResolver;
import android.content.Context;
import android.nfc.NfcAdapter;
import android.provider.Settings;
-import androidx.preference.Preference;
+import android.provider.Settings.Global;
import androidx.preference.SwitchPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -52,8 +53,8 @@
mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
- mNfcAirplaneModeObserver = new NfcAirplaneModeObserver(mContext, mNfcAdapter,
- (Preference) mNfcPreference);
+ mNfcAirplaneModeObserver =
+ new NfcAirplaneModeObserver(mContext, mNfcAdapter, mNfcPreference);
}
@Test
@@ -67,20 +68,51 @@
NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
assertThat(mNfcAdapter.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void NfcAirplaneModeObserver_airplaneModeOnNfcToggleable_shouldEnablePreference() {
+ ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 0);
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
+
+ mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+
+ assertThat(mNfcPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void NfcAirplaneModeObserver_airplaneModeOnNfcNotToggleable_shouldDisablePreference() {
+ ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 0);
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Global.RADIO_WIFI);
+
+ mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+
assertThat(mNfcPreference.isEnabled()).isFalse();
}
@Test
- public void NfcAirplaneModeObserver_airplaneOff_shouldEnableNfc() {
- ReflectionHelpers.setField(mNfcAirplaneModeObserver,
- "mAirplaneMode", 1);
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0);
+ public void NfcAirplaneModeObserver_airplaneModeOff_shouldEnablePreference() {
+ ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 1);
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
- mNfcAirplaneModeObserver.onChange(false,
- NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+ mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
- assertThat(mNfcAdapter.isEnabled()).isTrue();
assertThat(mNfcPreference.isEnabled()).isTrue();
}
+
+ @Test
+ public void NfcAirplaneModeObserver_airplaneModeOff_shouldNotEnableNfcAutomatically() {
+ ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 1);
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
+
+ mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+
+ assertThat(mNfcAdapter.isEnabled()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java
new file mode 100644
index 0000000..a10c27a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.nfc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.nfc.NfcAdapter;
+import android.provider.Settings;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class NfcEnablerTest {
+
+ @Mock
+ private SwitchPreference mNfcPreference;
+
+ private Context mContext;
+ private NfcEnabler mNfcEnabler;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mNfcEnabler = spy(new NfcEnabler(mContext, mNfcPreference));
+ }
+
+ @Test
+ public void isToggleable_AirplaneModeOff_shouldReturnTrue() {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
+
+ assertThat(mNfcEnabler.isToggleable()).isTrue();
+ }
+
+ @Test
+ public void isToggleable_AirplaneModeOnNfcNotInAirplaneModeRadio_shouldReturnTrue() {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
+ Settings.Global.putString(contentResolver, Settings.Global.AIRPLANE_MODE_RADIOS, "");
+
+ assertThat(mNfcEnabler.isToggleable()).isTrue();
+ }
+
+ @Test
+ public void isToggleable_AirplaneModeOnNfcToggleable_shouldReturnTrue() {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
+
+ assertThat(mNfcEnabler.isToggleable()).isTrue();
+ }
+
+ @Test
+ public void isToggleable_AirplaneModeOnNfcNotToggleable_shouldReturnFalse() {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
+ Settings.Global.putString(contentResolver,
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, "");
+
+ assertThat(mNfcEnabler.isToggleable()).isFalse();
+ }
+
+ @Test
+ public void handleNfcStateChanged_stateOff_shouldCheckIfPreferenceEnableState() {
+ mNfcEnabler.handleNfcStateChanged(NfcAdapter.STATE_OFF);
+
+ verify(mNfcEnabler).isToggleable();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
index eaf6425..758f72c 100644
--- a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
@@ -75,15 +75,6 @@
mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
when(mScreen.findPreference(mNfcController.getPreferenceKey())).thenReturn(mNfcPreference);
-
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
- Settings.Global.RADIO_NFC);
-
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON,
- 0);
- mNfcController.displayPreference(mScreen);
}
@Test
@@ -102,6 +93,7 @@
@Test
public void isNfcEnable_nfcStateNotTurning_shouldReturnTrue() {
+ mNfcController.displayPreference(mScreen);
when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON);
mNfcController.onResume();
assertThat(mNfcPreference.isEnabled()).isTrue();
@@ -113,6 +105,7 @@
@Test
public void isNfcEnable_nfcStateTurning_shouldReturnFalse() {
+ mNfcController.displayPreference(mScreen);
when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON);
mNfcController.onResume();
assertThat(mNfcPreference.isEnabled()).isFalse();
@@ -124,6 +117,7 @@
@Test
public void isNfcChecked_nfcStateOn_shouldReturnTrue() {
+ mNfcController.displayPreference(mScreen);
when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON);
mNfcController.onResume();
assertThat(mNfcPreference.isChecked()).isTrue();
@@ -205,4 +199,52 @@
assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isFalse();
}
+
+ @Test
+ public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosContainsNfc_shouldReturnTrue() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
+
+ assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isTrue();
+ }
+
+ @Test
+ public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosWithoutNfc_shouldReturnFalse() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_RADIOS, "");
+
+ assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isFalse();
+ }
+
+ @Test
+ public void displayPreference_airplaneModeRadiosContainsNfc_shouldCreateAirplaneModeObserver() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
+
+ mNfcController.displayPreference(mScreen);
+
+ assertThat(mNfcController.mAirplaneModeObserver).isNotNull();
+ }
+
+ @Test
+ public void displayPreference_nfcToggleableInAirplaneMode_shouldCreateAirplaneModeObserver() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
+
+ mNfcController.displayPreference(mScreen);
+
+ assertThat(mNfcController.mAirplaneModeObserver).isNotNull();
+ }
+
+ @Test
+ public void displayPreference_nfcNotAffectByAirplaneMode_shouldNotCreateAirplaneModeObserver() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, "");
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_RADIOS, "");
+
+ mNfcController.displayPreference(mScreen);
+
+ assertThat(mNfcController.mAirplaneModeObserver).isNull();
+ }
}