Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9eac1828 authored by Salvador Martinez's avatar Salvador Martinez
Browse files

Update bluetooth preference to take user to new screen

This CL removes the toggle from the bluetooth preference and instead
takes users to a new dedicated screen for toggling bluetooth status.
On this screen we show a different summary text depending on whether
bluetooth and bluetooth scanning are on/off. Also, we were able to
delegate most of the UI/bluetooth handling to already existing
classes.

Test: robotests
Bug: 77543471
Merged-In: I036a3992bbd78896da8364b55ecc51afc4464b6e
Change-Id: I036a3992bbd78896da8364b55ecc51afc4464b6e
parent d57d27ac
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -1613,6 +1613,8 @@
    <string name="bluetooth_advanced_titlebar">Advanced Bluetooth</string>
    <string name="bluetooth_advanced_titlebar">Advanced Bluetooth</string>
    <!-- Bluetooth settings. Text displayed when Bluetooth is off and device list is empty [CHAR LIMIT=50]-->
    <!-- Bluetooth settings. Text displayed when Bluetooth is off and device list is empty [CHAR LIMIT=50]-->
    <string name="bluetooth_empty_list_bluetooth_off">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices.</string>
    <string name="bluetooth_empty_list_bluetooth_off">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices.</string>
    <!-- Bluetooth settings. Text displayed when Bluetooth is off and bluetooth scanning is turned on [CHAR LIMIT=NONE] -->
    <string name="bluetooth_scanning_on_info_message">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices.\n\nTo improve device experience, apps and services can still scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services. you can change this in <annotation id="link">scanning settings</annotation>.</string>
    <!-- Message to describe "BLE scan always available feature" when Bluetooth is off. The
    <!-- Message to describe "BLE scan always available feature" when Bluetooth is off. The
      place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated. They mark a link to bring
      place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated. They mark a link to bring
      the user to "scanning settings" screen. -->
      the user to "scanning settings" screen. -->
@@ -6692,6 +6694,8 @@
    <string name="help_uri_wifi_calling" translatable="false"></string>
    <string name="help_uri_wifi_calling" translatable="false"></string>
    <!-- url for the wifi scanning required dialog help page -->
    <!-- url for the wifi scanning required dialog help page -->
    <string name="help_uri_wifi_scanning_required" translatable="false"></string>
    <string name="help_uri_wifi_scanning_required" translatable="false"></string>
    <!-- url for the bluetooth toggle required dialog help page -->
    <string name="help_uri_bluetooth_screen" translatable="false"></string>
    <!-- User account title [CHAR LIMIT=30] -->
    <!-- User account title [CHAR LIMIT=30] -->
    <string name="user_account_title">Account for content</string>
    <string name="user_account_title">Account for content</string>
+19 −0
Original line number Original line Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:key="bluetooth_switchbar_screen"
    android:title="@string/bluetooth_settings_title" />
 No newline at end of file
+4 −6
Original line number Original line Diff line number Diff line
@@ -42,14 +42,12 @@
        android:fragment="com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment"
        android:fragment="com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment"
        settings:allowDividerAbove="true"/>
        settings:allowDividerAbove="true"/>


    <com.android.settingslib.RestrictedSwitchPreference
    <Preference
        android:key="toggle_bluetooth_switch"
        android:fragment="com.android.settings.connecteddevice.BluetoothDashboardFragment"
        android:key="bluetooth_settings"
        android:title="@string/bluetooth_settings_title"
        android:title="@string/bluetooth_settings_title"
        android:icon="@drawable/ic_settings_bluetooth"
        android:icon="@drawable/ic_settings_bluetooth"
        android:summary="@string/bluetooth_pref_summary"
        settings:allowDividerAbove="true"/>
        settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
        settings:userRestriction="no_bluetooth"
        settings:platform_slice="true"/>


    <SwitchPreference
    <SwitchPreference
        android:key="toggle_nfc"
        android:key="toggle_nfc"
+21 −0
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
    private final LocalBluetoothAdapter mLocalAdapter;
    private final LocalBluetoothAdapter mLocalAdapter;
    private final IntentFilter mIntentFilter;
    private final IntentFilter mIntentFilter;
    private final RestrictionUtils mRestrictionUtils;
    private final RestrictionUtils mRestrictionUtils;
    private SwitchWidgetController.OnSwitchChangeListener mCallback;


    private static final String EVENT_DATA_IS_BT_ON = "is_bluetooth_on";
    private static final String EVENT_DATA_IS_BT_ON = "is_bluetooth_on";
    private static final int EVENT_UPDATE_INDEX = 0;
    private static final int EVENT_UPDATE_INDEX = 0;
