diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml index 5417051103c..227dee25229 100644 --- a/res/xml/connected_devices.xml +++ b/res/xml/connected_devices.xml @@ -37,6 +37,7 @@ settings:allowDividerAbove="true"/> diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml new file mode 100644 index 00000000000..c45d0f38a35 --- /dev/null +++ b/res/xml/connected_devices_advanced.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java new file mode 100644 index 00000000000..05e460f137e --- /dev/null +++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2017 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.connecteddevice; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.provider.SearchIndexableResource; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController; +import com.android.settings.bluetooth.Utils; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.deviceinfo.UsbBackend; +import com.android.settings.nfc.NfcPreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.drawer.CategoryKey; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * This fragment contains all the advanced connection preferences(i.e, Bluetooth, NFC, USB..) + */ +public class AdvancedConnectedDeviceDashboardFragment extends DashboardFragment { + + private static final String TAG = "AdvancedConnectedDeviceFrag"; + private UsbModePreferenceController mUsbPrefController; + + @Override + public int getMetricsCategory() { + return MetricsProto.MetricsEvent.CONNECTION_DEVICE_ADVANCED; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + public int getHelpResource() { + return R.string.help_url_connected_devices; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.connected_devices_advanced; + } + + @Override + public String getCategoryKey() { + //TODO(b/69926683): remove this method and change DashboardFragmentRegistry directly for P + return CategoryKey.CATEGORY_DEVICE; + } + + @Override + protected List getPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); + final Lifecycle lifecycle = getLifecycle(); + final NfcPreferenceController nfcPreferenceController = + new NfcPreferenceController(context); + lifecycle.addObserver(nfcPreferenceController); + controllers.add(nfcPreferenceController); + mUsbPrefController = new UsbModePreferenceController(context, new UsbBackend(context)); + lifecycle.addObserver(mUsbPrefController); + controllers.add(mUsbPrefController); + final BluetoothMasterSwitchPreferenceController bluetoothPreferenceController = + new BluetoothMasterSwitchPreferenceController( + context, Utils.getLocalBtManager(context), this, + (SettingsActivity) getActivity()); + lifecycle.addObserver(bluetoothPreferenceController); + controllers.add(bluetoothPreferenceController); + + SmsMirroringFeatureProvider smsMirroringFeatureProvider = + FeatureFactory.getFactory(context).getSmsMirroringFeatureProvider(); + AbstractPreferenceController smsMirroringController = + smsMirroringFeatureProvider.getController(context); + controllers.add(smsMirroringController); + return controllers; + } + + /** + * For Search. + */ + public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.connected_devices_advanced; + return Arrays.asList(sir); + } + + @Override + public List getNonIndexableKeys(Context context) { + 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(BluetoothMasterSwitchPreferenceController.KEY_TOGGLE_BLUETOOTH); + + SmsMirroringFeatureProvider smsMirroringFeatureProvider = + FeatureFactory.getFactory(context).getSmsMirroringFeatureProvider(); + SmsMirroringPreferenceController smsMirroringController = + smsMirroringFeatureProvider.getController(context); + smsMirroringController.updateNonIndexableKeys(keys); + + return keys; + } + }; +} diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 1f8887246a5..c4e178f764c 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -33,6 +33,7 @@ import com.android.settings.applications.assist.ManageAssist; import com.android.settings.backup.BackupSettingsActivity; import com.android.settings.backup.BackupSettingsFragment; import com.android.settings.bluetooth.BluetoothSettings; +import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragmentOld; import com.android.settings.datausage.DataUsageMeteredSettings; @@ -155,6 +156,7 @@ public final class SearchIndexableResources { addIndex(StorageDashboardFragment.class); addIndex(ConnectedDeviceDashboardFragment.class); addIndex(ConnectedDeviceDashboardFragmentOld.class); + addIndex(AdvancedConnectedDeviceDashboardFragment.class); addIndex(EnterprisePrivacySettings.class); addIndex(PaymentSettings.class); addIndex(TextToSpeechSettings.class); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java new file mode 100644 index 00000000000..bb3591193e5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2017 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.connecteddevice; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.provider.SearchIndexableResource; + +import com.android.settings.TestConfig; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settings.nfc.NfcPreferenceController; +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.XmlTestUtils; +import com.android.settingslib.drawer.CategoryKey; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O) +public class AdvancedConnectedDeviceDashboardFragmentTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + Context mContext; + + @Mock + private PackageManager mManager; + + private FakeFeatureFactory mFeatureFactory; + private SmsMirroringFeatureProvider mFeatureProvider; + private AdvancedConnectedDeviceDashboardFragment mFragment; + private TestSmsMirroringPreferenceController mSmsMirroringPreferenceController; + + private static final class TestSmsMirroringPreferenceController + extends SmsMirroringPreferenceController implements PreferenceControllerMixin { + + private boolean mIsAvailable; + + public TestSmsMirroringPreferenceController(Context context) { + super(context); + } + + @Override + public boolean isAvailable() { + return mIsAvailable; + } + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + mFeatureProvider = mFeatureFactory.smsMirroringFeatureProvider; + + mFragment = new AdvancedConnectedDeviceDashboardFragment(); + when(mContext.getPackageManager()).thenReturn(mManager); + + mSmsMirroringPreferenceController = new TestSmsMirroringPreferenceController(mContext); + when(mFeatureProvider.getController(mContext)).thenReturn( + mSmsMirroringPreferenceController); + } + + @Test + public void testCategory_isConnectedDevice() { + assertThat(mFragment.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_DEVICE); + } + + @Test + public void testSearchIndexProvider_shouldIndexResource() { + final List indexRes = + mFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(mContext, + true /* enabled */); + + assertThat(indexRes).isNotNull(); + assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId()); + } + + @Test + public void testSearchIndexProvider_NoNfc_KeyAdded() { + when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(false); + final List keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( + mContext); + + assertThat(keys).isNotNull(); + assertThat(keys).contains(NfcPreferenceController.KEY_TOGGLE_NFC); + assertThat(keys).contains(NfcPreferenceController.KEY_ANDROID_BEAM_SETTINGS); + } + + @Test + public void testSearchIndexProvider_NFC_KeyNotAdded() { + when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(true); + final List keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( + mContext); + + assertThat(keys).isNotNull(); + assertThat(keys).doesNotContain(NfcPreferenceController.KEY_TOGGLE_NFC); + assertThat(keys).doesNotContain(NfcPreferenceController.KEY_ANDROID_BEAM_SETTINGS); + } + + @Test + public void testSearchIndexProvider_NoSmsMirroring_KeyAdded() { + when(mFeatureProvider.shouldShowSmsMirroring(mContext)).thenReturn(false); + mSmsMirroringPreferenceController.mIsAvailable = false; + + final List keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( + mContext); + + assertThat(keys).isNotNull(); + assertThat(keys).contains(mSmsMirroringPreferenceController.getPreferenceKey()); + } + + @Test + public void testSearchIndexProvider_SmsMirroring_KeyNotAdded() { + when(mFeatureProvider.shouldShowSmsMirroring(mContext)).thenReturn(true); + mSmsMirroringPreferenceController.mIsAvailable = true; + + final List keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( + mContext); + + assertThat(keys).isNotNull(); + assertThat(keys).doesNotContain(mSmsMirroringPreferenceController.getPreferenceKey()); + } + + @Test + public void testNonIndexableKeys_existInXmlLayout() { + final Context context = RuntimeEnvironment.application; + when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(false); + final List niks = ConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(mContext); + final int xmlId = (new ConnectedDeviceDashboardFragment()).getPreferenceScreenResId(); + + final List keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId); + + assertThat(keys).containsAllIn(niks); + } +}