19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.bluetooth;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager.WakeLock;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The Android Bluetooth API is not finalized, and *will* change. Use at your
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * own risk.
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The base RFCOMM (service) connection for a headset or handsfree device.
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In the future this class will be removed.
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
34bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic final class HeadsetBase {
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "Bluetooth HeadsetBase";
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean DBG = false;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RFCOMM_DISCONNECTED = 1;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DIRECTION_INCOMING = 1;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DIRECTION_OUTGOING = 2;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
436c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly    private static int sAtInputCount = 0;  /* TODO: Consider not using a static variable */
446c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly
45bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private final BluetoothAdapter mAdapter;
46bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private final BluetoothDevice mRemoteDevice;
47bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private final String mAddress;  // for native code
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int mRfcommChannel;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNativeData;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Thread mEventThread;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private volatile boolean mEventThreadInterrupted;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Handler mEventThreadHandler;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTimeoutRemainingMs;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int mDirection;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final long mConnectTimestamp;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected AtParser mAtParser;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WakeLock mWakeLock;  // held while processing an AT command
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native static void classInitNative();
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        classInitNative();
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() throws Throwable {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cleanupNativeDataNative();
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            releaseWakeLock();
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.finalize();
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void cleanupNativeDataNative();
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
77a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
78a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek                       BluetoothDevice device, int rfcommChannel) {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDirection = DIRECTION_OUTGOING;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConnectTimestamp = System.currentTimeMillis();
81bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapter = adapter;
82bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mRemoteDevice = device;
83bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAddress = device.getAddress();
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRfcommChannel = rfcommChannel;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock.setReferenceCounted(false);
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initializeAtParser();
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Must be called after this.mAddress is set.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initializeNativeDataNative(-1);
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
92a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    /* Create from an existing rfcomm connection */
93a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
94a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek                       BluetoothDevice device,
95a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek                       int socketFd, int rfcommChannel, Handler handler) {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDirection = DIRECTION_INCOMING;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mConnectTimestamp = System.currentTimeMillis();
98bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapter = adapter;
99bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mRemoteDevice = device;
100bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAddress = device.getAddress();
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRfcommChannel = rfcommChannel;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventThreadHandler = handler;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock.setReferenceCounted(false);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initializeAtParser();
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Must be called after this.mAddress is set.
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initializeNativeDataNative(socketFd);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void initializeNativeDataNative(int socketFd);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* Process an incoming AT command line
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1145903c977941c731cb4cc0df67cfeb2a3821c47edJaikumar Ganesh    protected void handleInput(String input) {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        acquireWakeLock();
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long timestamp;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1186c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly        synchronized(HeadsetBase.class) {
1196c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly            if (sAtInputCount == Integer.MAX_VALUE) {
1206c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly                sAtInputCount = 0;
1216c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly            } else {
1226c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly                sAtInputCount++;
1236c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly            }
1246c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly        }
1256c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG) timestamp = System.currentTimeMillis();
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AtCommandResult result = mAtParser.process(input);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG) Log.d(TAG, "Processing " + input + " took " +
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       (System.currentTimeMillis() - timestamp) + " ms");
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result.getResultCode() == AtCommandResult.ERROR) {
132a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek            Log.i(TAG, "Error processing <" + input + ">");
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sendURC(result.toString());
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        releaseWakeLock();
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register AT commands that are common to all Headset / Handsets. This
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * function is called by the HeadsetBase constructor.
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void initializeAtParser() {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAtParser = new AtParser();
146a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek
147a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek        //TODO(): Get rid of this as there are no parsers registered. But because of dependencies
148a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek        // it needs to be done as part of refactoring HeadsetBase and BluetoothHandsfree
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AtParser getAtParser() {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAtParser;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startEventThread() {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventThread =
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            new Thread("HeadsetBase Event Thread") {
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                public void run() {
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int last_read_error;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while (!mEventThreadInterrupted) {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String input = readNative(500);
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (input != null) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            handleInput(input);
164a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek                        } else {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            last_read_error = getLastReadStatusNative();
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (last_read_error != 0) {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.i(TAG, "headset read error " + last_read_error);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (mEventThreadHandler != null) {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    mEventThreadHandler.obtainMessage(RFCOMM_DISCONNECTED)
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            .sendToTarget();
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                disconnectNative();
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            };
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventThreadInterrupted = false;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventThread.start();
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native String readNative(int timeout_ms);
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int getLastReadStatusNative();
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void stopEventThread() {
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventThreadInterrupted = true;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventThread.interrupt();
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread.join();
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (java.lang.InterruptedException e) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // FIXME: handle this,
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventThread = null;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean connect(Handler handler) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEventThread == null) {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!connectNative()) return false;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThreadHandler = handler;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean connectNative();
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true when either the asynchronous connect is in progress, or
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the connect is complete.  Call waitForAsyncConnect() to find out whether
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the connect is actually complete, or disconnect() to cancel.
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean connectAsync() {
21354172d92afec5d7d18c830d7428a3230a39d4c02Jaikumar Ganesh        int ret = connectAsyncNative();
21454172d92afec5d7d18c830d7428a3230a39d4c02Jaikumar Ganesh        return (ret == 0) ? true : false;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21654172d92afec5d7d18c830d7428a3230a39d4c02Jaikumar Ganesh    private native int connectAsyncNative();
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getRemainingAsyncConnectWaitingTimeMs() {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTimeoutRemainingMs;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns 1 when an async connect is complete, 0 on timeout, and -1 on
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * error.  On error, handler will be called, and you need to re-initiate
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the async connect.
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int waitForAsyncConnect(int timeout_ms, Handler handler) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int res = waitForAsyncConnectNative(timeout_ms);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res > 0) {
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThreadHandler = handler;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return res;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int waitForAsyncConnectNative(int timeout_ms);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void disconnect() {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEventThread != null) {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopEventThread();
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        disconnectNative();
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void disconnectNative();
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Note that if a remote side disconnects, this method will still return
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * true until disconnect() is called.  You know when a remote side
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * disconnects because you will receive the intent
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * IBluetoothService.REMOTE_DEVICE_DISCONNECTED_ACTION.  If, when you get
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this intent, method isConnected() returns true, you know that the
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * disconnect was initiated by the remote device.
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isConnected() {
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEventThread != null;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
258bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothDevice getRemoteDevice() {
259bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        return mRemoteDevice;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDirection() {
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDirection;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getConnectTimestamp() {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mConnectTimestamp;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean sendURC(String urc) {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (urc.length() > 0) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean ret = sendURCNative(urc);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ret;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean sendURCNative(String urc);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2795903c977941c731cb4cc0df67cfeb2a3821c47edJaikumar Ganesh    private synchronized void acquireWakeLock() {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mWakeLock.isHeld()) {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWakeLock.acquire();
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2855903c977941c731cb4cc0df67cfeb2a3821c47edJaikumar Ganesh    private synchronized void releaseWakeLock() {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWakeLock.isHeld()) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWakeLock.release();
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2916c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly    public static int getAtInputCount() {
2926c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly        return sAtInputCount;
2936c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly    }
2946c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly
2956c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly    private static void log(String msg) {
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.d(TAG, msg);
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
299