android:title="@string/nfc_quick_toggle_title"
android:icon="@drawable/ic_nfc"
android:summary="@string/nfc_quick_toggle_summary"
+ settings:controller="com.android.settings.nfc.NfcPreferenceController"
android:order="-7"/>
<com.android.settingslib.RestrictedPreference
android:fragment="com.android.settings.nfc.AndroidBeam"
android:key="android_beam_settings"
android:title="@string/android_beam_settings_title"
+ settings:controller="com.android.settings.nfc.AndroidBeamPreferenceController"
android:icon="@drawable/ic_android"
android:order="-6"/>
*/
public static int getConnectedDevicesSummaryResourceId(Context context) {
final NfcPreferenceController nfcPreferenceController =
- new NfcPreferenceController(context);
+ new NfcPreferenceController(context, NfcPreferenceController.KEY_TOGGLE_NFC);
return getConnectedDevicesSummaryResourceId(nfcPreferenceController,
isDrivingModeAvailable(context));
import com.android.settings.bluetooth.BluetoothFilesPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.nfc.AndroidBeamPreferenceController;
-import com.android.settings.nfc.NfcPreferenceController;
import com.android.settings.print.PrintSettingPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- final AndroidBeamPreferenceController beamPreferenceController =
- new AndroidBeamPreferenceController(context);
- controllers.add(beamPreferenceController);
-
controllers.add(new BluetoothFilesPreferenceController(context));
controllers.add(new BluetoothOnWhileDrivingPreferenceController(context));
final PrintSettingPreferenceController printerController =
new PrintSettingPreferenceController(context);
- final NfcPreferenceController nfcPreferenceController =
- new NfcPreferenceController(context);
if (lifecycle != null) {
- lifecycle.addObserver(beamPreferenceController);
lifecycle.addObserver(printerController);
- lifecycle.addObserver(nfcPreferenceController);
}
-
- controllers.add(nfcPreferenceController);
controllers.add(printerController);
return controllers;
}
/**
+ * @return {@code true} if the setting update asynchronously.
+ * <p>
+ * For example, a Wifi controller would return true, because it needs to update the radio
+ * and wait for it to turn on.
+ */
+ public boolean hasAsyncUpdate() {
+ return false;
+ }
+
+ /**
* Updates non-indexable keys for search provider.
*
* Called by SearchIndexProvider#getNonIndexableKeys
import android.nfc.NfcAdapter;
import android.os.UserHandle;
import android.os.UserManager;
-import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settingslib.RestrictedLockUtils;
public AndroidBeamEnabler(Context context, RestrictedPreference preference) {
super(context);
-
mPreference = preference;
-
mBeamDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(context,
UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
-
if (!isNfcAvailable()) {
// NFC is not supported
mPreference.setEnabled(false);
return;
}
-
if (mBeamDisallowedBySystem) {
mPreference.setEnabled(false);
}
package com.android.settings.nfc;
import android.content.Context;
+import android.nfc.NfcAdapter;
+import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.RestrictedPreference;
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 AndroidBeamPreferenceController extends BaseNfcPreferenceController {
+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) {
- super(context);
+ public AndroidBeamPreferenceController(Context context, String key) {
+ super(context, key);
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (!isAvailable()) {
+ mAndroidBeamEnabler = null;
return;
}
- mNfcEnabler = new AndroidBeamEnabler(mContext, (RestrictedPreference) mPreference);
+ 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
- public String getPreferenceKey() {
- return KEY_ANDROID_BEAM_SETTINGS;
+ @AvailabilityStatus
+ public int getAvailabilityStatus() {
+ return mNfcAdapter != null
+ ? AVAILABLE
+ : UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public void onResume() {
+ if (mAirplaneModeObserver != null) {
+ mAirplaneModeObserver.register();
+ }
+ if (mAndroidBeamEnabler != null) {
+ mAndroidBeamEnabler.resume();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ if (mAirplaneModeObserver != null) {
+ mAirplaneModeObserver.unregister();
+ }
+ if (mAndroidBeamEnabler != null) {
+ mAndroidBeamEnabler.pause();
+ }
}
}
+++ /dev/null
-/*
- * 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 android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcManager;
-import android.os.Handler;
-import android.provider.Settings;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-
-import java.util.List;
-
-public abstract class BaseNfcPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
-
- protected BaseNfcEnabler mNfcEnabler;
- private NfcAdapter mNfcAdapter;
- private int mAirplaneMode;
- private AirplaneModeObserver mAirplaneModeObserver;
- protected Preference mPreference;
-
- public BaseNfcPreferenceController(Context context) {
- super(context);
- mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
-
- if (!isAvailable()) {
- mNfcEnabler = null;
- return;
- }
-
- mPreference = screen.findPreference(getPreferenceKey());
-
- // Manually set dependencies for NFC when not toggleable.
- if (!isToggleableInAirplaneMode(mContext)) {
- mAirplaneModeObserver = new AirplaneModeObserver();
- updateNfcPreference();
- }
- }
-
- @Override
- public void updateNonIndexableKeys(List<String> keys) {
- if (!isAvailable()) {
- keys.add(getPreferenceKey());
- }
- }
-
- @Override
- public boolean isAvailable() {
- return mNfcAdapter != null;
- }
-
- public abstract String getPreferenceKey();
-
- @Override
- public void onResume() {
- if (mAirplaneModeObserver != null) {
- mAirplaneModeObserver.register();
- }
- if (mNfcEnabler != null) {
- mNfcEnabler.resume();
- }
- }
-
- @Override
- public void onPause() {
- if (mAirplaneModeObserver != null) {
- mAirplaneModeObserver.unregister();
- }
- if (mNfcEnabler != null) {
- mNfcEnabler.pause();
- }
- }
-
- private void updateNfcPreference() {
- final int airplaneMode = Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, mAirplaneMode);
- if (airplaneMode == mAirplaneMode) {
- return;
- }
- mAirplaneMode = airplaneMode;
- boolean toggleable = mAirplaneMode != 1;
- if (toggleable) {
- mNfcAdapter.enable();
- } else {
- mNfcAdapter.disable();
- }
- mPreference.setEnabled(toggleable);
- }
-
- public static boolean isToggleableInAirplaneMode(Context context) {
- String toggleable = Settings.Global.getString(context.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
- return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC);
- }
-
- private final class AirplaneModeObserver extends ContentObserver {
- private final Uri AIRPLANE_MODE_URI =
- Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
-
- private AirplaneModeObserver() {
- super(new Handler());
- }
-
- public void register() {
- mContext.getContentResolver().registerContentObserver(AIRPLANE_MODE_URI, false, this);
- }
-
- public void unregister() {
- mContext.getContentResolver().unregisterContentObserver(this);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- super.onChange(selfChange, uri);
- updateNfcPreference();
- }
- }
-
-}
--- /dev/null
+/*
+ * 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 android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.nfc.NfcAdapter;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+
+/**
+ * NfcAirplaneModeObserver is a helper to manage the Nfc on/off when airplane mode status
+ * is changed.
+ */
+public class NfcAirplaneModeObserver extends ContentObserver {
+
+ private final Context mContext;
+ private final NfcAdapter mNfcAdapter;
+ private final Preference mPreference;
+ private int mAirplaneMode;
+
+ @VisibleForTesting
+ final static Uri AIRPLANE_MODE_URI =
+ Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+
+ public NfcAirplaneModeObserver(Context context, NfcAdapter nfcAdapter, Preference preference) {
+ super(new Handler(Looper.getMainLooper()));
+ mContext = context;
+ mNfcAdapter = nfcAdapter;
+ mPreference = preference;
+ updateNfcPreference();
+ }
+
+ public void register() {
+ mContext.getContentResolver().registerContentObserver(AIRPLANE_MODE_URI, false, this);
+ }
+
+ public void unregister() {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ updateNfcPreference();
+ }
+
+ private void updateNfcPreference() {
+ final int airplaneMode = Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, mAirplaneMode);
+ if (airplaneMode == mAirplaneMode) {
+ return;
+ }
+
+ mAirplaneMode = airplaneMode;
+ boolean toggleable = mAirplaneMode != 1;
+ if (toggleable) {
+ mNfcAdapter.enable();
+ } else {
+ mNfcAdapter.disable();
+ }
+ mPreference.setEnabled(toggleable);
+ }
+}
import android.content.Context;
import android.nfc.NfcAdapter;
-import android.support.v7.preference.Preference;
import android.support.v14.preference.SwitchPreference;
/**
* NfcEnabler is a helper to manage the Nfc on/off checkbox preference. It turns on/off Nfc
* and ensures the summary of the preference reflects the current state.
*/
-public class NfcEnabler extends BaseNfcEnabler implements Preference.OnPreferenceChangeListener {
+public class NfcEnabler extends BaseNfcEnabler {
private final SwitchPreference mPreference;
public NfcEnabler(Context context, SwitchPreference preference) {
super(context);
-
mPreference = preference;
}
- public void resume() {
- super.resume();
- if (isNfcAvailable()) {
- mPreference.setOnPreferenceChangeListener(this);
- }
- }
-
- public void pause() {
- super.pause();
- if (isNfcAvailable()) {
- mPreference.setOnPreferenceChangeListener(null);
- }
- }
-
- public boolean onPreferenceChange(Preference preference, Object value) {
- // Turn NFC on/off
-
- final boolean desiredState = (Boolean) value;
- mPreference.setChecked(desiredState);
- mPreference.setEnabled(false);
-
- if (desiredState) {
- mNfcAdapter.enable();
- } else {
- mNfcAdapter.disable();
- }
-
- return false;
- }
-
@Override
protected void handleNfcStateChanged(int newState) {
switch (newState) {
package com.android.settings.nfc;
import android.content.Context;
+import android.content.IntentFilter;
+import android.nfc.NfcAdapter;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.support.v14.preference.SwitchPreference;
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
+import java.util.List;
-public class NfcPreferenceController extends BaseNfcPreferenceController {
+public class NfcPreferenceController extends TogglePreferenceController
+ implements LifecycleObserver, OnResume, OnPause {
public static final String KEY_TOGGLE_NFC = "toggle_nfc";
+ private final NfcAdapter mNfcAdapter;
+ private NfcEnabler mNfcEnabler;
+ private NfcAirplaneModeObserver mAirplaneModeObserver;
- public NfcPreferenceController(Context context) {
- super(context);
+ public NfcPreferenceController(Context context, String key) {
+ super(context, key);
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (!isAvailable()) {
+ mNfcEnabler = null;
return;
}
- mNfcEnabler = new NfcEnabler(mContext, (SwitchPreference) mPreference);
+ final SwitchPreference switchPreference =
+ (SwitchPreference) screen.findPreference(getPreferenceKey());
+
+ mNfcEnabler = new NfcEnabler(mContext, switchPreference);
+
+ // Manually set dependencies for NFC when not toggleable.
+ if (!isToggleableInAirplaneMode(mContext)) {
+ mAirplaneModeObserver = new NfcAirplaneModeObserver(mContext,
+ mNfcAdapter, (Preference) switchPreference);
+ }
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mNfcAdapter.isEnabled();
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (isChecked) {
+ mNfcAdapter.enable();
+ } else {
+ mNfcAdapter.disable();
+ }
+ return true;
+ }
+
+ @Override
+ @AvailabilityStatus
+ public int getAvailabilityStatus() {
+ return mNfcAdapter != null
+ ? AVAILABLE
+ : UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public IntentFilter getIntentFilter() {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+ filter.addAction(NfcAdapter.EXTRA_ADAPTER_STATE);
+ return filter;
+ }
+
+ @Override
+ public boolean hasAsyncUpdate() {
+ return true;
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return TextUtils.equals(getPreferenceKey(), KEY_TOGGLE_NFC);
+ }
+
+ @Override
+ public void onResume() {
+ if (mAirplaneModeObserver != null) {
+ mAirplaneModeObserver.register();
+ }
+ if (mNfcEnabler != null) {
+ mNfcEnabler.resume();
+ }
}
@Override
- public String getPreferenceKey() {
- return KEY_TOGGLE_NFC;
+ public void onPause() {
+ if (mAirplaneModeObserver != null) {
+ mAirplaneModeObserver.unregister();
+ }
+ if (mNfcEnabler != null) {
+ mNfcEnabler.pause();
+ }
+ }
+
+ public static boolean isToggleableInAirplaneMode(Context context) {
+ final String toggleable = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+ return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC);
}
}
if (!controller.isAvailable()) {
Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
- updateUri(context, key, isPlatformSlice);
+ if (!controller.hasAsyncUpdate()) {
+ updateUri(context, key, isPlatformSlice);
+ }
return;
}
final TogglePreferenceController toggleController = (TogglePreferenceController) controller;
toggleController.setChecked(isChecked);
logSliceValueChange(context, key, isChecked ? 1 : 0);
- updateUri(context, key, isPlatformSlice);
+ if (!controller.hasAsyncUpdate()) {
+ updateUri(context, key, isPlatformSlice);
+ }
}
private void handleSliderAction(Context context, String key, int newPosition,
mContext = spy(RuntimeEnvironment.application);
mContentResolver = mContext.getContentResolver();
- mNfcController = new NfcPreferenceController(mContext);
+ mNfcController = new NfcPreferenceController(mContext,
+ NfcPreferenceController.KEY_TOGGLE_NFC);
mShadowNfcAdapter = shadowOf(ShadowNfcAdapter.getNfcAdapter(mContext));
}
}
@Test
+ public void hasAsyncUpdate_shouldReturnFalse() {
+ assertThat(mPreferenceController.hasAsyncUpdate()).isFalse();
+ }
+
+ @Test
public void settingAvailable_disabledOnDisplayPreference_preferenceEnabled() {
final PreferenceScreen screen = mock(PreferenceScreen.class);
final Preference preference = new Preference(mContext);
UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(false);
when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter);
- mAndroidBeamController = new AndroidBeamPreferenceController(mContext);
+ mAndroidBeamController = new AndroidBeamPreferenceController(mContext,
+ AndroidBeamPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
mAndroidBeamPreference = new RestrictedPreference(RuntimeEnvironment.application);
when(mScreen.findPreference(mAndroidBeamController.getPreferenceKey())).thenReturn(
mAndroidBeamPreference);
--- /dev/null
+/*
+ * 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 android.content.Context;
+import android.nfc.NfcAdapter;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v14.preference.SwitchPreference;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowNfcAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowNfcAdapter.class})
+public class NfcAirplaneModeObserverTest {
+
+ Context mContext;
+ private NfcAdapter mNfcAdapter;
+ private SwitchPreference mNfcPreference;
+ private NfcAirplaneModeObserver mNfcAirplaneModeObserver;
+
+ @Before
+ public void setUp() {
+ mContext = ShadowApplication.getInstance().getApplicationContext();
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
+
+ mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
+
+ mNfcAirplaneModeObserver = new NfcAirplaneModeObserver(mContext, mNfcAdapter,
+ (Preference) mNfcPreference);
+ }
+
+ @Test
+ public void NfcAirplaneModeObserver_airplaneOn_shouldDisableNfc() {
+ ReflectionHelpers.setField(mNfcAirplaneModeObserver,
+ "mAirplaneMode", 0);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 1);
+
+ mNfcAirplaneModeObserver.onChange(false,
+ NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+
+ assertThat(mNfcAdapter.isEnabled()).isFalse();
+ 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);
+
+ mNfcAirplaneModeObserver.onChange(false,
+ NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+
+ assertThat(mNfcAdapter.isEnabled()).isTrue();
+ assertThat(mNfcPreference.isEnabled()).isTrue();
+ }
+}
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.nfc.NfcManager;
import android.os.UserManager;
import android.provider.Settings;
-import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
+import android.support.v14.preference.SwitchPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager);
when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter);
- mNfcController = new NfcPreferenceController(mContext);
+ mNfcController = new NfcPreferenceController(mContext,
+ NfcPreferenceController.KEY_TOGGLE_NFC);
mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
+
when(mScreen.findPreference(mNfcController.getPreferenceKey())).thenReturn(mNfcPreference);
Settings.Global.putString(mContext.getContentResolver(),
}
@Test
- public void isAvailable_hasNfc_shouldReturnTrue() {
+ public void getAvailabilityStatus_hasNfc_shouldReturnAvailable() {
when(mNfcAdapter.isEnabled()).thenReturn(true);
- assertThat(mNfcController.isAvailable()).isTrue();
+ assertThat(mNfcController.getAvailabilityStatus())
+ .isEqualTo(NfcPreferenceController.AVAILABLE);
}
@Test
- public void isAvailable_noNfcAdapter_shouldReturnFalse() {
+ public void getAvailabilityStatus_noNfcAdapter_shouldReturnDisabledUnsupported() {
ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null);
- assertThat(mNfcController.isAvailable()).isFalse();
+ assertThat(mNfcController.getAvailabilityStatus())
+ .isEqualTo(NfcPreferenceController.UNSUPPORTED_ON_DEVICE);
}
@Test
assertThat(keys).hasSize(1);
}
+ @Test
+ public void setChecked_True_nfcShouldEnable() {
+ mNfcController.setChecked(true);
+ mNfcController.onResume();
+
+ verify(mNfcAdapter).enable();
+ }
+
+ @Test
+ public void setChecked_False_nfcShouldDisable() {
+ mNfcController.setChecked(false);
+ mNfcController.onResume();
+
+ verify(mNfcAdapter).disable();
+ }
+
+ @Test
+ public void hasAsyncUpdate_shouldReturnTrue() {
+ assertThat(mNfcController.hasAsyncUpdate()).isTrue();
+ }
+
+ @Test
+ public void isToggleableInAirplaneMode_containNfc_shouldReturnTrue() {
+ 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, 1);
+
+ assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isTrue();
+ }
+
+ @Test
+ public void isToggleableInAirplaneMode_withoutNfc_shouldReturnFalse() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
+ "null");
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 1);
+
+ assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isFalse();
+ }
}
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
}
@Test
+ public void toggleUpdate_synchronously_notifyChange_should_be_called() {
+ // Monitor the ContentResolver
+ final ContentResolver resolver = spy(mContext.getContentResolver());
+ doReturn(resolver).when(mContext).getContentResolver();
+
+ final String key = "key";
+ mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+ insertSpecialCase(key);
+
+ FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
+ fakeToggleController.setChecked(true);
+ // Set the toggle setting update synchronously.
+ fakeToggleController.setAsyncUpdate(false);
+ Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
+ intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+ assertThat(fakeToggleController.isChecked()).isTrue();
+
+ // Toggle setting
+ mReceiver.onReceive(mContext, intent);
+
+ assertThat(fakeToggleController.isChecked()).isFalse();
+
+ final Uri expectedUri = SliceBuilderUtils.getUri(
+ SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+ verify(resolver).notifyChange(eq(expectedUri), eq(null));
+ }
+
+ @Test
+ public void toggleUpdate_asynchronously_notifyChange_should_not_be_called() {
+ // Monitor the ContentResolver
+ final ContentResolver resolver = spy(mContext.getContentResolver());
+ doReturn(resolver).when(mContext).getContentResolver();
+
+ final String key = "key";
+ mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+ insertSpecialCase(key);
+
+ FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
+ fakeToggleController.setChecked(true);
+ // Set the toggle setting update asynchronously.
+ fakeToggleController.setAsyncUpdate(true);
+ Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
+ intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+ assertThat(fakeToggleController.isChecked()).isTrue();
+
+ // Toggle setting
+ mReceiver.onReceive(mContext, intent);
+
+ verify(resolver, never()).notifyChange(null, null);
+ }
+
+ @Test
public void onReceive_sliderChanged() {
final String key = "key";
final int position = FakeSliderController.MAX_STEPS - 1;
private final int ON = 1;
private final int OFF = 0;
+ private boolean mIsAsyncUpdate = false;
+
public FakeToggleController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
public boolean isSliceable() {
return true;
}
+
+ @Override
+ public boolean hasAsyncUpdate() {
+ return mIsAsyncUpdate;
+ }
+
+ public void setAsyncUpdate(boolean isAsyncUpdate) {
+ mIsAsyncUpdate = isAsyncUpdate;
+ }
}
@Implements(NfcAdapter.class)
public class ShadowNfcAdapter {
private static boolean sReaderModeEnabled;
+ private boolean mIsNfcEnabled = false;
@Implementation
public void enableReaderMode(Activity activity, NfcAdapter.ReaderCallback callback, int flags,
NfcAdapter.class, ClassParameter.from(Context.class, context));
}
+ @Implementation
+ public boolean isEnabled() {
+ return mIsNfcEnabled;
+ }
+
+ @Implementation
+ public boolean enable() {
+ mIsNfcEnabled = true;
+ return true;
+ }
+
+ @Implementation
+ public boolean disable() {
+ mIsNfcEnabled = false;
+ return true;
+ }
+
public static boolean isReaderModeEnabled() {
return sReaderModeEnabled;
}