If the Bluetooth enable(true) returns false currently we are waiting for a broadcast (which may not happen if enable returns false). We mark the toggle to have failed (i.e. it is clickable and in OFF state) and the switch bar text is appropriately shown. Bug: b/28318203 Change-Id: I09ba46d2e102e7f2c4ef9a72bf38dedc1346364f
207 lines
7.1 KiB
Java
207 lines
7.1 KiB
Java
/*
|
|
* Copyright (C) 2010 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.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.os.Handler;
|
|
import android.os.Message;
|
|
import android.provider.Settings;
|
|
import android.util.Log;
|
|
import android.widget.Switch;
|
|
import android.widget.Toast;
|
|
|
|
import com.android.internal.logging.MetricsLogger;
|
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
|
import com.android.settings.R;
|
|
import com.android.settings.search.Index;
|
|
import com.android.settings.widget.SwitchBar;
|
|
import com.android.settingslib.WirelessUtils;
|
|
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
|
|
|
/**
|
|
* BluetoothEnabler is a helper to manage the Bluetooth on/off checkbox
|
|
* preference. It turns on/off Bluetooth and ensures the summary of the
|
|
* preference reflects the current state.
|
|
*/
|
|
public final class BluetoothEnabler implements SwitchBar.OnSwitchChangeListener {
|
|
private Context mContext;
|
|
private Switch mSwitch;
|
|
private SwitchBar mSwitchBar;
|
|
private boolean mValidListener;
|
|
private final LocalBluetoothAdapter mLocalAdapter;
|
|
private final IntentFilter mIntentFilter;
|
|
|
|
private static final String EVENT_DATA_IS_BT_ON = "is_bluetooth_on";
|
|
private static final int EVENT_UPDATE_INDEX = 0;
|
|
|
|
private Handler mHandler = new Handler() {
|
|
@Override
|
|
public void handleMessage(Message msg) {
|
|
switch (msg.what) {
|
|
case EVENT_UPDATE_INDEX:
|
|
final boolean isBluetoothOn = msg.getData().getBoolean(EVENT_DATA_IS_BT_ON);
|
|
Index.getInstance(mContext).updateFromClassNameResource(
|
|
BluetoothSettings.class.getName(), true, isBluetoothOn);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
// Broadcast receiver is always running on the UI thread here,
|
|
// so we don't need consider thread synchronization.
|
|
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
|
|
handleStateChanged(state);
|
|
}
|
|
};
|
|
|
|
public BluetoothEnabler(Context context, SwitchBar switchBar) {
|
|
mContext = context;
|
|
mSwitchBar = switchBar;
|
|
mSwitch = switchBar.getSwitch();
|
|
mValidListener = false;
|
|
|
|
LocalBluetoothManager manager = Utils.getLocalBtManager(context);
|
|
if (manager == null) {
|
|
// Bluetooth is not supported
|
|
mLocalAdapter = null;
|
|
mSwitch.setEnabled(false);
|
|
} else {
|
|
mLocalAdapter = manager.getBluetoothAdapter();
|
|
}
|
|
mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
|
|
}
|
|
|
|
public void setupSwitchBar() {
|
|
mSwitchBar.show();
|
|
}
|
|
|
|
public void teardownSwitchBar() {
|
|
mSwitchBar.hide();
|
|
}
|
|
|
|
public void resume(Context context) {
|
|
if (mLocalAdapter == null) {
|
|
mSwitch.setEnabled(false);
|
|
return;
|
|
}
|
|
|
|
if (mContext != context) {
|
|
mContext = context;
|
|
}
|
|
|
|
// Bluetooth state is not sticky, so set it manually
|
|
handleStateChanged(mLocalAdapter.getBluetoothState());
|
|
|
|
mSwitchBar.addOnSwitchChangeListener(this);
|
|
mContext.registerReceiver(mReceiver, mIntentFilter);
|
|
mValidListener = true;
|
|
}
|
|
|
|
public void pause() {
|
|
if (mLocalAdapter == null) {
|
|
return;
|
|
}
|
|
|
|
mSwitchBar.removeOnSwitchChangeListener(this);
|
|
mContext.unregisterReceiver(mReceiver);
|
|
mValidListener = false;
|
|
}
|
|
|
|
void handleStateChanged(int state) {
|
|
switch (state) {
|
|
case BluetoothAdapter.STATE_TURNING_ON:
|
|
mSwitch.setEnabled(false);
|
|
break;
|
|
case BluetoothAdapter.STATE_ON:
|
|
setChecked(true);
|
|
mSwitch.setEnabled(true);
|
|
updateSearchIndex(true);
|
|
break;
|
|
case BluetoothAdapter.STATE_TURNING_OFF:
|
|
mSwitch.setEnabled(false);
|
|
break;
|
|
case BluetoothAdapter.STATE_OFF:
|
|
setChecked(false);
|
|
mSwitch.setEnabled(true);
|
|
updateSearchIndex(false);
|
|
break;
|
|
default:
|
|
setChecked(false);
|
|
mSwitch.setEnabled(true);
|
|
updateSearchIndex(false);
|
|
}
|
|
}
|
|
|
|
private void setChecked(boolean isChecked) {
|
|
if (isChecked != mSwitch.isChecked()) {
|
|
// set listener to null, so onCheckedChanged won't be called
|
|
// if the checked status on Switch isn't changed by user click
|
|
if (mValidListener) {
|
|
mSwitchBar.removeOnSwitchChangeListener(this);
|
|
}
|
|
mSwitch.setChecked(isChecked);
|
|
if (mValidListener) {
|
|
mSwitchBar.addOnSwitchChangeListener(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void updateSearchIndex(boolean isBluetoothOn) {
|
|
mHandler.removeMessages(EVENT_UPDATE_INDEX);
|
|
|
|
Message msg = new Message();
|
|
msg.what = EVENT_UPDATE_INDEX;
|
|
msg.getData().putBoolean(EVENT_DATA_IS_BT_ON, isBluetoothOn);
|
|
mHandler.sendMessage(msg);
|
|
}
|
|
|
|
@Override
|
|
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
|
// Show toast message if Bluetooth is not allowed in airplane mode
|
|
if (isChecked &&
|
|
!WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
|
|
Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
|
|
// Reset switch to off
|
|
switchView.setChecked(false);
|
|
}
|
|
|
|
MetricsLogger.action(mContext, MetricsEvent.ACTION_BLUETOOTH_TOGGLE, isChecked);
|
|
|
|
if (mLocalAdapter != null) {
|
|
boolean status = mLocalAdapter.setBluetoothEnabled(isChecked);
|
|
// If we cannot toggle it ON then reset the UI assets:
|
|
// a) The switch should be OFF but it should still be togglable (enabled = True)
|
|
// b) The switch bar should have OFF text.
|
|
if (isChecked && !status) {
|
|
switchView.setChecked(false);
|
|
mSwitch.setEnabled(true);
|
|
mSwitchBar.setTextViewLabel(false);
|
|
return;
|
|
}
|
|
}
|
|
mSwitch.setEnabled(false);
|
|
}
|
|
}
|