OSDN Git Service

Dupe BluetoothSettings and DeviceListPreferenceFragment
authorjackqdyulei <jackqdyulei@google.com>
Wed, 17 May 2017 03:17:35 +0000 (20:17 -0700)
committerjackqdyulei <jackqdyulei@google.com>
Thu, 18 May 2017 21:12:02 +0000 (14:12 -0700)
Create the obsolete version of the belowing fragments, so we could
flip between old page and new page.

BluetoothSettingsObsolete and DeviceListPreferenceObsoleteFragment
contains all the old logic but:
1. Logic about BluetoothPairingPreferenceController(ag/2239482),
since this preference shouldn't be checked in without the flag :(

This cl also adds logic in MasterSwitchPreferenceController to flip
these two pages.

Following cl will refactor these fragment to make it compatible
to new framework.

Bug: 35877041
Test: RunSettingsRoboTests
Change-Id: I1cc1bc2d49d8a3e11c3127e56f6409fbc84028d8

15 files changed:
res/xml/bluetooth_settings_obsolete.xml [new file with mode: 0644]
res/xml/connected_devices.xml
src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceController.java
src/com/android/settings/bluetooth/BluetoothSettings.java
src/com/android/settings/bluetooth/BluetoothSettingsObsolete.java [new file with mode: 0644]
src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
src/com/android/settings/bluetooth/DeviceListPreferenceObsoleteFragment.java [new file with mode: 0644]
src/com/android/settings/bluetooth/DevicePickerFragment.java
src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
src/com/android/settings/search/SearchIndexableResources.java
src/com/android/settings/search2/CursorToSearchResultConverter.java
tests/robotests/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceControllerTest.java
tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsObsoleteTest.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsTest.java
tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java

diff --git a/res/xml/bluetooth_settings_obsolete.xml b/res/xml/bluetooth_settings_obsolete.xml
new file mode 100644 (file)
index 0000000..55a099c
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/bluetooth_settings" >
+
+</PreferenceScreen>
index d70cc33..ecbcbd1 100644 (file)
@@ -19,7 +19,6 @@
     android:title="@string/connected_devices_dashboard_title">
 
     <com.android.settings.widget.MasterSwitchPreference
-      android:fragment="com.android.settings.bluetooth.BluetoothSettings"
       android:key="toggle_bluetooth"
       android:title="@string/bluetooth_settings_title"
       android:icon="@drawable/ic_settings_bluetooth"
index f9b7975..6d474ee 100644 (file)
  */
 package com.android.settings.bluetooth;
 
+import android.app.Fragment;
 import android.content.Context;
+import android.os.UserHandle;
+import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.MasterSwitchController;
@@ -43,19 +48,27 @@ public class BluetoothMasterSwitchPreferenceController extends PreferenceControl
     private BluetoothEnabler mBluetoothEnabler;
     private BluetoothSummaryUpdater mSummaryUpdater;
     private RestrictionUtils mRestrictionUtils;
+    private Fragment mFragment;
+    private SettingsActivity mActivity;
+    private BluetoothFeatureProvider mBluetoothFeatureProvider;
 
     public BluetoothMasterSwitchPreferenceController(Context context,
-            LocalBluetoothManager bluetoothManager) {
-        this(context, bluetoothManager, new RestrictionUtils());
+            LocalBluetoothManager bluetoothManager, Fragment fragment, SettingsActivity activity) {
+        this(context, bluetoothManager, new RestrictionUtils(), fragment, activity);
     }
 
     @VisibleForTesting
     public BluetoothMasterSwitchPreferenceController(Context context,
-            LocalBluetoothManager bluetoothManager, RestrictionUtils restrictionUtils) {
+            LocalBluetoothManager bluetoothManager, RestrictionUtils restrictionUtils,
+            Fragment fragment, SettingsActivity activity) {
         super(context);
         mBluetoothManager = bluetoothManager;
         mSummaryUpdater = new BluetoothSummaryUpdater(mContext, this, mBluetoothManager);
         mRestrictionUtils = restrictionUtils;
+        mFragment = fragment;
+        mActivity = activity;
+        mBluetoothFeatureProvider = FeatureFactory.getFactory(
+                mContext).getBluetoothFeatureProvider(mContext);
     }
 
     @Override
@@ -63,10 +76,23 @@ public class BluetoothMasterSwitchPreferenceController extends PreferenceControl
         super.displayPreference(screen);
         mBtPreference = (MasterSwitchPreference) screen.findPreference(KEY_TOGGLE_BLUETOOTH);
         mBluetoothEnabler = new BluetoothEnabler(mContext,
-            new MasterSwitchController(mBtPreference),
-            FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(), mBluetoothManager,
-            MetricsEvent.ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE,
-            mRestrictionUtils);
+                new MasterSwitchController(mBtPreference),
+                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(), mBluetoothManager,
+                MetricsEvent.ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE,
+                mRestrictionUtils);
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (KEY_TOGGLE_BLUETOOTH.equals(preference.getKey())) {
+            final String fragmentClass = mBluetoothFeatureProvider.isPairingPageEnabled() ?
+                    BluetoothSettings.class.getName() :
+                    BluetoothSettingsObsolete.class.getName();
+            mActivity.startPreferencePanelAsUser(mFragment, fragmentClass, null, R.string.bluetooth,
+                    null, new UserHandle(UserHandle.myUserId()));
+            return true;
+        }
+        return super.handlePreferenceTreeClick(preference);
     }
 
     @Override