@@ -170,6 +171,7 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
    @Override
    @Override
    public boolean onSwitchToggled(boolean isChecked) {
    public boolean onSwitchToggled(boolean isChecked) {
        if (maybeEnforceRestrictions()) {
        if (maybeEnforceRestrictions()) {
            triggerParentPreferenceCallback(isChecked);
            return true;
            return true;
        }
        }


@@ -179,6 +181,7 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
            Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
            Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
            // Reset switch to off
            // Reset switch to off
            mSwitchController.setChecked(false);
            mSwitchController.setChecked(false);
            triggerParentPreferenceCallback(false);
            return false;
            return false;
        }
        }


@@ -193,13 +196,24 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
                mSwitchController.setChecked(false);
                mSwitchController.setChecked(false);
                mSwitchController.setEnabled(true);
                mSwitchController.setEnabled(true);
                mSwitchController.updateTitle(false);
                mSwitchController.updateTitle(false);
                triggerParentPreferenceCallback(false);
                return false;
                return false;
            }
            }
        }
        }
        mSwitchController.setEnabled(false);
        mSwitchController.setEnabled(false);
        triggerParentPreferenceCallback(isChecked);
        return true;
        return true;
    }
    }


    /**
     * Sets a callback back that this enabler will trigger in case the preference using the enabler
     * still needed the callback on the SwitchController (which we now use).
     * @param listener The listener with a callback to trigger.
     */
    public void setToggleCallback(SwitchWidgetController.OnSwitchChangeListener listener) {
        mCallback = listener;
    }

    /**
    /**
     * Enforces user restrictions disallowing Bluetooth (or its configuration) if there are any.
     * Enforces user restrictions disallowing Bluetooth (or its configuration) if there are any.
     *
     *
@@ -227,4 +241,11 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
        return admin;
        return admin;
    }
    }


    // This triggers the callback which was manually set for this enabler since the enabler will
    // take over the switch controller callback
    private void triggerParentPreferenceCallback(boolean isChecked) {
        if (mCallback != null) {
            mCallback.onSwitchToggled(isChecked);
        }
    }
}
}
+57 −93
Original line number Original line Diff line number Diff line
@@ -16,75 +16,79 @@
package com.android.settings.bluetooth;
package com.android.settings.bluetooth;


import android.content.Context;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.view.View;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.location.ScanningSettings;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.utils.AnnotationSpan;
import com.android.settings.widget.SwitchWidgetController;
import com.android.settings.widget.SwitchWidgetController;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.widget.FooterPreference;


/**
/**
 * PreferenceController to update of bluetooth {@link SwitchPreference}. It will
 * PreferenceController to update of bluetooth state. All behavior except managing the footer text
 *
 * is delegated to the SwitchWidgetController it uses.
 * 1. Invoke the user toggle
 * 2. Listen to the update from {@link LocalBluetoothManager}
 */
 */
