17ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/*
27ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Copyright (C) 2008 The Android Open Source Project
37ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
47ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
57ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * you may not use this file except in compliance with the License.
67ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * You may obtain a copy of the License at
77ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
87ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
97ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Unless required by applicable law or agreed to in writing, software
117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * See the License for the specific language governing permissions and
147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * limitations under the License.
157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */
167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpackage com.android.settingslib.bluetooth;
187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothAdapter;
207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothDevice;
217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.Context;
227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.util.Log;
237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.ArrayList;
257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.Collection;
267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.List;
277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/**
297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */
317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpublic final class CachedBluetoothDeviceManager {
327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final String TAG = "CachedBluetoothDeviceManager";
337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final boolean DEBUG = Utils.D;
347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private Context mContext;
367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final List<CachedBluetoothDevice> mCachedDevices =
377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            new ArrayList<CachedBluetoothDevice>();
38be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk    private final LocalBluetoothManager mBtManager;
397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
40be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk    CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mContext = context;
42be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk        mBtManager = localBtManager;
437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return new ArrayList<CachedBluetoothDevice>(mCachedDevices);
477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) {
507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        cachedDevice.setVisible(false);
517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE;
527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public void onDeviceNameUpdated(BluetoothDevice device) {
557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        CachedBluetoothDevice cachedDevice = findDevice(device);
567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (cachedDevice != null) {
577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            cachedDevice.refreshName();
587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Search for existing {@link CachedBluetoothDevice} or return null
637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * if this device isn't in the cache. Use {@link #addDevice}
647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * to create and return a new {@link CachedBluetoothDevice} for
657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * a newly discovered {@link BluetoothDevice}.
667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     *
677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param device the address of the Bluetooth device
687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @return the cached device object for this device, or null if it has
697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     *   not been previously seen
707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public CachedBluetoothDevice findDevice(BluetoothDevice device) {
727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (cachedDevice.getDevice().equals(device)) {
747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                return cachedDevice;
757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return null;
787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Create and return a new {@link CachedBluetoothDevice}. This assumes
827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * that {@link #findDevice} has already been called and returned null.
837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param device the address of the new Bluetooth device
847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @return the newly created CachedBluetoothDevice object
857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter,
877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            LocalBluetoothProfileManager profileManager,
887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            BluetoothDevice device) {
897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter,
907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            profileManager, device);
917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        synchronized (mCachedDevices) {
927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mCachedDevices.add(newDevice);
93be3c5dbee66758517a8198f98ed2e20c80af326bJason Monk            mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return newDevice;
967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Attempts to get the name of a remote device, otherwise returns the address.
1007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     *
1017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param device The remote device.
1027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @return The name, or if unavailable, the address.
1037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
1047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public String getName(BluetoothDevice device) {
1057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        CachedBluetoothDevice cachedDevice = findDevice(device);
1067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (cachedDevice != null) {
1077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return cachedDevice.getName();
1087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1097ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        String name = device.getAliasName();
1117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (name != null) {
1127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return name;
1137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return device.getAddress();
1167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public synchronized void clearNonBondedDevices() {
1197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
1207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
1217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
1227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                mCachedDevices.remove(i);
1237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public synchronized void onScanningStateChanged(boolean started) {
1287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (!started) return;
1297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // If starting a new scan, clear old visibility
1317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // Iterate in reverse order since devices may be removed.
1327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
1337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
1347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            cachedDevice.setVisible(false);
1357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public synchronized void onBtClassChanged(BluetoothDevice device) {
1397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        CachedBluetoothDevice cachedDevice = findDevice(device);
1407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (cachedDevice != null) {
1417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            cachedDevice.refreshBtClass();
1427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public synchronized void onUuidChanged(BluetoothDevice device) {
1467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        CachedBluetoothDevice cachedDevice = findDevice(device);
1477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (cachedDevice != null) {
1487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            cachedDevice.onUuidChanged();
1497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public synchronized void onBluetoothStateChanged(int bluetoothState) {
1537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // When Bluetooth is turning off, we need to clear the non-bonded devices
1547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // Otherwise, they end up showing up on the next BT enable
1557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
1567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
1577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
1587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
1597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    cachedDevice.setVisible(false);
1607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    mCachedDevices.remove(i);
1617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                } else {
1627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    // For bonded devices, we need to clear the connection status so that
1637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    // when BT is enabled next time, device connection status shall be retrieved
1647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    // by making a binder call.
1657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    cachedDevice.clearProfileConnectionState();
1667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private void log(String msg) {
1717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (DEBUG) {
1727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            Log.d(TAG, msg);
1737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk}
176