• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.bluetooth;
18 
19 import android.content.Context;
20 import android.os.Binder;
21 import android.os.IBinder;
22 import android.os.RemoteException;
23 import android.util.Log;
24 
25 import java.util.ArrayList;
26 import java.util.List;
27 
28 /**
29  * This class provides the APIs to control the Bluetooth PBAP Client Profile.
30  *
31  * @hide
32  */
33 public 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 =
40             "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
41 
42     /** There was an error trying to obtain the state */
43     public static final int STATE_ERROR = -1;
44 
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 
50     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));
57                 }
58     };
59 
60     /**
61      * Create a BluetoothPbapClient proxy object.
62      */
BluetoothPbapClient(Context context, ServiceListener listener)63     BluetoothPbapClient(Context context, ServiceListener listener) {
64         if (DBG) {
65             Log.d(TAG, "Create BluetoothPbapClient proxy object");
66         }
67         mAdapter = BluetoothAdapter.getDefaultAdapter();
68         mProfileConnector.connect(context, listener);
69     }
70 
finalize()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      */
close()85     public synchronized void close() {
86         mProfileConnector.disconnect();
87     }
88 
getService()89     private IBluetoothPbapClient getService() {
90         return mProfileConnector.getService();
91     }
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      *
98      * @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;
101      */
connect(BluetoothDevice device)102     public boolean connect(BluetoothDevice device) {
103         if (DBG) {
104             log("connect(" + device + ") for PBAP Client.");
105         }
106         final IBluetoothPbapClient service = getService();
107         if (service != null && isEnabled() && isValidDevice(device)) {
108             try {
109                 return service.connect(device);
110             } catch (RemoteException e) {
111                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
112                 return false;
113             }
114         }
115         if (service == null) {
116             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
125      * @return false on error, true otherwise
126      */
disconnect(BluetoothDevice device)127     public boolean disconnect(BluetoothDevice device) {
128         if (DBG) {
129             log("disconnect(" + device + ")" + new Exception());
130         }
131         final IBluetoothPbapClient service = getService();
132         if (service != null && isEnabled() && isValidDevice(device)) {
133             try {
134                 service.disconnect(device);
135                 return true;
136             } catch (RemoteException e) {
137                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
138                 return false;
139             }
140         }
141         if (service == null) {
142             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
getConnectedDevices()154     public List<BluetoothDevice> getConnectedDevices() {
155         if (DBG) {
156             log("getConnectedDevices()");
157         }
158         final IBluetoothPbapClient service = getService();
159         if (service != null && isEnabled()) {
160             try {
161                 return service.getConnectedDevices();
162             } catch (RemoteException e) {
163                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
164                 return new ArrayList<BluetoothDevice>();
165             }
166         }
167         if (service == null) {
168             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
getDevicesMatchingConnectionStates(int[] states)179     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
180         if (DBG) {
181             log("getDevicesMatchingStates()");
182         }
183         final IBluetoothPbapClient service = getService();
184         if (service != null && isEnabled()) {
185             try {
186                 return service.getDevicesMatchingConnectionStates(states);
187             } catch (RemoteException e) {
188                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
189                 return new ArrayList<BluetoothDevice>();
190             }
191         }
192         if (service == null) {
193             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
getConnectionState(BluetoothDevice device)204     public int getConnectionState(BluetoothDevice device) {
205         if (DBG) {
206             log("getConnectionState(" + device + ")");
207         }
208         final IBluetoothPbapClient service = getService();
209         if (service != null && isEnabled() && isValidDevice(device)) {
210             try {
211                 return service.getConnectionState(device);
212             } catch (RemoteException e) {
213                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
214                 return BluetoothProfile.STATE_DISCONNECTED;
215             }
216         }
217         if (service == null) {
218             Log.w(TAG, "Proxy not attached to service");
219         }
220         return BluetoothProfile.STATE_DISCONNECTED;
221     }
222 
log(String msg)223     private static void log(String msg) {
224         Log.d(TAG, msg);
225     }
226 
isEnabled()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 
isValidDevice(BluetoothDevice device)236     private static boolean isValidDevice(BluetoothDevice device) {
237         return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
238     }
239 
240     /**
241      * Set priority of the profile
242      *
243      * <p> The device should already be paired.
244      * Priority can be one of {@link #PRIORITY_ON} or
245      * {@link #PRIORITY_OFF},
246      *
247      * @param device Paired bluetooth device
248      * @param priority Priority of this profile
249      * @return true if priority is set, false on error
250      */
setPriority(BluetoothDevice device, int priority)251     public boolean setPriority(BluetoothDevice device, int priority) {
252         if (DBG) {
253             log("setPriority(" + device + ", " + priority + ")");
254         }
255         final IBluetoothPbapClient service = getService();
256         if (service != null && isEnabled() && isValidDevice(device)) {
257             if (priority != BluetoothProfile.PRIORITY_OFF
258                     && priority != BluetoothProfile.PRIORITY_ON) {
259                 return false;
260             }
261             try {
262                 return service.setPriority(device, priority);
263             } catch (RemoteException e) {
264                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
265                 return false;
266             }
267         }
268         if (service == null) {
269             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      */
getPriority(BluetoothDevice device)284     public int getPriority(BluetoothDevice device) {
285         if (VDBG) {
286             log("getPriority(" + device + ")");
287         }
288         final IBluetoothPbapClient service = getService();
289         if (service != null && isEnabled() && isValidDevice(device)) {
290             try {
291                 return service.getPriority(device);
292             } catch (RemoteException e) {
293                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
294                 return PRIORITY_OFF;
295             }
296         }
297         if (service == null) {
298             Log.w(TAG, "Proxy not attached to service");
299         }
300         return PRIORITY_OFF;
301     }
302 }
303