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.BluetoothClass;
20436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothDevice;
21436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothUuid;
22436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.os.ParcelUuid;
23436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.util.Log;
24436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
25436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/**
26436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * BluetoothDeviceFilter contains a static method that returns a
27436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Filter object that returns whether or not the BluetoothDevice
28436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * passed to it matches the specified filter type constant from
29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * {@link android.bluetooth.BluetoothDevicePicker}.
30436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */
31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class BluetoothDeviceFilter {
32436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final String TAG = "BluetoothDeviceFilter";
33436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
34436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** The filter interface to external classes. */
35436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    interface Filter {
36436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        boolean matches(BluetoothDevice device);
37436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
38436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
39436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** All filter singleton (referenced directly). */
40436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    static final Filter ALL_FILTER = new AllFilter();
41436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
42436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Bonded devices only filter (referenced directly). */
43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    static final Filter BONDED_DEVICE_FILTER = new BondedDeviceFilter();
44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
454346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    /** Unbonded devices only filter (referenced directly). */
464346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    static final Filter UNBONDED_DEVICE_FILTER = new UnbondedDeviceFilter();
474346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne
48436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Table of singleton filter objects. */
49436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final Filter[] FILTERS = {
50436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            ALL_FILTER,             // FILTER_TYPE_ALL
51436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            new AudioFilter(),      // FILTER_TYPE_AUDIO
52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            new TransferFilter(),   // FILTER_TYPE_TRANSFER
53436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            new PanuFilter(),       // FILTER_TYPE_PANU
54436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            new NapFilter()         // FILTER_TYPE_NAP
55436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    };
56436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
57436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Private constructor. */
58436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private BluetoothDeviceFilter() {
59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
60436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
61436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /**
62436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * Returns the singleton {@link Filter} object for the specified type,
63436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * or {@link #ALL_FILTER} if the type value is out of range.
64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     *
65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @param filterType a constant from BluetoothDevicePicker
66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @return a singleton object implementing the {@link Filter} interface.
67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     */
68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    static Filter getFilter(int filterType) {
69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (filterType >= 0 && filterType < FILTERS.length) {
70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return FILTERS[filterType];
71436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        } else {
72436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            Log.w(TAG, "Invalid filter type " + filterType + " for device picker");
73436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return ALL_FILTER;
74436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
75436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
76436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Filter that matches all devices. */
78436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final class AllFilter implements Filter {
79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        public boolean matches(BluetoothDevice device) {
80436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return true;
81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Filter that matches only bonded devices. */
85436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final class BondedDeviceFilter implements Filter {
86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        public boolean matches(BluetoothDevice device) {
87436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return device.getBondState() == BluetoothDevice.BOND_BONDED;
88436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
89436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
90436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
914346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    /** Filter that matches only unbonded devices. */
924346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    private static final class UnbondedDeviceFilter implements Filter {
934346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne        public boolean matches(BluetoothDevice device) {
944346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne            return device.getBondState() != BluetoothDevice.BOND_BONDED;
954346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne        }
964346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne    }
974346cda76c6faa69d7341eb5e4e5bf21c2210e7fGilles Debunne
98436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Parent class of filters based on UUID and/or Bluetooth class. */
99436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private abstract static class ClassUuidFilter implements Filter {
100436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        abstract boolean matches(ParcelUuid[] uuids, BluetoothClass btClass);
101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        public boolean matches(BluetoothDevice device) {
103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return matches(device.getUuids(), device.getBluetoothClass());
104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
105436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Filter that matches devices that support AUDIO profiles. */
108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final class AudioFilter extends ClassUuidFilter {
109436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        @Override
110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
111436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (uuids != null) {
112436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS)) {
113436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return true;
114436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
115436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (BluetoothUuid.containsAnyUuid(uuids, HeadsetProfile.UUIDS)) {
116436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return true;
117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            } else if (btClass != null) {
119436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP) ||
120436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                        btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
121436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return true;
122436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
123436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
124436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return false;
125436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
127436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Filter that matches devices that support Object Transfer. */
129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final class TransferFilter extends ClassUuidFilter {
130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        @Override
131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (uuids != null) {
133436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
134436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return true;
135436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
136436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return btClass != null
138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    && btClass.doesClassMatch(BluetoothClass.PROFILE_OPP);
139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
141436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
142436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Filter that matches devices that support PAN User (PANU) profile. */
143436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final class PanuFilter extends ClassUuidFilter {
144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        @Override
145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (uuids != null) {
147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.PANU)) {
148436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return true;
149436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
150436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
151436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return btClass != null
152436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    && btClass.doesClassMatch(BluetoothClass.PROFILE_PANU);
153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
154436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
155436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
156436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /** Filter that matches devices that support NAP profile. */
157436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private static final class NapFilter extends ClassUuidFilter {
158436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        @Override
159436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
160436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (uuids != null) {
161436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP)) {
162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return true;
163436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            }
165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return btClass != null
166436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    && btClass.doesClassMatch(BluetoothClass.PROFILE_NAP);
167436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
168436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    }
169436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby}
170