1d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly/*
2d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * Copyright (C) 2008 The Android Open Source Project
3d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly *
4d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * you may not use this file except in compliance with the License.
6d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * You may obtain a copy of the License at
7d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly *
8d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly *
10d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * Unless required by applicable law or agreed to in writing, software
11d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * See the License for the specific language governing permissions and
14d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * limitations under the License.
15d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly */
16d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
17d63c0112251ab4e4e977545368dd703d875012a4Nick Pellypackage com.android.settings.bluetooth;
18d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
19737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamyimport android.bluetooth.BluetoothAdapter;
20d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport android.bluetooth.BluetoothDevice;
21b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xieimport android.content.Context;
22b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xieimport android.util.Log;
23d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
24d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport java.util.ArrayList;
25436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection;
26d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport java.util.List;
27d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
28d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly/**
29d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
30d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly */
31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class CachedBluetoothDeviceManager {
32b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie    private static final String TAG = "CachedBluetoothDeviceManager";
33b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie    private static final boolean DEBUG = Utils.D;
34d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
35b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie    private Context mContext;
36436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private final List<CachedBluetoothDevice> mCachedDevices =
37436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            new ArrayList<CachedBluetoothDevice>();
38d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
39b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie    CachedBluetoothDeviceManager(Context context) {
40b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie        mContext = context;
41b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie    }
42b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie
43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
44d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        return new ArrayList<CachedBluetoothDevice>(mCachedDevices);
45d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    }
46d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
4779be0b3e6b5639c4cbe2bbcd9adb0ec4c28716edJake Hamby    public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) {
48d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        cachedDevice.setVisible(false);
4979be0b3e6b5639c4cbe2bbcd9adb0ec4c28716edJake Hamby        return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE;
50d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    }
51d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    public void onDeviceNameUpdated(BluetoothDevice device) {
53d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        CachedBluetoothDevice cachedDevice = findDevice(device);
54d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        if (cachedDevice != null) {
55d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            cachedDevice.refreshName();
56d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        }
57d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    }
58d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /**
60436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * Search for existing {@link CachedBluetoothDevice} or return null
61436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * if this device isn't in the cache. Use {@link #addDevice}
62436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * to create and return a new {@link CachedBluetoothDevice} for
63436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * a newly discovered {@link BluetoothDevice}.
64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     *
65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @param device the address of the Bluetooth device
66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @return the cached device object for this device, or null if it has
67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     *   not been previously seen
68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     */
69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    CachedBluetoothDevice findDevice(BluetoothDevice device) {
70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
71d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            if (cachedDevice.getDevice().equals(device)) {
72d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly                return cachedDevice;
73d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            }
74d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        }
75d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        return null;
76d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    }
77d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
78d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    /**
79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * Create and return a new {@link CachedBluetoothDevice}. This assumes
80436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * that {@link #findDevice} has already been called and returned null.
81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @param device the address of the new Bluetooth device
82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @return the newly created CachedBluetoothDevice object
83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     */
84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter,
85436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            LocalBluetoothProfileManager profileManager,
86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            BluetoothDevice device) {
87b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie        CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter,
88b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie            profileManager, device);
89436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mCachedDevices.add(newDevice);
90436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return newDevice;
91436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
92436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
93436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /**
94d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly     * Attempts to get the name of a remote device, otherwise returns the address.
95d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly     *
96d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly     * @param device The remote device.
97d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly     * @return The name, or if unavailable, the address.
98d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly     */
99d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    public String getName(BluetoothDevice device) {
100d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        CachedBluetoothDevice cachedDevice = findDevice(device);
101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (cachedDevice != null) {
102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return cachedDevice.getName();
103d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        }
104d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
1052036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie        String name = device.getAliasName();
106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (name != null) {
107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return name;
108d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        }
109d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        return device.getAddress();
111d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    }
112d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
113d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    public synchronized void onScanningStateChanged(boolean started) {
114d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        if (!started) return;
115d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
116d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        // If starting a new scan, clear old visibility
117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        // Iterate in reverse order since devices may be removed.
118d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
119d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
120d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            cachedDevice.setVisible(false);
121d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        }
122d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    }
123d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly
124d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    public synchronized void onBtClassChanged(BluetoothDevice device) {
125d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        CachedBluetoothDevice cachedDevice = findDevice(device);
126d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        if (cachedDevice != null) {
127d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            cachedDevice.refreshBtClass();
128d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        }
129d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    }
1302aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
1312aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    public synchronized void onUuidChanged(BluetoothDevice device) {
1322aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        CachedBluetoothDevice cachedDevice = findDevice(device);
1332aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        if (cachedDevice != null) {
1342aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan            cachedDevice.onUuidChanged();
1352aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        }
1362aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    }
137b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie
138737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy    public synchronized void onBluetoothStateChanged(int bluetoothState) {
139737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy        // When Bluetooth is turning off, we need to clear the non-bonded devices
140737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy        // Otherwise, they end up showing up on the next BT enable
141737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy        if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
142737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy            for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
143737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy                CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
1442582e6ca94e6cbb80a8bf2b3abcb83da5f7d3a09Ravi Nagarajan                if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
145737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy                   cachedDevice.setVisible(false);
146737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy                   mCachedDevices.remove(i);
1477951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta                } else {
1487951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta                    // For bonded devices, we need to clear the connection status so that
1497951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta                    // when BT is enabled next time, device connection status shall be retrieved
1507951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta                    // by making a binder call.
1517951b43bd9a759b01ea994b341c102b03011ca3cGanesh Ganapathi Batta                    cachedDevice.clearProfileConnectionState();
152737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy                }
153737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy            }
154737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy        }
155737a30f593300a9731adfe899144af64b1d71057Kausik Sinnaswamy    }
156b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie    private void log(String msg) {
157b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie        if (DEBUG) {
158b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie            Log.d(TAG, msg);
159b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie        }
160b707255a440e53ec2865c4b34c7ea07d16d471bdMatthew Xie    }
161d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly}
162