blob: 37e48ff9f0acaf2cc91f0a87e3f89a28a70b0702 [file] [log] [blame]
/*
* Copyright (C) 2008 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 com.android.settings.R;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.SystemProperties;
import android.preference.Preference;
import android.preference.CheckBoxPreference;
/**
* BluetoothDiscoverableEnabler is a helper to manage the "Discoverable"
* checkbox. It sets/unsets discoverability and keeps track of how much time
* until the the discoverability is automatically turned off.
*/
public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChangeListener {
private static final String TAG = "BluetoothDiscoverableEnabler";
private static final String SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT =
"debug.bt.discoverable_time";
/* package */ static final int DEFAULT_DISCOVERABLE_TIMEOUT = 120;
/* package */ static final String SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP =
"discoverable_end_timestamp";
private final Context mContext;
private final Handler mUiHandler;
private final CheckBoxPreference mCheckBoxPreference;
private final LocalBluetoothManager mLocalManager;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
BluetoothAdapter.ERROR);
if (mode != BluetoothAdapter.ERROR) {
handleModeChanged(mode);
}
}
}
};
private final Runnable mUpdateCountdownSummaryRunnable = new Runnable() {
public void run() {
updateCountdownSummary();
}
};
public BluetoothDiscoverableEnabler(Context context, CheckBoxPreference checkBoxPreference) {
mContext = context;
mUiHandler = new Handler();
mCheckBoxPreference = checkBoxPreference;
checkBoxPreference.setPersistent(false);
mLocalManager = LocalBluetoothManager.getInstance(context);
if (mLocalManager == null) {
// Bluetooth not supported
checkBoxPreference.setEnabled(false);
}
}
public void resume() {
if (mLocalManager == null) {
return;
}
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
mContext.registerReceiver(mReceiver, filter);
mCheckBoxPreference.setOnPreferenceChangeListener(this);
handleModeChanged(mLocalManager.getBluetoothAdapter().getScanMode());
}
public void pause() {
if (mLocalManager == null) {
return;
}
mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable);
mCheckBoxPreference.setOnPreferenceChangeListener(null);
mContext.unregisterReceiver(mReceiver);
}
public boolean onPreferenceChange(Preference preference, Object value) {
// Turn on/off BT discoverability
setEnabled((Boolean) value);
return true;
}
private void setEnabled(final boolean enable) {
BluetoothAdapter manager = mLocalManager.getBluetoothAdapter();
if (enable) {
int timeout = getDiscoverableTimeout();
manager.setDiscoverableTimeout(timeout);
mCheckBoxPreference.setSummaryOn(
mContext.getResources().getString(R.string.bluetooth_is_discoverable, timeout));
long endTimestamp = System.currentTimeMillis() + timeout * 1000;
persistDiscoverableEndTimestamp(endTimestamp);
manager.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
} else {
manager.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
}
}
private int getDiscoverableTimeout() {
int timeout = SystemProperties.getInt(SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT, -1);
if (timeout <= 0) {
timeout = DEFAULT_DISCOVERABLE_TIMEOUT;
}
return timeout;
}
private void persistDiscoverableEndTimestamp(long endTimestamp) {
SharedPreferences.Editor editor = mLocalManager.getSharedPreferences().edit();
editor.putLong(SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, endTimestamp);
editor.apply();
}
private void handleModeChanged(int mode) {
if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
mCheckBoxPreference.setChecked(true);
updateCountdownSummary();
} else {
mCheckBoxPreference.setChecked(false);
}
}
private void updateCountdownSummary() {
int mode = mLocalManager.getBluetoothAdapter().getScanMode();
if (mode != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
return;
}
long currentTimestamp = System.currentTimeMillis();
long endTimestamp = mLocalManager.getSharedPreferences().getLong(
SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, 0);
if (currentTimestamp > endTimestamp) {
// We're still in discoverable mode, but maybe there isn't a timeout.
mCheckBoxPreference.setSummaryOn(null);
return;
}
String formattedTimeLeft = String.valueOf((endTimestamp - currentTimestamp) / 1000);
mCheckBoxPreference.setSummaryOn(
mContext.getResources().getString(R.string.bluetooth_is_discoverable,
formattedTimeLeft));
synchronized (this) {
mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable);
mUiHandler.postDelayed(mUpdateCountdownSummaryRunnable, 1000);
}
}
}