diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:46 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:46 -0700 |
commit | 105925376f8d0f6b318c9938c7b83ef7fef094da (patch) | |
tree | 3b19ee2bd8704cb9c6a0da7e42dec6759183de6d /core/java/android/server/BluetoothDeviceService.java | |
parent | ba87e3e6c985e7175152993b5efcc7dd2f0e1c93 (diff) | |
download | frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.zip frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.tar.gz frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.tar.bz2 |
auto import from //branches/cupcake_rel/...@140373
Diffstat (limited to 'core/java/android/server/BluetoothDeviceService.java')
-rw-r--r-- | core/java/android/server/BluetoothDeviceService.java | 288 |
1 files changed, 182 insertions, 106 deletions
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 9e9ba62..b7e3846 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -37,8 +37,10 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemService; import android.provider.Settings; import android.util.Log; @@ -51,6 +53,8 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import com.android.internal.app.IBatteryStats; + public class BluetoothDeviceService extends IBluetoothDevice.Stub { private static final String TAG = "BluetoothDeviceService"; private static final boolean DBG = true; @@ -60,14 +64,18 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private IntentFilter mIntentFilter; private boolean mIsAirplaneSensitive; private final BondState mBondState = new BondState(); // local cache of bondings - private volatile boolean mIsEnabled; // local cache of isEnabledNative() + private int mBluetoothState; private boolean mIsDiscovering; + private final IBatteryStats mBatteryStats; private final Context mContext; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; + private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; + private static final int MESSAGE_FINISH_DISABLE = 2; + static { classInitNative(); } @@ -75,6 +83,12 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public BluetoothDeviceService(Context context) { mContext = context; + + // Need to do this in place of: + // mBatteryStats = BatteryStatsService.getService(); + // Since we can not import BatteryStatsService from here. This class really needs to be + // moved to java/services/com/android/server/ + mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); } /** Must be called after construction, and before any other method. @@ -87,7 +101,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { disableNative(); } - mIsEnabled = false; + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF); mIsDiscovering = false; mEventLoop = new BluetoothEventLoop(mContext, this); registerForAirplaneMode(); @@ -109,10 +123,16 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public boolean isEnabled() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return mIsEnabled; + return mBluetoothState == BluetoothDevice.BLUETOOTH_STATE_ON; } private native int isEnabledNative(); + public int getBluetoothState() { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + return mBluetoothState; + } + + /** * Bring down bluetooth and disable BT in settings. Returns true on success. */ @@ -124,17 +144,36 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { * Bring down bluetooth. Returns true on success. * * @param saveSetting If true, disable BT in settings - * */ public synchronized boolean disable(boolean saveSetting) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); + switch (mBluetoothState) { + case BluetoothDevice.BLUETOOTH_STATE_OFF: + return true; + case BluetoothDevice.BLUETOOTH_STATE_ON: + break; + default: + return false; + } if (mEnableThread != null && mEnableThread.isAlive()) { return false; } - if (!mIsEnabled) { - return true; + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF); + + // Allow 3 seconds for profiles to gracefully disconnect + // TODO: Introduce a callback mechanism so that each profile can notify + // BluetoothDeviceService when it is done shutting down + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); + return true; + } + + + private synchronized void finishDisable(boolean saveSetting) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) { + return; } mEventLoop.stop(); disableNative(); @@ -163,38 +202,37 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mIsEnabled = false; + mIsDiscovering = false; + if (saveSetting) { persistBluetoothOnSetting(false); } - mIsDiscovering = false; - intent = new Intent(BluetoothIntent.DISABLED_ACTION); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - return true; + + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF); + + // Log bluetooth off to battery stats. + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteBluetoothOff(); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } } - /** - * Bring up bluetooth, asynchronously, and enable BT in settings. - * This turns on/off the underlying hardware. - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. - */ - public boolean enable(IBluetoothDeviceCallback callback) { - return enable(callback, true); + /** Bring up BT and persist BT on in settings */ + public boolean enable() { + return enable(true); } /** * Enable this Bluetooth device, asynchronously. * This turns on/off the underlying hardware. * - * @param saveSetting If true, enable BT in settings - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. + * @param saveSetting If true, persist the new state of BT in settings + * @return True on success (so far) */ - public synchronized boolean enable(IBluetoothDeviceCallback callback, - boolean saveSetting) { + public synchronized boolean enable(boolean saveSetting) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); @@ -202,28 +240,49 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { if (mIsAirplaneSensitive && isAirplaneModeOn()) { return false; } - if (mIsEnabled) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_OFF) { return false; } if (mEnableThread != null && mEnableThread.isAlive()) { return false; } - mEnableThread = new EnableThread(callback, saveSetting); + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON); + mEnableThread = new EnableThread(saveSetting); mEnableThread.start(); return true; } - private static final int REGISTER_SDP_RECORDS = 1; + private synchronized void setBluetoothState(int state) { + if (state == mBluetoothState) { + return; + } + + if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state); + + Intent intent = new Intent(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION); + intent.putExtra(BluetoothIntent.BLUETOOTH_PREVIOUS_STATE, mBluetoothState); + intent.putExtra(BluetoothIntent.BLUETOOTH_STATE, state); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + + mBluetoothState = state; + + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + } + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { - case REGISTER_SDP_RECORDS: + case MESSAGE_REGISTER_SDP_RECORDS: //TODO: Don't assume HSP/HFP is running, don't use sdptool, if (isEnabled()) { SystemService.start("hsag"); SystemService.start("hfag"); } + break; + case MESSAGE_FINISH_DISABLE: + finishDisable(msg.arg1 != 0); + break; } } }; @@ -231,10 +290,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private EnableThread mEnableThread; private class EnableThread extends Thread { - private final IBluetoothDeviceCallback mEnableCallback; private final boolean mSaveSetting; - public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) { - mEnableCallback = callback; + public EnableThread(boolean saveSetting) { mSaveSetting = saveSetting; } public void run() { @@ -244,7 +301,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { boolean running = false; while ((retryCount-- > 0) && !running) { mEventLoop.start(); - // it may take a momement for the other thread to do its + // it may take a momement for the other thread to do its // thing. Check periodically for a while. int pollCount = 5; while ((pollCount-- > 0) && !running) { @@ -264,36 +321,37 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } } - if (mEnableCallback != null) { - try { - mEnableCallback.onEnableResult(res ? - BluetoothDevice.RESULT_SUCCESS : - BluetoothDevice.RESULT_FAILURE); - } catch (RemoteException e) {} - } if (res) { - mIsEnabled = true; if (mSaveSetting) { persistBluetoothOnSetting(true); } mIsDiscovering = false; mBondState.loadBondState(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS), + 3000); - // Update mode - mEventLoop.onModeChanged(getModeNative()); + // Log bluetooth on to battery stats. + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteBluetoothOn(); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } } - Intent intent = null; + + mEnableThread = null; + + setBluetoothState(res ? + BluetoothDevice.BLUETOOTH_STATE_ON : + BluetoothDevice.BLUETOOTH_STATE_OFF); + if (res) { - intent = new Intent(BluetoothIntent.ENABLED_ACTION); - } else { - intent = new Intent(BluetoothIntent.DISABLED_ACTION); + // Update mode + mEventLoop.onModeChanged(getModeNative()); } - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mEnableThread = null; } } @@ -320,18 +378,24 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private final HashMap<String, Integer> mState = new HashMap<String, Integer>(); private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>(); private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>(); - // List of all the vendor_id prefix of Bluetooth addresses for which - // auto pairing is not attempted + // List of all the vendor_id prefix of Bluetooth addresses for + // which auto pairing is not attempted. + // The following companies are included in the list below: + // ALPS (lexus), Murata (Prius 2007, Nokia 616), TEMIC SDS (Porsche, Audi), + // Parrot, Zhongshan General K-mate Electronics, Great Well + // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi, + // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura), private final ArrayList<String> mAutoPairingBlacklisted = new ArrayList<String>(Arrays.asList( - "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS - "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS - "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57",// Murata for Prius 2007 - "00:0E:9F" // TEMIC SDS for Porsche + "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", "00:21:4F", + "00:23:06", "00:24:33", "00:A0:79", "00:0E:6D", "00:13:E0", "00:21:E8", + "00:60:57", "00:0E:9F", "00:12:1C", "00:18:91", "00:18:96", "00:13:04", + "00:16:FD", "00:22:A0", "00:0B:4C", "00:60:6F", "00:23:3D", "00:C0:59", + "00:0A:30" )); public synchronized void loadBondState() { - if (!mIsEnabled) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_ON) { return; } String[] bonds = listBondingsNative(); @@ -1051,7 +1115,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { // If bluetooth is currently expected to be on, then enable or disable bluetooth if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { if (enabled) { - enable(null, false); + enable(false); } else { disable(false); } @@ -1079,52 +1143,63 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mIsEnabled) { - pw.println("\nBluetooth ENABLED: " + getAddress() + " (" + getName() + ")"); - pw.println("\nisDiscovering() = " + isDiscovering()); - - BluetoothHeadset headset = new BluetoothHeadset(mContext, null); - - String[] addresses = listRemoteDevices(); - - pw.println("\n--Known devices--"); - for (String address : addresses) { - pw.printf("%s %10s (%d) %s\n", address, - toBondStateString(mBondState.getBondState(address)), - mBondState.getAttempt(address), - getRemoteName(address)); - } - - addresses = listAclConnections(); - pw.println("\n--ACL connected devices--"); - for (String address : addresses) { - pw.println(address); - } - - // Rather not do this from here, but no-where else and I need this - // dump - pw.println("\n--Headset Service--"); - switch (headset.getState()) { - case BluetoothHeadset.STATE_DISCONNECTED: - pw.println("getState() = STATE_DISCONNECTED"); - break; - case BluetoothHeadset.STATE_CONNECTING: - pw.println("getState() = STATE_CONNECTING"); - break; - case BluetoothHeadset.STATE_CONNECTED: - pw.println("getState() = STATE_CONNECTED"); - break; - case BluetoothHeadset.STATE_ERROR: - pw.println("getState() = STATE_ERROR"); - break; - } - pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress()); - headset.close(); - - } else { - pw.println("\nBluetooth DISABLED"); - } - pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive); + pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n"); + + switch(mBluetoothState) { + case BluetoothDevice.BLUETOOTH_STATE_OFF: + pw.println("\nBluetooth OFF\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_ON: + pw.println("\nBluetooth TURNING ON\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF: + pw.println("\nBluetooth TURNING OFF\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_ON: + pw.println("\nBluetooth ON\n"); + } + + pw.println("\nLocal address = " + getAddress()); + pw.println("\nLocal name = " + getName()); + pw.println("\nisDiscovering() = " + isDiscovering()); + + BluetoothHeadset headset = new BluetoothHeadset(mContext, null); + + String[] addresses = listRemoteDevices(); + + pw.println("\n--Known devices--"); + for (String address : addresses) { + pw.printf("%s %10s (%d) %s\n", address, + toBondStateString(mBondState.getBondState(address)), + mBondState.getAttempt(address), + getRemoteName(address)); + } + + addresses = listAclConnections(); + pw.println("\n--ACL connected devices--"); + for (String address : addresses) { + pw.println(address); + } + + // Rather not do this from here, but no-where else and I need this + // dump + pw.println("\n--Headset Service--"); + switch (headset.getState()) { + case BluetoothHeadset.STATE_DISCONNECTED: + pw.println("getState() = STATE_DISCONNECTED"); + break; + case BluetoothHeadset.STATE_CONNECTING: + pw.println("getState() = STATE_CONNECTING"); + break; + case BluetoothHeadset.STATE_CONNECTED: + pw.println("getState() = STATE_CONNECTED"); + break; + case BluetoothHeadset.STATE_ERROR: + pw.println("getState() = STATE_ERROR"); + break; + } + pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress()); + headset.close(); } /* package */ static int bluezStringToScanMode(String mode) { @@ -1159,3 +1234,4 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { Log.d(TAG, msg); } } + |