A2dpProfile.java revision 7ce96b9e610de2782ec5f2af806e7bc0f90c8578
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.BluetoothA2dp; 207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothAdapter; 217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothClass; 227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothDevice; 237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothProfile; 247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothUuid; 257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.Context; 267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.os.ParcelUuid; 277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.util.Log; 287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport com.android.settingslib.R; 307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.ArrayList; 327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.List; 337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpublic final class A2dpProfile implements LocalBluetoothProfile { 357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private static final String TAG = "A2dpProfile"; 367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private static boolean V = false; 377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private BluetoothA2dp mService; 397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private boolean mIsProfileReady; 407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final LocalBluetoothAdapter mLocalAdapter; 427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final CachedBluetoothDeviceManager mDeviceManager; 437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk static final ParcelUuid[] SINK_UUIDS = { 457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothUuid.AudioSink, 467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothUuid.AdvAudioDist, 477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk }; 487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk static final String NAME = "A2DP"; 507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final LocalBluetoothProfileManager mProfileManager; 517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Order of this profile in device profiles list 537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private static final int ORDINAL = 1; 547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // These callbacks run on the main thread. 567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk private final class A2dpServiceListener 577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk implements BluetoothProfile.ServiceListener { 587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onServiceConnected(int profile, BluetoothProfile proxy) { 607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (V) Log.d(TAG,"Bluetooth service connected"); 617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mService = (BluetoothA2dp) proxy; 627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // We just bound to the service, so refresh the UI for any connected A2DP devices. 637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk while (!deviceList.isEmpty()) { 657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothDevice nextDevice = deviceList.remove(0); 667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice); 677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // we may add a new device here, but generally this should not happen 687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (device == null) { 697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.w(TAG, "A2dpProfile found new device: " + nextDevice); 707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice); 717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk device.onProfileStateChanged(A2dpProfile.this, BluetoothProfile.STATE_CONNECTED); 737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk device.refresh(); 747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mIsProfileReady=true; 767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void onServiceDisconnected(int profile) { 797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (V) Log.d(TAG,"Bluetooth service disconnected"); 807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mIsProfileReady=false; 817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public boolean isProfileReady() { 857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return mIsProfileReady; 867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk A2dpProfile(Context context, LocalBluetoothAdapter adapter, 897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk CachedBluetoothDeviceManager deviceManager, 907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk LocalBluetoothProfileManager profileManager) { 917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mLocalAdapter = adapter; 927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mDeviceManager = deviceManager; 937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mProfileManager = profileManager; 947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mLocalAdapter.getProfileProxy(context, new A2dpServiceListener(), 957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothProfile.A2DP); 967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public boolean isConnectable() { 997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return true; 1007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public boolean isAutoConnectable() { 1037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return true; 1047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public List<BluetoothDevice> getConnectedDevices() { 1077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) return new ArrayList<BluetoothDevice>(0); 1087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return mService.getDevicesMatchingConnectionStates( 1097ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk new int[] {BluetoothProfile.STATE_CONNECTED, 1107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothProfile.STATE_CONNECTING, 1117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothProfile.STATE_DISCONNECTING}); 1127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public boolean connect(BluetoothDevice device) { 1157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) return false; 1167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk List<BluetoothDevice> sinks = getConnectedDevices(); 1177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (sinks != null) { 1187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk for (BluetoothDevice sink : sinks) { 1197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mService.disconnect(sink); 1207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return mService.connect(device); 1237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public boolean disconnect(BluetoothDevice device) { 1267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) return false; 1277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk // Downgrade priority as user is disconnecting the headset. 1287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){ 1297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return mService.disconnect(device); 1327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public int getConnectionStatus(BluetoothDevice device) { 1357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) { 1367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return BluetoothProfile.STATE_DISCONNECTED; 1377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return mService.getConnectionState(device); 1397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public boolean isPreferred(BluetoothDevice device) { 1427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) return false; 1437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 1447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public int getPreferred(BluetoothDevice device) { 1477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) return BluetoothProfile.PRIORITY_OFF; 1487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return mService.getPriority(device); 1497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public void setPreferred(BluetoothDevice device, boolean preferred) { 1527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) return; 1537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (preferred) { 1547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 1557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } else { 1587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 1597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk boolean isA2dpPlaying() { 1627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService == null) return false; 1637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk List<BluetoothDevice> sinks = mService.getConnectedDevices(); 1647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (!sinks.isEmpty()) { 1657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService.isA2dpPlaying(sinks.get(0))) { 1667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return true; 1677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return false; 1707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public String toString() { 1737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return NAME; 1747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public int getOrdinal() { 1777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return ORDINAL; 1787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public int getNameResource(BluetoothDevice device) { 1817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return R.string.bluetooth_profile_a2dp; 1827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public int getSummaryResourceForDevice(BluetoothDevice device) { 1857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk int state = getConnectionStatus(device); 1867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk switch (state) { 1877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothProfile.STATE_DISCONNECTED: 1887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return R.string.bluetooth_a2dp_profile_summary_use_for; 1897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk case BluetoothProfile.STATE_CONNECTED: 1917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return R.string.bluetooth_a2dp_profile_summary_connected; 1927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk default: 1947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return Utils.getConnectionStateSummary(state); 1957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 1977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 1987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk public int getDrawableResource(BluetoothClass btClass) { 1997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk return R.drawable.ic_bt_headphones_a2dp; 2007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk 2027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk protected void finalize() { 2037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (V) Log.d(TAG, "finalize()"); 2047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk if (mService != null) { 2057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk try { 2067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP, 2077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mService); 2087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk mService = null; 2097ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk }catch (Throwable t) { 2107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk Log.w(TAG, "Error cleaning up A2DP proxy", t); 2117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk } 2147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk} 215