@@ -79,6 +105,7 @@ public class BluetoothMasterSwitchPreferenceController extends PreferenceControl
         return KEY_TOGGLE_BLUETOOTH;
     }
 
+    @Override
     public void onResume() {
         mSummaryUpdater.register(true);
     }
index ed2629e..db0e307 100644 (file)
@@ -49,6 +49,7 @@ import com.android.settings.SettingsActivity;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.location.ScanningSettings;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
@@ -64,7 +65,6 @@ import com.android.settingslib.widget.FooterPreference;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Set;
 
 import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
@@ -72,7 +72,9 @@ import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
 /**
  * BluetoothSettings is the Settings screen for Bluetooth configuration and
  * connection management.
+ *
  */
+// TODO: Refactor this fragment
 public class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable {
     private static final String TAG = "BluetoothSettings";
 
@@ -107,7 +109,8 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
     private BluetoothPairingPreferenceController mPairingPrefController;
 
     // For Search
-    private static final String DATA_KEY_REFERENCE = "main_toggle_bluetooth";
+    @VisibleForTesting
+    static final String DATA_KEY_REFERENCE = "main_toggle_bluetooth";
 
     // accessed from inner class (not private to avoid thunks)
     FooterPreference mMyDevicePreference;
@@ -593,23 +596,18 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
                     data.key = DATA_KEY_REFERENCE;
                     result.add(data);
 
-                    // Add cached paired BT devices
-                    LocalBluetoothManager lbtm = Utils.getLocalBtManager(context);
-                    // LocalBluetoothManager.getInstance can return null if the device does not
-                    // support bluetooth (e.g. the emulator).
-                    if (lbtm != null) {
-                        Set<BluetoothDevice> bondedDevices =
-                                lbtm.getBluetoothAdapter().getBondedDevices();
-
-                        for (BluetoothDevice device : bondedDevices) {
-                            data = new SearchIndexableRaw(context);
-                            data.title = device.getName();
-                            data.screenTitle = res.getString(R.string.bluetooth_settings);
-                            data.enabled = enabled;
-                            result.add(data);
-                        }
-                    }
+                    // Removed paired bluetooth device indexing. See BluetoothSettingsObsolete.java.
                     return result;
                 }
