BluetoothPbap.java revision 3f41673265dcaaef058703311c5481e8a51fd8be
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.annotation.SdkConstant;
203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.annotation.SdkConstant.SdkConstantType;
213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.ComponentName;
223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.Context;
233f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.Intent;
243f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.ServiceConnection;
253f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.RemoteException;
263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.IBinder;
273f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.ServiceManager;
283f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.util.Log;
293f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu/**
313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * The Android Bluetooth API is not finalized, and *will* change. Use at your
323f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * own risk.
333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Public API for controlling the Bluetooth Pbap Service. This includes
353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Bluetooth Phone book Access profile.
363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap
373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Service via IPC.
383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Creating a BluetoothPbap object will create a binding with the
403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Users of this object should call close() when they
413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * are finished with the BluetoothPbap, so that this proxy object can unbind
423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * from the service.
433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * This BluetoothPbap object is not immediately bound to the
453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Use the ServiceListener interface to obtain a
463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * notification when it is bound, this is especially important if you wish to
473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * immediately call methods on BluetoothPbap after construction.
483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Android only supports one connected Bluetooth Pce at a time.
503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu *
513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * @hide
523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */
533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liupublic class BluetoothPbap {
543f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static final String TAG = "BluetoothPbap";
563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static final boolean DBG = false;
573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** int extra for PBAP_STATE_CHANGED_ACTION */
593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_STATE =
603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.PBAP_STATE";
613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** int extra for PBAP_STATE_CHANGED_ACTION */
623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_PREVIOUS_STATE =
633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE";
643f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** Indicates the state of an pbap connection state has changed.
663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *  This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and
673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *  BluetoothIntent.ADDRESS extras.
683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final String PBAP_STATE_CHANGED_ACTION =
703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private IBluetoothPbap mService;
733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private final Context mContext;
743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private final ServiceListener mServiceListener;
753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** There was an error trying to obtain the state */
773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int STATE_ERROR        = -1;
783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** No headset 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;
823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /** A headset 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    public static final int PRIORITY_AUTO = 100;
913f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static final int PRIORITY_OFF = 0;
923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * An interface for notifying Bluetooth PCE IPC clients when they have
943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * been connected to the BluetoothHeadset service.
953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public interface ServiceListener {
973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        /**
983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * Called to notify the client when this proxy object has been
993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * connected to the BluetoothPbap service. Clients must wait for
1003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * this callback before making IPC calls on the BluetoothPbap
1013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * service.
1023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         */
1033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceConnected();
1043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        /**
1063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * Called to notify the client that this proxy object has been
1073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * disconnected from the BluetoothPbap service. Clients must not
1083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * make IPC calls on the BluetoothPbap service after this callback.
1093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * This callback will currently only occur if the application hosting
1103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         * the BluetoothPbap service, but may be called more often in future.
1113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu         */
1123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceDisconnected();
1133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Create a BluetoothHeadset proxy object.
1173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public BluetoothPbap(Context context, ServiceListener l) {
1193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mContext = context;
1203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        mServiceListener = l;
1213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (!context.bindService(new Intent(IBluetoothPbap.class.getName()), mConnection, 0)) {
1223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.e(TAG, "Could not bind to Bluetooth Pbap Service");
1233f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1243f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1253f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    protected void finalize() throws Throwable {
1273f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        try {
1283f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            close();
1293f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } finally {
1303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            super.finalize();
1313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1323f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Close the connection to the backing service.
1363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Other public functions of BluetoothHeadset will return default error
1373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * results once close() has been called. Multiple invocations of close()
1383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * are ok.
1393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public synchronized void close() {
1413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mConnection != null) {
1423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mContext.unbindService(mConnection);
1433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mConnection = null;
1443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Get the current state of the Bluetooth Headset service.
1493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return One of the STATE_ return codes, or STATE_ERROR if this proxy
1503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *         object is currently not connected to the Headset service.
1513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public int getState() {
1533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (DBG) log("getState()");
1543f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
1553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
1563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return mService.getState();
1573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
1583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
1593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
1603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
1613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return BluetoothHeadset.STATE_ERROR;
1633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1643f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Get the Bluetooth address of the current headset.
1673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return The Bluetooth address, or null if not in connected or connecting
1683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *         state, or if this proxy object is not connected to the Headset
1693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     *         service.
1703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public String getPceAddress() {
1723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (DBG) log("getPceAddress()");
1733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
1743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
1753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return mService.getPceAddress();
1763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
1773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
1783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
1793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
1803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1813f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return null;
1823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
1833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
1843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
1853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Returns true if the specified headset is connected (does not include
1863f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * connecting). Returns false if not connected, or if this proxy object
1873f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * if not currently connected to the headset service.
1883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
1893f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public boolean isConnected(String address) {
1903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (DBG) log("isConnected(" + address + ")");
1913f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
1923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
1933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return mService.isConnected(address);
1943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            } catch (RemoteException e) {Log.e(TAG, e.toString());}
1953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        } else {
1963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            Log.w(TAG, "Proxy not attached to service");
1973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log(Log.getStackTraceString(new Throwable()));
1983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
1993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
2033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Disconnects the current headset. Currently this call blocks, it may soon
2043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * be made asynchornous. Returns false if this proxy object is
2053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * not currently connected to the Headset service.
2063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
2073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public boolean disconnectPce() {
2083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (DBG) log("disconnectPce()");
2093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        if (mService != null) {
2103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            try {
2113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                mService.disconnectPce();
2123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                return true;
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        }
2183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        return false;
2193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    /**
2223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * Check class bits for possible PBAP support.
2233f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * This is a simple heuristic that tries to guess if a device with the
2243f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * given class bits might support PBAP. It is not accurate for all
2253f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * devices. It tries to err on the side of false positives.
2263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     * @return True if this device might support PBAP.
2273f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu     */
2283f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    public static boolean doesClassMatchSink(int btClass) {
2293f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        // TODO optimize the rule
2303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        switch (BluetoothClass.Device.getDevice(btClass)) {
2313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_DESKTOP:
2323f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_LAPTOP:
2333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_SERVER:
2343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
2353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return true;
2363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        default:
2373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            return false;
2383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private ServiceConnection mConnection = new ServiceConnection() {
2423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceConnected(ComponentName className, IBinder service) {
2433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object connected");
2443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = IBluetoothPbap.Stub.asInterface(service);
2453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
2463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                mServiceListener.onServiceConnected();
2473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
2483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        public void onServiceDisconnected(ComponentName className) {
2503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (DBG) log("Proxy object disconnected");
2513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            mService = null;
2523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            if (mServiceListener != null) {
2533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu                mServiceListener.onServiceDisconnected();
2543f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu            }
2553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        }
2563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    };
2573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu
2583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    private static void log(String msg) {
2593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu        Log.d(TAG, msg);
2603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    }
2613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu}
262