1436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/*
2436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Copyright (C) 2011 The Android Open Source Project
3436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby *
4436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Licensed under the Apache License, Version 2.0 (the "License");
5436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * you may not use this file except in compliance with the License.
6436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * You may obtain a copy of the License at
7436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby *
8436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby *      http://www.apache.org/licenses/LICENSE-2.0
9436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby *
10436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Unless required by applicable law or agreed to in writing, software
11436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * distributed under the License is distributed on an "AS IS" BASIS,
12436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * See the License for the specific language governing permissions and
14436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * limitations under the License.
15436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */
16436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
17436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambypackage com.android.settings.bluetooth;
18436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
19436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothAdapter;
20436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothDevice;
21436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothProfile;
22436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.Context;
23436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.os.ParcelUuid;
24436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.util.Log;
25436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
26436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Set;
27436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
28436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/**
29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * LocalBluetoothAdapter provides an interface between the Settings app
30436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * and the functionality of the local {@link BluetoothAdapter}, specifically
31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * those related to state transitions of the adapter itself.
32436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby *
33436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * <p>Connection and bonding state changes affecting specific devices
34436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * are handled by {@link CachedBluetoothDeviceManager},
35436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * {@link BluetoothEventManager}, and {@link LocalBluetoothProfileManager}.
36436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */
37436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambypublic final class LocalBluetoothAdapter {
38436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final String TAG = "LocalBluetoothAdapter";
39436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
40436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** This class does not allow direct access to the BluetoothAdapter. */
41436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private final BluetoothAdapter mAdapter;
42436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private LocalBluetoothProfileManager mProfileManager;
44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
45436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static LocalBluetoothAdapter sInstance;
46436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
47436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private int mState = BluetoothAdapter.ERROR;
48436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
49436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final int SCAN_EXPIRATION_MS = 5 * 60 * 1000; // 5 mins
50436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
51436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private long mLastScan;
52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
53436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private LocalBluetoothAdapter(BluetoothAdapter adapter) {
54436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mAdapter = adapter;
55436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
56436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
57436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void setProfileManager(LocalBluetoothProfileManager manager) {
58436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mProfileManager = manager;
59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
60436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
61436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /**
62436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * Get the singleton instance of the LocalBluetoothAdapter. If this device
63436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * doesn't support Bluetooth, then null will be returned. Callers must be
64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * prepared to handle a null return value.
65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @return the LocalBluetoothAdapter object, or null if not supported
66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     */
67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    static synchronized LocalBluetoothAdapter getInstance() {
68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (sInstance == null) {
69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (adapter != null) {
71436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                sInstance = new LocalBluetoothAdapter(adapter);
72436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
73436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
74436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
75436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return sInstance;
76436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
78436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    // Pass-through BluetoothAdapter methods that we can intercept if necessary
79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
80436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void cancelDiscovery() {
81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mAdapter.cancelDiscovery();
82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    boolean enable() {
85436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.enable();
86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
87436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
88436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    boolean disable() {
89436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.disable();
90436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
91436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
92436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void getProfileProxy(Context context,
93436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            BluetoothProfile.ServiceListener listener, int profile) {
94436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mAdapter.getProfileProxy(context, listener, profile);
95436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
96436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
97436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    Set<BluetoothDevice> getBondedDevices() {
98436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.getBondedDevices();
99436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
100436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    String getName() {
102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.getName();
103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
105436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    int getScanMode() {
106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.getScanMode();
107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
109436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    int getState() {
110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.getState();
111436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
112436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
113436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    ParcelUuid[] getUuids() {
114436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.getUuids();
115436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
116436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    boolean isDiscovering() {
118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.isDiscovering();
119436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
120436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
121436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    boolean isEnabled() {
122436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.isEnabled();
123436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
124436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
125436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void setDiscoverableTimeout(int timeout) {
126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mAdapter.setDiscoverableTimeout(timeout);
127436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void setName(String name) {
130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mAdapter.setName(name);
131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
133436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void setScanMode(int mode) {
134436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mAdapter.setScanMode(mode);
135436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
136436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    boolean setScanMode(int mode, int duration) {
138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mAdapter.setScanMode(mode, duration);
139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
141436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void startScanning(boolean force) {
142436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        // Only start if we're not already scanning
143436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (!mAdapter.isDiscovering()) {
144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (!force) {
145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                // Don't scan more than frequently than SCAN_EXPIRATION_MS,
146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                // unless forced
147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) {
148436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return;
149436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
150436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
151436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                // If we are playing music, don't scan unless forced.
152436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                A2dpProfile a2dp = mProfileManager.getA2dpProfile();
153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (a2dp != null && a2dp.isA2dpPlaying()) {
154436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return;
155436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
156436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
157436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
158436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (mAdapter.startDiscovery()) {
159436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                mLastScan = System.currentTimeMillis();
160436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
161436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
163436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    void stopScanning() {
165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (mAdapter.isDiscovering()) {
166436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            mAdapter.cancelDiscovery();
167436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
168436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
169436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
170436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    public synchronized int getBluetoothState() {
171436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        // Always sync state, in case it changed while paused
172436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        syncBluetoothState();
173436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return mState;
174436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
175436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
176436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    synchronized void setBluetoothStateInt(int state) {
177436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mState = state;
178436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
179436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (state == BluetoothAdapter.STATE_ON) {
180436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            // if mProfileManager hasn't been constructed yet, it will
181436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            // get the adapter UUIDs in its constructor when it is.
182436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (mProfileManager != null) {
183436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                mProfileManager.setBluetoothStateOn();
184436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
185436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
186436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
187436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
188436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    // Returns true if the state changed; false otherwise.
189436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    boolean syncBluetoothState() {
190436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        int currentState = mAdapter.getState();
191436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (currentState != mState) {
192436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            setBluetoothStateInt(mAdapter.getState());
193436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return true;
194436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
195436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return false;
196436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
197436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
198436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    public void setBluetoothEnabled(boolean enabled) {
199436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        boolean success = enabled
200436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                ? mAdapter.enable()
201436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                : mAdapter.disable();
202436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
203436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (success) {
204436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            setBluetoothStateInt(enabled
205436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                ? BluetoothAdapter.STATE_TURNING_ON
206436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                : BluetoothAdapter.STATE_TURNING_OFF);
207436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        } else {
208436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (Utils.V) {
209436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +
210436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                        "success for enabled: " + enabled);
211436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
212436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
213436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            syncBluetoothState();
214436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
215436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
216436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby}
217