+
+                @Override
+                public List<String> getNonIndexableKeys(Context context) {
+                    List<String> keys = super.getNonIndexableKeys(context);
+                    if (!FeatureFactory.getFactory(context).getBluetoothFeatureProvider(
+                            context).isPairingPageEnabled()) {
+                        keys.add(DATA_KEY_REFERENCE);
+                    }
+                    return keys;
+                }
             };
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothSettingsObsolete.java b/src/com/android/settings/bluetooth/BluetoothSettingsObsolete.java
new file mode 100644 (file)
index 0000000..207d313
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * 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.bluetooth;
+
+import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.BidiFormatter;
+import android.text.Spannable;
+import android.text.style.TextAppearanceSpan;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.LinkifyUtils;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.dashboard.SummaryLoader;
+import com.android.settings.location.ScanningSettings;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.widget.GearPreference;
+import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBarController;
+import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * BluetoothSettingsObsolete is the Settings screen for Bluetooth configuration and
+ * connection management.
+ *
+ * This fragment stores old implementation of {@link BluetoothSettings} and is
+ * deprecated, please use {@link BluetoothSettings} instead.
+ */
+@Deprecated
+public class BluetoothSettingsObsolete extends DeviceListPreferenceObsoleteFragment
+        implements Indexable {
+    private static final String TAG = "BluetoothSettingsObsolete";
+
+    private static final int MENU_ID_SCAN = Menu.FIRST;
+    private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 1;
+
+    /* Private intent to show the list of received files */
+    private static final String BTOPP_ACTION_OPEN_RECEIVED_FILES =
+            "android.btopp.intent.action.OPEN_RECEIVED_FILES";
+    private static final String BTOPP_PACKAGE =
+            "com.android.bluetooth";
+
+    private static final String KEY_PAIRED_DEVICES = "paired_devices";
+
+    private static View mSettingsDialogView = null;
+
+    private BluetoothEnabler mBluetoothEnabler;
+
+    private PreferenceGroup mPairedDevicesCategory;
+    private PreferenceGroup mAvailableDevicesCategory;
+    private Preference mDeviceNamePreference;
+    private boolean mAvailableDevicesCategoryIsPresent;
+
+    private boolean mInitialScanStarted;
+    private boolean mInitiateDiscoverable;
+
+    private SwitchBar mSwitchBar;
+
+    private final IntentFilter mIntentFilter;
+    private BluetoothDeviceNamePreferenceController mDeviceNamePrefController;
+
+    // For Search
+    @VisibleForTesting
+    static final String DATA_KEY_REFERENCE = "main_toggle_bluetooth_obsolete";
+
+    // accessed from inner class (not private to avoid thunks)
+    FooterPreference mMyDevicePreference;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            final int state =
+                    intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+
+            if (state == BluetoothAdapter.STATE_ON) {
+                mInitiateDiscoverable = true;
+            }
+        }
+    };
+
+    public BluetoothSettingsObsolete() {
+        super(DISALLOW_CONFIG_BLUETOOTH);
+        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.BLUETOOTH;
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mInitialScanStarted = false;
+        mInitiateDiscoverable = true;
+
+        final SettingsActivity activity = (SettingsActivity) getActivity();
+        mSwitchBar = activity.getSwitchBar();
+
+        mBluetoothEnabler = new BluetoothEnabler(activity, new SwitchBarController(mSwitchBar),
+                mMetricsFeatureProvider, Utils.getLocalBtManager(activity),
+                MetricsEvent.ACTION_BLUETOOTH_TOGGLE);
+        mBluetoothEnabler.setupSwitchController();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+
+        mBluetoothEnabler.teardownSwitchController();
+    }
+
+    @Override
+    void addPreferencesForActivity() {
+        final Context prefContext = getPrefContext();
+
+        mDeviceNamePreference = mDeviceNamePrefController.createBluetoothDeviceNamePreference(
+                getPreferenceScreen(), 1 /* order */);
+
+        mPairedDevicesCategory = new PreferenceCategory(prefContext);
+        mPairedDevicesCategory.setKey(KEY_PAIRED_DEVICES);
+        mPairedDevicesCategory.setOrder(2);
+        getPreferenceScreen().addPreference(mPairedDevicesCategory);
+
+        mAvailableDevicesCategory = new BluetoothProgressCategory(prefContext);
+        mAvailableDevicesCategory.setSelectable(false);
+        mAvailableDevicesCategory.setOrder(3);
+        getPreferenceScreen().addPreference(mAvailableDevicesCategory);
+
+        mMyDevicePreference = mFooterPreferenceMixin.createFooterPreference();
+        mMyDevicePreference.setSelectable(false);
+
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onStart() {
+        // resume BluetoothEnabler before calling super.onStart() so we don't get
+        // any onDeviceAdded() callbacks before setting up view in updateContent()
+        if (mBluetoothEnabler != null) {
+            mBluetoothEnabler.resume(getActivity());
+        }
+        super.onStart();
+
+        mInitiateDiscoverable = true;
+
+        if (isUiRestricted()) {
+            setDeviceListGroup(getPreferenceScreen());
+            if (!isUiRestrictedByOnlyAdmin()) {
+                getEmptyTextView().setText(R.string.bluetooth_empty_list_user_restricted);
+            }
+            removeAllDevices();
+            return;
+        }
+
+        getActivity().registerReceiver(mReceiver, mIntentFilter);
+        if (mLocalAdapter != null) {
+            updateContent(mLocalAdapter.getBluetoothState());
+        }
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        if (mBluetoothEnabler != null) {
+            mBluetoothEnabler.pause();
+        }
+
+        // Make the device only visible to connected devices.
+        mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+
+        if (isUiRestricted()) {
+            return;
+        }
+
+        getActivity().unregisterReceiver(mReceiver);
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        if (mLocalAdapter == null) return;
+        // If the user is not allowed to configure bluetooth, do not show the menu.
+        if (isUiRestricted()) return;
+
+        boolean bluetoothIsEnabled = mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON;
+        boolean isDiscovering = mLocalAdapter.isDiscovering();
+        int textId = isDiscovering ? R.string.bluetooth_searching_for_devices :
+                R.string.bluetooth_search_for_devices;
+        menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
+                .setEnabled(bluetoothIsEnabled && !isDiscovering)
+                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
+                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_ID_SCAN:
+                if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
+                    mMetricsFeatureProvider.action(getActivity(),
+                            MetricsEvent.ACTION_BLUETOOTH_SCAN);
+                    startScanning();
+                }
+                return true;
+
+            case MENU_ID_SHOW_RECEIVED:
+                mMetricsFeatureProvider.action(getActivity(),
+                        MetricsEvent.ACTION_BLUETOOTH_FILES);
+                Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
+                intent.setPackage(BTOPP_PACKAGE);
+                getActivity().sendBroadcast(intent);
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    private void startScanning() {
+        if (isUiRestricted()) {
+            return;
+        }
+
+        if (!mAvailableDevicesCategoryIsPresent) {
+            getPreferenceScreen().addPreference(mAvailableDevicesCategory);
+            mAvailableDevicesCategoryIsPresent = true;
+        }
+
+        if (mAvailableDevicesCategory != null) {
+            setDeviceListGroup(mAvailableDevicesCategory);
+            removeAllDevices();
+        }
+
+        mLocalManager.getCachedDeviceManager().clearNonBondedDevices();
+        mAvailableDevicesCategory.removeAll();
+        mInitialScanStarted = true;
+        mLocalAdapter.startScanning(true);
+    }
+
+    @Override
+    void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
+        mLocalAdapter.stopScanning();
+        super.onDevicePreferenceClick(btPreference);
+    }
+
+    private void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
+            BluetoothDeviceFilter.Filter filter, boolean addCachedDevices) {
+        cacheRemoveAllPrefs(preferenceGroup);
+        preferenceGroup.setTitle(titleId);
+        setFilter(filter);
+        setDeviceListGroup(preferenceGroup);
+        if (addCachedDevices) {
+            addCachedDevices();
+        }
+        preferenceGroup.setEnabled(true);
+        removeCachedPrefs(preferenceGroup);
+    }
+
+    private void updateContent(int bluetoothState) {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        int messageId = 0;
+
+        switch (bluetoothState) {
+            case BluetoothAdapter.STATE_ON:
+                mDevicePreferenceMap.clear();
+
+                if (isUiRestricted()) {
+                    messageId = R.string.bluetooth_empty_list_user_restricted;
+                    break;
+                }
+                getPreferenceScreen().removeAll();
+                getPreferenceScreen().addPreference(mDeviceNamePreference);
+                getPreferenceScreen().addPreference(mPairedDevicesCategory);
+                getPreferenceScreen().addPreference(mAvailableDevicesCategory);
+                getPreferenceScreen().addPreference(mMyDevicePreference);
+
+                // Paired devices category
+                addDeviceCategory(mPairedDevicesCategory,
+                        R.string.bluetooth_preference_paired_devices,
+                        BluetoothDeviceFilter.BONDED_DEVICE_FILTER, true);
+                int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
+
+                if (isUiRestricted() || numberOfPairedDevices <= 0) {
+                    if (preferenceScreen.findPreference(KEY_PAIRED_DEVICES) != null) {
+                        preferenceScreen.removePreference(mPairedDevicesCategory);
+                    }
+                } else {
+                    if (preferenceScreen.findPreference(KEY_PAIRED_DEVICES) == null) {
+                        preferenceScreen.addPreference(mPairedDevicesCategory);
+                    }
+                }
+
+                // Available devices category
+                addDeviceCategory(mAvailableDevicesCategory,
+                        R.string.bluetooth_preference_found_devices,
+                        BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, mInitialScanStarted);
+
+                if (!mInitialScanStarted) {
+                    startScanning();
+                }
+
+                updateMyDevicePreference(mMyDevicePreference);
+                getActivity().invalidateOptionsMenu();
+
+                // mLocalAdapter.setScanMode is internally synchronized so it is okay for multiple
+                // threads to execute.
+                if (mInitiateDiscoverable) {
+                    // Make the device visible to other devices.
+                    mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+                    mInitiateDiscoverable = false;
+                }
+                return; // not break
+
+            case BluetoothAdapter.STATE_TURNING_OFF:
+                messageId = R.string.bluetooth_turning_off;
+                break;
+
+            case BluetoothAdapter.STATE_OFF:
+                setOffMessage();
+                if (isUiRestricted()) {
+                    messageId = R.string.bluetooth_empty_list_user_restricted;
+                }
+                break;
+
+            case BluetoothAdapter.STATE_TURNING_ON:
+                messageId = R.string.bluetooth_turning_on;
+                mInitialScanStarted = false;
+                break;
+        }
+
+        setDeviceListGroup(preferenceScreen);
+        removeAllDevices();
+        if (messageId != 0) {
+            getEmptyTextView().setText(messageId);
+        }
+        if (!isUiRestricted()) {
+            getActivity().invalidateOptionsMenu();
+        }
+    }
+
+    private void setOffMessage() {
+        final TextView emptyView = getEmptyTextView();
+        if (emptyView == null) {
+            return;
+        }
+        final CharSequence briefText = getText(R.string.bluetooth_empty_list_bluetooth_off);
+
+        final ContentResolver resolver = getActivity().getContentResolver();
+        final boolean bleScanningMode = Settings.Global.getInt(
+                resolver, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
+
+        if (!bleScanningMode) {
+            // Show only the brief text if the scanning mode has been turned off.
+            emptyView.setText(briefText, TextView.BufferType.SPANNABLE);
+        } else {
+            final StringBuilder contentBuilder = new StringBuilder();
+            contentBuilder.append(briefText);
+            contentBuilder.append("\n\n");
+            contentBuilder.append(getText(R.string.ble_scan_notify_text));
+            LinkifyUtils.linkify(emptyView, contentBuilder, new LinkifyUtils.OnClickListener() {
+                @Override
+                public void onClick() {
+                    final SettingsActivity activity =
+                            (SettingsActivity) BluetoothSettingsObsolete.this.getActivity();
+                    activity.startPreferencePanel(BluetoothSettingsObsolete.this,
+                            ScanningSettings.class.getName(), null,
+                            R.string.location_scanning_screen_title, null, null, 0);
+                }
+            });
+        }
+        getPreferenceScreen().removeAll();
+        setTextSpan(emptyView.getText(), briefText);
+    }
+
+    @Override
+    public void onBluetoothStateChanged(int bluetoothState) {
+        super.onBluetoothStateChanged(bluetoothState);
+        // If BT is turned off/on staying in the same BT Settings screen
+        // discoverability to be set again
+        if (BluetoothAdapter.STATE_ON == bluetoothState) {
+            mInitiateDiscoverable = true;
+        }
+        updateContent(bluetoothState);
+    }
+
+    @Override
+    public void onScanningStateChanged(boolean started) {
+        super.onScanningStateChanged(started);
+        // Update options' enabled state
+        if (getActivity() != null) {
+            getActivity().invalidateOptionsMenu();
+        }
+    }
+
+    @Override
+    public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
+        setDeviceListGroup(getPreferenceScreen());
+        removeAllDevices();
+        updateContent(mLocalAdapter.getBluetoothState());
+    }
+
+    @VisibleForTesting
+    void setTextSpan(CharSequence text, CharSequence briefText) {
+        if (text instanceof Spannable) {
+            Spannable boldSpan = (Spannable) text;
+            boldSpan.setSpan(
+                    new TextAppearanceSpan(getActivity(), android.R.style.TextAppearance_Medium), 0,
+                    briefText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }
+    }
+
+    @VisibleForTesting
+    void updateMyDevicePreference(Preference myDevicePreference) {
+        final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+
+        myDevicePreference.setTitle(getString(
+                R.string.bluetooth_footer_mac_message,
+                bidiFormatter.unicodeWrap(mLocalAdapter.getAddress())));
+    }
+
+    @VisibleForTesting
+    void setLocalBluetoothAdapter(LocalBluetoothAdapter localAdapter) {
+        mLocalAdapter = localAdapter;
+    }
+
+    private final GearPreference.OnGearClickListener mDeviceProfilesListener = pref -> {
+        // User clicked on advanced options icon for a device in the list
+        if (!(pref instanceof BluetoothDevicePreference)) {
+            Log.w(TAG, "onClick() called for other View: " + pref);
+            return;
+        }
+        final CachedBluetoothDevice device =
+                ((BluetoothDevicePreference) pref).getBluetoothDevice();
+        if (device == null) {
+            Log.w(TAG, "No BT device attached with this pref: " + pref);
+            return;
+        }
+        final Bundle args = new Bundle();
+        args.putString(DeviceProfilesSettings.ARG_DEVICE_ADDRESS,
+                device.getDevice().getAddress());
+        final DeviceProfilesSettings profileSettings = new DeviceProfilesSettings();
+        profileSettings.setArguments(args);
+        profileSettings.show(getFragmentManager(),
+                DeviceProfilesSettings.class.getSimpleName());
+    };
+
+    /**
+     * Add a listener, which enables the advanced settings icon.
+     *
+     * @param preference the newly added preference
+     */
+    @Override
+    void initDevicePreference(BluetoothDevicePreference preference) {
+        CachedBluetoothDevice cachedDevice = preference.getCachedDevice();
+        if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
+            // Only paired device have an associated advanced settings screen
+            preference.setOnGearClickListener(mDeviceProfilesListener);
+        }
+    }
+
+    @Override
+    protected int getHelpResource() {
+        return R.string.help_url_bluetooth;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.bluetooth_settings_obsolete;
+    }
+
+    @Override
+    protected List<PreferenceController> getPreferenceControllers(Context context) {
+        List<PreferenceController> controllers = new ArrayList<>();
+        mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context,
+                this, getLifecycle());
+        controllers.add(mDeviceNamePrefController);
+
+        return controllers;
+    }
+
+    @VisibleForTesting
+    static class SummaryProvider implements SummaryLoader.SummaryProvider, OnSummaryChangeListener {
+
+        private final LocalBluetoothManager mBluetoothManager;
+        private final Context mContext;
+        private final SummaryLoader mSummaryLoader;
+
+        @VisibleForTesting
+        BluetoothSummaryUpdater mSummaryUpdater;
+
+        public SummaryProvider(Context context, SummaryLoader summaryLoader,
+                LocalBluetoothManager bluetoothManager) {
+            mBluetoothManager = bluetoothManager;
+            mContext = context;
+            mSummaryLoader = summaryLoader;
+            mSummaryUpdater = new BluetoothSummaryUpdater(mContext, this, mBluetoothManager);
+        }
+
+        @Override
+        public void setListening(boolean listening) {
+            mSummaryUpdater.register(listening);
+        }
+
+        @Override
+        public void onSummaryChanged(String summary) {
+            if (mSummaryLoader != null) {
+                mSummaryLoader.setSummary(this, summary);
+            }
+        }
+    }
+
+    public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
+            = new SummaryLoader.SummaryProviderFactory() {
+        @Override
+        public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
+                SummaryLoader summaryLoader) {
+
+            return new SummaryProvider(activity, summaryLoader, Utils.getLocalBtManager(activity));
+        }
+    };
+
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableRaw> getRawDataToIndex(Context context,
+                        boolean enabled) {
+
+                    final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
+
+                    final Resources res = context.getResources();
+
+                    // Add fragment title
+                    SearchIndexableRaw data = new SearchIndexableRaw(context);
+                    data.title = res.getString(R.string.bluetooth_settings);
+                    data.screenTitle = res.getString(R.string.bluetooth_settings);
+                    data.key = DATA_KEY_REFERENCE;
+                    result.add(data);
+
+                    // Add cached paired BT devices
+                    LocalBluetoothManager lbtm = Utils.getLocalBtManager(context);
+                    // LocalBluetoothManager.getInstance can return null if the device does not
+                    // support bluetooth (e.g. the emulator).
+                    if (lbtm != null) {
+                        Set<BluetoothDevice> bondedDevices =
+                                lbtm.getBluetoothAdapter().getBondedDevices();
+
+                        for (BluetoothDevice device : bondedDevices) {
+                            data = new SearchIndexableRaw(context);
+                            data.title = device.getName();
+                            data.screenTitle = res.getString(R.string.bluetooth_settings);
+                            data.enabled = enabled;
+                            result.add(data);
+                        }
+                    }
+                    return result;
+                }
+
+                @Override
+                public List<String> getNonIndexableKeys(Context context) {
+                    List<String> keys = super.getNonIndexableKeys(context);
+                    if (FeatureFactory.getFactory(context).getBluetoothFeatureProvider(
+                            context).isPairingPageEnabled()) {
+                        keys.add(DATA_KEY_REFERENCE);
+                    }
+                    return keys;
+                }
+
+            };
+}
index 4034316..c35e652 100644 (file)
@@ -41,6 +41,7 @@ import java.util.WeakHashMap;
  * @see BluetoothSettings
  * @see DevicePickerFragment
  */
