1424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde/* 2424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * Copyright (C) 2015 The Android Open Source Project 3424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * 4424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * Licensed under the Apache License, Version 2.0 (the "License"); 5424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * you may not use this file except in compliance with the License. 6424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * You may obtain a copy of the License at 7424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * 8424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * http://www.apache.org/licenses/LICENSE-2.0 9424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * 10424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * Unless required by applicable law or agreed to in writing, software 11424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * distributed under the License is distributed on an "AS IS" BASIS, 12424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * See the License for the specific language governing permissions and 14424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * limitations under the License. 15424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde */ 16424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 17424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondepackage com.android.settingslib.bluetooth; 18424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 19424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.bluetooth.BluetoothAdapter; 20424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.bluetooth.BluetoothClass; 21424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.bluetooth.BluetoothDevice; 22424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.bluetooth.BluetoothSap; 23424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.bluetooth.BluetoothProfile; 24424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.bluetooth.BluetoothUuid; 25424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.content.Context; 26424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.os.ParcelUuid; 27424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport android.util.Log; 28424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 29424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport com.android.settingslib.R; 30424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 31424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport java.util.ArrayList; 32424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondeimport java.util.List; 33424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 34424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde/** 35424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde * SapProfile handles Bluetooth SAP profile. 36424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde */ 37424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bondefinal class SapProfile implements LocalBluetoothProfile { 38424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private static final String TAG = "SapProfile"; 39424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private static boolean V = true; 40424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 41424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private BluetoothSap mService; 42424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private boolean mIsProfileReady; 43424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 44424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private final LocalBluetoothAdapter mLocalAdapter; 45424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private final CachedBluetoothDeviceManager mDeviceManager; 46424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private final LocalBluetoothProfileManager mProfileManager; 47424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 48424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde static final ParcelUuid[] UUIDS = { 49424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde BluetoothUuid.SAP, 50424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde }; 51424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 52424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde static final String NAME = "SAP"; 53424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 54424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde // Order of this profile in device profiles list 55424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private static final int ORDINAL = 10; 56424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 57424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde // These callbacks run on the main thread. 58424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde private final class SapServiceListener 59424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde implements BluetoothProfile.ServiceListener { 60424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 61424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public void onServiceConnected(int profile, BluetoothProfile proxy) { 62424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (V) Log.d(TAG,"Bluetooth service connected"); 63424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mService = (BluetoothSap) proxy; 64424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde // We just bound to the service, so refresh the UI for any connected SAP devices. 65424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 66424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde while (!deviceList.isEmpty()) { 67424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde BluetoothDevice nextDevice = deviceList.remove(0); 68424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice); 69424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde // we may add a new device here, but generally this should not happen 70424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (device == null) { 71424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde Log.w(TAG, "SapProfile found new device: " + nextDevice); 72424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice); 73424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 74424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde device.onProfileStateChanged(SapProfile.this, 75424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde BluetoothProfile.STATE_CONNECTED); 76424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde device.refresh(); 77424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 78424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 79424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mProfileManager.callServiceConnectedListeners(); 80424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mIsProfileReady=true; 81424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 82424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 83424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public void onServiceDisconnected(int profile) { 84424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (V) Log.d(TAG,"Bluetooth service disconnected"); 85424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mProfileManager.callServiceDisconnectedListeners(); 86424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mIsProfileReady=false; 87424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 88424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 89424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 90424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public boolean isProfileReady() { 91424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return mIsProfileReady; 92424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 93424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 94424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde SapProfile(Context context, LocalBluetoothAdapter adapter, 95424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde CachedBluetoothDeviceManager deviceManager, 96424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde LocalBluetoothProfileManager profileManager) { 97424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mLocalAdapter = adapter; 98424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mDeviceManager = deviceManager; 99424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mProfileManager = profileManager; 100424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mLocalAdapter.getProfileProxy(context, new SapServiceListener(), 101424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde BluetoothProfile.SAP); 102424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 103424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 104424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public boolean isConnectable() { 105424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return true; 106424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 107424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 108424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public boolean isAutoConnectable() { 109424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return true; 110424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 111424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 112424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public boolean connect(BluetoothDevice device) { 113424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService == null) return false; 114424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde List<BluetoothDevice> sinks = mService.getConnectedDevices(); 115424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (sinks != null) { 116424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde for (BluetoothDevice sink : sinks) { 117424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mService.disconnect(sink); 118424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 119424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 120424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return mService.connect(device); 121424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 122424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 123424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public boolean disconnect(BluetoothDevice device) { 124424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService == null) return false; 125424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 126424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) { 127424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) { 128424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 129424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 130424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return mService.disconnect(device); 131424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } else { 132424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return false; 133424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 134424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 135424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 136424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public int getConnectionStatus(BluetoothDevice device) { 137424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService == null) return BluetoothProfile.STATE_DISCONNECTED; 138424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 139424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 140424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return !deviceList.isEmpty() && deviceList.get(0).equals(device) 141424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde ? mService.getConnectionState(device) 142424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde : BluetoothProfile.STATE_DISCONNECTED; 143424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 144424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 145424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public boolean isPreferred(BluetoothDevice device) { 146424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService == null) return false; 147424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 148424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 149424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 150424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public int getPreferred(BluetoothDevice device) { 151424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService == null) return BluetoothProfile.PRIORITY_OFF; 152424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return mService.getPriority(device); 153424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 154424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 155424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public void setPreferred(BluetoothDevice device, boolean preferred) { 156424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService == null) return; 157424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (preferred) { 158424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 159424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 160424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 161424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } else { 162424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 163424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 164424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 165424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 166424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public List<BluetoothDevice> getConnectedDevices() { 167424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService == null) return new ArrayList<BluetoothDevice>(0); 168424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return mService.getDevicesMatchingConnectionStates( 169424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde new int[] {BluetoothProfile.STATE_CONNECTED, 170424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde BluetoothProfile.STATE_CONNECTING, 171424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde BluetoothProfile.STATE_DISCONNECTING}); 172424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 173424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 174424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public String toString() { 175424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return NAME; 176424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 177424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 178424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public int getOrdinal() { 179424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return ORDINAL; 180424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 181424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 182424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public int getNameResource(BluetoothDevice device) { 183424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return R.string.bluetooth_profile_sap; 184424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 185424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 186424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public int getSummaryResourceForDevice(BluetoothDevice device) { 187424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde int state = getConnectionStatus(device); 188424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde switch (state) { 189424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde case BluetoothProfile.STATE_DISCONNECTED: 190424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return R.string.bluetooth_sap_profile_summary_use_for; 191424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 192424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde case BluetoothProfile.STATE_CONNECTED: 193424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return R.string.bluetooth_sap_profile_summary_connected; 194424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 195424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde default: 196424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return Utils.getConnectionStateSummary(state); 197424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 198424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 199424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 200424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde public int getDrawableResource(BluetoothClass btClass) { 201424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde return R.drawable.ic_bt_cellphone; 202424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 203424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde 204424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde protected void finalize() { 205424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (V) Log.d(TAG, "finalize()"); 206424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde if (mService != null) { 207424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde try { 208424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.SAP, 209424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mService); 210424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde mService = null; 211424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde }catch (Throwable t) { 212424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde Log.w(TAG, "Error cleaning up SAP proxy", t); 213424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 214424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 215424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde } 216424681e43e454bfcbceb863ddccb875ea57ec26fCasper Bonde} 217