1 /*
2  * Copyright (C) 2017 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 android.bluetooth.BluetoothAdapter;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 
25 import androidx.annotation.VisibleForTesting;
26 
27 /** Helper class, intended to be used by an Activity, to keep the local Bluetooth adapter in
28  *  discoverable mode indefinitely. By default setting the scan mode to
29  *  BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE will time out after some time, but some
30  *  Bluetooth settings pages would like to keep the device discoverable as long as the page is
31  *  visible. */
32 public class AlwaysDiscoverable extends BroadcastReceiver {
33     private static final String TAG = "AlwaysDiscoverable";
34 
35     private Context mContext;
36     private BluetoothAdapter mBluetoothAdapter;
37     private IntentFilter mIntentFilter;
38 
39     @VisibleForTesting
40     boolean mStarted;
41 
AlwaysDiscoverable(Context context)42     public AlwaysDiscoverable(Context context) {
43         mContext = context;
44         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
45         mIntentFilter = new IntentFilter();
46         mIntentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
47     }
48 
49     /** After calling start(), consumers should make a matching call to stop() when they no longer
50      * wish to enforce discoverable mode. */
start()51     public void start() {
52         if (mStarted) {
53             return;
54         }
55         mContext.registerReceiver(this, mIntentFilter);
56         mStarted = true;
57         if (mBluetoothAdapter.getScanMode()
58                 != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
59             mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
60         }
61     }
62 
stop()63     public void stop() {
64         if (!mStarted) {
65             return;
66         }
67         mContext.unregisterReceiver(this);
68         mStarted = false;
69         mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
70     }
71 
72     @Override
onReceive(Context context, Intent intent)73     public void onReceive(Context context, Intent intent) {
74         String action = intent.getAction();
75         if (action != BluetoothAdapter.ACTION_SCAN_MODE_CHANGED) {
76             return;
77         }
78         if (mBluetoothAdapter.getScanMode()
79                 != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
80             mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
81         }
82     }
83 }
84