BluetoothDiscoverableEnabler.java revision abc48f80d8747b4fc051b7dd364355ee667a9bac
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.settings.bluetooth; 18 19import com.android.settings.R; 20 21import android.bluetooth.BluetoothDevice; 22import android.bluetooth.BluetoothIntent; 23import android.content.BroadcastReceiver; 24import android.content.Context; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.content.SharedPreferences; 28import android.os.Handler; 29import android.os.SystemProperties; 30import android.preference.Preference; 31import android.preference.CheckBoxPreference; 32import android.util.Log; 33 34/** 35 * BluetoothDiscoverableEnabler is a helper to manage the "Discoverable" 36 * checkbox. It sets/unsets discoverability and keeps track of how much time 37 * until the the discoverability is automatically turned off. 38 */ 39public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChangeListener { 40 private static final String TAG = "BluetoothDiscoverableEnabler"; 41 private static final boolean V = LocalBluetoothManager.V; 42 43 private static final String SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT = 44 "debug.bt.discoverable_time"; 45 private static final int DISCOVERABLE_TIMEOUT = 120; 46 47 private static final String SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP = 48 "discoverable_end_timestamp"; 49 50 private final Context mContext; 51 private final Handler mUiHandler; 52 private final CheckBoxPreference mCheckBoxPreference; 53 54 private final LocalBluetoothManager mLocalManager; 55 56 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 57 @Override 58 public void onReceive(Context context, Intent intent) { 59 handleModeChanged(intent.getIntExtra(BluetoothIntent.MODE, 60 BluetoothDevice.MODE_UNKNOWN)); 61 } 62 }; 63 64 private final Runnable mUpdateCountdownSummaryRunnable = new Runnable() { 65 public void run() { 66 updateCountdownSummary(); 67 } 68 }; 69 70 public BluetoothDiscoverableEnabler(Context context, CheckBoxPreference checkBoxPreference) { 71 mContext = context; 72 mUiHandler = new Handler(); 73 mCheckBoxPreference = checkBoxPreference; 74 75 checkBoxPreference.setPersistent(false); 76 77 mLocalManager = LocalBluetoothManager.getInstance(context); 78 if (mLocalManager == null) { 79 // Bluetooth not supported 80 checkBoxPreference.setEnabled(false); 81 } 82 } 83 84 public void resume() { 85 if (mLocalManager == null) { 86 return; 87 } 88 89 mContext.registerReceiver(mReceiver, 90 new IntentFilter(BluetoothIntent.MODE_CHANGED_ACTION)); 91 mCheckBoxPreference.setOnPreferenceChangeListener(this); 92 93 handleModeChanged(mLocalManager.getBluetoothManager().getMode()); 94 } 95 96 public void pause() { 97 if (mLocalManager == null) { 98 return; 99 } 100 101 mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable); 102 mCheckBoxPreference.setOnPreferenceChangeListener(null); 103 mContext.unregisterReceiver(mReceiver); 104 } 105 106 public boolean onPreferenceChange(Preference preference, Object value) { 107 if (V) { 108 Log.v(TAG, "Preference changed to " + value); 109 } 110 111 // Turn on/off BT discoverability 112 setEnabled((Boolean) value); 113 114 return true; 115 } 116 117 private void setEnabled(final boolean enable) { 118 BluetoothDevice manager = mLocalManager.getBluetoothManager(); 119 120 if (enable) { 121 122 int timeout = getDiscoverableTimeout(); 123 manager.setDiscoverableTimeout(timeout); 124 125 long endTimestamp = System.currentTimeMillis() + timeout * 1000; 126 persistDiscoverableEndTimestamp(endTimestamp); 127 128 manager.setMode(BluetoothDevice.MODE_DISCOVERABLE); 129 handleModeChanged(BluetoothDevice.MODE_DISCOVERABLE); 130 131 } else { 132 manager.setMode(BluetoothDevice.MODE_CONNECTABLE); 133 } 134 } 135 136 private int getDiscoverableTimeout() { 137 int timeout = SystemProperties.getInt(SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT, -1); 138 if (timeout <= 0) { 139 timeout = DISCOVERABLE_TIMEOUT; 140 } 141 142 return timeout; 143 } 144 145 private void persistDiscoverableEndTimestamp(long endTimestamp) { 146 SharedPreferences.Editor editor = mLocalManager.getSharedPreferences().edit(); 147 editor.putLong(SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, endTimestamp); 148 editor.commit(); 149 } 150 151 private void handleModeChanged(int mode) { 152 if (V) { 153 Log.v(TAG, "Got mode changed: " + mode); 154 } 155 156 if (mode == BluetoothDevice.MODE_DISCOVERABLE) { 157 mCheckBoxPreference.setChecked(true); 158 updateCountdownSummary(); 159 160 } else { 161 mCheckBoxPreference.setChecked(false); 162 } 163 } 164 165 private void updateCountdownSummary() { 166 int mode = mLocalManager.getBluetoothManager().getMode(); 167 if (mode != BluetoothDevice.MODE_DISCOVERABLE) return; 168 169 long currentTimestamp = System.currentTimeMillis(); 170 long endTimestamp = mLocalManager.getSharedPreferences().getLong( 171 SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, 0); 172 173 if (currentTimestamp > endTimestamp) { 174 // We're still in discoverable mode, but maybe there isn't a timeout. 175 mCheckBoxPreference.setSummaryOn(null); 176 return; 177 } 178 179 String formattedTimeLeft = String.valueOf((endTimestamp - currentTimestamp) / 1000); 180 181 mCheckBoxPreference.setSummaryOn( 182 mContext.getResources().getString(R.string.bluetooth_is_discoverable, 183 formattedTimeLeft)); 184 185 synchronized (this) { 186 mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable); 187 mUiHandler.postDelayed(mUpdateCountdownSummaryRunnable, 1000); 188 } 189 } 190 191 192} 193