BluetoothPbap.java revision 6f6c54519a9b15379bb79e195655b6bd4fc5967a
13f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu/*
23f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Copyright (C) 2008 The Android Open Source Project
33f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
43f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Licensed under the Apache License, Version 2.0 (the "License");
53f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * you may not use this file except in compliance with the License.
63f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * You may obtain a copy of the License at
73f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
83f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *      http://www.apache.org/licenses/LICENSE-2.0
93f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Unless required by applicable law or agreed to in writing, software
113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * distributed under the License is distributed on an "AS IS" BASIS,
123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * See the License for the specific language governing permissions and
143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * limitations under the License.
153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */
163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liupackage android.bluetooth;
183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.ComponentName;
203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.Context;
213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.Intent;
223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.ServiceConnection;
233f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.RemoteException;
243f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.IBinder;
253f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.ServiceManager;
263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.util.Log;
273f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
283f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu/**
293f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * The Android Bluetooth API is not finalized, and *will* change. Use at your
303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * own risk.
313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
323f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Public API for controlling the Bluetooth Pbap Service. This includes
333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Bluetooth Phone book Access profile.
343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap
353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Service via IPC.
363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Creating a BluetoothPbap object will create a binding with the
383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Users of this object should call close() when they
393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * are finished with the BluetoothPbap, so that this proxy object can unbind
403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * from the service.
413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * This BluetoothPbap object is not immediately bound to the
433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Use the ServiceListener interface to obtain a
443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * notification when it is bound, this is especially important if you wish to
453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * immediately call methods on BluetoothPbap after construction.
463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Android only supports one connected Bluetooth Pce at a time.
483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * @hide
503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */
513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liupublic class BluetoothPbap {
523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static final String TAG = "BluetoothPbap";
543f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static final boolean DBG = false;
553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** int extra for PBAP_STATE_CHANGED_ACTION */
573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_STATE =
583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.PBAP_STATE";
593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** int extra for PBAP_STATE_CHANGED_ACTION */
603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_PREVIOUS_STATE =
613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE";
623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
63f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa    /** Indicates the state of a pbap connection state has changed.
643f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *  This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and
653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *  BluetoothIntent.ADDRESS extras.
663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_STATE_CHANGED_ACTION =
683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private IBluetoothPbap mService;
713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private final Context mContext;
729bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    private ServiceListener mServiceListener;
736f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta    private BluetoothAdapter mAdapter;
743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** There was an error trying to obtain the state */
763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_ERROR        = -1;
77bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /** No client currently connected */
783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_DISCONNECTED = 0;
793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** Connection attempt in progress */
803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_CONNECTING   = 1;
81bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /** Client is currently connected */
823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_CONNECTED    = 2;
833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int RESULT_FAILURE = 0;
853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int RESULT_SUCCESS = 1;
863f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** Connection canceled before completion. */
873f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int RESULT_CANCELED = 2;
883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
893f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * An interface for notifying Bluetooth PCE IPC clients when they have
91c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * been connected to the BluetoothPbap service.
923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public interface ServiceListener {
943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        /**
953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * Called to notify the client when this proxy object has been
963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * connected to the BluetoothPbap service. Clients must wait for
973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * this callback before making IPC calls on the BluetoothPbap
983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * service.
993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         */
1006f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        public void onServiceConnected(BluetoothPbap proxy);
1013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        /**
1033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * Called to notify the client that this proxy object has been
1043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * disconnected from the BluetoothPbap service. Clients must not
1053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * make IPC calls on the BluetoothPbap service after this callback.
1063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * This callback will currently only occur if the application hosting
1073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * the BluetoothPbap service, but may be called more often in future.
1083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         */
1093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceDisconnected();
1103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1126f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
1136f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            new IBluetoothStateChangeCallback.Stub() {
1146f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                public void onBluetoothStateChange(boolean up) {
1156f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
1166f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    if (!up) {
1176f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        if (DBG) Log.d(TAG,"Unbinding service...");
1186f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        synchronized (mConnection) {
1196f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            try {
1206f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                mService = null;
1216f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                mContext.unbindService(mConnection);
1226f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            } catch (Exception re) {
1236f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                Log.e(TAG,"",re);
1246f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            }
1256f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        }
1266f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    } else {
1276f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        synchronized (mConnection) {
1286f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            try {
1296f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                if (mService == null) {
1306f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                    if (DBG) Log.d(TAG,"Binding service...");
1316f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                    if (!mContext.bindService(
1326f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                                        new Intent(IBluetoothPbap.class.getName()),
1336f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                                        mConnection, 0)) {
1346f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                        Log.e(TAG, "Could not bind to Bluetooth PBAP Service");
1356f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                    }
1366f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                }
1376f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            } catch (Exception re) {
1386f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                Log.e(TAG,"",re);
1396f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            }
1406f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        }
1416f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    }
1426f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                }
1436f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        };
1446f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta
1453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
146c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Create a BluetoothPbap proxy object.
1473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public BluetoothPbap(Context context, ServiceListener l) {
1493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mContext = context;
1503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mServiceListener = l;
1516f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        mAdapter = BluetoothAdapter.getDefaultAdapter();
1526f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1536f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        if (mgr != null) {
1546f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            try {
1556f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
1566f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            } catch (RemoteException e) {
1576f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                Log.e(TAG,"",e);
1586f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
1596f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        }
1603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (!context.bindService(new Intent(IBluetoothPbap.class.getName()), mConnection, 0)) {
1613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.e(TAG, "Could not bind to Bluetooth Pbap Service");
1623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1643f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    protected void finalize() throws Throwable {
1663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        try {
1673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            close();
1683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } finally {
1693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            super.finalize();
1703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Close the connection to the backing service.
175c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Other public functions of BluetoothPbap will return default error
1763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * results once close() has been called. Multiple invocations of close()
1773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * are ok.
1783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public synchronized void close() {
1806f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1816f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        if (mgr != null) {
1826f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            try {
1836f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
1846f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            } catch (Exception e) {
1856f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                Log.e(TAG,"",e);
1866f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
1876f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        }
1886f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta
1896f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        synchronized (mConnection) {
1906f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            if (mService != null) {
1916f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                try {
1926f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mService = null;
1936f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mContext.unbindService(mConnection);
1946f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mConnection = null;
1956f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                } catch (Exception re) {
1966f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    Log.e(TAG,"",re);
1976f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                }
1986f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
1993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2009bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
2013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
204c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Get the current state of the BluetoothPbap service.
2053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return One of the STATE_ return codes, or STATE_ERROR if this proxy
206c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     *         object is currently not connected to the Pbap service.
2073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
2083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public int getState() {
2093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (DBG) log("getState()");
2103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
2123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return mService.getState();
2133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
218c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan        return BluetoothPbap.STATE_ERROR;
2193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
222bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Get the currently connected remote Bluetooth device (PCE).
223bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @return The remote Bluetooth device, or null if not in connected or
224bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     *         connecting state, or if this proxy object is not connected to
225bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     *         the Pbap service.
2263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
227bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothDevice getClient() {
228bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (DBG) log("getClient()");
2293f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
231bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                return mService.getClient();
2323f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return null;
2383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
241bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Returns true if the specified Bluetooth device is connected (does not
242bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * include connecting). Returns false if not connected, or if this proxy
243bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * object is not currently connected to the Pbap service.
2443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
245bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public boolean isConnected(BluetoothDevice device) {
246bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (DBG) log("isConnected(" + device + ")");
2473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
249bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                return mService.isConnected(device);
2503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2543f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
259bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Disconnects the current Pbap client (PCE). Currently this call blocks,
260f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby     * it may soon be made asynchronous. Returns false if this proxy object is
261c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * not currently connected to the Pbap service.
2623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
263bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public boolean disconnect() {
264bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (DBG) log("disconnect()");
2653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
267bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                mService.disconnect();
2683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return true;
2693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
2783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Check class bits for possible PBAP support.
2793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * This is a simple heuristic that tries to guess if a device with the
2803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * given class bits might support PBAP. It is not accurate for all
2813f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * devices. It tries to err on the side of false positives.
2823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return True if this device might support PBAP.
2833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
284005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    public static boolean doesClassMatchSink(BluetoothClass btClass) {
2853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        // TODO optimize the rule
286005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        switch (btClass.getDeviceClass()) {
2873f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_DESKTOP:
2883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_LAPTOP:
2893f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_SERVER:
2903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
2913f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return true;
2923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        default:
2933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return false;
2943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private ServiceConnection mConnection = new ServiceConnection() {
2983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceConnected(ComponentName className, IBinder service) {
2993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object connected");
3003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = IBluetoothPbap.Stub.asInterface(service);
3013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
3026f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mServiceListener.onServiceConnected(BluetoothPbap.this);
3033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
3043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
3053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceDisconnected(ComponentName className) {
3063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object disconnected");
3073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = null;
3083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
3093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                mServiceListener.onServiceDisconnected();
3103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
3113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
3123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    };
3133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
3143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static void log(String msg) {
3153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        Log.d(TAG, msg);
3163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
3173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu}
318