17ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/*
27ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Copyright (C) 2011 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.BluetoothClass;
207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothDevice;
217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothUuid;
227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.os.ParcelUuid;
237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.util.Log;
247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/**
267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * BluetoothDeviceFilter contains a static method that returns a
277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Filter object that returns whether or not the BluetoothDevice
287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * passed to it matches the specified filter type constant from
297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * {@link android.bluetooth.BluetoothDevicePicker}.
307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */
317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpublic final class BluetoothDeviceFilter {
327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final String TAG = "BluetoothDeviceFilter";
337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** The filter interface to external classes. */
357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public interface Filter {
367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        boolean matches(BluetoothDevice device);
377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** All filter singleton (referenced directly). */
407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public static final Filter ALL_FILTER = new AllFilter();
417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Bonded devices only filter (referenced directly). */
437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public static final Filter BONDED_DEVICE_FILTER = new BondedDeviceFilter();
447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Unbonded devices only filter (referenced directly). */
467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public static final Filter UNBONDED_DEVICE_FILTER = new UnbondedDeviceFilter();
477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Table of singleton filter objects. */
497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final Filter[] FILTERS = {
507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            ALL_FILTER,             // FILTER_TYPE_ALL
517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            new AudioFilter(),      // FILTER_TYPE_AUDIO
527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            new TransferFilter(),   // FILTER_TYPE_TRANSFER
537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            new PanuFilter(),       // FILTER_TYPE_PANU
547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            new NapFilter()         // FILTER_TYPE_NAP
557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    };
567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Private constructor. */
587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private BluetoothDeviceFilter() {
597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /**
627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * Returns the singleton {@link Filter} object for the specified type,
637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * or {@link #ALL_FILTER} if the type value is out of range.
647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     *
657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @param filterType a constant from BluetoothDevicePicker
667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     * @return a singleton object implementing the {@link Filter} interface.
677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk     */
687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public static Filter getFilter(int filterType) {
697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (filterType >= 0 && filterType < FILTERS.length) {
707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return FILTERS[filterType];
717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        } else {
727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            Log.w(TAG, "Invalid filter type " + filterType + " for device picker");
737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return ALL_FILTER;
747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Filter that matches all devices. */
787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final class AllFilter implements Filter {
797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public boolean matches(BluetoothDevice device) {
807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return true;
817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Filter that matches only bonded devices. */
857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final class BondedDeviceFilter implements Filter {
867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public boolean matches(BluetoothDevice device) {
877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return device.getBondState() == BluetoothDevice.BOND_BONDED;
887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Filter that matches only unbonded devices. */
927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final class UnbondedDeviceFilter implements Filter {
937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public boolean matches(BluetoothDevice device) {
947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return device.getBondState() != BluetoothDevice.BOND_BONDED;
957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Parent class of filters based on UUID and/or Bluetooth class. */
997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private abstract static class ClassUuidFilter implements Filter {
1007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        abstract boolean matches(ParcelUuid[] uuids, BluetoothClass btClass);
1017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public boolean matches(BluetoothDevice device) {
1037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return matches(device.getUuids(), device.getBluetoothClass());
1047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Filter that matches devices that support AUDIO profiles. */
1087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final class AudioFilter extends ClassUuidFilter {
1097ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        @Override
1107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
1117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (uuids != null) {
1127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS)) {
1137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return true;
1147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (BluetoothUuid.containsAnyUuid(uuids, HeadsetProfile.UUIDS)) {
1167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return true;
1177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            } else if (btClass != null) {
1197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP) ||
1207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                        btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
1217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return true;
1227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return false;
1257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Filter that matches devices that support Object Transfer. */
1297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final class TransferFilter extends ClassUuidFilter {
1307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        @Override
1317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
1327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (uuids != null) {
1337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
1347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return true;
1357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return btClass != null
1387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    && btClass.doesClassMatch(BluetoothClass.PROFILE_OPP);
1397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Filter that matches devices that support PAN User (PANU) profile. */
1437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final class PanuFilter extends ClassUuidFilter {
1447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        @Override
1457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
1467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (uuids != null) {
1477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.PANU)) {
1487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return true;
1497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return btClass != null
1527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    && btClass.doesClassMatch(BluetoothClass.PROFILE_PANU);
1537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    /** Filter that matches devices that support NAP profile. */
1577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final class NapFilter extends ClassUuidFilter {
1587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        @Override
1597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
1607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (uuids != null) {
1617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP)) {
1627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return true;
1637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return btClass != null
1667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    && btClass.doesClassMatch(BluetoothClass.PROFILE_NAP);
1677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk}
170