blob: d70e1e7f3f5f49d1febdbbc1148106e196945581 [file] [log] [blame]
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08001/*
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 android.bluetooth;
18
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080019import android.content.Context;
Jeff Sharkey0a17db12016-11-04 11:23:46 -060020import android.os.Binder;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080021import android.os.IBinder;
Jack Hea355e5e2017-08-22 16:06:54 -070022import android.os.RemoteException;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080023import android.util.Log;
24
Jack Hea355e5e2017-08-22 16:06:54 -070025import java.util.ArrayList;
26import java.util.List;
27
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080028/**
29 * This class provides the APIs to control the Bluetooth PBAP Client Profile.
Jack Hea355e5e2017-08-22 16:06:54 -070030 *
31 * @hide
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080032 */
33public final class BluetoothPbapClient implements BluetoothProfile {
34
35 private static final String TAG = "BluetoothPbapClient";
36 private static final boolean DBG = false;
37 private static final boolean VDBG = false;
38
39 public static final String ACTION_CONNECTION_STATE_CHANGED =
Jack He37ab8152017-10-02 19:08:30 -070040 "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080041
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080042 /** There was an error trying to obtain the state */
Jack Hea355e5e2017-08-22 16:06:54 -070043 public static final int STATE_ERROR = -1;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080044
45 public static final int RESULT_FAILURE = 0;
46 public static final int RESULT_SUCCESS = 1;
47 /** Connection canceled before completion. */
48 public static final int RESULT_CANCELED = 2;
49
Ugo Yud0115462019-03-26 21:38:08 +080050 private BluetoothAdapter mAdapter;
51 private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector =
52 new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT,
53 "BluetoothPbapClient", IBluetoothPbapClient.class.getName()) {
54 @Override
55 public IBluetoothPbapClient getServiceInterface(IBinder service) {
56 return IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080057 }
Ugo Yud0115462019-03-26 21:38:08 +080058 };
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080059
60 /**
61 * Create a BluetoothPbapClient proxy object.
62 */
Ugo Yud0115462019-03-26 21:38:08 +080063 BluetoothPbapClient(Context context, ServiceListener listener) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080064 if (DBG) {
65 Log.d(TAG, "Create BluetoothPbapClient proxy object");
66 }
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080067 mAdapter = BluetoothAdapter.getDefaultAdapter();
Ugo Yud0115462019-03-26 21:38:08 +080068 mProfileConnector.connect(context, listener);
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080069 }
70
71 protected void finalize() throws Throwable {
72 try {
73 close();
74 } finally {
75 super.finalize();
76 }
77 }
78
79 /**
80 * Close the connection to the backing service.
81 * Other public functions of BluetoothPbapClient will return default error
82 * results once close() has been called. Multiple invocations of close()
83 * are ok.
84 */
85 public synchronized void close() {
Ugo Yud0115462019-03-26 21:38:08 +080086 mProfileConnector.disconnect();
87 }
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080088
Ugo Yud0115462019-03-26 21:38:08 +080089 private IBluetoothPbapClient getService() {
90 return mProfileConnector.getService();
Joseph Pirozzocfa8a642016-03-04 13:02:54 -080091 }
92
93 /**
94 * Initiate connection.
95 * Upon successful connection to remote PBAP server the Client will
96 * attempt to automatically download the users phonebook and call log.
97 *
Jack Hea355e5e2017-08-22 16:06:54 -070098 * @param device a remote device we want connect to
99 * @return <code>true</code> if command has been issued successfully; <code>false</code>
100 * otherwise;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800101 */
102 public boolean connect(BluetoothDevice device) {
103 if (DBG) {
104 log("connect(" + device + ") for PBAP Client.");
105 }
Ugo Yud0115462019-03-26 21:38:08 +0800106 final IBluetoothPbapClient service = getService();
Jack He16eeac32017-08-17 12:11:18 -0700107 if (service != null && isEnabled() && isValidDevice(device)) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800108 try {
Jack He16eeac32017-08-17 12:11:18 -0700109 return service.connect(device);
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800110 } catch (RemoteException e) {
111 Log.e(TAG, Log.getStackTraceString(new Throwable()));
112 return false;
113 }
114 }
Jack He16eeac32017-08-17 12:11:18 -0700115 if (service == null) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800116 Log.w(TAG, "Proxy not attached to service");
117 }
118 return false;
119 }
120
121 /**
122 * Initiate disconnect.
123 *
124 * @param device Remote Bluetooth Device
Jack Hea355e5e2017-08-22 16:06:54 -0700125 * @return false on error, true otherwise
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800126 */
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700127 public boolean disconnect(BluetoothDevice device) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800128 if (DBG) {
Jack Hea355e5e2017-08-22 16:06:54 -0700129 log("disconnect(" + device + ")" + new Exception());
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800130 }
Ugo Yud0115462019-03-26 21:38:08 +0800131 final IBluetoothPbapClient service = getService();
Jack He16eeac32017-08-17 12:11:18 -0700132 if (service != null && isEnabled() && isValidDevice(device)) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800133 try {
Jack He16eeac32017-08-17 12:11:18 -0700134 service.disconnect(device);
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800135 return true;
136 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -0700137 Log.e(TAG, Log.getStackTraceString(new Throwable()));
138 return false;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800139 }
140 }
Jack He16eeac32017-08-17 12:11:18 -0700141 if (service == null) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800142 Log.w(TAG, "Proxy not attached to service");
143 }
144 return false;
145 }
146
147 /**
148 * Get the list of connected devices.
149 * Currently at most one.
150 *
151 * @return list of connected devices
152 */
153 @Override
154 public List<BluetoothDevice> getConnectedDevices() {
155 if (DBG) {
156 log("getConnectedDevices()");
157 }
Ugo Yud0115462019-03-26 21:38:08 +0800158 final IBluetoothPbapClient service = getService();
Jack He16eeac32017-08-17 12:11:18 -0700159 if (service != null && isEnabled()) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800160 try {
Jack He16eeac32017-08-17 12:11:18 -0700161 return service.getConnectedDevices();
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800162 } catch (RemoteException e) {
163 Log.e(TAG, Log.getStackTraceString(new Throwable()));
164 return new ArrayList<BluetoothDevice>();
165 }
166 }
Jack He16eeac32017-08-17 12:11:18 -0700167 if (service == null) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800168 Log.w(TAG, "Proxy not attached to service");
169 }
170 return new ArrayList<BluetoothDevice>();
171 }
172
173 /**
174 * Get the list of devices matching specified states. Currently at most one.
175 *
176 * @return list of matching devices
177 */
178 @Override
179 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
180 if (DBG) {
181 log("getDevicesMatchingStates()");
182 }
Ugo Yud0115462019-03-26 21:38:08 +0800183 final IBluetoothPbapClient service = getService();
Jack He16eeac32017-08-17 12:11:18 -0700184 if (service != null && isEnabled()) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800185 try {
Jack He16eeac32017-08-17 12:11:18 -0700186 return service.getDevicesMatchingConnectionStates(states);
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800187 } catch (RemoteException e) {
188 Log.e(TAG, Log.getStackTraceString(new Throwable()));
189 return new ArrayList<BluetoothDevice>();
190 }
191 }
Jack He16eeac32017-08-17 12:11:18 -0700192 if (service == null) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800193 Log.w(TAG, "Proxy not attached to service");
194 }
195 return new ArrayList<BluetoothDevice>();
196 }
197
198 /**
199 * Get connection state of device
200 *
201 * @return device connection state
202 */
203 @Override
204 public int getConnectionState(BluetoothDevice device) {
205 if (DBG) {
206 log("getConnectionState(" + device + ")");
207 }
Ugo Yud0115462019-03-26 21:38:08 +0800208 final IBluetoothPbapClient service = getService();
Jack He16eeac32017-08-17 12:11:18 -0700209 if (service != null && isEnabled() && isValidDevice(device)) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800210 try {
Jack He16eeac32017-08-17 12:11:18 -0700211 return service.getConnectionState(device);
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800212 } catch (RemoteException e) {
213 Log.e(TAG, Log.getStackTraceString(new Throwable()));
214 return BluetoothProfile.STATE_DISCONNECTED;
215 }
216 }
Jack He16eeac32017-08-17 12:11:18 -0700217 if (service == null) {
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800218 Log.w(TAG, "Proxy not attached to service");
219 }
220 return BluetoothProfile.STATE_DISCONNECTED;
221 }
222
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800223 private static void log(String msg) {
224 Log.d(TAG, msg);
225 }
226
227 private boolean isEnabled() {
228 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
229 if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) {
230 return true;
231 }
232 log("Bluetooth is Not enabled");
233 return false;
234 }
235
Jack He16eeac32017-08-17 12:11:18 -0700236 private static boolean isValidDevice(BluetoothDevice device) {
237 return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800238 }
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700239
240 /**
241 * Set priority of the profile
242 *
243 * <p> The device should already be paired.
Jack Hea355e5e2017-08-22 16:06:54 -0700244 * Priority can be one of {@link #PRIORITY_ON} or
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700245 * {@link #PRIORITY_OFF},
246 *
247 * @param device Paired bluetooth device
Jack He16eeac32017-08-17 12:11:18 -0700248 * @param priority Priority of this profile
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700249 * @return true if priority is set, false on error
250 */
251 public boolean setPriority(BluetoothDevice device, int priority) {
252 if (DBG) {
253 log("setPriority(" + device + ", " + priority + ")");
254 }
Ugo Yud0115462019-03-26 21:38:08 +0800255 final IBluetoothPbapClient service = getService();
Jack He16eeac32017-08-17 12:11:18 -0700256 if (service != null && isEnabled() && isValidDevice(device)) {
Jack He2992cd02017-08-22 21:21:23 -0700257 if (priority != BluetoothProfile.PRIORITY_OFF
258 && priority != BluetoothProfile.PRIORITY_ON) {
Jack Hea355e5e2017-08-22 16:06:54 -0700259 return false;
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700260 }
261 try {
Jack He16eeac32017-08-17 12:11:18 -0700262 return service.setPriority(device, priority);
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700263 } catch (RemoteException e) {
264 Log.e(TAG, Log.getStackTraceString(new Throwable()));
265 return false;
266 }
267 }
Jack He16eeac32017-08-17 12:11:18 -0700268 if (service == null) {
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700269 Log.w(TAG, "Proxy not attached to service");
270 }
271 return false;
272 }
273
274 /**
275 * Get the priority of the profile.
276 *
277 * <p> The priority can be any of:
278 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
279 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
280 *
281 * @param device Bluetooth device
282 * @return priority of the device
283 */
284 public int getPriority(BluetoothDevice device) {
285 if (VDBG) {
286 log("getPriority(" + device + ")");
287 }
Ugo Yud0115462019-03-26 21:38:08 +0800288 final IBluetoothPbapClient service = getService();
Jack He16eeac32017-08-17 12:11:18 -0700289 if (service != null && isEnabled() && isValidDevice(device)) {
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700290 try {
Jack He16eeac32017-08-17 12:11:18 -0700291 return service.getPriority(device);
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700292 } catch (RemoteException e) {
293 Log.e(TAG, Log.getStackTraceString(new Throwable()));
294 return PRIORITY_OFF;
295 }
296 }
Jack He16eeac32017-08-17 12:11:18 -0700297 if (service == null) {
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700298 Log.w(TAG, "Proxy not attached to service");
299 }
300 return PRIORITY_OFF;
301 }
Joseph Pirozzocfa8a642016-03-04 13:02:54 -0800302}