+// TODO: Refactor this fragment
 public abstract class DeviceListPreferenceFragment extends
         RestrictedDashboardFragment implements BluetoothCallback {
 
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceObsoleteFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceObsoleteFragment.java
new file mode 100644 (file)
index 0000000..84d8558
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.os.Bundle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceGroup;
+import android.util.Log;
+
+import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import java.util.Collection;
+import java.util.WeakHashMap;
+
+/**
+ * Parent class for settings fragments that contain a list of Bluetooth
+ * devices.
+ *
+ * This fragment stores old implementation of {@link DeviceListPreferenceFragment} and is
+ * deprecated, please use {@link DeviceListPreferenceFragment} instead.
+ *
+ * @see BluetoothSettingsObsolete
+ * @see DevicePickerFragment
+ */
+@Deprecated
+public abstract class DeviceListPreferenceObsoleteFragment extends
+        RestrictedDashboardFragment implements BluetoothCallback {
+
+    private static final String TAG = "DeviceListPreferenceFragment";
+
+    private static final String KEY_BT_DEVICE_LIST = "bt_device_list";
+    private static final String KEY_BT_SCAN = "bt_scan";
+
+    private BluetoothDeviceFilter.Filter mFilter;
+
+    BluetoothDevice mSelectedDevice;
+
+    LocalBluetoothAdapter mLocalAdapter;
+    LocalBluetoothManager mLocalManager;
+
+    private PreferenceGroup mDeviceListGroup;
+
+    final WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
+            new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();
+
+    DeviceListPreferenceObsoleteFragment(String restrictedKey) {
+        super(restrictedKey);
+        mFilter = BluetoothDeviceFilter.ALL_FILTER;
+    }
+
+    final void setFilter(BluetoothDeviceFilter.Filter filter) {
+        mFilter = filter;
+    }
+
+    final void setFilter(int filterType) {
+        mFilter = BluetoothDeviceFilter.getFilter(filterType);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mLocalManager = Utils.getLocalBtManager(getActivity());
+        if (mLocalManager == null) {
+            Log.e(TAG, "Bluetooth is not supported on this device");
+            return;
+        }
+        mLocalAdapter = mLocalManager.getBluetoothAdapter();
+
+        addPreferencesForActivity();
+
+        mDeviceListGroup = (PreferenceCategory) findPreference(KEY_BT_DEVICE_LIST);
+    }
+
+    void setDeviceListGroup(PreferenceGroup preferenceGroup) {
+        mDeviceListGroup = preferenceGroup;
+    }
+
+    /** Add preferences from the subclass. */
+    abstract void addPreferencesForActivity();
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        if (mLocalManager == null || isUiRestricted()) return;
+
+        mLocalManager.setForegroundActivity(getActivity());
+        mLocalManager.getEventManager().registerCallback(this);
+
+        updateProgressUi(mLocalAdapter.isDiscovering());
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        if (mLocalManager == null || isUiRestricted()) {
+            return;
+        }
+
+        removeAllDevices();
+        mLocalManager.setForegroundActivity(null);
+        mLocalManager.getEventManager().unregisterCallback(this);
+    }
+
+    void removeAllDevices() {
+        mLocalAdapter.stopScanning();
+        mDevicePreferenceMap.clear();
+        mDeviceListGroup.removeAll();
+    }
+
+    void addCachedDevices() {
+        Collection<CachedBluetoothDevice> cachedDevices =
+                mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
+        for (CachedBluetoothDevice cachedDevice : cachedDevices) {
+            onDeviceAdded(cachedDevice);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        if (KEY_BT_SCAN.equals(preference.getKey())) {
+            mLocalAdapter.startScanning(true);
+            return true;
+        }
+
+        if (preference instanceof BluetoothDevicePreference) {
+            BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
+            CachedBluetoothDevice device = btPreference.getCachedDevice();
+            mSelectedDevice = device.getDevice();
+            onDevicePreferenceClick(btPreference);
+            return true;
+        }
+
+        return super.onPreferenceTreeClick(preference);
+    }
+
+    void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
+        btPreference.onClicked();
+    }
+
+    public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
+        if (mDevicePreferenceMap.get(cachedDevice) != null) {
+            return;
+        }
+
+        // Prevent updates while the list shows one of the state messages
+        if (mLocalAdapter.getBluetoothState() != BluetoothAdapter.STATE_ON) return;
+
+        if (mFilter.matches(cachedDevice.getDevice())) {
+            createDevicePreference(cachedDevice);
+        }
+    }
+
+    void createDevicePreference(CachedBluetoothDevice cachedDevice) {
+        if (mDeviceListGroup == null) {
+            Log.w(TAG, "Trying to create a device preference before the list group/category "
+                    + "exists!");
+            return;
+        }
+
+        String key = cachedDevice.getDevice().getAddress();
+        BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key);
+
+        if (preference == null) {
+            preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice);
+            preference.setKey(key);
+            mDeviceListGroup.addPreference(preference);
+        } else {
+            // Tell the preference it is being re-used in case there is new info in the
+            // cached device.
+            preference.rebind();
+        }
+
+        initDevicePreference(preference);
+        mDevicePreferenceMap.put(cachedDevice, preference);
+    }
+
+    /**
+     * Overridden in {@link BluetoothSettings} to add a listener.
+     * @param preference the newly added preference
+     */
+    void initDevicePreference(BluetoothDevicePreference preference) {
+        // Does nothing by default
+    }
+
+    public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
+        BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
+        if (preference != null) {
+            mDeviceListGroup.removePreference(preference);
+        }
+    }
+
+    public void onScanningStateChanged(boolean started) {
+        updateProgressUi(started);
+    }
+
+    private void updateProgressUi(boolean start) {
+        if (mDeviceListGroup instanceof BluetoothProgressCategory) {
+            ((BluetoothProgressCategory) mDeviceListGroup).setProgress(start);
+        }
+    }
+
+    public void onBluetoothStateChanged(int bluetoothState) {
+        if (bluetoothState == BluetoothAdapter.STATE_OFF) {
+            updateProgressUi(false);
+        }
+    }
+
+    public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { }
+}
index 8bf8202..cb8be50 100644 (file)
@@ -40,7 +40,7 @@ import java.util.List;
  * BluetoothSettings is the Settings screen for Bluetooth configuration and
  * connection management.
  */
