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.util.Log;
263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
273f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu/**
283f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * The Android Bluetooth API is not finalized, and *will* change. Use at your
293f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * own risk.
303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Public API for controlling the Bluetooth Pbap Service. This includes
323f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Bluetooth Phone book Access profile.
333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap
343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Service via IPC.
353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Creating a BluetoothPbap object will create a binding with the
373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Users of this object should call close() when they
383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * are finished with the BluetoothPbap, so that this proxy object can unbind
393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * from the service.
403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * This BluetoothPbap object is not immediately bound to the
423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Use the ServiceListener interface to obtain a
433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * notification when it is bound, this is especially important if you wish to
443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * immediately call methods on BluetoothPbap after construction.
453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Android only supports one connected Bluetooth Pce at a time.
473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * @hide
493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */
503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liupublic class BluetoothPbap {
513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static final String TAG = "BluetoothPbap";
53563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean DBG = true;
54563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean VDBG = 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) {
117563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                        if (VDBG) 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) {
130563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                                    if (VDBG) Log.d(TAG,"Binding service...");
131221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn                                    doBind();
1326f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                }
1336f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            } catch (Exception re) {
1346f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                                Log.e(TAG,"",re);
1356f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                            }
1366f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                        }
1376f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    }
1386f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                }
1396f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        };
1406f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta
1413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
142c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Create a BluetoothPbap proxy object.
1433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public BluetoothPbap(Context context, ServiceListener l) {
1453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mContext = context;
1463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mServiceListener = l;
1476f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        mAdapter = BluetoothAdapter.getDefaultAdapter();
1486f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1496f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        if (mgr != null) {
1506f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            try {
1516f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
1526f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            } catch (RemoteException e) {
1536f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                Log.e(TAG,"",e);
1546f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
1556f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        }
156221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        doBind();
157221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    }
158221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn
159221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    boolean doBind() {
160221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        Intent intent = new Intent(IBluetoothPbap.class.getName());
161221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
162221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        intent.setComponent(comp);
163466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
164466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn                android.os.Process.myUserHandle())) {
165221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn            Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
166221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn            return false;
1673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
168221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        return true;
1693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    protected void finalize() throws Throwable {
1723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        try {
1733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            close();
1743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } finally {
1753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            super.finalize();
1763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Close the connection to the backing service.
181c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Other public functions of BluetoothPbap will return default error
1823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * results once close() has been called. Multiple invocations of close()
1833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * are ok.
1843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public synchronized void close() {
1866f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1876f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        if (mgr != null) {
1886f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            try {
1896f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
1906f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            } catch (Exception e) {
1916f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                Log.e(TAG,"",e);
1926f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
1936f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        }
1946f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta
1956f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta        synchronized (mConnection) {
1966f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            if (mService != null) {
1976f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                try {
1986f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mService = null;
1996f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    mContext.unbindService(mConnection);
2006f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                } catch (Exception re) {
2016f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                    Log.e(TAG,"",re);
2026f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                }
2036f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta            }
2043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2059bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
2063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
209c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * Get the current state of the BluetoothPbap service.
2103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return One of the STATE_ return codes, or STATE_ERROR if this proxy
211c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     *         object is currently not connected to the Pbap service.
2123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
2133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public int getState() {
214563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getState()");
2153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
2173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return mService.getState();
2183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
223c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan        return BluetoothPbap.STATE_ERROR;
2243f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2253f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
227bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Get the currently connected remote Bluetooth device (PCE).
228bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * @return The remote Bluetooth device, or null if not in connected or
229bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     *         connecting state, or if this proxy object is not connected to
230bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     *         the Pbap service.
2313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
232bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothDevice getClient() {
233563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getClient()");
2343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
236bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                return mService.getClient();
2373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return null;
2433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
246bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Returns true if the specified Bluetooth device is connected (does not
247bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * include connecting). Returns false if not connected, or if this proxy
248bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * object is not currently connected to the Pbap service.
2493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
250bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public boolean isConnected(BluetoothDevice device) {
251563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("isConnected(" + device + ")");
2523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
254bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                return mService.isConnected(device);
2553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
264bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly     * Disconnects the current Pbap client (PCE). Currently this call blocks,
265f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby     * it may soon be made asynchronous. Returns false if this proxy object is
266c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan     * not currently connected to the Pbap service.
2673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
268bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public boolean disconnect() {
269bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (DBG) log("disconnect()");
2703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
272bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly                mService.disconnect();
2733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return true;
2743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
2753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
2763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
2773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
2783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2813f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
2833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Check class bits for possible PBAP support.
2843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * This is a simple heuristic that tries to guess if a device with the
2853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * given class bits might support PBAP. It is not accurate for all
2863f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * devices. It tries to err on the side of false positives.
2873f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return True if this device might support PBAP.
2883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
289005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    public static boolean doesClassMatchSink(BluetoothClass btClass) {
2903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        // TODO optimize the rule
291005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        switch (btClass.getDeviceClass()) {
2923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_DESKTOP:
2933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_LAPTOP:
2943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_SERVER:
2953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
2963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return true;
2973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        default:
2983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return false;
2993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
3003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
3013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
3029b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie    private final ServiceConnection mConnection = new ServiceConnection() {
3033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceConnected(ComponentName className, IBinder service) {
3043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object connected");
3053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = IBluetoothPbap.Stub.asInterface(service);
3063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
3076f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                mServiceListener.onServiceConnected(BluetoothPbap.this);
3083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
3093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
3103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceDisconnected(ComponentName className) {
3113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object disconnected");
3123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = null;
3133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
3143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                mServiceListener.onServiceDisconnected();
3153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
3163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
3173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    };
3183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
3193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static void log(String msg) {
3203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        Log.d(TAG, msg);
3213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
3223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu}
323