Loading packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +9 −8 Original line number Diff line number Diff line Loading @@ -183,12 +183,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { @Override public void onBluetoothDevicesChanged() { mUiHandler.post(new Runnable() { @Override public void run() { mDetailAdapter.updateItems(); } }); refreshState(); if (isShowingDetail()) { mDetailAdapter.updateItems(); Loading @@ -202,6 +196,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { } 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; @Override Loading Loading @@ -264,13 +261,14 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { final Collection<CachedBluetoothDevice> devices = mController.getDevices(); if (devices != null) { int connectedDevices = 0; int count = 0; for (CachedBluetoothDevice device : devices) { if (device.getBondState() == BluetoothDevice.BOND_NONE) continue; if (mController.getBondState(device) == BluetoothDevice.BOND_NONE) continue; final Item item = new Item(); item.icon = R.drawable.ic_qs_bluetooth_on; item.line1 = device.getName(); item.tag = device; int state = device.getMaxConnectionState(); int state = mController.getMaxConnectionState(device); if (state == BluetoothProfile.STATE_CONNECTED) { item.icon = R.drawable.ic_qs_bluetooth_connected; item.line2 = mContext.getString(R.string.quick_settings_connected); Loading @@ -284,6 +282,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { } else { items.add(item); } if (++count == MAX_DEVICES) { break; } } } mItems.setItems(items.toArray(new Item[items.size()])); Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java +3 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ public interface BluetoothController extends CallbackController<Callback>, Dumpa void disconnect(CachedBluetoothDevice device); boolean canConfigBluetooth(); int getMaxConnectionState(CachedBluetoothDevice device); int getBondState(CachedBluetoothDevice device); public interface Callback { void onBluetoothStateChange(boolean enabled); void onBluetoothDevicesChanged(); Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +59 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.policy; import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.os.Handler; import android.os.Looper; Loading @@ -33,8 +35,10 @@ import com.android.systemui.Dependency; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.WeakHashMap; public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback, CachedBluetoothDevice.Callback { Loading @@ -44,18 +48,22 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa private final LocalBluetoothManager mLocalBluetoothManager; private final UserManager mUserManager; private final int mCurrentUser; private final WeakHashMap<CachedBluetoothDevice, ActuallyCachedState> mCachedState = new WeakHashMap<>(); private final Handler mBgHandler; private boolean mEnabled; private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; private CachedBluetoothDevice mLastDevice; private final H mHandler = new H(); private final H mHandler = new H(Looper.getMainLooper()); private int mState; public BluetoothControllerImpl(Context context, Looper bgLooper) { mLocalBluetoothManager = Dependency.get(LocalBluetoothManager.class); mBgHandler = new Handler(bgLooper); if (mLocalBluetoothManager != null) { mLocalBluetoothManager.getEventManager().setReceiverHandler(new Handler(bgLooper)); mLocalBluetoothManager.getEventManager().setReceiverHandler(mBgHandler); mLocalBluetoothManager.getEventManager().registerCallback(this); onBluetoothStateChanged( mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState()); Loading Loading @@ -105,6 +113,16 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa 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 public void addCallback(Callback cb) { mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget(); Loading Loading @@ -225,12 +243,14 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } @Override public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } Loading @@ -243,11 +263,44 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { mCachedState.remove(cachedDevice); mLastDevice = cachedDevice; updateConnected(); 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 ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>(); Loading @@ -256,6 +309,10 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa private static final int MSG_ADD_CALLBACK = 3; private static final int MSG_REMOVE_CALLBACK = 4; public H(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java +57 −0 Original line number Diff line number Diff line Loading @@ -14,16 +14,21 @@ package com.android.systemui.statusbar.policy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.os.Looper; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.util.Log; import com.android.settingslib.bluetooth.BluetoothEventManager; import com.android.settingslib.bluetooth.CachedBluetoothDevice; Loading Loading @@ -80,4 +85,56 @@ public class BluetoothControllerImplTest extends SysuiTestCase { BluetoothAdapter.STATE_DISCONNECTED); 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(); } } packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java +10 −0 Original line number Diff line number Diff line Loading @@ -83,4 +83,14 @@ public class FakeBluetoothController extends BaseLeakChecker<Callback> implement public boolean canConfigBluetooth() { return false; } @Override public int getMaxConnectionState(CachedBluetoothDevice device) { return 0; } @Override public int getBondState(CachedBluetoothDevice device) { return 0; } } Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +9 −8 Original line number Diff line number Diff line Loading @@ -183,12 +183,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { @Override public void onBluetoothDevicesChanged() { mUiHandler.post(new Runnable() { @Override public void run() { mDetailAdapter.updateItems(); } }); refreshState(); if (isShowingDetail()) { mDetailAdapter.updateItems(); Loading @@ -202,6 +196,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { } 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; @Override Loading Loading @@ -264,13 +261,14 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { final Collection<CachedBluetoothDevice> devices = mController.getDevices(); if (devices != null) { int connectedDevices = 0; int count = 0; for (CachedBluetoothDevice device : devices) { if (device.getBondState() == BluetoothDevice.BOND_NONE) continue; if (mController.getBondState(device) == BluetoothDevice.BOND_NONE) continue; final Item item = new Item(); item.icon = R.drawable.ic_qs_bluetooth_on; item.line1 = device.getName(); item.tag = device; int state = device.getMaxConnectionState(); int state = mController.getMaxConnectionState(device); if (state == BluetoothProfile.STATE_CONNECTED) { item.icon = R.drawable.ic_qs_bluetooth_connected; item.line2 = mContext.getString(R.string.quick_settings_connected); Loading @@ -284,6 +282,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { } else { items.add(item); } if (++count == MAX_DEVICES) { break; } } } mItems.setItems(items.toArray(new Item[items.size()])); Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java +3 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ public interface BluetoothController extends CallbackController<Callback>, Dumpa void disconnect(CachedBluetoothDevice device); boolean canConfigBluetooth(); int getMaxConnectionState(CachedBluetoothDevice device); int getBondState(CachedBluetoothDevice device); public interface Callback { void onBluetoothStateChange(boolean enabled); void onBluetoothDevicesChanged(); Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +59 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.policy; import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.os.Handler; import android.os.Looper; Loading @@ -33,8 +35,10 @@ import com.android.systemui.Dependency; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.WeakHashMap; public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback, CachedBluetoothDevice.Callback { Loading @@ -44,18 +48,22 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa private final LocalBluetoothManager mLocalBluetoothManager; private final UserManager mUserManager; private final int mCurrentUser; private final WeakHashMap<CachedBluetoothDevice, ActuallyCachedState> mCachedState = new WeakHashMap<>(); private final Handler mBgHandler; private boolean mEnabled; private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; private CachedBluetoothDevice mLastDevice; private final H mHandler = new H(); private final H mHandler = new H(Looper.getMainLooper()); private int mState; public BluetoothControllerImpl(Context context, Looper bgLooper) { mLocalBluetoothManager = Dependency.get(LocalBluetoothManager.class); mBgHandler = new Handler(bgLooper); if (mLocalBluetoothManager != null) { mLocalBluetoothManager.getEventManager().setReceiverHandler(new Handler(bgLooper)); mLocalBluetoothManager.getEventManager().setReceiverHandler(mBgHandler); mLocalBluetoothManager.getEventManager().registerCallback(this); onBluetoothStateChanged( mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState()); Loading Loading @@ -105,6 +113,16 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa 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 public void addCallback(Callback cb) { mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget(); Loading Loading @@ -225,12 +243,14 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } @Override public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } Loading @@ -243,11 +263,44 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { mCachedState.remove(cachedDevice); mLastDevice = cachedDevice; updateConnected(); 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 ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>(); Loading @@ -256,6 +309,10 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa private static final int MSG_ADD_CALLBACK = 3; private static final int MSG_REMOVE_CALLBACK = 4; public H(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java +57 −0 Original line number Diff line number Diff line Loading @@ -14,16 +14,21 @@ package com.android.systemui.statusbar.policy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.os.Looper; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.util.Log; import com.android.settingslib.bluetooth.BluetoothEventManager; import com.android.settingslib.bluetooth.CachedBluetoothDevice; Loading Loading @@ -80,4 +85,56 @@ public class BluetoothControllerImplTest extends SysuiTestCase { BluetoothAdapter.STATE_DISCONNECTED); 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(); } }
packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java +10 −0 Original line number Diff line number Diff line Loading @@ -83,4 +83,14 @@ public class FakeBluetoothController extends BaseLeakChecker<Callback> implement public boolean canConfigBluetooth() { return false; } @Override public int getMaxConnectionState(CachedBluetoothDevice device) { return 0; } @Override public int getBondState(CachedBluetoothDevice device) { return 0; } }