public class BluetoothSwitchPreferenceController extends TogglePreferenceController
public class BluetoothSwitchPreferenceController
        implements LifecycleObserver, OnStart, OnStop {
        implements LifecycleObserver, OnStart, OnStop,
        SwitchWidgetController.OnSwitchChangeListener, View.OnClickListener {


    public static final String KEY_TOGGLE_BLUETOOTH = "toggle_bluetooth_switch";
    @VisibleForTesting
    LocalBluetoothAdapter mBluetoothAdapter;


    private LocalBluetoothManager mBluetoothManager;
    private LocalBluetoothManager mBluetoothManager;
    private SwitchPreference mBtPreference;
    private BluetoothEnabler mBluetoothEnabler;
    private BluetoothEnabler mBluetoothEnabler;
    private RestrictionUtils mRestrictionUtils;
    private RestrictionUtils mRestrictionUtils;
    @VisibleForTesting
    private SwitchWidgetController mSwitch;
    LocalBluetoothAdapter mBluetoothAdapter;
    private Context mContext;
    private FooterPreference mFooterPreference;


    public BluetoothSwitchPreferenceController(Context context) {
    public BluetoothSwitchPreferenceController(Context context,
        this(context, Utils.getLocalBtManager(context), new RestrictionUtils());
            SwitchWidgetController switchController,
            FooterPreference footerPreference) {
        this(context, Utils.getLocalBtManager(context), new RestrictionUtils(), switchController,
                footerPreference);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
    public BluetoothSwitchPreferenceController(Context context,
    public BluetoothSwitchPreferenceController(Context context,
            LocalBluetoothManager bluetoothManager, RestrictionUtils restrictionUtils) {
            LocalBluetoothManager bluetoothManager, RestrictionUtils restrictionUtils,
        super(context, KEY_TOGGLE_BLUETOOTH);
            SwitchWidgetController switchController, FooterPreference footerPreference) {
        mBluetoothManager = bluetoothManager;
        mBluetoothManager = bluetoothManager;
        mRestrictionUtils = restrictionUtils;
        mRestrictionUtils = restrictionUtils;
        mSwitch = switchController;
        mContext = context;
        mFooterPreference = footerPreference;

        mSwitch.setupView();
        updateText(mSwitch.isChecked());


        if (mBluetoothManager != null) {
        if (mBluetoothManager != null) {
            mBluetoothAdapter = mBluetoothManager.getBluetoothAdapter();
            mBluetoothAdapter = mBluetoothManager.getBluetoothAdapter();
        }
        }
    }
        mBluetoothEnabler = new BluetoothEnabler(context,

                switchController,
    @Override
                FeatureFactory.getFactory(context).getMetricsFeatureProvider(), mBluetoothManager,
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mBtPreference = (SwitchPreference) screen.findPreference(KEY_TOGGLE_BLUETOOTH);
        mBluetoothEnabler = new BluetoothEnabler(mContext,
                new SwitchController(mBtPreference),
                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(), mBluetoothManager,
                MetricsEvent.ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE,
                MetricsEvent.ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE,
                mRestrictionUtils);
                mRestrictionUtils);
    }
        mBluetoothEnabler.setToggleCallback(this);

    @Override
    public int getAvailabilityStatus() {
        return mBluetoothAdapter != null ? AVAILABLE : DISABLED_UNSUPPORTED;
    }
    }


    @Override
    @Override
    public void onStart() {
    public void onStart() {
        mBluetoothEnabler.resume(mContext);
        mBluetoothEnabler.resume(mContext);
        if (mSwitch != null) {
            updateText(mSwitch.isChecked());
        }
    }
    }


    @Override
    @Override
@@ -93,70 +97,30 @@ public class BluetoothSwitchPreferenceController extends TogglePreferenceControl
    }
    }


    @Override
    @Override
    public boolean isChecked() {
    public boolean onSwitchToggled(boolean isChecked) {
        return mBluetoothAdapter != null ? mBluetoothAdapter.isEnabled() : false;
        updateText(isChecked);
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.setBluetoothEnabled(isChecked);
        }
        return true;
        return true;
    }
    }


    /**
     * Control the switch inside {@link SwitchPreference}
     */
    @VisibleForTesting
    static class SwitchController extends SwitchWidgetController implements
            Preference.OnPreferenceChangeListener {
        private SwitchPreference mSwitchPreference;

        public SwitchController(SwitchPreference switchPreference) {
            mSwitchPreference = switchPreference;
        }

        @Override
        public void updateTitle(boolean isChecked) {
        }

        @Override
        public void startListening() {
            mSwitchPreference.setOnPreferenceChangeListener(this);
        }

        @Override
        public void stopListening() {
            mSwitchPreference.setOnPreferenceChangeListener(null);
        }

        @Override
        public void setChecked(boolean checked) {
            mSwitchPreference.setChecked(checked);
        }

        @Override
        public boolean isChecked() {
            return mSwitchPreference.isChecked();
        }

        @Override
        public void setEnabled(boolean enabled) {
            mSwitchPreference.setEnabled(enabled);
        }

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            if (mListener != null) {
                return mListener.onSwitchToggled((Boolean) newValue);
            }
            return false;
        }

    @Override
    @Override
        public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
    public void onClick(View v) {
            mSwitchPreference.setEnabled(admin == null);
        // send users to scanning settings if they click on the link in the summary text
        new SubSettingLauncher(mContext)
                .setDestination(ScanningSettings.class.getName())
                .setSourceMetricsCategory(MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT)
                .launch();
    }

    @VisibleForTesting void updateText(boolean isChecked) {
        if (!isChecked
                && Utils.isBluetoothScanningEnabled(mContext)) {
            AnnotationSpan.LinkInfo info = new AnnotationSpan.LinkInfo(
                    AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, this);
            CharSequence text = AnnotationSpan.linkify(
                    mContext.getText(R.string.bluetooth_scanning_on_info_message), info);
            mFooterPreference.setTitle(text);
        } else {
            mFooterPreference.setTitle(R.string.bluetooth_empty_list_bluetooth_off);
        }
        }
    }
    }
}
}
 No newline at end of file
Loading