A2dpProfile.java revision 654a3ab77dac5acaf6e100c518ba322cc1edb3c0
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.BluetoothA2dp; 20436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothAdapter; 21436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothClass; 22436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothDevice; 23436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothProfile; 24436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothUuid; 25436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.Context; 26436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.os.ParcelUuid; 27654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredcimport android.util.Log; 28436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport com.android.settings.R; 30436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.List; 32436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 33436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/** 34436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * A2dpProfile handles Bluetooth A2DP. 35436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * TODO: add null checks around calls to mService object. 36436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 37436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class A2dpProfile implements LocalBluetoothProfile { 38654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc private static final String TAG = "A2dpProfile"; 39654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc private static boolean V = true; 40654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc 41436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private BluetoothA2dp mService; 42654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc private boolean mIsProfileReady; 43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby static final ParcelUuid[] SINK_UUIDS = { 45436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothUuid.AudioSink, 46436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothUuid.AdvAudioDist, 47436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby }; 48436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 49436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby static final String NAME = "A2DP"; 502ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji private final LocalBluetoothProfileManager mProfileManager; 51436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Order of this profile in device profiles list 53436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final int ORDINAL = 1; 54436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 55436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // These callbacks run on the main thread. 56436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final class A2dpServiceListener 57436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby implements BluetoothProfile.ServiceListener { 58436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onServiceConnected(int profile, BluetoothProfile proxy) { 60654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (V) Log.d(TAG,"Bluetooth service disconnected"); 61436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mService = (BluetoothA2dp) proxy; 622ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mProfileManager.setA2dpServiceUp(true); 63654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc mIsProfileReady=true; 64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onServiceDisconnected(int profile) { 67654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (V) Log.d(TAG,"Bluetooth service disconnected"); 682ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mProfileManager.setA2dpServiceUp(false); 69654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc mIsProfileReady=false; 70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 71436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 72436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 73654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc public boolean isProfileReady() { 74654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc return mIsProfileReady; 75654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 762ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji A2dpProfile(Context context, LocalBluetoothProfileManager profileManager) { 772ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji 782ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mProfileManager = profileManager; 79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 80436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby adapter.getProfileProxy(context, new A2dpServiceListener(), 81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothProfile.A2DP); 82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean isConnectable() { 85436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 87436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 88436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean isAutoConnectable() { 89436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 90436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 91436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 92436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private List<BluetoothDevice> getConnectedDevices() { 93436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.getDevicesMatchingConnectionStates( 94436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new int[] {BluetoothProfile.STATE_CONNECTED, 95436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothProfile.STATE_CONNECTING, 96436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothProfile.STATE_DISCONNECTING}); 97436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 98436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 99436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean connect(BluetoothDevice device) { 100436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<BluetoothDevice> sinks = getConnectedDevices(); 101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (sinks != null) { 102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (BluetoothDevice sink : sinks) { 103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mService.disconnect(sink); 104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 105436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.connect(device); 107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 109436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean disconnect(BluetoothDevice device) { 110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.disconnect(device); 111436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 112436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 1132ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji // This function is added as the AUTO CONNECT priority could not be set by using setPreferred(), 1142ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji // as setPreferred() takes only boolean input but getPreferred() supports interger output. 1152ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji // Also this need not implemented by all profiles so this has been added here. 1162ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji public void enableAutoConnect(BluetoothDevice device, boolean enable) { 1172ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if (enable) { 1182ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT); 1192ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } else { 1202ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) { 1212ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1222ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 1232ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 1242ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji } 1252ac143fff796ff1bd5b73484db17b6934c05f18eSwaminatha Balaji 126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getConnectionStatus(BluetoothDevice device) { 127436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.getConnectionState(device); 128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean isPreferred(BluetoothDevice device) { 131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 133436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 134436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getPreferred(BluetoothDevice device) { 135436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.getPriority(device); 136436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void setPreferred(BluetoothDevice device, boolean preferred) { 139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (preferred) { 140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 141436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 142436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 143436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else { 144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 148436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean isA2dpPlaying() { 149436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<BluetoothDevice> sinks = mService.getConnectedDevices(); 150436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!sinks.isEmpty()) { 151436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mService.isA2dpPlaying(sinks.get(0))) { 152436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 154436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 155436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 156436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 157436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 158436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public String toString() { 159436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return NAME; 160436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 161436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getOrdinal() { 163436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return ORDINAL; 164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 16679be0b3e6b5639c4cbe2bbcd9adb0ec4c28716edJake Hamby public int getNameResource(BluetoothDevice device) { 167436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.string.bluetooth_profile_a2dp; 168436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 169436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 170436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getSummaryResourceForDevice(BluetoothDevice device) { 171436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state = mService.getConnectionState(device); 172436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby switch (state) { 173436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothProfile.STATE_DISCONNECTED: 174436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.string.bluetooth_a2dp_profile_summary_use_for; 175436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 176436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothProfile.STATE_CONNECTED: 177436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.string.bluetooth_a2dp_profile_summary_connected; 178436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 179436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby default: 180436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return Utils.getConnectionStateSummary(state); 181436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 182436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 183436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 184436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getDrawableResource(BluetoothClass btClass) { 185436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.drawable.ic_bt_headphones_a2dp; 186436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 187654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc 188654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc protected void finalize() { 189654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (V) Log.d(TAG, "finalize()"); 190654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (mService != null) { 191654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc try { 192654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP, mService); 193654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc mService = null; 194654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc }catch (Throwable t) { 195654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc Log.w(TAG, "Error cleaning up A2DP proxy", t); 196654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 197654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 198654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 199436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby} 200