Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.bluetooth;
     18 
     19 import android.bluetooth.BluetoothClass;
     20 import android.bluetooth.BluetoothDevice;
     21 import android.bluetooth.BluetoothUuid;
     22 import android.os.ParcelUuid;
     23 import android.util.Log;
     24 
     25 /**
     26  * BluetoothDeviceFilter contains a static method that returns a
     27  * Filter object that returns whether or not the BluetoothDevice
     28  * passed to it matches the specified filter type constant from
     29  * {@link android.bluetooth.BluetoothDevicePicker}.
     30  */
     31 final class BluetoothDeviceFilter {
     32     private static final String TAG = "BluetoothDeviceFilter";
     33 
     34     /** The filter interface to external classes. */
     35     interface Filter {
     36         boolean matches(BluetoothDevice device);
     37     }
     38 
     39     /** All filter singleton (referenced directly). */
     40     static final Filter ALL_FILTER = new AllFilter();
     41 
     42     /** Bonded devices only filter (referenced directly). */
     43     static final Filter BONDED_DEVICE_FILTER = new BondedDeviceFilter();
     44 
     45     /** Unbonded devices only filter (referenced directly). */
     46     static final Filter UNBONDED_DEVICE_FILTER = new UnbondedDeviceFilter();
     47 
     48     /** Table of singleton filter objects. */
     49     private static final Filter[] FILTERS = {
     50             ALL_FILTER,             // FILTER_TYPE_ALL
     51             new AudioFilter(),      // FILTER_TYPE_AUDIO
     52             new TransferFilter(),   // FILTER_TYPE_TRANSFER
     53             new PanuFilter(),       // FILTER_TYPE_PANU
     54             new NapFilter()         // FILTER_TYPE_NAP
     55     };
     56 
     57     /** Private constructor. */
     58     private BluetoothDeviceFilter() {
     59     }
     60 
     61     /**
     62      * Returns the singleton {@link Filter} object for the specified type,
     63      * or {@link #ALL_FILTER} if the type value is out of range.
     64      *
     65      * @param filterType a constant from BluetoothDevicePicker
     66      * @return a singleton object implementing the {@link Filter} interface.
     67      */
     68     static Filter getFilter(int filterType) {
     69         if (filterType >= 0 && filterType < FILTERS.length) {
     70             return FILTERS[filterType];
     71         } else {
     72             Log.w(TAG, "Invalid filter type " + filterType + " for device picker");
     73             return ALL_FILTER;
     74         }
     75     }
     76 
     77     /** Filter that matches all devices. */
     78     private static final class AllFilter implements Filter {
     79         public boolean matches(BluetoothDevice device) {
     80             return true;
     81         }
     82     }
     83 
     84     /** Filter that matches only bonded devices. */
     85     private static final class BondedDeviceFilter implements Filter {
     86         public boolean matches(BluetoothDevice device) {
     87             return device.getBondState() == BluetoothDevice.BOND_BONDED;
     88         }
     89     }
     90 
     91     /** Filter that matches only unbonded devices. */
     92     private static final class UnbondedDeviceFilter implements Filter {
     93         public boolean matches(BluetoothDevice device) {
     94             return device.getBondState() != BluetoothDevice.BOND_BONDED;
     95         }
     96     }
     97 
     98     /** Parent class of filters based on UUID and/or Bluetooth class. */
     99     private abstract static class ClassUuidFilter implements Filter {
    100         abstract boolean matches(ParcelUuid[] uuids, BluetoothClass btClass);
    101 
    102         public boolean matches(BluetoothDevice device) {
    103             return matches(device.getUuids(), device.getBluetoothClass());
    104         }
    105     }
    106 
    107     /** Filter that matches devices that support AUDIO profiles. */
    108     private static final class AudioFilter extends ClassUuidFilter {
    109         @Override
    110         boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
    111             if (uuids != null) {
    112                 if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS)) {
    113                     return true;
    114                 }
    115                 if (BluetoothUuid.containsAnyUuid(uuids, HeadsetProfile.UUIDS)) {
    116                     return true;
    117                 }
    118             } else if (btClass != null) {
    119                 if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP) ||
    120                         btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
    121                     return true;
    122                 }
    123             }
    124             return false;
    125         }
    126     }
    127 
    128     /** Filter that matches devices that support Object Transfer. */
    129     private static final class TransferFilter extends ClassUuidFilter {
    130         @Override
    131         boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
    132             if (uuids != null) {
    133                 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
    134                     return true;
    135                 }
    136             }
    137             return btClass != null
    138                     && btClass.doesClassMatch(BluetoothClass.PROFILE_OPP);
    139         }
    140     }
    141 
    142     /** Filter that matches devices that support PAN User (PANU) profile. */
    143     private static final class PanuFilter extends ClassUuidFilter {
    144         @Override
    145         boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
    146             if (uuids != null) {
    147                 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.PANU)) {
    148                     return true;
    149                 }
    150             }
    151             return btClass != null
    152                     && btClass.doesClassMatch(BluetoothClass.PROFILE_PANU);
    153         }
    154     }
    155 
    156     /** Filter that matches devices that support NAP profile. */
    157     private static final class NapFilter extends ClassUuidFilter {
    158         @Override
    159         boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
    160             if (uuids != null) {
    161                 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP)) {
    162                     return true;
    163                 }
    164             }
    165             return btClass != null
    166                     && btClass.doesClassMatch(BluetoothClass.PROFILE_NAP);
    167         }
    168     }
    169 }
    170