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:
@@ -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() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
||||||
|
Reference in New Issue
Block a user