Merge "Add Api to get profile connection state."

This commit is contained in:
Jaikumar Ganesh
2011-08-22 15:59:19 -07:00
committed by Android (Google) Code Review
8 changed files with 134 additions and 18 deletions

View File

@@ -773,6 +773,31 @@ public final class BluetoothAdapter {
return BluetoothAdapter.STATE_DISCONNECTED; return BluetoothAdapter.STATE_DISCONNECTED;
} }
/**
* Get the current connection state of a profile.
* This function can be used to check whether the local Bluetooth adapter
* is connected to any remote device for a specific profile.
* Profile can be one of {@link BluetoothProfile.HEADSET},
* {@link BluetoothProfile.A2DP}.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
*
* <p> Return value can be one of
* {@link * BluetoothProfile.STATE_DISCONNECTED},
* {@link * BluetoothProfile.STATE_CONNECTING},
* {@link * BluetoothProfile.STATE_CONNECTED},
* {@link * BluetoothProfile.STATE_DISCONNECTING}
* @hide
*/
public int getProfileConnectionState(int profile) {
if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
try {
return mService.getProfileConnectionState(profile);
} catch (RemoteException e) {Log.e(TAG, "getProfileConnectionState:", e);}
return BluetoothProfile.STATE_DISCONNECTED;
}
/**
/** /**
* Picks RFCOMM channels until none are left. * Picks RFCOMM channels until none are left.
* Avoids reserved channels. * Avoids reserved channels.

View File

@@ -82,6 +82,12 @@ public interface BluetoothProfile {
*/ */
public static final int PAN = 5; public static final int PAN = 5;
/**
* PBAP
* @hide
*/
public static final int PBAP = 6;
/** /**
* Default priority for devices that we try to auto-connect to and * Default priority for devices that we try to auto-connect to and
* and allow incoming connections for the profile * and allow incoming connections for the profile

View File

@@ -53,6 +53,7 @@ interface IBluetooth
byte[] readOutOfBandData(); byte[] readOutOfBandData();
int getAdapterConnectionState(); int getAdapterConnectionState();
int getProfileConnectionState(int profile);
boolean changeApplicationBluetoothState(boolean on, boolean changeApplicationBluetoothState(boolean on,
in IBluetoothStateChangeCallback callback, in in IBluetoothStateChangeCallback callback, in
IBinder b); IBinder b);
@@ -121,5 +122,5 @@ interface IBluetooth
List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states); List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
int getHealthDeviceConnectionState(in BluetoothDevice device); int getHealthDeviceConnectionState(in BluetoothDevice device);
void sendConnectionStateChange(in BluetoothDevice device, int state, int prevState); void sendConnectionStateChange(in BluetoothDevice device, int profile, int state, int prevState);
} }

View File

@@ -523,7 +523,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state); if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
mBluetoothService.sendConnectionStateChange(device, state, prevState); mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state,
prevState);
} }
} }

View File

@@ -20,6 +20,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHealth; import android.bluetooth.BluetoothHealth;
import android.bluetooth.BluetoothHealthAppConfiguration; import android.bluetooth.BluetoothHealthAppConfiguration;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothHealthCallback; import android.bluetooth.IBluetoothHealthCallback;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
@@ -567,7 +568,8 @@ final class BluetoothHealthProfileHandler {
private void updateAndSendIntent(BluetoothDevice device, int prevDeviceState, private void updateAndSendIntent(BluetoothDevice device, int prevDeviceState,
int newDeviceState) { int newDeviceState) {
mHealthDevices.put(device, newDeviceState); mHealthDevices.put(device, newDeviceState);
mBluetoothService.sendConnectionStateChange(device, prevDeviceState, newDeviceState); mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.HEALTH,
prevDeviceState, newDeviceState);
} }
/** /**

View File

@@ -20,6 +20,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDeviceProfileState; import android.bluetooth.BluetoothDeviceProfileState;
import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProfileState; import android.bluetooth.BluetoothProfileState;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -191,7 +192,8 @@ final class BluetoothInputProfileHandler {
mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM); mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state); debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state);
mBluetoothService.sendConnectionStateChange(device, state, prevState); mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.INPUT_DEVICE, state,
prevState);
} }
void handleInputDevicePropertyChange(String address, boolean connected) { void handleInputDevicePropertyChange(String address, boolean connected) {

View File

@@ -19,6 +19,7 @@ package android.server;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothTetheringDataTracker; import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -303,7 +304,8 @@ final class BluetoothPanProfileHandler {
mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM); mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
debugLog("Pan Device state : device: " + device + " State:" + prevState + "->" + state); debugLog("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
mBluetoothService.sendConnectionStateChange(device, state, prevState); mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.PAN, state,
prevState);
} }
private class BluetoothPanDevice { private class BluetoothPanDevice {

View File

@@ -166,6 +166,7 @@ public class BluetoothService extends IBluetooth.Stub {
private static final String INCOMING_CONNECTION_FILE = private static final String INCOMING_CONNECTION_FILE =
"/data/misc/bluetooth/incoming_connection.conf"; "/data/misc/bluetooth/incoming_connection.conf";
private HashMap<String, Pair<Integer, String>> mIncomingConnections; private HashMap<String, Pair<Integer, String>> mIncomingConnections;
private HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState;
private static class RemoteService { private static class RemoteService {
public String address; public String address;
@@ -237,6 +238,7 @@ public class BluetoothService extends IBluetooth.Stub {
mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this); mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this); mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);
mIncomingConnections = new HashMap<String, Pair<Integer, String>>(); mIncomingConnections = new HashMap<String, Pair<Integer, String>>();
mProfileConnectionState = new HashMap<Integer, Pair<Integer, Integer>>();
} }
public static synchronized String readDockBluetoothAddress() { public static synchronized String readDockBluetoothAddress() {
@@ -1742,6 +1744,19 @@ public class BluetoothService extends IBluetooth.Stub {
dumpInputDeviceProfile(pw); dumpInputDeviceProfile(pw);
dumpPanProfile(pw); dumpPanProfile(pw);
dumpApplicationServiceRecords(pw); dumpApplicationServiceRecords(pw);
dumpProfileState(pw);
}
private void dumpProfileState(PrintWriter pw) {
pw.println("\n--Profile State dump--");
pw.println("\n Headset profile state:" +
mAdapter.getProfileConnectionState(BluetoothProfile.HEADSET));
pw.println("\n A2dp profile state:" +
mAdapter.getProfileConnectionState(BluetoothProfile.A2DP));
pw.println("\n HID profile state:" +
mAdapter.getProfileConnectionState(BluetoothProfile.INPUT_DEVICE));
pw.println("\n PAN profile state:" +
mAdapter.getProfileConnectionState(BluetoothProfile.PAN));
} }
private void dumpHeadsetService(PrintWriter pw) { private void dumpHeadsetService(PrintWriter pw) {
@@ -2443,23 +2458,85 @@ public class BluetoothService extends IBluetooth.Stub {
return mAdapterConnectionState; return mAdapterConnectionState;
} }
public synchronized void sendConnectionStateChange(BluetoothDevice device, int state, public int getProfileConnectionState(int profile) {
int prevState) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Pair<Integer, Integer> state = mProfileConnectionState.get(profile);
if (state == null) return BluetoothProfile.STATE_DISCONNECTED;
return state.first;
}
private void updateProfileConnectionState(int profile, int newState, int oldState) {
// mProfileConnectionState is a hashmap -
// <Integer, Pair<Integer, Integer>>
// The key is the profile, the value is a pair. first element
// is the state and the second element is the number of devices
// in that state.
int numDev = 1;
int newHashState = newState;
boolean update = true;
// The following conditions are considered in this function:
// 1. If there is no record of profile and state - update
// 2. If a new device's state is current hash state - increment
// number of devices in the state.
// 3. If a state change has happened to Connected or Connecting
// (if current state is not connected), update.
// 4. If numDevices is 1 and that device state is being updated, update
// 5. If numDevices is > 1 and one of the devices is changing state,
// decrement numDevices but maintain oldState if it is Connected or
// Connecting
Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile);
if (stateNumDev != null) {
int currHashState = stateNumDev.first;
numDev = stateNumDev.second;
if (newState == currHashState) {
numDev ++;
} else if (newState == BluetoothProfile.STATE_CONNECTED ||
(newState == BluetoothProfile.STATE_CONNECTING &&
currHashState != BluetoothProfile.STATE_CONNECTED)) {
numDev = 1;
} else if (numDev == 1 && oldState == currHashState) {
update = true;
} else if (numDev > 1 && oldState == currHashState) {
numDev --;
if (currHashState == BluetoothProfile.STATE_CONNECTED ||
currHashState == BluetoothProfile.STATE_CONNECTING) {
newHashState = currHashState;
}
} else {
update = false;
}
}
if (update) {
mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState,
numDev));
}
}
public synchronized void sendConnectionStateChange(BluetoothDevice
device, int profile, int state, int prevState) {
// Since this is a binder call check if Bluetooth is on still // Since this is a binder call check if Bluetooth is on still
if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return; if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
if (updateCountersAndCheckForConnectionStateChange(state, prevState)) { if (!validateProfileConnectionState(state) ||
if (!validateProfileConnectionState(state) || !validateProfileConnectionState(prevState)) {
!validateProfileConnectionState(prevState)) { // Previously, an invalid state was broadcast anyway,
// Previously, an invalid state was broadcast anyway, // with the invalid state converted to -1 in the intent.
// with the invalid state converted to -1 in the intent. // Better to log an error and not send an intent with
// Better to log an error and not send an intent with // invalid contents or set mAdapterConnectionState to -1.
// invalid contents or set mAdapterConnectionState to -1. Log.e(TAG, "Error in sendConnectionStateChange: "
Log.e(TAG, "Error in sendConnectionStateChange: " + "prevState " + prevState + " state " + state);
+ "prevState " + prevState + " state " + state); return;
return; }
}
updateProfileConnectionState(profile, state, prevState);
if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
mAdapterConnectionState = state; mAdapterConnectionState = state;
if (state == BluetoothProfile.STATE_DISCONNECTED) { if (state == BluetoothProfile.STATE_DISCONNECTED) {