-public final class DevicePickerFragment extends DeviceListPreferenceFragment {
+public final class DevicePickerFragment extends DeviceListPreferenceObsoleteFragment {
     private static final int MENU_ID_REFRESH = Menu.FIRST;
     private static final String TAG = "DevicePickerFragment";
 
index 6b172c2..27492ce 100644 (file)
@@ -23,6 +23,7 @@ import android.support.annotation.VisibleForTesting;
 
 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.core.PreferenceController;
@@ -71,7 +72,8 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
         controllers.add(mUsbPrefController);
         final BluetoothMasterSwitchPreferenceController bluetoothPreferenceController =
                 new BluetoothMasterSwitchPreferenceController(
-                        context, Utils.getLocalBtManager(context));
+                        context, Utils.getLocalBtManager(context), this,
+                        (SettingsActivity) getActivity());
         lifecycle.addObserver(bluetoothPreferenceController);
         controllers.add(bluetoothPreferenceController);
         return controllers;
index ce8135c..ab1af49 100644 (file)
@@ -40,6 +40,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.bluetooth.BluetoothSettingsObsolete;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.datausage.DataUsageMeteredSettings;
 import com.android.settings.datausage.DataUsageSummary;
@@ -110,6 +111,7 @@ public final class SearchIndexableResources {
         addIndex(SavedAccessPointsWifiSettings.class, NO_DATA_RES_ID,
                 R.drawable.ic_settings_wireless);
         addIndex(BluetoothSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_bluetooth);
+        addIndex(BluetoothSettingsObsolete.class, NO_DATA_RES_ID, R.drawable.ic_settings_bluetooth);
         addIndex(SimSettings.class, NO_DATA_RES_ID, R.drawable.ic_sim_sd);
         addIndex(DataUsageSummary.class, NO_DATA_RES_ID, R.drawable.ic_settings_data_usage);
         addIndex(DataUsageMeteredSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_data_usage);
index 706f33b..30afbd0 100644 (file)
@@ -74,6 +74,7 @@ class CursorToSearchResultConverter {
     private static final String[] whiteList = {
             "main_toggle_wifi",
             "main_toggle_bluetooth",
+            "main_toggle_bluetooth_obsolete",
             "toggle_airplane",
             "tether_settings",
             "battery_saver",
index 177130e..f0fb91c 100644 (file)
 
 package com.android.settings.bluetooth;
 
+import android.app.Fragment;
 import android.content.Context;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.widget.MasterSwitchPreference;
 import com.android.settingslib.bluetooth.BluetoothCallback;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -38,7 +42,10 @@ import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -54,17 +61,26 @@ public class BluetoothMasterSwitchPreferenceControllerTest {
     private MasterSwitchPreference mPreference;
     @Mock
     private RestrictionUtils mRestrictionUtils;
+    @Mock
+    private Fragment mFragment;
+    @Mock
+    private SettingsActivity mActivity;
 
     private Context mContext;
     private BluetoothMasterSwitchPreferenceController mController;
+    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application.getApplicationContext();
+        mContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
         mController = new BluetoothMasterSwitchPreferenceController(
-                mContext, mBluetoothManager, mRestrictionUtils);
+                mContext, mBluetoothManager, mRestrictionUtils, mFragment, mActivity);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
     }
 
     @Test
@@ -84,7 +100,7 @@ public class BluetoothMasterSwitchPreferenceControllerTest {
         mController.onPause();
 
         verify(mBluetoothManager.getEventManager()).unregisterCallback(
-            any(BluetoothCallback.class));
+                any(BluetoothCallback.class));
     }
 
     @Test
@@ -114,4 +130,22 @@ public class BluetoothMasterSwitchPreferenceControllerTest {
         verify(mPreference).setSummary("test summary");
     }
 
+    @Test
+    public void testHandlePreferenceTreeClick_pairPageEnabled_showNewPage() {
+        when(mFeatureFactory.bluetoothFeatureProvider.isPairingPageEnabled()).thenReturn(true);
+
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mActivity).startPreferencePanelAsUser(eq(mFragment),
+                eq(BluetoothSettings.class.getName()), any(), eq(R.string.bluetooth), any(), any());
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_pairPageDisabled_showOldPage() {
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mActivity).startPreferencePanelAsUser(eq(mFragment),
+                eq(BluetoothSettingsObsolete.class.getName()), any(), eq(R.string.bluetooth), any(),
+                any());
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsObsoleteTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsObsoleteTest.java
new file mode 100644 (file)
index 0000000..549eeb7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+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.annotation.Config;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BluetoothSettingsObsoleteTest {
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    private BluetoothSettingsObsolete mFragment;
+    private FakeFeatureFactory mFeatureFactory;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
+        mFragment = spy(new BluetoothSettingsObsolete());
+        doReturn(mContext).when(mFragment).getContext();
+    }
+
+    @Test
+    public void testSearchIndexProvider_pairPageEnabled_keyAdded() {
+        doReturn(true).when(mFeatureFactory.bluetoothFeatureProvider).isPairingPageEnabled();
+
+        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+                mContext);
+
+        assertThat(keys).contains(BluetoothSettingsObsolete.DATA_KEY_REFERENCE);
+    }
+
+    @Test
+    public void testSearchIndexProvider_pairPageDisabled_keyNotAdded() {
+        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+                mContext);
+
+        assertThat(keys).doesNotContain(BluetoothSettingsObsolete.DATA_KEY_REFERENCE);
+    }
+
+}
index 35207f5..c0aa723 100644 (file)
@@ -31,16 +31,20 @@ import android.support.v7.preference.Preference;
 import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 
 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)
 public class BluetoothSettingsTest {
@@ -50,17 +54,21 @@ public class BluetoothSettingsTest {
     private UserManager mUserManager;
     @Mock
     private Resources mResource;
-    @Mock
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     @Mock
     private LocalBluetoothAdapter mLocalAdapter;
     private BluetoothSettings mFragment;
     private Preference mMyDevicePreference;
+    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
         mFragment = spy(new BluetoothSettings());
         doReturn(mContext).when(mFragment).getContext();
         doReturn(mResource).when(mFragment).getResources();
@@ -86,4 +94,22 @@ public class BluetoothSettingsTest {
         assertThat(mMyDevicePreference.getTitle()).isEqualTo(FOOTAGE_MAC_STRING);
     }
 
+    @Test
+    public void testSearchIndexProvider_pairPageEnabled_keyNotAdded() {
+        doReturn(true).when(mFeatureFactory.bluetoothFeatureProvider).isPairingPageEnabled();
+
+        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+                mContext);
+
+        assertThat(keys).doesNotContain(BluetoothSettings.DATA_KEY_REFERENCE);
+    }
+
+    @Test
+    public void testSearchIndexProvider_pairPageDisabled_keyAdded() {
+        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+                mContext);
+
+        assertThat(keys).contains(BluetoothSettings.DATA_KEY_REFERENCE);
+    }
+
 }
index 7421570..72cbf4e 100644 (file)
@@ -22,10 +22,10 @@ import android.nfc.NfcManager;
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.R;
+import com.android.settings.nfc.NfcPreferenceController;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.dashboard.SummaryLoader;
-import com.android.settings.nfc.NfcPreferenceController;
 import com.android.settings.testutils.XmlTestUtils;
 import com.android.settingslib.drawer.CategoryKey;