1cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo/*
2cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Copyright (C) 2016 The Android Open Source Project
3cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo *
4cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Licensed under the Apache License, Version 2.0 (the "License");
5cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * you may not use this file except in compliance with the License.
6cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * You may obtain a copy of the License at
7cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo *
8cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo *      http://www.apache.org/licenses/LICENSE-2.0
9cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo *
10cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Unless required by applicable law or agreed to in writing, software
11cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * distributed under the License is distributed on an "AS IS" BASIS,
12cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * See the License for the specific language governing permissions and
14cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * limitations under the License.
15cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */
16cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
17cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzopackage android.bluetooth;
18cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
19cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport java.util.List;
20cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport java.util.ArrayList;
21cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.ComponentName;
22cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.Context;
23cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.Intent;
24cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.ServiceConnection;
25cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.os.RemoteException;
260a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkeyimport android.os.Binder;
27cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.os.IBinder;
28cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.util.Log;
29cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
30cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo/**
31cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * This class provides the APIs to control the Bluetooth PBAP Client Profile.
32cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo *@hide
33cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */
34cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzopublic final class BluetoothPbapClient implements BluetoothProfile {
35cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
36cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private static final String TAG = "BluetoothPbapClient";
37cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private static final boolean DBG = false;
38cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private static final boolean VDBG = false;
39cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
40cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public static final String ACTION_CONNECTION_STATE_CHANGED =
41cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
42cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
43cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private IBluetoothPbapClient mService;
44cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private final Context mContext;
45cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private ServiceListener mServiceListener;
46cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private BluetoothAdapter mAdapter;
47cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
48cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /** There was an error trying to obtain the state */
49cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public static final int STATE_ERROR        = -1;
50cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
51cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public static final int RESULT_FAILURE = 0;
52cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public static final int RESULT_SUCCESS = 1;
53cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /** Connection canceled before completion. */
54cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public static final int RESULT_CANCELED = 2;
55cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
56cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
57cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            new IBluetoothStateChangeCallback.Stub() {
58cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                public void onBluetoothStateChange(boolean up) {
59cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    if (DBG) {
60cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                        Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up);
61cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    }
62cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    if (!up) {
63cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                        if (VDBG) {
64cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                            Log.d(TAG,"Unbinding service...");
65cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                        }
66cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                        synchronized (mConnection) {
67cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                            try {
68cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                mService = null;
69cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                mContext.unbindService(mConnection);
70cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                            } catch (Exception re) {
71cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                Log.e(TAG,"",re);
72cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                            }
73cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                        }
74cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    } else {
75cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                        synchronized (mConnection) {
76cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                            try {
77cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                if (mService == null) {
78cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                    if (VDBG) {
79cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                        Log.d(TAG,"Binding service...");
80cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                    }
81cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                    doBind();
82cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                }
83cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                            } catch (Exception re) {
84cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                                Log.e(TAG,"",re);
85cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                            }
86cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                        }
87cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    }
88cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                }
89cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        };
90cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
91cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /**
92cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Create a BluetoothPbapClient proxy object.
93cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     */
94cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    BluetoothPbapClient(Context context, ServiceListener l) {
95cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (DBG) {
96cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            Log.d(TAG, "Create BluetoothPbapClient proxy object");
97cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
98cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        mContext = context;
99cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        mServiceListener = l;
100cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        mAdapter = BluetoothAdapter.getDefaultAdapter();
101cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        IBluetoothManager mgr = mAdapter.getBluetoothManager();
102cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mgr != null) {
103cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            try {
104cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
105cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            } catch (RemoteException e) {
106cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                Log.e(TAG,"",e);
107cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
108cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
109cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        doBind();
110cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
111cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
112cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private boolean doBind() {
113cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        Intent intent = new Intent(IBluetoothPbapClient.class.getName());
114cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
115cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        intent.setComponent(comp);
116cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
117cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                android.os.Process.myUserHandle())) {
118cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent);
119cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            return false;
120cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
121cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        return true;
122cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
123cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
124cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    protected void finalize() throws Throwable {
125cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        try {
126cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            close();
127cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        } finally {
128cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            super.finalize();
129cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
130cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
131cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
132cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /**
133cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Close the connection to the backing service.
134cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Other public functions of BluetoothPbapClient will return default error
135cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * results once close() has been called. Multiple invocations of close()
136cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * are ok.
137cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     */
138cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public synchronized void close() {
139cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        IBluetoothManager mgr = mAdapter.getBluetoothManager();
140cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mgr != null) {
141cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            try {
142cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
143cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            } catch (Exception e) {
144cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                Log.e(TAG,"",e);
145cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
146cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
147cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
148cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        synchronized (mConnection) {
149cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            if (mService != null) {
150cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                try {
151cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    mService = null;
152cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    mContext.unbindService(mConnection);
153cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                } catch (Exception re) {
154cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                    Log.e(TAG,"",re);
155cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                }
156cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
157cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
158cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        mServiceListener = null;
159cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
160cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
161cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /**
162cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Initiate connection.
163cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Upon successful connection to remote PBAP server the Client will
164cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * attempt to automatically download the users phonebook and call log.
165cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     *
166cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * @param device    a remote device we want connect to
167cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * @return <code>true</code> if command has been issued successfully;
168cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     *         <code>false</code> otherwise;
169cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     */
170cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public boolean connect(BluetoothDevice device) {
171cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (DBG) {
172cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            log("connect(" + device + ") for PBAP Client.");
173cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
174cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService != null && isEnabled() && isValidDevice(device)) {
175cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            try {
176cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return mService.connect(device);
177cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            } catch (RemoteException e) {
178cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                Log.e(TAG, Log.getStackTraceString(new Throwable()));
179cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return false;
180cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
181cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
182cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService == null) {
183cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            Log.w(TAG, "Proxy not attached to service");
184cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
185cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        return false;
186cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
187cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
188cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /**
189cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Initiate disconnect.
190cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     *
191cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * @param device Remote Bluetooth Device
192cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * @return false on error,
193cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     *               true otherwise
194cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     */
195563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    public boolean disconnect(BluetoothDevice device) {
196cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (DBG) {
197563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            log("disconnect(" + device + ")" + new Exception() );
198cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
199563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (mService != null && isEnabled() && isValidDevice(device)) {
200cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            try {
201563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                mService.disconnect(device);
202cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return true;
203cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            } catch (RemoteException e) {
204cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo              Log.e(TAG, Log.getStackTraceString(new Throwable()));
205cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo              return false;
206cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
207cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
208cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService == null) {
209cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            Log.w(TAG, "Proxy not attached to service");
210cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
211cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        return false;
212cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
213cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
214cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /**
215cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Get the list of connected devices.
216cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Currently at most one.
217cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     *
218cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * @return list of connected devices
219cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     */
220cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    @Override
221cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public List<BluetoothDevice> getConnectedDevices() {
222cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (DBG) {
223cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            log("getConnectedDevices()");
224cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
225cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService != null && isEnabled()) {
226cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            try {
227cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return mService.getConnectedDevices();
228cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            } catch (RemoteException e) {
229cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                Log.e(TAG, Log.getStackTraceString(new Throwable()));
230cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return new ArrayList<BluetoothDevice>();
231cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
232cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
233cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService == null) {
234cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            Log.w(TAG, "Proxy not attached to service");
235cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
236cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        return new ArrayList<BluetoothDevice>();
237cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
238cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
239cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /**
240cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Get the list of devices matching specified states. Currently at most one.
241cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     *
242cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * @return list of matching devices
243cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     */
244cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    @Override
245cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
246cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (DBG) {
247cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            log("getDevicesMatchingStates()");
248cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
249cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService != null && isEnabled()) {
250cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            try {
251cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return mService.getDevicesMatchingConnectionStates(states);
252cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            } catch (RemoteException e) {
253cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                Log.e(TAG, Log.getStackTraceString(new Throwable()));
254cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return new ArrayList<BluetoothDevice>();
255cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
256cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
257cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService == null) {
258cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            Log.w(TAG, "Proxy not attached to service");
259cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
260cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        return new ArrayList<BluetoothDevice>();
261cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
262cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
263cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    /**
264cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * Get connection state of device
265cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     *
266cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     * @return device connection state
267cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo     */
268cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    @Override
269cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    public int getConnectionState(BluetoothDevice device) {
270cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (DBG) {
271cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            log("getConnectionState(" + device + ")");
272cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
273cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService != null && isEnabled() && isValidDevice(device)) {
274cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            try {
275cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return mService.getConnectionState(device);
276cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            } catch (RemoteException e) {
277cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                Log.e(TAG, Log.getStackTraceString(new Throwable()));
278cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                return BluetoothProfile.STATE_DISCONNECTED;
279cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
280cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
281cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (mService == null) {
282cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            Log.w(TAG, "Proxy not attached to service");
283cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
284cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        return BluetoothProfile.STATE_DISCONNECTED;
285cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
286cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
287cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private final ServiceConnection mConnection = new ServiceConnection() {
288cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        public void onServiceConnected(ComponentName className, IBinder service) {
289cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            if (DBG) {
290cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                log("Proxy object connected");
291cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
2920a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkey            mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
293cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            if (mServiceListener != null) {
294cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, BluetoothPbapClient.this);
295cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
296cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
297cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        public void onServiceDisconnected(ComponentName className) {
298cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            if (DBG) {
299cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                log("Proxy object disconnected");
300cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
301cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            mService = null;
302cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            if (mServiceListener != null) {
303cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo                mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT);
304cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            }
305cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
306cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    };
307cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
308cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private static void log(String msg) {
309cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        Log.d(TAG, msg);
310cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
311cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
312cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private boolean isEnabled() {
313cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
314cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) {
315cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo            return true;
316cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        }
317cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        log("Bluetooth is Not enabled");
318cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo        return false;
319cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
320cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo
321cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    private boolean isValidDevice(BluetoothDevice device) {
322cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo       if (device == null) {
323cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo           return false;
324cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo       }
325cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
326cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo           return true;
327cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo       }
328cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo       return false;
329cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo    }
330563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo
331563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    /**
332563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * Set priority of the profile
333563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     *
334563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * <p> The device should already be paired.
335563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     *  Priority can be one of {@link #PRIORITY_ON} or
336563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * {@link #PRIORITY_OFF},
337563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     *
338563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * @param device Paired bluetooth device
339563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * @param priority
340563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * @return true if priority is set, false on error
341563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     */
342563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    public boolean setPriority(BluetoothDevice device, int priority) {
343563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (DBG) {
344563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            log("setPriority(" + device + ", " + priority + ")");
345563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
346563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (mService != null && isEnabled() &&
347563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            isValidDevice(device)) {
348563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            if (priority != BluetoothProfile.PRIORITY_OFF &&
349563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                priority != BluetoothProfile.PRIORITY_ON) {
350563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo              return false;
351563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            }
352563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            try {
353563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                return mService.setPriority(device, priority);
354563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            } catch (RemoteException e) {
355563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                Log.e(TAG, Log.getStackTraceString(new Throwable()));
356563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                return false;
357563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            }
358563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
359563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (mService == null) {
360563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            Log.w(TAG, "Proxy not attached to service");
361563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
362563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        return false;
363563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    }
364563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo
365563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    /**
366563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * Get the priority of the profile.
367563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     *
368563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * <p> The priority can be any of:
369563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
370563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
371563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     *
372563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * @param device Bluetooth device
373563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     * @return priority of the device
374563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo     */
375563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    public int getPriority(BluetoothDevice device) {
376563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (VDBG) {
377563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            log("getPriority(" + device + ")");
378563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
379563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (mService != null && isEnabled() && isValidDevice(device)) {
380563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            try {
381563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                return mService.getPriority(device);
382563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            } catch (RemoteException e) {
383563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                Log.e(TAG, Log.getStackTraceString(new Throwable()));
384563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo                return PRIORITY_OFF;
385563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            }
386563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
387563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        if (mService == null) {
388563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo            Log.w(TAG, "Proxy not attached to service");
389563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        }
390563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo        return PRIORITY_OFF;
391563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo    }
392cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo}
393