Merge "b/2680057 Fixed a bug where bt won't connect when the phone is docked (if Settings wasn't running)." into kraken

This commit is contained in:
Michael Chan
2010-05-27 17:11:24 -07:00
committed by Android (Google) Code Review
2 changed files with 125 additions and 8 deletions

View File

@@ -18,6 +18,7 @@ package com.android.settings.bluetooth;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.ServiceListener;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Notification; import android.app.Notification;
@@ -48,7 +49,7 @@ import java.util.Set;
public class DockService extends Service implements AlertDialog.OnMultiChoiceClickListener, public class DockService extends Service implements AlertDialog.OnMultiChoiceClickListener,
DialogInterface.OnClickListener, DialogInterface.OnDismissListener, DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
CompoundButton.OnCheckedChangeListener { CompoundButton.OnCheckedChangeListener, ServiceListener {
private static final String TAG = "DockService"; private static final String TAG = "DockService";
@@ -101,6 +102,7 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
// Created in OnCreate() // Created in OnCreate()
private volatile Looper mServiceLooper; private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler; private volatile ServiceHandler mServiceHandler;
private Runnable mRunnable;
private DockService mContext; private DockService mContext;
private LocalBluetoothManager mBtManager; private LocalBluetoothManager mBtManager;
@@ -138,6 +140,8 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
@Override @Override
public void onDestroy() { public void onDestroy() {
if (DEBUG) Log.d(TAG, "onDestroy"); if (DEBUG) Log.d(TAG, "onDestroy");
mRunnable = null;
LocalBluetoothProfileManager.removeServiceListener(this);
if (mDialog != null) { if (mDialog != null) {
mDialog.dismiss(); mDialog.dismiss();
mDialog = null; mDialog = null;
@@ -228,8 +232,8 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
// This method gets messages from both onStartCommand and mServiceHandler/mServiceLooper // This method gets messages from both onStartCommand and mServiceHandler/mServiceLooper
private synchronized void processMessage(Message msg) { private synchronized void processMessage(Message msg) {
int msgType = msg.what; int msgType = msg.what;
int state = msg.arg1; final int state = msg.arg1;
int startId = msg.arg2; final int startId = msg.arg2;
boolean deferFinishCall = false; boolean deferFinishCall = false;
BluetoothDevice device = null; BluetoothDevice device = null;
if (msg.obj != null) { if (msg.obj != null) {
@@ -271,12 +275,23 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
} }
mDevice = device; mDevice = device;
if (mBtManager.getDockAutoConnectSetting(device.getAddress())) {
// Setting == auto connect // Register first in case LocalBluetoothProfileManager
initBtSettings(mContext, device, state, false); // becomes ready after isManagerReady is called and it
applyBtSettings(mDevice, startId); // would be too late to register a service listener.
LocalBluetoothProfileManager.addServiceListener(this);
if (LocalBluetoothProfileManager.isManagerReady()) {
handleDocked(device, state, startId);
// Not needed after all
LocalBluetoothProfileManager.removeServiceListener(this);
} else { } else {
createDialog(mContext, mDevice, state, startId); final BluetoothDevice d = device;
mRunnable = new Runnable() {
public void run() {
handleDocked(d, state, startId);
}
};
deferFinishCall = true;
} }
} }
break; break;
@@ -721,8 +736,21 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
} }
} }
private synchronized void handleDocked(final BluetoothDevice device, final int state,
final int startId) {
if (mBtManager.getDockAutoConnectSetting(device.getAddress())) {
// Setting == auto connect
initBtSettings(mContext, device, state, false);
applyBtSettings(mDevice, startId);
} else {
createDialog(mContext, device, state, startId);
}
}
private synchronized void handleUndocked(Context context, LocalBluetoothManager localManager, private synchronized void handleUndocked(Context context, LocalBluetoothManager localManager,
BluetoothDevice device) { BluetoothDevice device) {
mRunnable = null;
LocalBluetoothProfileManager.removeServiceListener(this);
if (mDialog != null) { if (mDialog != null) {
mDialog.dismiss(); mDialog.dismiss();
mDialog = null; mDialog = null;
@@ -778,4 +806,15 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
editor.commit(); editor.commit();
return; return;
} }
public synchronized void onServiceConnected() {
if (mRunnable != null) {
mRunnable.run();
mRunnable = null;
LocalBluetoothProfileManager.removeServiceListener(this);
}
}
public void onServiceDisconnected() {
}
} }

View File

@@ -28,6 +28,8 @@ import android.util.Log;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -53,6 +55,29 @@ public abstract class LocalBluetoothProfileManager {
BluetoothUuid.ObexObjectPush BluetoothUuid.ObexObjectPush
}; };
/**
* An interface for notifying BluetoothHeadset IPC clients when they have
* been connected to the BluetoothHeadset service.
*/
public interface ServiceListener {
/**
* Called to notify the client when this proxy object has been
* connected to the BluetoothHeadset service. Clients must wait for
* this callback before making IPC calls on the BluetoothHeadset
* service.
*/
public void onServiceConnected();
/**
* Called to notify the client that this proxy object has been
* disconnected from the BluetoothHeadset service. Clients must not
* make IPC calls on the BluetoothHeadset service after this callback.
* This callback will currently only occur if the application hosting
* the BluetoothHeadset service, but may be called more often in future.
*/
public void onServiceDisconnected();
}
// TODO: close profiles when we're shutting down // TODO: close profiles when we're shutting down
private static Map<Profile, LocalBluetoothProfileManager> sProfileMap = private static Map<Profile, LocalBluetoothProfileManager> sProfileMap =
new HashMap<Profile, LocalBluetoothProfileManager>(); new HashMap<Profile, LocalBluetoothProfileManager>();
@@ -76,6 +101,26 @@ public abstract class LocalBluetoothProfileManager {
} }
} }
private static LinkedList<ServiceListener> mServiceListeners = new LinkedList<ServiceListener>();
public static void addServiceListener(ServiceListener l) {
mServiceListeners.add(l);
}
public static void removeServiceListener(ServiceListener l) {
mServiceListeners.remove(l);
}
public static boolean isManagerReady() {
// Getting just the headset profile is fine for now. Will need to deal with A2DP
// and others if they aren't always in a ready state.
LocalBluetoothProfileManager profileManager = sProfileMap.get(Profile.HEADSET);
if (profileManager == null) {
return sProfileMap.size() > 0;
}
return profileManager.isProfileReady();
}
public static LocalBluetoothProfileManager getProfileManager(LocalBluetoothManager localManager, public static LocalBluetoothProfileManager getProfileManager(LocalBluetoothManager localManager,
Profile profile) { Profile profile) {
// Note: This code assumes that "localManager" is same as the // Note: This code assumes that "localManager" is same as the
@@ -144,6 +189,8 @@ public abstract class LocalBluetoothProfileManager {
return SettingsBtStatus.isConnectionStatusConnected(getConnectionStatus(device)); return SettingsBtStatus.isConnectionStatusConnected(getConnectionStatus(device));
} }
public abstract boolean isProfileReady();
// TODO: int instead of enum // TODO: int instead of enum
public enum Profile { public enum Profile {
HEADSET(R.string.bluetooth_profile_headset), HEADSET(R.string.bluetooth_profile_headset),
@@ -247,6 +294,11 @@ public abstract class LocalBluetoothProfileManager {
return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN;
} }
} }
@Override
public boolean isProfileReady() {
return true;
}
} }
/** /**
@@ -256,6 +308,7 @@ public abstract class LocalBluetoothProfileManager {
implements BluetoothHeadset.ServiceListener { implements BluetoothHeadset.ServiceListener {
private BluetoothHeadset mService; private BluetoothHeadset mService;
private Handler mUiHandler = new Handler(); private Handler mUiHandler = new Handler();
private boolean profileReady = false;
public HeadsetProfileManager(LocalBluetoothManager localManager) { public HeadsetProfileManager(LocalBluetoothManager localManager) {
super(localManager); super(localManager);
@@ -263,6 +316,7 @@ public abstract class LocalBluetoothProfileManager {
} }
public void onServiceConnected() { public void onServiceConnected() {
profileReady = true;
// This could be called on a non-UI thread, funnel to UI thread. // This could be called on a non-UI thread, funnel to UI thread.
mUiHandler.post(new Runnable() { mUiHandler.post(new Runnable() {
public void run() { public void run() {
@@ -277,9 +331,28 @@ public abstract class LocalBluetoothProfileManager {
BluetoothHeadset.STATE_CONNECTED); BluetoothHeadset.STATE_CONNECTED);
} }
}); });
if (mServiceListeners.size() > 0) {
Iterator<ServiceListener> it = mServiceListeners.iterator();
while(it.hasNext()) {
it.next().onServiceConnected();
}
}
} }
public void onServiceDisconnected() { public void onServiceDisconnected() {
profileReady = false;
if (mServiceListeners.size() > 0) {
Iterator<ServiceListener> it = mServiceListeners.iterator();
while(it.hasNext()) {
it.next().onServiceDisconnected();
}
}
}
@Override
public boolean isProfileReady() {
return profileReady;
} }
@Override @Override
@@ -423,6 +496,11 @@ public abstract class LocalBluetoothProfileManager {
public void setPreferred(BluetoothDevice device, boolean preferred) { public void setPreferred(BluetoothDevice device, boolean preferred) {
} }
@Override
public boolean isProfileReady() {
return true;
}
@Override @Override
public int convertState(int oppState) { public int convertState(int oppState) {
switch (oppState) { switch (oppState) {