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