Home | History | Annotate | Download | only in bluetooth
      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 
     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 
     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 
     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 
    108     public boolean onPreferenceChange(Preference preference, Object value) {
    109         // Turn on/off BT discoverability
    110         setEnabled((Boolean) value);
    111 
    112         return true;
    113     }
    114 
    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 
    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 
    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 
    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 
    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