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