diff options
| author | 2011-02-02 14:44:49 -0800 | |
|---|---|---|
| committer | 2011-02-03 17:02:06 -0800 | |
| commit | 50b40cec9c43eeeb9389ba2a99bcffd160246132 (patch) | |
| tree | f7447c4b8b244ca68338c74509d13c62e2ecf4e3 | |
| parent | 4eb02a13b33a868ac323d3079cea663f50fbbddb (diff) | |
Wait till SDP records are registered before sending intent.
Wait till all SDP records are registered, before sending STATE_ON intent.
This would fix crashes in Settings app when the profile manager
is not registered.
Problem:
We were sending Bluetooth State on intent before we got the uuid state
change intent from Bluez, which is asynchronous.
Hence when the Settings app queries for the profiles
to decide if headset profile was registered it would get false and
the profile manager would be null causing crashes.
This was not 100 % reproducible, well because it was a race condition.
Change-Id: I791eb63dfbc78aba4c06fd8db933069cb5fde00d
| -rw-r--r-- | core/java/android/server/BluetoothEventLoop.java | 3 | ||||
| -rw-r--r-- | core/java/android/server/BluetoothService.java | 99 |
2 files changed, 63 insertions, 39 deletions
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index cd3bc3e7c32a..e9f28fa9cc31 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -306,6 +306,9 @@ class BluetoothEventLoop { value = str.toString(); } mBluetoothService.setProperty(name, value); + if (name.equals("UUIDs")) { + mBluetoothService.updateBluetoothState(value); + } } else if (name.equals("Powered")) { // bluetoothd has restarted, re-read all our properties. // Note: bluez only sends this property change when it restarts. diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index ab1e9c660be7..78d47fbf9ad4 100644 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -96,8 +96,8 @@ public class BluetoothService extends IBluetooth.Stub { private boolean mRestart = false; // need to call enable() after disable() private boolean mIsDiscovering; private boolean mTetheringOn; - private int[] mAdapterSdpUuids; private int[] mAdapterSdpHandles; + private ParcelUuid[] mAdapterUuids; private BluetoothAdapter mAdapter; // constant after init() private final BondState mBondState = new BondState(); // local cache of bondings @@ -438,6 +438,8 @@ public class BluetoothService extends IBluetooth.Stub { mProfilesConnecting = 0; mProfilesDisconnecting = 0; mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED; + mAdapterUuids = null; + mAdapterSdpHandles = null; if (saveSetting) { persistBluetoothOnSetting(false); @@ -579,7 +581,6 @@ public class BluetoothService extends IBluetooth.Stub { } } - if (res) { if (!setupNativeDataNative()) { return; @@ -587,33 +588,8 @@ public class BluetoothService extends IBluetooth.Stub { if (mSaveSetting) { persistBluetoothOnSetting(true); } - //Register SDP records. - if (mContext.getResources(). - getBoolean(com.android.internal.R.bool.config_voice_capable)) { - int[] uuids = { - BluetoothUuid.getServiceIdentifierFromParcelUuid( - BluetoothUuid.Handsfree_AG), - BluetoothUuid.getServiceIdentifierFromParcelUuid( - BluetoothUuid.HSP_AG), - BluetoothUuid.getServiceIdentifierFromParcelUuid( - BluetoothUuid.PBAP_PSE), - BluetoothUuid.getServiceIdentifierFromParcelUuid( - BluetoothUuid.ObexObjectPush), - }; - mAdapterSdpUuids = uuids; - - } else { - int[] uuids = { - BluetoothUuid.getServiceIdentifierFromParcelUuid( - BluetoothUuid.HSP_AG), - BluetoothUuid.getServiceIdentifierFromParcelUuid( - BluetoothUuid.ObexObjectPush), - }; - mAdapterSdpUuids = uuids; - } - mAdapterSdpHandles = addReservedServiceRecordsNative(mAdapterSdpUuids); - setBluetoothTetheringNative(true, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); + updateSdpRecords(); mIsDiscovering = false; mBondState.readAutoPairingData(); @@ -628,24 +604,67 @@ public class BluetoothService extends IBluetooth.Stub { } finally { Binder.restoreCallingIdentity(ident); } + } else { + setBluetoothState(BluetoothAdapter.STATE_OFF); } - mEnableThread = null; + } + } - setBluetoothState(res ? - BluetoothAdapter.STATE_ON : - BluetoothAdapter.STATE_OFF); + private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) { + //Register SDP records. + int[] svcIdentifiers = new int[uuids.size()]; + for (int i = 0; i < uuids.size(); i++) { + svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i)); + } + mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers); + } - if (res) { - // Update mode + private synchronized void updateSdpRecords() { + ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); + + // Add the default records + uuids.add(BluetoothUuid.HSP_AG); + uuids.add(BluetoothUuid.ObexObjectPush); + + if (mContext.getResources(). + getBoolean(com.android.internal.R.bool.config_voice_capable)) { + uuids.add(BluetoothUuid.Handsfree_AG); + uuids.add(BluetoothUuid.PBAP_PSE); + } + + // Add SDP records for profiles maintained by Android userspace + addReservedSdpRecords(uuids); + + // Enable profiles maintained by Bluez userspace. + setBluetoothTetheringNative(true, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); + + // Add SDP records for profiles maintained by Bluez userspace + uuids.add(BluetoothUuid.AudioSource); + uuids.add(BluetoothUuid.AvrcpTarget); + uuids.add(BluetoothUuid.NAP); + + // Cannot cast uuids.toArray directly since ParcelUuid is parcelable + mAdapterUuids = new ParcelUuid[uuids.size()]; + for (int i = 0; i < uuids.size(); i++) { + mAdapterUuids[i] = uuids.get(i); + } + } + + synchronized void updateBluetoothState(String uuids) { + if (mBluetoothState == BluetoothAdapter.STATE_TURNING_ON) { + ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids); + + if (mAdapterUuids != null && + BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { + setBluetoothState(BluetoothAdapter.STATE_ON); String[] propVal = {"Pairable", getProperty("Pairable")}; mEventLoop.onPropertyChanged(propVal); - } - if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { - disable(false); + if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { + disable(false); + } } - } } @@ -1201,7 +1220,10 @@ public class BluetoothService extends IBluetooth.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); String value = getProperty("UUIDs"); if (value == null) return null; + return convertStringToParcelUuid(value); + } + private synchronized ParcelUuid[] convertStringToParcelUuid(String value) { String[] uuidStrings = null; // The UUIDs are stored as a "," separated string. uuidStrings = value.split(","); @@ -1211,7 +1233,6 @@ public class BluetoothService extends IBluetooth.Stub { uuids[i] = ParcelUuid.fromString(uuidStrings[i]); } return uuids; - } |