BluetoothDiscoverableEnabler.java revision 5962e18d0e5741511e78102a3746828b05f9f9ea
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 /* 60 * TODO: remove this once the BT framework broadcasts the 61 * MODE_CHANGED action when going into MODE_OFF. 62 */ 63 int mode = BluetoothIntent.DISABLED_ACTION.equals(intent.getAction()) 64 ? BluetoothDevice.MODE_OFF 65 : intent.getIntExtra(BluetoothIntent.MODE, BluetoothDevice.MODE_UNKNOWN); 66 handleModeChanged(mode); 67 } 68 }; 69 70 private final Runnable mUpdateCountdownSummaryRunnable = new Runnable() { 71 public void run() { 72 updateCountdownSummary(); 73 } 74 }; 75 76 public BluetoothDiscoverableEnabler(Context context, CheckBoxPreference checkBoxPreference) { 77 mContext = context; 78 mUiHandler = new Handler(); 79 mCheckBoxPreference = checkBoxPreference; 80 81 checkBoxPreference.setPersistent(false); 82 83 mLocalManager = LocalBluetoothManager.getInstance(context); 84 if (mLocalManager == null) { 85 // Bluetooth not supported 86 checkBoxPreference.setEnabled(false); 87 } 88 } 89 90 public void resume() { 91 if (mLocalManager == null) { 92 return; 93 } 94 95 IntentFilter filter = new IntentFilter(BluetoothIntent.MODE_CHANGED_ACTION); 96 filter.addAction(BluetoothIntent.DISABLED_ACTION); 97 mContext.registerReceiver(mReceiver, filter); 98 mCheckBoxPreference.setOnPreferenceChangeListener(this); 99 100 handleModeChanged(mLocalManager.getBluetoothManager().getMode()); 101 } 102 103 public void pause() { 104 if (mLocalManager == null) { 105 return; 106 } 107 108 mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable); 109 mCheckBoxPreference.setOnPreferenceChangeListener(null); 110 mContext.unregisterReceiver(mReceiver); 111 } 112 113 public boolean onPreferenceChange(Preference preference, Object value) { 114 if (V) { 115 Log.v(TAG, "Preference changed to " + value); 116 } 117 118 // Turn on/off BT discoverability 119 setEnabled((Boolean) value); 120 121 return true; 122 } 123 124 private void setEnabled(final boolean enable) { 125 BluetoothDevice manager = mLocalManager.getBluetoothManager(); 126 127 if (enable) { 128 129 int timeout = getDiscoverableTimeout(); 130 manager.setDiscoverableTimeout(timeout); 131 132 long endTimestamp = System.currentTimeMillis() + timeout * 1000; 133 persistDiscoverableEndTimestamp(endTimestamp); 134 135 manager.setMode(BluetoothDevice.MODE_DISCOVERABLE); 136 handleModeChanged(BluetoothDevice.MODE_DISCOVERABLE); 137 138 } else { 139 manager.setMode(BluetoothDevice.MODE_CONNECTABLE); 140 } 141 } 142 143 private int getDiscoverableTimeout() { 144 int timeout = SystemProperties.getInt(SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT, -1); 145 if (timeout <= 0) { 146 timeout = DISCOVERABLE_TIMEOUT; 147 } 148 149 return timeout; 150 } 151 152 private void persistDiscoverableEndTimestamp(long endTimestamp) { 153 SharedPreferences.Editor editor = mLocalManager.getSharedPreferences().edit(); 154 editor.putLong(SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, endTimestamp); 155 editor.commit(); 156 } 157 158 private void handleModeChanged(int mode) { 159 if (V) { 160 Log.v(TAG, "Got mode changed: " + mode); 161 } 162 163 if (mode == BluetoothDevice.MODE_DISCOVERABLE) { 164 mCheckBoxPreference.setChecked(true); 165 updateCountdownSummary(); 166 167 } else { 168 mCheckBoxPreference.setChecked(false); 169 } 170 } 171 172 private void updateCountdownSummary() { 173 int mode = mLocalManager.getBluetoothManager().getMode(); 174 if (mode != BluetoothDevice.MODE_DISCOVERABLE) { 175 return; 176 } 177 178 long currentTimestamp = System.currentTimeMillis(); 179 long endTimestamp = mLocalManager.getSharedPreferences().getLong( 180 SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, 0); 181 182 if (currentTimestamp > endTimestamp) { 183 // We're still in discoverable mode, but maybe there isn't a timeout. 184 mCheckBoxPreference.setSummaryOn(null); 185 return; 186 } 187 188 String formattedTimeLeft = String.valueOf((endTimestamp - currentTimestamp) / 1000); 189 190 mCheckBoxPreference.setSummaryOn( 191 mContext.getResources().getString(R.string.bluetooth_is_discoverable, 192 formattedTimeLeft)); 193 194 synchronized (this) { 195 mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable); 196 mUiHandler.postDelayed(mUpdateCountdownSummaryRunnable, 1000); 197 } 198 } 199 200 201} 202