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