19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 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.Message; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager.WakeLock; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The Android Bluetooth API is not finalized, and *will* change. Use at your 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * own risk. 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Simple SCO Socket. 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Currently in Android, there is no support for sending data over a SCO 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * socket - this is managed by the hardware link to the Bluetooth Chip. This 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * class is instead intended for management of the SCO socket lifetime, 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and is tailored for use with the headset / handsfree profiles. 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ScoSocket { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "ScoSocket"; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean VDBG = false; // even more logging 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_READY = 1; // Ready for use. No threads or sockets 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_ACCEPT = 2; // accept() thread running 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_CONNECTING = 3; // connect() thread running 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_CONNECTED = 4; // connected, waiting for close() 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_CLOSED = 5; // was connected, now closed. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mState; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Handler mHandler; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mAcceptedCode; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mConnectedCode; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mClosedCode; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private WakeLock mWakeLock; // held while in STATE_CONNECTING 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native static void classInitNative(); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ScoSocket(PowerManager pm, Handler handler, int acceptedCode, int connectedCode, 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int closedCode) { 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initNative(); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_READY; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler = handler; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAcceptedCode = acceptedCode; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnectedCode = connectedCode; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClosedCode = closedCode; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ScoSocket"); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(false); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (VDBG) log(this + " SCO OBJECT CTOR"); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void initNative(); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (VDBG) log(this + " SCO OBJECT DTOR"); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project destroyNative(); 79105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project releaseWakeLockNow(); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void destroyNative(); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Connect this SCO socket to the given BT address. 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Does not block. 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean connect(String address) { 9037e0828cf9a6e08d791b23057d98bf00fbf74505Nick Pelly if (DBG) log("connect() " + this); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_READY) { 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("connect(): Bad state"); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project acquireWakeLock(); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (connectNative(address)) { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CONNECTING; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CLOSED; 101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project releaseWakeLockNow(); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native boolean connectNative(String address); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Accept incoming SCO connections. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Does not block. 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean accept() { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (VDBG) log("accept() " + this); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_READY) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("Bad state"); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (acceptNative()) { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_ACCEPT; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CLOSED; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native boolean acceptNative(); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void close() { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log(this + " SCO OBJECT close() mState = " + mState); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project acquireWakeLock(); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CLOSED; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closeNative(); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project releaseWakeLock(); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void closeNative(); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getState() { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private synchronized void onConnected(int result) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (VDBG) log(this + " onConnected() mState = " + mState + " " + this); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_CONNECTING) { 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("Strange state, closing " + mState + " " + this); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result >= 0) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CONNECTED; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CLOSED; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.obtainMessage(mConnectedCode, mState, -1, this).sendToTarget(); 151105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project releaseWakeLockNow(); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private synchronized void onAccepted(int result) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (VDBG) log("onAccepted() " + this); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_ACCEPT) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("Strange state " + this); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result >= 0) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CONNECTED; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CLOSED; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.obtainMessage(mAcceptedCode, mState, -1, this).sendToTarget(); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private synchronized void onClosed() { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("onClosed() " + this); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_CLOSED) { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_CLOSED; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.obtainMessage(mClosedCode, mState, -1, this).sendToTarget(); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project releaseWakeLock(); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void acquireWakeLock() { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mWakeLock.isHeld()) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (VDBG) log("mWakeLock.acquire() " + this); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void releaseWakeLock() { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mWakeLock.isHeld()) { 186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Keep apps processor awake for a further 2 seconds. 187105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // This is a hack to resolve issue http://b/1616263 - in which 188105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // we are left in a 80 mA power state when remotely terminating a 189105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // call while connected to BT headset "HTC BH S100 " with A2DP and 190105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // HFP profiles. 191105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (VDBG) log("mWakeLock.release() in 2 sec" + this); 192105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mWakeLock.acquire(2000); 193105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 194105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 196105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private void releaseWakeLockNow() { 197105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mWakeLock.isHeld()) { 198105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (VDBG) log("mWakeLock.release() now" + this); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void log(String msg) { 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, msg); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 207