Merge "Fix sysui depending on slow bt calls" into oc-dev
am: 02d5b79cf6
Change-Id: I9a1dbc2f382562fb8ced63fd70f1a5e1674285f0
This commit is contained in:
@@ -179,12 +179,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBluetoothDevicesChanged() {
|
public void onBluetoothDevicesChanged() {
|
||||||
mUiHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mDetailAdapter.updateItems();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
refreshState();
|
refreshState();
|
||||||
if (isShowingDetail()) {
|
if (isShowingDetail()) {
|
||||||
mDetailAdapter.updateItems();
|
mDetailAdapter.updateItems();
|
||||||
@@ -198,6 +192,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
|
protected class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
|
||||||
|
// We probably won't ever have space in the UI for more than 20 devices, so don't
|
||||||
|
// get info for them.
|
||||||
|
private static final int MAX_DEVICES = 20;
|
||||||
private QSDetailItems mItems;
|
private QSDetailItems mItems;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -260,13 +257,14 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
|
|||||||
final Collection<CachedBluetoothDevice> devices = mController.getDevices();
|
final Collection<CachedBluetoothDevice> devices = mController.getDevices();
|
||||||
if (devices != null) {
|
if (devices != null) {
|
||||||
int connectedDevices = 0;
|
int connectedDevices = 0;
|
||||||
|
int count = 0;
|
||||||
for (CachedBluetoothDevice device : devices) {
|
for (CachedBluetoothDevice device : devices) {
|
||||||
if (device.getBondState() == BluetoothDevice.BOND_NONE) continue;
|
if (mController.getBondState(device) == BluetoothDevice.BOND_NONE) continue;
|
||||||
final Item item = new Item();
|
final Item item = new Item();
|
||||||
item.icon = R.drawable.ic_qs_bluetooth_on;
|
item.icon = R.drawable.ic_qs_bluetooth_on;
|
||||||
item.line1 = device.getName();
|
item.line1 = device.getName();
|
||||||
item.tag = device;
|
item.tag = device;
|
||||||
int state = device.getMaxConnectionState();
|
int state = mController.getMaxConnectionState(device);
|
||||||
if (state == BluetoothProfile.STATE_CONNECTED) {
|
if (state == BluetoothProfile.STATE_CONNECTED) {
|
||||||
item.icon = R.drawable.ic_qs_bluetooth_connected;
|
item.icon = R.drawable.ic_qs_bluetooth_connected;
|
||||||
item.line2 = mContext.getString(R.string.quick_settings_connected);
|
item.line2 = mContext.getString(R.string.quick_settings_connected);
|
||||||
@@ -280,6 +278,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
|
|||||||
} else {
|
} else {
|
||||||
items.add(item);
|
items.add(item);
|
||||||
}
|
}
|
||||||
|
if (++count == MAX_DEVICES) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mItems.setItems(items.toArray(new Item[items.size()]));
|
mItems.setItems(items.toArray(new Item[items.size()]));
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ public interface BluetoothController extends CallbackController<Callback>, Dumpa
|
|||||||
void disconnect(CachedBluetoothDevice device);
|
void disconnect(CachedBluetoothDevice device);
|
||||||
boolean canConfigBluetooth();
|
boolean canConfigBluetooth();
|
||||||
|
|
||||||
|
int getMaxConnectionState(CachedBluetoothDevice device);
|
||||||
|
int getBondState(CachedBluetoothDevice device);
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
void onBluetoothStateChange(boolean enabled);
|
void onBluetoothStateChange(boolean enabled);
|
||||||
void onBluetoothDevicesChanged();
|
void onBluetoothDevicesChanged();
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.policy;
|
|||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -33,8 +35,10 @@ import com.android.systemui.Dependency;
|
|||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback,
|
public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback,
|
||||||
CachedBluetoothDevice.Callback {
|
CachedBluetoothDevice.Callback {
|
||||||
@@ -44,18 +48,22 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
|
|||||||
private final LocalBluetoothManager mLocalBluetoothManager;
|
private final LocalBluetoothManager mLocalBluetoothManager;
|
||||||
private final UserManager mUserManager;
|
private final UserManager mUserManager;
|
||||||
private final int mCurrentUser;
|
private final int mCurrentUser;
|
||||||
|
private final WeakHashMap<CachedBluetoothDevice, ActuallyCachedState> mCachedState =
|
||||||
|
new WeakHashMap<>();
|
||||||
|
private final Handler mBgHandler;
|
||||||
|
|
||||||
private boolean mEnabled;
|
private boolean mEnabled;
|
||||||
private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
||||||
private CachedBluetoothDevice mLastDevice;
|
private CachedBluetoothDevice mLastDevice;
|
||||||
|
|
||||||
private final H mHandler = new H();
|
private final H mHandler = new H(Looper.getMainLooper());
|
||||||
private int mState;
|
private int mState;
|
||||||
|
|
||||||
public BluetoothControllerImpl(Context context, Looper bgLooper) {
|
public BluetoothControllerImpl(Context context, Looper bgLooper) {
|
||||||
mLocalBluetoothManager = Dependency.get(LocalBluetoothManager.class);
|
mLocalBluetoothManager = Dependency.get(LocalBluetoothManager.class);
|
||||||
|
mBgHandler = new Handler(bgLooper);
|
||||||
if (mLocalBluetoothManager != null) {
|
if (mLocalBluetoothManager != null) {
|
||||||
mLocalBluetoothManager.getEventManager().setReceiverHandler(new Handler(bgLooper));
|
mLocalBluetoothManager.getEventManager().setReceiverHandler(mBgHandler);
|
||||||
mLocalBluetoothManager.getEventManager().registerCallback(this);
|
mLocalBluetoothManager.getEventManager().registerCallback(this);
|
||||||
onBluetoothStateChanged(
|
onBluetoothStateChanged(
|
||||||
mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
|
mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
|
||||||
@@ -105,6 +113,16 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
|
|||||||
return device.getName() + " " + device.getBondState() + " " + device.isConnected();
|
return device.getName() + " " + device.getBondState() + " " + device.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBondState(CachedBluetoothDevice device) {
|
||||||
|
return getCachedState(device).mBondState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxConnectionState(CachedBluetoothDevice device) {
|
||||||
|
return getCachedState(device).mMaxConnectionState;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCallback(Callback cb) {
|
public void addCallback(Callback cb) {
|
||||||
mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
|
mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
|
||||||
@@ -225,12 +243,14 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
|
public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
|
||||||
|
mCachedState.remove(cachedDevice);
|
||||||
updateConnected();
|
updateConnected();
|
||||||
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
|
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
|
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
|
||||||
|
mCachedState.remove(cachedDevice);
|
||||||
updateConnected();
|
updateConnected();
|
||||||
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
|
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
|
||||||
}
|
}
|
||||||
@@ -243,11 +263,44 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||||
|
mCachedState.remove(cachedDevice);
|
||||||
mLastDevice = cachedDevice;
|
mLastDevice = cachedDevice;
|
||||||
updateConnected();
|
updateConnected();
|
||||||
mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
|
mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ActuallyCachedState getCachedState(CachedBluetoothDevice device) {
|
||||||
|
ActuallyCachedState state = mCachedState.get(device);
|
||||||
|
if (state == null) {
|
||||||
|
state = new ActuallyCachedState(device, mHandler);
|
||||||
|
mBgHandler.post(state);
|
||||||
|
mCachedState.put(device, state);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ActuallyCachedState implements Runnable {
|
||||||
|
|
||||||
|
private final WeakReference<CachedBluetoothDevice> mDevice;
|
||||||
|
private final Handler mUiHandler;
|
||||||
|
private int mBondState = BluetoothDevice.BOND_NONE;
|
||||||
|
private int mMaxConnectionState = BluetoothProfile.STATE_DISCONNECTED;
|
||||||
|
|
||||||
|
private ActuallyCachedState(CachedBluetoothDevice device, Handler uiHandler) {
|
||||||
|
mDevice = new WeakReference<>(device);
|
||||||
|
mUiHandler = uiHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mBondState = mDevice.get().getBondState();
|
||||||
|
mMaxConnectionState = mDevice.get().getMaxConnectionState();
|
||||||
|
mUiHandler.removeMessages(H.MSG_PAIRED_DEVICES_CHANGED);
|
||||||
|
mUiHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class H extends Handler {
|
private final class H extends Handler {
|
||||||
private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>();
|
private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>();
|
||||||
|
|
||||||
@@ -256,6 +309,10 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
|
|||||||
private static final int MSG_ADD_CALLBACK = 3;
|
private static final int MSG_ADD_CALLBACK = 3;
|
||||||
private static final int MSG_REMOVE_CALLBACK = 4;
|
private static final int MSG_REMOVE_CALLBACK = 4;
|
||||||
|
|
||||||
|
public H(Looper looper) {
|
||||||
|
super(looper);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
|
|||||||
@@ -14,16 +14,21 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.policy;
|
package com.android.systemui.statusbar.policy;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
import android.os.Looper;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
import android.testing.TestableLooper.RunWithLooper;
|
import android.testing.TestableLooper.RunWithLooper;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
@@ -80,4 +85,56 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
|
|||||||
BluetoothAdapter.STATE_DISCONNECTED);
|
BluetoothAdapter.STATE_DISCONNECTED);
|
||||||
assertTrue(mBluetoothControllerImpl.isBluetoothConnected());
|
assertTrue(mBluetoothControllerImpl.isBluetoothConnected());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultConnectionState() {
|
||||||
|
CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
|
||||||
|
assertEquals(BluetoothDevice.BOND_NONE, mBluetoothControllerImpl.getBondState(device));
|
||||||
|
assertEquals(BluetoothProfile.STATE_DISCONNECTED,
|
||||||
|
mBluetoothControllerImpl.getMaxConnectionState(device));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAsyncBondState() throws Exception {
|
||||||
|
CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
|
||||||
|
when(device.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||||
|
BluetoothController.Callback callback = mock(BluetoothController.Callback.class);
|
||||||
|
mBluetoothControllerImpl.addCallback(callback);
|
||||||
|
|
||||||
|
// Grab the main looper, we'll need it later.
|
||||||
|
TestableLooper mainLooper = new TestableLooper(Looper.getMainLooper());
|
||||||
|
|
||||||
|
// Trigger the state getting.
|
||||||
|
assertEquals(BluetoothDevice.BOND_NONE, mBluetoothControllerImpl.getBondState(device));
|
||||||
|
|
||||||
|
mTestableLooper.processMessages(1);
|
||||||
|
mainLooper.processAllMessages();
|
||||||
|
|
||||||
|
assertEquals(BluetoothDevice.BOND_BONDED, mBluetoothControllerImpl.getBondState(device));
|
||||||
|
verify(callback).onBluetoothDevicesChanged();
|
||||||
|
mainLooper.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAsyncConnectionState() throws Exception {
|
||||||
|
CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
|
||||||
|
when(device.getMaxConnectionState()).thenReturn(BluetoothProfile.STATE_CONNECTED);
|
||||||
|
BluetoothController.Callback callback = mock(BluetoothController.Callback.class);
|
||||||
|
mBluetoothControllerImpl.addCallback(callback);
|
||||||
|
|
||||||
|
// Grab the main looper, we'll need it later.
|
||||||
|
TestableLooper mainLooper = new TestableLooper(Looper.getMainLooper());
|
||||||
|
|
||||||
|
// Trigger the state getting.
|
||||||
|
assertEquals(BluetoothProfile.STATE_DISCONNECTED,
|
||||||
|
mBluetoothControllerImpl.getMaxConnectionState(device));
|
||||||
|
|
||||||
|
mTestableLooper.processMessages(1);
|
||||||
|
mainLooper.processAllMessages();
|
||||||
|
|
||||||
|
assertEquals(BluetoothProfile.STATE_CONNECTED,
|
||||||
|
mBluetoothControllerImpl.getMaxConnectionState(device));
|
||||||
|
verify(callback).onBluetoothDevicesChanged();
|
||||||
|
mainLooper.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,4 +83,14 @@ public class FakeBluetoothController extends BaseLeakChecker<Callback> implement
|
|||||||
public boolean canConfigBluetooth() {
|
public boolean canConfigBluetooth() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxConnectionState(CachedBluetoothDevice device) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBondState(CachedBluetoothDevice device) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user