• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.settings.bluetooth;
18 
19 import com.android.settings.R;
20 
21 import android.bluetooth.BluetoothAdapter;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.IntentFilter;
26 import android.content.SharedPreferences;
27 import android.os.Handler;
28 import android.os.SystemProperties;
29 import android.preference.Preference;
30 import android.preference.CheckBoxPreference;
31 
32 /**
33  * BluetoothDiscoverableEnabler is a helper to manage the "Discoverable"
34  * checkbox. It sets/unsets discoverability and keeps track of how much time
35  * until the the discoverability is automatically turned off.
36  */
37 public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChangeListener {
38     private static final String TAG = "BluetoothDiscoverableEnabler";
39 
40     private static final String SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT =
41             "debug.bt.discoverable_time";
42     /* package */  static final int DEFAULT_DISCOVERABLE_TIMEOUT = 120;
43 
44     /* package */ static final String SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP =
45             "discoverable_end_timestamp";
46 
47     private final Context mContext;
48     private final Handler mUiHandler;
49     private final CheckBoxPreference mCheckBoxPreference;
50 
51     private final LocalBluetoothManager mLocalManager;
52 
53     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
54         @Override
55         public void onReceive(Context context, Intent intent) {
56             if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
57                 int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
58                         BluetoothAdapter.ERROR);
59                 if (mode != BluetoothAdapter.ERROR) {
60                     handleModeChanged(mode);
61                 }
62             }
63         }
64     };
65 
66     private final Runnable mUpdateCountdownSummaryRunnable = new Runnable() {
67         public void run() {
68             updateCountdownSummary();
69         }
70     };
71 
BluetoothDiscoverableEnabler(Context context, CheckBoxPreference checkBoxPreference)72     public BluetoothDiscoverableEnabler(Context context, CheckBoxPreference checkBoxPreference) {
73         mContext = context;
74         mUiHandler = new Handler();
75         mCheckBoxPreference = checkBoxPreference;
76 
77         checkBoxPreference.setPersistent(false);
78 
79         mLocalManager = LocalBluetoothManager.getInstance(context);
80         if (mLocalManager == null) {
81             // Bluetooth not supported
82             checkBoxPreference.setEnabled(false);
83         }
84     }
85 
resume()86     public void resume() {
87         if (mLocalManager == null) {
88             return;
89         }
90 
91         IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
92         mContext.registerReceiver(mReceiver, filter);
93         mCheckBoxPreference.setOnPreferenceChangeListener(this);
94 
95         handleModeChanged(mLocalManager.getBluetoothAdapter().getScanMode());
96     }
97 
pause()98     public void pause() {
99         if (mLocalManager == null) {
100             return;
101         }
102 
103         mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable);
104         mCheckBoxPreference.setOnPreferenceChangeListener(null);
105         mContext.unregisterReceiver(mReceiver);
106     }
107 
onPreferenceChange(Preference preference, Object value)108     public boolean onPreferenceChange(Preference preference, Object value) {
109         // Turn on/off BT discoverability
110         setEnabled((Boolean) value);
111 
112         return true;
113     }
114 
setEnabled(final boolean enable)115     private void setEnabled(final boolean enable) {
116         BluetoothAdapter manager = mLocalManager.getBluetoothAdapter();
117 
118         if (enable) {
119 
120             int timeout = getDiscoverableTimeout();
121             manager.setDiscoverableTimeout(timeout);
122 
123             mCheckBoxPreference.setSummaryOn(
124                     mContext.getResources().getString(R.string.bluetooth_is_discoverable, timeout));
125 
126             long endTimestamp = System.currentTimeMillis() + timeout * 1000;
127             persistDiscoverableEndTimestamp(endTimestamp);
128 
129             manager.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
130         } else {
131             manager.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
132         }
133     }
134 
getDiscoverableTimeout()135     private int getDiscoverableTimeout() {
136         int timeout = SystemProperties.getInt(SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT, -1);
137         if (timeout <= 0) {
138             timeout = DEFAULT_DISCOVERABLE_TIMEOUT;
139         }
140 
141         return timeout;
142     }
143 
persistDiscoverableEndTimestamp(long endTimestamp)144     private void persistDiscoverableEndTimestamp(long endTimestamp) {
145         SharedPreferences.Editor editor = mLocalManager.getSharedPreferences().edit();
146         editor.putLong(SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, endTimestamp);
147         editor.commit();
148     }
149 
handleModeChanged(int mode)150     private void handleModeChanged(int mode) {
151         if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
152             mCheckBoxPreference.setChecked(true);
153             updateCountdownSummary();
154 
155         } else {
156             mCheckBoxPreference.setChecked(false);
157         }
158     }
159 
updateCountdownSummary()160     private void updateCountdownSummary() {
161         int mode = mLocalManager.getBluetoothAdapter().getScanMode();
162         if (mode != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
163             return;
164         }
165 
166         long currentTimestamp = System.currentTimeMillis();
167         long endTimestamp = mLocalManager.getSharedPreferences().getLong(
168                 SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, 0);
169 
170         if (currentTimestamp > endTimestamp) {
171             // We're still in discoverable mode, but maybe there isn't a timeout.
172             mCheckBoxPreference.setSummaryOn(null);
173             return;
174         }
175 
176         String formattedTimeLeft = String.valueOf((endTimestamp - currentTimestamp) / 1000);
177 
178         mCheckBoxPreference.setSummaryOn(
179                 mContext.getResources().getString(R.string.bluetooth_is_discoverable,
180                         formattedTimeLeft));
181 
182         synchronized (this) {
183             mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable);
184             mUiHandler.postDelayed(mUpdateCountdownSummaryRunnable, 1000);
185         }
186     }
187 
188 
189 }
190