diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml
index 9b84a434d8e..66f95581b5b 100644
--- a/res/xml/connected_devices.xml
+++ b/res/xml/connected_devices.xml
@@ -38,9 +38,24 @@
settings:userRestriction="no_config_bluetooth"
settings:useAdminDisabledSummary="true"/>
+
+
+
+
+ android:title="@string/connected_device_connections_title"/>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 72cd2379bfa..1917df1ae92 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -20,23 +20,6 @@
android:key="connected_devices_advanced_screen"
android:title="@string/connected_device_connections_title">
-
-
-
-
+ android:title="@string/bluetooth_show_received_files"/>
buildControllers(Context context,
Lifecycle lifecycle) {
final List controllers = new ArrayList<>();
- final NfcPreferenceController nfcPreferenceController =
- new NfcPreferenceController(context);
- controllers.add(nfcPreferenceController);
- final BluetoothSwitchPreferenceController bluetoothPreferenceController =
- new BluetoothSwitchPreferenceController(context);
- controllers.add(bluetoothPreferenceController);
+
+ 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);
if (lifecycle != null) {
+ lifecycle.addObserver(beamPreferenceController);
lifecycle.addObserver(printerController);
- lifecycle.addObserver(nfcPreferenceController);
- lifecycle.addObserver(bluetoothPreferenceController);
}
controllers.add(printerController);
@@ -109,10 +105,8 @@ public class AdvancedConnectedDeviceDashboardFragment extends DashboardFragment
final List keys = super.getNonIndexableKeys(context);
PackageManager pm = context.getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
- keys.add(NfcPreferenceController.KEY_TOGGLE_NFC);
- keys.add(NfcPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
+ keys.add(AndroidBeamPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
}
- keys.add(BluetoothMasterSwitchPreferenceController.KEY_TOGGLE_BLUETOOTH);
return keys;
}
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index 4218219533e..ec0671614e2 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -17,11 +17,14 @@ package com.android.settings.connecteddevice;
import android.app.Activity;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settings.bluetooth.BluetoothSwitchPreferenceController;
+import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.nfc.NfcPreferenceController;
@@ -73,6 +76,19 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
controllers.add(new ConnectedDeviceGroupController(context, dashboardFragment, lifecycle));
controllers.add(new SavedDeviceGroupController(context, dashboardFragment, lifecycle));
+ final NfcPreferenceController nfcPreferenceController =
+ new NfcPreferenceController(context);
+ controllers.add(nfcPreferenceController);
+
+ final BluetoothSwitchPreferenceController bluetoothPreferenceController =
+ new BluetoothSwitchPreferenceController(context);
+ controllers.add(bluetoothPreferenceController);
+
+ if (lifecycle != null) {
+ lifecycle.addObserver(nfcPreferenceController);
+ lifecycle.addObserver(bluetoothPreferenceController);
+ }
+
return controllers;
}
diff --git a/src/com/android/settings/nfc/AndroidBeamEnabler.java b/src/com/android/settings/nfc/AndroidBeamEnabler.java
new file mode 100644
index 00000000000..66e42b64188
--- /dev/null
+++ b/src/com/android/settings/nfc/AndroidBeamEnabler.java
@@ -0,0 +1,84 @@
+/*
+ * 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.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;
+import com.android.settingslib.RestrictedPreference;
+
+/**
+ * AndroidBeanEnabler is a helper to manage the Android Beam preference. It turns on/off
+ * Android Beam and ensures the summary of the preference reflects the current state.
+ */
+public class AndroidBeamEnabler extends BaseNfcEnabler {
+ private final boolean mBeamDisallowedBySystem;
+ private final RestrictedPreference mPreference;
+
+ 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);
+ }
+ }
+
+ @Override
+ protected void handleNfcStateChanged(int newState) {
+ switch (newState) {
+ case NfcAdapter.STATE_OFF:
+ mPreference.setEnabled(false);
+ mPreference.setSummary(R.string.android_beam_disabled_summary);
+ break;
+ case NfcAdapter.STATE_ON:
+ if (mBeamDisallowedBySystem) {
+ mPreference.setDisabledByAdmin(null);
+ mPreference.setEnabled(false);
+ } else {
+ mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_OUTGOING_BEAM);
+ }
+ if (mNfcAdapter.isNdefPushEnabled() && mPreference.isEnabled()) {
+ mPreference.setSummary(R.string.android_beam_on_summary);
+ } else {
+ mPreference.setSummary(R.string.android_beam_off_summary);
+ }
+ break;
+ case NfcAdapter.STATE_TURNING_ON:
+ mPreference.setEnabled(false);
+ break;
+ case NfcAdapter.STATE_TURNING_OFF:
+ mPreference.setEnabled(false);
+ break;
+ }
+ }
+}
diff --git a/src/com/android/settings/nfc/AndroidBeamPreferenceController.java b/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
new file mode 100644
index 00000000000..6ae7fe5ccf2
--- /dev/null
+++ b/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
@@ -0,0 +1,49 @@
+/*
+ * 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.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.PreferenceControllerMixin;
+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 {
+
+ public static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
+
+ public AndroidBeamPreferenceController(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ if (!isAvailable()) {
+ return;
+ }
+
+ mNfcEnabler = new AndroidBeamEnabler(mContext, (RestrictedPreference) mPreference);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_ANDROID_BEAM_SETTINGS;
+ }
+}
diff --git a/src/com/android/settings/nfc/BaseNfcEnabler.java b/src/com/android/settings/nfc/BaseNfcEnabler.java
new file mode 100644
index 00000000000..5c5f95ca7cb
--- /dev/null
+++ b/src/com/android/settings/nfc/BaseNfcEnabler.java
@@ -0,0 +1,78 @@
+/*
+ * 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.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.nfc.NfcAdapter;
+import android.support.v7.preference.Preference;
+
+/**
+ * BaseNfcEnabler is a abstract helper to manage the Nfc state for Nfc and Android Beam
+ * preference. It will receive intent and update state to ensure preference show correct state.
+ */
+public abstract class BaseNfcEnabler {
+ private final Context mContext;
+ protected final NfcAdapter mNfcAdapter;
+ private final IntentFilter mIntentFilter;
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(action)) {
+ handleNfcStateChanged(intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
+ NfcAdapter.STATE_OFF));
+ }
+ }
+ };
+
+ public BaseNfcEnabler(Context context) {
+ mContext = context;
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
+
+ if (!isNfcAvailable()) {
+ // NFC is not supported
+ mIntentFilter = null;
+ return;
+ }
+ mIntentFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+ }
+
+ public void resume() {
+ if (!isNfcAvailable()) {
+ return;
+ }
+ handleNfcStateChanged(mNfcAdapter.getAdapterState());
+ mContext.registerReceiver(mReceiver, mIntentFilter);
+ }
+
+ public void pause() {
+ if (!isNfcAvailable()) {
+ return;
+ }
+ mContext.unregisterReceiver(mReceiver);
+ }
+
+ public boolean isNfcAvailable() {
+ return mNfcAdapter != null;
+ }
+
+ protected abstract void handleNfcStateChanged(int newState);
+}
diff --git a/src/com/android/settings/nfc/BaseNfcPreferenceController.java b/src/com/android/settings/nfc/BaseNfcPreferenceController.java
new file mode 100644
index 00000000000..b945738eab5
--- /dev/null
+++ b/src/com/android/settings/nfc/BaseNfcPreferenceController.java
@@ -0,0 +1,147 @@
+/*
+ * 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 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();
+ }
+ }
+
+}
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 14ee779bed4..29cef993552 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -16,90 +16,44 @@
package com.android.settings.nfc;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.nfc.NfcAdapter;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedPreference;
+import android.support.v14.preference.SwitchPreference;
/**
- * NfcEnabler is a helper to manage the Nfc on/off checkbox preference. It is
- * turns on/off Nfc and ensures the summary of the preference reflects the
- * current state.
+ * 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 implements Preference.OnPreferenceChangeListener {
- private final Context mContext;
- private final SwitchPreference mSwitch;
- private final RestrictedPreference mAndroidBeam;
- private final NfcAdapter mNfcAdapter;
- private final IntentFilter mIntentFilter;
- private boolean mBeamDisallowedBySystem;
+public class NfcEnabler extends BaseNfcEnabler implements Preference.OnPreferenceChangeListener {
+ private final SwitchPreference mPreference;
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(action)) {
- handleNfcStateChanged(intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
- NfcAdapter.STATE_OFF));
- }
- }
- };
+ public NfcEnabler(Context context, SwitchPreference preference) {
+ super(context);
- public NfcEnabler(Context context, SwitchPreference switchPreference,
- RestrictedPreference androidBeam) {
- mContext = context;
- mSwitch = switchPreference;
- mAndroidBeam = androidBeam;
- mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
- mBeamDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(context,
- UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
-
- if (mNfcAdapter == null) {
- // NFC is not supported
- mSwitch.setEnabled(false);
- mAndroidBeam.setEnabled(false);
- mIntentFilter = null;
- return;
- }
- if (mBeamDisallowedBySystem) {
- mAndroidBeam.setEnabled(false);
- }
- mIntentFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+ mPreference = preference;
}
public void resume() {
- if (mNfcAdapter == null) {
- return;
+ super.resume();
+ if (isNfcAvailable()) {
+ mPreference.setOnPreferenceChangeListener(this);
}
- handleNfcStateChanged(mNfcAdapter.getAdapterState());
- mContext.registerReceiver(mReceiver, mIntentFilter);
- mSwitch.setOnPreferenceChangeListener(this);
}
public void pause() {
- if (mNfcAdapter == null) {
- return;
+ super.pause();
+ if (isNfcAvailable()) {
+ mPreference.setOnPreferenceChangeListener(null);
}
- mContext.unregisterReceiver(mReceiver);
- mSwitch.setOnPreferenceChangeListener(null);
}
public boolean onPreferenceChange(Preference preference, Object value) {
// Turn NFC on/off
final boolean desiredState = (Boolean) value;
- mSwitch.setChecked(desiredState);
- mSwitch.setEnabled(false);
+ mPreference.setChecked(desiredState);
+ mPreference.setEnabled(false);
if (desiredState) {
mNfcAdapter.enable();
@@ -110,39 +64,25 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
return false;
}
- private void handleNfcStateChanged(int newState) {
+ @Override
+ protected void handleNfcStateChanged(int newState) {
switch (newState) {
- case NfcAdapter.STATE_OFF:
- mSwitch.setChecked(false);
- mSwitch.setEnabled(true);
- mAndroidBeam.setEnabled(false);
- mAndroidBeam.setSummary(R.string.android_beam_disabled_summary);
- break;
- case NfcAdapter.STATE_ON:
- mSwitch.setChecked(true);
- mSwitch.setEnabled(true);
- if (mBeamDisallowedBySystem) {
- mAndroidBeam.setDisabledByAdmin(null);
- mAndroidBeam.setEnabled(false);
- } else {
- mAndroidBeam.checkRestrictionAndSetDisabled(UserManager.DISALLOW_OUTGOING_BEAM);
- }
- if (mNfcAdapter.isNdefPushEnabled() && mAndroidBeam.isEnabled()) {
- mAndroidBeam.setSummary(R.string.android_beam_on_summary);
- } else {
- mAndroidBeam.setSummary(R.string.android_beam_off_summary);
- }
- break;
- case NfcAdapter.STATE_TURNING_ON:
- mSwitch.setChecked(true);
- mSwitch.setEnabled(false);
- mAndroidBeam.setEnabled(false);
- break;
- case NfcAdapter.STATE_TURNING_OFF:
- mSwitch.setChecked(false);
- mSwitch.setEnabled(false);
- mAndroidBeam.setEnabled(false);
- break;
+ case NfcAdapter.STATE_OFF:
+ mPreference.setChecked(false);
+ mPreference.setEnabled(true);
+ break;
+ case NfcAdapter.STATE_ON:
+ mPreference.setChecked(true);
+ mPreference.setEnabled(true);
+ break;
+ case NfcAdapter.STATE_TURNING_ON:
+ mPreference.setChecked(true);
+ mPreference.setEnabled(false);
+ break;
+ case NfcAdapter.STATE_TURNING_OFF:
+ mPreference.setChecked(false);
+ mPreference.setEnabled(false);
+ break;
}
}
}
diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java
index 76977d24e21..a0678e0afab 100644
--- a/src/com/android/settings/nfc/NfcPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPreferenceController.java
@@ -16,146 +16,35 @@
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.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
+import android.support.v14.preference.SwitchPreference;
import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.RestrictedPreference;
-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 class NfcPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
+public class NfcPreferenceController extends BaseNfcPreferenceController {
public static final String KEY_TOGGLE_NFC = "toggle_nfc";
- public static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
-
- private NfcEnabler mNfcEnabler;
- private NfcAdapter mNfcAdapter;
- private int mAirplaneMode;
- private AirplaneModeObserver mAirplaneModeObserver;
- private SwitchPreference mNfcPreference;
- private RestrictedPreference mBeamPreference;
public NfcPreferenceController(Context context) {
super(context);
- mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
}
@Override
public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
if (!isAvailable()) {
- setVisible(screen, KEY_TOGGLE_NFC, false /* visible */);
- setVisible(screen, KEY_ANDROID_BEAM_SETTINGS, false /* visible */);
- mNfcEnabler = null;
return;
}
- mNfcPreference = (SwitchPreference) screen.findPreference(KEY_TOGGLE_NFC);
- mBeamPreference = (RestrictedPreference) screen.findPreference(
- KEY_ANDROID_BEAM_SETTINGS);
- mNfcEnabler = new NfcEnabler(mContext, mNfcPreference, mBeamPreference);
- // Manually set dependencies for NFC when not toggleable.
- if (!isToggleableInAirplaneMode(mContext)) {
- mAirplaneModeObserver = new AirplaneModeObserver();
- updateNfcPreference();
- }
- }
- @Override
- public void updateNonIndexableKeys(List keys) {
- final NfcManager manager = (NfcManager) mContext.getSystemService(Context.NFC_SERVICE);
- if (manager != null) {
- NfcAdapter adapter = manager.getDefaultAdapter();
- if (adapter == null) {
- keys.add(KEY_TOGGLE_NFC);
- keys.add(KEY_ANDROID_BEAM_SETTINGS);
- }
- }
- }
-
- @Override
- public boolean isAvailable() {
- return mNfcAdapter != null;
+ mNfcEnabler = new NfcEnabler(mContext, (SwitchPreference) mPreference);
}
@Override
public String getPreferenceKey() {
- return null;
+ return KEY_TOGGLE_NFC;
}
-
- 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();
- }
- mNfcPreference.setEnabled(toggleable);
- mBeamPreference.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();
- }
- }
-
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java
index 982de54cd93..2e2dd9d7d3e 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java
@@ -16,13 +16,10 @@
package com.android.settings.connecteddevice;
import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
+;
import android.provider.SearchIndexableResource;
-import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowBluetoothPan;
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -59,8 +56,8 @@ public class AdvancedConnectedDeviceDashboardFragmentTest {
@Test
public void testSearchIndexProvider_shouldIndexResource() {
final List indexRes =
- AdvancedConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
- .getXmlResourcesToIndex(RuntimeEnvironment.application, true /* enabled */);
+ AdvancedConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+ .getXmlResourcesToIndex(RuntimeEnvironment.application, true /* enabled */);
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
@@ -70,14 +67,4 @@ public class AdvancedConnectedDeviceDashboardFragmentTest {
public void testGetCategoryKey_returnCategoryDevice() {
assertThat(mFragment.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_DEVICE);
}
-
- @Test
- public void testNonIndexableKeys_existInXmlLayout() {
- final Context context = RuntimeEnvironment.application;
- final List niks =
- AdvancedConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
- .getNonIndexableKeys(context);
-
- assertThat(niks).contains(BluetoothMasterSwitchPreferenceController.KEY_TOGGLE_BLUETOOTH);
- }
-}
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
index c68771c2fdf..443e885eb4d 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
import android.provider.SearchIndexableResource;
import com.android.settings.R;
+import com.android.settings.nfc.NfcPreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowBluetoothPan;
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
@@ -77,6 +78,7 @@ public class ConnectedDeviceDashboardFragmentTest {
final List niks = ConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
- assertThat(niks).containsExactly(KEY_CONNECTED_DEVICES, KEY_SAVED_DEVICES);
+ assertThat(niks).containsExactly(KEY_CONNECTED_DEVICES, KEY_SAVED_DEVICES,
+ NfcPreferenceController.KEY_TOGGLE_NFC);
}
}
diff --git a/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
new file mode 100644
index 00000000000..cb18b5abd9e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.when;
+
+import android.content.Context;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedPreference;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AndroidBeamPreferenceControllerTest {
+
+ Context mContext;
+ @Mock
+ private NfcAdapter mNfcAdapter;
+ @Mock
+ NfcManager mManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private RestrictedPreference mAndroidBeamPreference;
+ private AndroidBeamPreferenceController mAndroidBeamController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager);
+ when(RestrictedLockUtils.hasBaseUserRestriction(mContext,
+ UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(false);
+ when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter);
+
+ mAndroidBeamController = new AndroidBeamPreferenceController(mContext);
+ mAndroidBeamPreference = new RestrictedPreference(RuntimeEnvironment.application);
+ when(mScreen.findPreference(mAndroidBeamController.getPreferenceKey())).thenReturn(
+ mAndroidBeamPreference);
+
+ 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);
+ mAndroidBeamController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void isAvailable_hasNfc_shouldReturnTrue() {
+ when(mNfcAdapter.isEnabled()).thenReturn(true);
+ assertThat(mAndroidBeamController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_noNfcAdapter_shouldReturnFalse() {
+ ReflectionHelpers.setField(mAndroidBeamController, "mNfcAdapter", null);
+ assertThat(mAndroidBeamController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isBeamEnable_disAllowBeam_shouldReturnFalse() {
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF);
+
+ when(RestrictedLockUtils.hasBaseUserRestriction(mContext,
+ UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(true);
+ mAndroidBeamController.displayPreference(mScreen);
+
+ assertThat(mAndroidBeamPreference.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void isBeamEnable_nfcStateOn_shouldReturnTrue() {
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON);
+ try {
+ mAndroidBeamController.onResume();
+ } catch (NullPointerException e) {
+ // skip because it's just test
+ // it will meet NullPointerException in checkRestrictionAndSetDisabled
+ }
+ assertThat(mAndroidBeamPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void isBeamEnable_nfcStateNotOn_shouldReturnFalse() {
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF);
+ mAndroidBeamController.onResume();
+ assertThat(mAndroidBeamPreference.isEnabled()).isFalse();
+
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON);
+ mAndroidBeamController.onResume();
+ assertThat(mAndroidBeamPreference.isEnabled()).isFalse();
+
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_OFF);
+ mAndroidBeamController.onResume();
+ assertThat(mAndroidBeamPreference.isEnabled()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
new file mode 100644
index 00000000000..cd90820b449
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.when;
+
+import android.content.Context;
+import android.nfc.NfcAdapter;
+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 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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class NfcPreferenceControllerTest {
+
+ Context mContext;
+ @Mock
+ private NfcAdapter mNfcAdapter;
+ @Mock
+ NfcManager mManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private SwitchPreference mNfcPreference;
+ private NfcPreferenceController mNfcController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager);
+ when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter);
+
+ mNfcController = new NfcPreferenceController(mContext);
+ 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
+ public void isAvailable_hasNfc_shouldReturnTrue() {
+ when(mNfcAdapter.isEnabled()).thenReturn(true);
+ assertThat(mNfcController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_noNfcAdapter_shouldReturnFalse() {
+ ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null);
+ assertThat(mNfcController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isNfcEnable_nfcStateNotTurning_shouldReturnTrue() {
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isEnabled()).isTrue();
+
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void isNfcEnable_nfcStateTurning_shouldReturnFalse() {
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isEnabled()).isFalse();
+
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_OFF);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void isNfcChecked_nfcStateOn_shouldReturnTrue() {
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isChecked()).isTrue();
+
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isNfcChecked_nfcStateOff_shouldReturnFalse() {
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isChecked()).isFalse();
+
+ when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_OFF);
+ mNfcController.onResume();
+ assertThat(mNfcPreference.isChecked()).isFalse();
+ }
+}