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";
54563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean DBG = true;
55563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean VDBG = false;
563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** int extra for PBAP_STATE_CHANGED_ACTION */
583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_STATE =
593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.PBAP_STATE";
603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** int extra for PBAP_STATE_CHANGED_ACTION */
613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_PREVIOUS_STATE =
623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE";
633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
64f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa    /** Indicates the state of a pbap connection state has changed.
653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *  This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and
663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *  BluetoothIntent.ADDRESS extras.
673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_STATE_CHANGED_ACTION =
693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private IBluetoothPbap mService;
723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private final Context mContext;
739bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    private ServiceListener mServiceListener;
746f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta    private BluetoothAdapter mAdapter;
753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** There was an error trying to obtain the state */
773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_ERROR        = -1;
78bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /** No client currently connected */
793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_DISCONNECTED = 0;
803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** Connection attempt in progress */
813f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_CONNECTING   = 1;
82bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    /** Client is currently connected */
833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_CONNECTED    = 2;
843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int RESULT_FAILURE = 0;
863f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int RESULT_SUCCESS = 1;
873f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** Connection canceled before completion. */
883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int RESULT_CANCELED = 2;
893f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
913f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * An interface for notifying Bluetooth PCE IPC clients when they have
92c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * been connected to the BluetoothPbap service.
933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public interface ServiceListener {
953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        /**
963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * Called to notify the client when this proxy object has been
973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * connected to the BluetoothPbap service. Clients must wait for
983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * this callback before making IPC calls on the BluetoothPbap
993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * service.
1003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         */
1016f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        public void onServiceConnected(BluetoothPbap proxy);
1023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        /**
1043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * Called to notify the client that this proxy object has been
1053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * disconnected from the BluetoothPbap service. Clients must not
1063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * make IPC calls on the BluetoothPbap service after this callback.
1073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * This callback will currently only occur if the application hosting
1083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * the BluetoothPbap service, but may be called more often in future.
1093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         */
1103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceDisconnected();
1113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1136f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
1146f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            new IBluetoothStateChangeCallback.Stub() {
1156f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                public void onBluetoothStateChange(boolean up) {
1166f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
1176f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    if (!up) {
118563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                        if (VDBG) Log.d(TAG,"Unbinding service...");
1196f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        synchronized (mConnection) {
1206f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            try {
1216f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                mService = null;
1226f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                mContext.unbindService(mConnection);
1236f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            } catch (Exception re) {
1246f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                Log.e(TAG,"",re);
1256f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            }
1266f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        }
1276f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    } else {
1286f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        synchronized (mConnection) {
1296f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            try {
1306f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                if (mService == null) {
131563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                                    if (VDBG) Log.d(TAG,"Binding service...");
1326f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                    if (!mContext.bindService(
1336f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                                        new Intent(IBluetoothPbap.class.getName()),
1346f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                                        mConnection, 0)) {
1356f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                        Log.e(TAG, "Could not bind to Bluetooth PBAP Service");
1366f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                    }
1376f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                }
1386f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            } catch (Exception re) {
1396f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                Log.e(TAG,"",re);
1406f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            }
1416f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        }
1426f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    }
1436f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                }
1446f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        };
1456f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta
1463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
147c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Create a BluetoothPbap proxy object.
1483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public BluetoothPbap(Context context, ServiceListener l) {
1503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mContext = context;
1513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mServiceListener = l;
1526f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        mAdapter = BluetoothAdapter.getDefaultAdapter();
1536f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1546f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        if (mgr != null) {
1556f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            try {
1566f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
1576f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            } catch (RemoteException e) {
1586f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                Log.e(TAG,"",e);
1596f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
1606f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        }
1613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (!context.bindService(new Intent(IBluetoothPbap.class.getName()), mConnection, 0)) {
1623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.e(TAG, "Could not bind to Bluetooth Pbap Service");
1633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1643f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    protected void finalize() throws Throwable {
1673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        try {
1683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            close();
1693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } finally {
1703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            super.finalize();
1713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Close the connection to the backing service.
176c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Other public functions of BluetoothPbap will return default error
1773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * results once close() has been called. Multiple invocations of close()
1783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * are ok.
1793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public synchronized void close() {
1816f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1826f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        if (mgr != null) {
1836f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            try {
1846f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
1856f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            } catch (Exception e) {
1866f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                Log.e(TAG,"",e);
1876f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
1886f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        }
1896f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta
1906f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        synchronized (mConnection) {
1916f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            if (mService != null) {
1926f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                try {
1936f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mService = null;
1946f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mContext.unbindService(mConnection);
1956f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mConnection = null;
1966f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                } catch (Exception re) {
1976f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    Log.e(TAG,"",re);
1986f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                }
1996f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
2003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2019bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
2023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
205c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Get the current state of the BluetoothPbap service.
2063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return One of the STATE_ return codes, or STATE_ERROR if this proxy
207c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     *         object is currently not connected to the Pbap service.
2083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
2093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public int getState() {
210563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getState()");
2113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
2133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return mService.getState();
2143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
219c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan        return BluetoothPbap.STATE_ERROR;
2203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
223bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Get the currently connected remote Bluetooth device (PCE).
224bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @return The remote Bluetooth device, or null if not in connected or
225bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     *         connecting state, or if this proxy object is not connected to
226bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     *         the Pbap service.
2273f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
228bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothDevice getClient() {
229563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getClient()");
2303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
232bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                return mService.getClient();
2333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return null;
2393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
242bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Returns true if the specified Bluetooth device is connected (does not
243bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * include connecting). Returns false if not connected, or if this proxy
244bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * object is not currently connected to the Pbap service.
2453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
246bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public boolean isConnected(BluetoothDevice device) {
247563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("isConnected(" + device + ")");
2483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
250bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                return mService.isConnected(device);
2513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2543f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
260bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Disconnects the current Pbap client (PCE). Currently this call blocks,
261f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby     * it may soon be made asynchronous. Returns false if this proxy object is
262c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * not currently connected to the Pbap service.
2633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
264bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public boolean disconnect() {
265bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (DBG) log("disconnect()");
2663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
268bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                mService.disconnect();
2693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return true;
2703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
2793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Check class bits for possible PBAP support.
2803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * This is a simple heuristic that tries to guess if a device with the
2813f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * given class bits might support PBAP. It is not accurate for all
2823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * devices. It tries to err on the side of false positives.
2833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return True if this device might support PBAP.
2843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
285005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    public static boolean doesClassMatchSink(BluetoothClass btClass) {
2863f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        // TODO optimize the rule
287005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        switch (btClass.getDeviceClass()) {
2883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_DESKTOP:
2893f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_LAPTOP:
2903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_SERVER:
2913f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
2923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return true;
2933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        default:
2943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return false;
2953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private ServiceConnection mConnection = new ServiceConnection() {
2993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceConnected(ComponentName className, IBinder service) {
3003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object connected");
3013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = IBluetoothPbap.Stub.asInterface(service);
3023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
3036f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mServiceListener.onServiceConnected(BluetoothPbap.this);
3043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
3053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
3063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceDisconnected(ComponentName className) {
3073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object disconnected");
3083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = null;
3093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
3103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                mServiceListener.onServiceDisconnected();
3113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
3123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
3133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    };
3143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
3153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static void log(String msg) {
3163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        Log.d(TAG, msg);
3173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
3183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu}
319