PbapClientService.java revision b2c3dc95628314b060cef05d59ce2fe4ef747b84
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 17package com.android.bluetooth.pbapclient; 18 19import android.bluetooth.BluetoothDevice; 20import android.bluetooth.BluetoothProfile; 21import android.bluetooth.IBluetoothPbapClient; 22import android.content.BroadcastReceiver; 23import android.content.Context; 24import android.content.Intent; 25import android.content.IntentFilter; 26import android.provider.Settings; 27import android.util.Log; 28 29import com.android.bluetooth.btservice.ProfileService; 30import com.android.bluetooth.Utils; 31 32import java.lang.IllegalArgumentException; 33import java.util.ArrayList; 34import java.util.List; 35 36/** 37 * Provides Bluetooth Phone Book Access Profile Client profile. 38 * 39 * @hide 40 */ 41public class PbapClientService extends ProfileService { 42 private static final boolean DBG = false; 43 private static final String TAG = "PbapClientService"; 44 private PbapClientStateMachine mPbapClientStateMachine; 45 private static PbapClientService sPbapClientService; 46 private PbapBroadcastReceiver mPbapBroadcastReceiver = new PbapBroadcastReceiver(); 47 48 @Override 49 protected String getName() { 50 return TAG; 51 } 52 53 @Override 54 public IProfileServiceBinder initBinder() { 55 return new BluetoothPbapClientBinder(this); 56 } 57 58 @Override 59 protected boolean start() { 60 if (DBG) Log.d(TAG, "onStart"); 61 IntentFilter filter = new IntentFilter(); 62 filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); 63 // delay initial download until after the user is unlocked to add an account. 64 filter.addAction(Intent.ACTION_USER_UNLOCKED); 65 try { 66 registerReceiver(mPbapBroadcastReceiver, filter); 67 } catch (Exception e) { 68 Log.w(TAG,"Unable to register pbapclient receiver", e); 69 } 70 mPbapClientStateMachine = new PbapClientStateMachine(this, this); 71 setPbapClientService(this); 72 mPbapClientStateMachine.start(); 73 return true; 74 } 75 76 @Override 77 protected boolean stop() { 78 try { 79 unregisterReceiver(mPbapBroadcastReceiver); 80 } catch (Exception e) { 81 Log.w(TAG,"Unable to unregister pbapclient receiver", e); 82 } 83 if (mPbapClientStateMachine != null) { 84 mPbapClientStateMachine.doQuit(); 85 } 86 return true; 87 } 88 89 @Override 90 protected boolean cleanup() { 91 clearPbapClientService(); 92 return true; 93 } 94 95 private class PbapBroadcastReceiver extends BroadcastReceiver { 96 @Override 97 public void onReceive(Context context, Intent intent) { 98 String action = intent.getAction(); 99 Log.v(TAG, "onReceive" + action); 100 if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { 101 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 102 if (getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) { 103 disconnect(device); 104 } 105 } else if(action.equals(Intent.ACTION_USER_UNLOCKED)) { 106 mPbapClientStateMachine.resumeDownload(); 107 } 108 } 109 } 110 111 /** 112 * Handler for incoming service calls 113 */ 114 private static class BluetoothPbapClientBinder extends IBluetoothPbapClient.Stub 115 implements IProfileServiceBinder { 116 private PbapClientService mService; 117 118 public BluetoothPbapClientBinder(PbapClientService svc) { 119 mService = svc; 120 } 121 122 @Override 123 public boolean cleanup() { 124 mService = null; 125 return true; 126 } 127 128 private PbapClientService getService() { 129 if (!Utils.checkCaller()) { 130 Log.w(TAG, "PbapClient call not allowed for non-active user"); 131 return null; 132 } 133 134 if (mService != null && mService.isAvailable()) { 135 return mService; 136 } 137 return null; 138 } 139 140 @Override 141 public boolean connect(BluetoothDevice device) { 142 PbapClientService service = getService(); 143 if (DBG) Log.d(TAG, "PbapClient Binder connect " ); 144 if (service == null) { 145 Log.e(TAG, "PbapClient Binder connect no service"); 146 return false; 147 } 148 return service.connect(device); 149 } 150 151 @Override 152 public boolean disconnect(BluetoothDevice device) { 153 PbapClientService service = getService(); 154 if (service == null) { 155 return false; 156 } 157 return service.disconnect(device); 158 } 159 160 @Override 161 public List<BluetoothDevice> getConnectedDevices() { 162 PbapClientService service = getService(); 163 if (service == null) { 164 return new ArrayList<BluetoothDevice>(0); 165 } 166 return service.getConnectedDevices(); 167 } 168 @Override 169 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 170 PbapClientService service = getService(); 171 if (service == null) { 172 return new ArrayList<BluetoothDevice>(0); 173 } 174 return service.getDevicesMatchingConnectionStates(states); 175 } 176 177 @Override 178 public int getConnectionState(BluetoothDevice device) { 179 PbapClientService service = getService(); 180 if (service == null) { 181 return BluetoothProfile.STATE_DISCONNECTED; 182 } 183 return service.getConnectionState(device); 184 } 185 186 public boolean setPriority(BluetoothDevice device, int priority) { 187 PbapClientService service = getService(); 188 if (service == null) { 189 return false; 190 } 191 return service.setPriority(device, priority); 192 } 193 194 public int getPriority(BluetoothDevice device) { 195 PbapClientService service = getService(); 196 if (service == null) { 197 return BluetoothProfile.PRIORITY_UNDEFINED; 198 } 199 return service.getPriority(device); 200 } 201 202 203 } 204 205 // API methods 206 public static synchronized PbapClientService getPbapClientService() { 207 if (sPbapClientService != null && sPbapClientService.isAvailable()) { 208 if (DBG) { 209 Log.d(TAG, "getPbapClientService(): returning " + sPbapClientService); 210 } 211 return sPbapClientService; 212 } 213 if (DBG) { 214 if (sPbapClientService == null) { 215 Log.d(TAG, "getPbapClientService(): service is NULL"); 216 } else if (!(sPbapClientService.isAvailable())) { 217 Log.d(TAG, "getPbapClientService(): service is not available"); 218 } 219 } 220 return null; 221 } 222 223 private static synchronized void setPbapClientService(PbapClientService instance) { 224 if (instance != null && instance.isAvailable()) { 225 if (DBG) { 226 Log.d(TAG, "setPbapClientService(): set to: " + sPbapClientService); 227 } 228 sPbapClientService = instance; 229 } else { 230 if (DBG) { 231 if (sPbapClientService == null) { 232 Log.d(TAG, "setPbapClientService(): service not available"); 233 } else if (!sPbapClientService.isAvailable()) { 234 Log.d(TAG, "setPbapClientService(): service is cleaning up"); 235 } 236 } 237 } 238 } 239 240 private static synchronized void clearPbapClientService() { 241 sPbapClientService = null; 242 } 243 244 public boolean connect(BluetoothDevice device) { 245 if (device == null) throw new IllegalArgumentException("Null device"); 246 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 247 Log.d(TAG,"Received request to ConnectPBAPPhonebook " + device.getAddress()); 248 int connectionState = mPbapClientStateMachine.getConnectionState(); 249 if (connectionState == BluetoothProfile.STATE_CONNECTED || 250 connectionState == BluetoothProfile.STATE_CONNECTING) { 251 Log.w(TAG,"Received connect request while already connecting/connected."); 252 return false; 253 } 254 if (getPriority(device) > BluetoothProfile.PRIORITY_OFF) { 255 mPbapClientStateMachine.connect(device); 256 return true; 257 } 258 return false; 259 } 260 261 boolean disconnect(BluetoothDevice device) { 262 if (device == null) throw new IllegalArgumentException("Null device"); 263 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 264 mPbapClientStateMachine.disconnect(device); 265 return true; 266 } 267 268 public List<BluetoothDevice> getConnectedDevices() { 269 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 270 int[] desiredStates = {BluetoothProfile.STATE_CONNECTED}; 271 return getDevicesMatchingConnectionStates(desiredStates); 272 } 273 274 private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 275 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 276 return mPbapClientStateMachine.getDevicesMatchingConnectionStates(states); 277 } 278 279 int getConnectionState(BluetoothDevice device) { 280 if (device == null) throw new IllegalArgumentException("Null device"); 281 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 282 return mPbapClientStateMachine.getConnectionState(device); 283 } 284 285 public boolean setPriority(BluetoothDevice device, int priority) { 286 if (device == null) throw new IllegalArgumentException("Null device"); 287 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 288 Settings.Global.putInt(getContentResolver(), 289 Settings.Global.getBluetoothPbapClientPriorityKey(device.getAddress()), 290 priority); 291 if (DBG) { 292 Log.d(TAG,"Saved priority " + device + " = " + priority); 293 } 294 return true; 295 } 296 297 public int getPriority(BluetoothDevice device) { 298 if (device == null) throw new IllegalArgumentException("Null device"); 299 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 300 int priority = Settings.Global.getInt(getContentResolver(), 301 Settings.Global.getBluetoothPbapClientPriorityKey(device.getAddress()), 302 BluetoothProfile.PRIORITY_UNDEFINED); 303 return priority; 304 } 305 306 @Override 307 public void dump(StringBuilder sb) { 308 super.dump(sb); 309 if (mPbapClientStateMachine != null) { 310 mPbapClientStateMachine.dump(sb); 311 } 312 } 313} 314