1 /* 2 * Copyright (C) 2016 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.settingslib.bluetooth; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.bluetooth.BluetoothClass; 21 import android.bluetooth.BluetoothDevice; 22 import android.bluetooth.BluetoothPbapClient; 23 import android.bluetooth.BluetoothProfile; 24 import android.bluetooth.BluetoothUuid; 25 import android.content.Context; 26 import android.os.ParcelUuid; 27 import android.util.Log; 28 29 import com.android.settingslib.R; 30 31 import java.util.ArrayList; 32 import java.util.Collection; 33 import java.util.List; 34 35 public final class PbapClientProfile implements LocalBluetoothProfile { 36 private static final String TAG = "PbapClientProfile"; 37 38 private BluetoothPbapClient mService; 39 private boolean mIsProfileReady; 40 41 private final CachedBluetoothDeviceManager mDeviceManager; 42 43 static final ParcelUuid[] SRC_UUIDS = { 44 BluetoothUuid.PBAP_PSE, 45 }; 46 47 static final String NAME = "PbapClient"; 48 private final LocalBluetoothProfileManager mProfileManager; 49 50 // Order of this profile in device profiles list 51 private static final int ORDINAL = 6; 52 53 // These callbacks run on the main thread. 54 private final class PbapClientServiceListener 55 implements BluetoothProfile.ServiceListener { 56 onServiceConnected(int profile, BluetoothProfile proxy)57 public void onServiceConnected(int profile, BluetoothProfile proxy) { 58 mService = (BluetoothPbapClient) proxy; 59 // We just bound to the service, so refresh the UI for any connected PBAP devices. 60 List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 61 while (!deviceList.isEmpty()) { 62 BluetoothDevice nextDevice = deviceList.remove(0); 63 CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice); 64 // we may add a new device here, but generally this should not happen 65 if (device == null) { 66 Log.w(TAG, "PbapClientProfile found new device: " + nextDevice); 67 device = mDeviceManager.addDevice(nextDevice); 68 } 69 device.onProfileStateChanged(PbapClientProfile.this, BluetoothProfile.STATE_CONNECTED); 70 device.refresh(); 71 } 72 mIsProfileReady = true; 73 } 74 onServiceDisconnected(int profile)75 public void onServiceDisconnected(int profile) { 76 mIsProfileReady = false; 77 } 78 } 79 refreshProfiles()80 private void refreshProfiles() { 81 Collection<CachedBluetoothDevice> cachedDevices = mDeviceManager.getCachedDevicesCopy(); 82 for (CachedBluetoothDevice device : cachedDevices) { 83 device.onUuidChanged(); 84 } 85 } 86 pbapClientExists()87 public boolean pbapClientExists() { 88 return (mService != null); 89 } 90 isProfileReady()91 public boolean isProfileReady() { 92 return mIsProfileReady; 93 } 94 95 @Override getProfileId()96 public int getProfileId() { 97 return BluetoothProfile.PBAP_CLIENT; 98 } 99 PbapClientProfile(Context context, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager)100 PbapClientProfile(Context context, CachedBluetoothDeviceManager deviceManager, 101 LocalBluetoothProfileManager profileManager) { 102 mDeviceManager = deviceManager; 103 mProfileManager = profileManager; 104 BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, 105 new PbapClientServiceListener(), BluetoothProfile.PBAP_CLIENT); 106 } 107 accessProfileEnabled()108 public boolean accessProfileEnabled() { 109 return true; 110 } 111 isAutoConnectable()112 public boolean isAutoConnectable() { 113 return true; 114 } 115 getConnectedDevices()116 public List<BluetoothDevice> getConnectedDevices() { 117 if (mService == null) { 118 return new ArrayList<BluetoothDevice>(0); 119 } 120 return mService.getDevicesMatchingConnectionStates( 121 new int[] {BluetoothProfile.STATE_CONNECTED, 122 BluetoothProfile.STATE_CONNECTING, 123 BluetoothProfile.STATE_DISCONNECTING}); 124 } 125 connect(BluetoothDevice device)126 public boolean connect(BluetoothDevice device) { 127 Log.d(TAG,"PBAPClientProfile got connect request"); 128 if (mService == null) { 129 return false; 130 } 131 Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress()); 132 return mService.connect(device); 133 } 134 disconnect(BluetoothDevice device)135 public boolean disconnect(BluetoothDevice device) { 136 Log.d(TAG,"PBAPClientProfile got disconnect request"); 137 if (mService == null) { 138 return false; 139 } 140 return mService.disconnect(device); 141 } 142 getConnectionStatus(BluetoothDevice device)143 public int getConnectionStatus(BluetoothDevice device) { 144 if (mService == null) { 145 return BluetoothProfile.STATE_DISCONNECTED; 146 } 147 return mService.getConnectionState(device); 148 } 149 isPreferred(BluetoothDevice device)150 public boolean isPreferred(BluetoothDevice device) { 151 if (mService == null) { 152 return false; 153 } 154 return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 155 } 156 getPreferred(BluetoothDevice device)157 public int getPreferred(BluetoothDevice device) { 158 if (mService == null) { 159 return BluetoothProfile.PRIORITY_OFF; 160 } 161 return mService.getPriority(device); 162 } 163 setPreferred(BluetoothDevice device, boolean preferred)164 public void setPreferred(BluetoothDevice device, boolean preferred) { 165 if (mService == null) { 166 return; 167 } 168 if (preferred) { 169 if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 170 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 171 } 172 } else { 173 mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 174 } 175 } 176 toString()177 public String toString() { 178 return NAME; 179 } 180 getOrdinal()181 public int getOrdinal() { 182 return ORDINAL; 183 } 184 getNameResource(BluetoothDevice device)185 public int getNameResource(BluetoothDevice device) { 186 // we need to have same string in UI as the server side. 187 return R.string.bluetooth_profile_pbap; 188 } 189 getSummaryResourceForDevice(BluetoothDevice device)190 public int getSummaryResourceForDevice(BluetoothDevice device) { 191 return R.string.bluetooth_profile_pbap_summary; 192 } 193 getDrawableResource(BluetoothClass btClass)194 public int getDrawableResource(BluetoothClass btClass) { 195 return com.android.internal.R.drawable.ic_phone; 196 } 197 finalize()198 protected void finalize() { 199 Log.d(TAG, "finalize()"); 200 if (mService != null) { 201 try { 202 BluetoothAdapter.getDefaultAdapter().closeProfileProxy( 203 BluetoothProfile.PBAP_CLIENT,mService); 204 mService = null; 205 } catch (Throwable t) { 206 Log.w(TAG, "Error cleaning up PBAP Client proxy", t); 207 } 208 } 209 } 210 } 211